Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(5409)

Unified Diff: chrome/browser/ui/views/tabs/tab.cc

Issue 22891016: Add support for rect-based event targeting in views (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: tests added Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/views/tabs/tab.cc
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc
index 73e01ea1492f8dfe4f4edbac3d2069bddc837bbe..8c71f31028565fdf43f9e999589acba71db69b60 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -39,8 +39,11 @@
#include "ui/gfx/font.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/path.h"
+#include "ui/gfx/rect_conversions.h"
+#include "ui/gfx/skia_util.h"
#include "ui/gfx/text_elider.h"
#include "ui/views/controls/button/image_button.h"
+#include "ui/views/rect_based_targeting_utils.h"
#include "ui/views/widget/tooltip_manager.h"
#include "ui/views/widget/widget.h"
#include "ui/views/window/non_client_view.h"
@@ -242,6 +245,8 @@ const double kImmersiveTabMinThrobOpacity = 0.66;
// Number of steps in the immersive mode loading animation.
const int kImmersiveLoadingStepCount = 32;
+const char kTabCloseButtonName[] = "TabCloseButton";
+
void DrawIconAtLocation(gfx::Canvas* canvas,
const gfx::ImageSkia& image,
int image_offset,
@@ -351,21 +356,26 @@ class Tab::TabCloseButton : public views::ImageButton {
virtual ~TabCloseButton() {}
// Overridden from views::View.
- virtual View* GetEventHandlerForPoint(const gfx::Point& point) OVERRIDE {
+ virtual View* GetEventHandlerForRect(const gfx::Rect& rect) OVERRIDE {
+ if (!views::UsePointBasedTargeting(rect))
+ return View::GetEventHandlerForRect(rect);
+
// Ignore the padding set on the button.
- gfx::Rect rect = GetContentsBounds();
- rect.set_x(GetMirroredXForRect(rect));
+ gfx::Rect contents_bounds = GetContentsBounds();
+ contents_bounds.set_x(GetMirroredXForRect(contents_bounds));
+ // TODO(tdanderson): Remove this ifdef if rect-based targeting
+ // is turned on by default.
#if defined(USE_ASH)
// Include the padding in hit-test for touch events.
if (aura::Env::GetInstance()->is_touch_down())
- rect = GetLocalBounds();
+ contents_bounds = GetLocalBounds();
#elif defined(OS_WIN)
// TODO(sky): Use local-bounds if a touch-point is active.
// http://crbug.com/145258
#endif
- return rect.Contains(point) ? this : parent();
+ return contents_bounds.Intersects(rect) ? this : parent();
}
// Overridden from views::View.
@@ -408,6 +418,39 @@ class Tab::TabCloseButton : public views::ImageButton {
event->SetHandled();
}
+ virtual bool HasHitTestMask() const OVERRIDE {
+ return true;
+ }
+
+ virtual void GetHitTestMask(gfx::Path* path,
+ HitTestSource source = HIT_TEST_SOURCE_MOUSE) const OVERRIDE {
+ // Use the button's contents bounds (which does not include padding)
+ // and the hit test mask of our parent |tab_| to determine if the
+ // button is completely hidden behind another tab.
+ gfx::Path tab_mask;
+ tab_->GetHitTestMask(&tab_mask, source);
+
+ gfx::Rect button_bounds(GetContentsBounds());
+ gfx::RectF tab_bounds_f(gfx::SkRectToRectF(tab_mask.getBounds()));
+ views::View::ConvertRectToTarget(tab_, this, &tab_bounds_f);
+ gfx::Rect tab_bounds = gfx::ToEnclosingRect(tab_bounds_f);
+
+ // If the button is completely hidden behind another tab, the hit test
+ // mask is empty. Otherwise set the hit test mask to be the contents bounds.
+ path->reset();
+ if (tab_bounds.Contains(button_bounds)) {
+ // Include the padding in the hit test mask for touch events.
+ if (source == HIT_TEST_SOURCE_TOUCH)
+ button_bounds = GetLocalBounds();
+
+ path->addRect(RectToSkRect(button_bounds));
+ }
+ }
+
+ virtual const char* GetClassName() const OVERRIDE {
+ return kTabCloseButtonName;
+ }
+
private:
Tab* tab_;
@@ -872,7 +915,7 @@ bool Tab::HasHitTestMask() const {
return true;
}
-void Tab::GetHitTestMask(gfx::Path* path) const {
+void Tab::GetHitTestMask(gfx::Path* path, HitTestSource source) const {
// When the window is maximized we don't want to shave off the edges or top
// shadow of the tab, such that the user can click anywhere along the top
// edge of the screen to select a tab. Ditto for immersive fullscreen.
@@ -880,6 +923,20 @@ void Tab::GetHitTestMask(gfx::Path* path) const {
bool include_top_shadow =
widget && (widget->IsMaximized() || widget->IsFullscreen());
TabResources::GetHitTestMask(width(), height(), include_top_shadow, path);
+
+ // It is possible for a portion of the tab to be occluded if tabs are
+ // stacked, so modify the hit test mask to only include the visible
+ // region of the tab.
+ if (controller()) {
+ gfx::Rect clip;
+ controller()->ShouldPaintTab(this, &clip);
+ if (clip.size().GetArea()) {
+ SkRect intersection(path->getBounds());
+ intersection.intersect(RectToSkRect(clip));
+ path->reset();
+ path->addRect(intersection);
+ }
+ }
}
bool Tab::GetTooltipText(const gfx::Point& p, string16* tooltip) const {

Powered by Google App Engine
This is Rietveld 408576698