Chromium Code Reviews| 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 be34f25a98ff8985fe21dc55286388f44300e882..13c4aa942e2ce2f00349e947c901d177aec3c989 100644 |
| --- a/chrome/browser/ui/views/tabs/tab.cc |
| +++ b/chrome/browser/ui/views/tabs/tab.cc |
| @@ -39,6 +39,8 @@ |
| #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/widget/tooltip_manager.h" |
| @@ -248,6 +250,8 @@ const double kProjectingFaviconResizeScale = 0.75; |
| // Scale to resize the projection sheet glow by. |
| const double kProjectingGlowResizeScale = 2.0; |
| +const char kTabCloseButtonName[] = "TabCloseButton"; |
| + |
| void DrawIconAtLocation(gfx::Canvas* canvas, |
| const gfx::ImageSkia& image, |
| int image_offset, |
| @@ -357,21 +361,24 @@ 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 (!View::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)); |
| #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. |
| @@ -414,6 +421,39 @@ class Tab::TabCloseButton : public views::ImageButton { |
| event->SetHandled(); |
| } |
| + virtual bool HasHitTestMask() const OVERRIDE { |
| + return true; |
| + } |
| + |
| + virtual void GetHitTestMask(gfx::Path* path) 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); |
| + |
| + gfx::Rect button_bounds(GetContentsBounds()); |
| + gfx::Rect tab_bounds( |
| + gfx::ToEnclosingRect(gfx::SkRectToRectF(tab_mask.getBounds()))); |
| + views::View::ConvertRectToTarget(tab_, this, &tab_bounds); |
| + |
| + // 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)) { |
| +#if defined(USE_ASH) |
|
tdanderson
2013/10/03 23:17:42
If this code stays, I think the #if defined(USE_AS
sky
2013/10/04 17:05:14
I don't like this ifdef. It implies the API should
tdanderson
2013/10/07 21:35:21
I'm also not a fan of having this ifdef where it i
sky
2013/10/08 15:39:07
My point is that if a view needs to know if touch
|
| + // Include the padding in the hit test mask for touch events. |
| + if (aura::Env::GetInstance()->is_touch_down()) |
| + button_bounds = GetLocalBounds(); |
| +#endif |
| + path->addRect(RectToSkRect(button_bounds)); |
| + } |
| + } |
| + |
| + virtual const char* GetClassName() const OVERRIDE { |
| + return kTabCloseButtonName; |
| + } |
| + |
| private: |
| Tab* tab_; |
| @@ -882,6 +922,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 { |