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

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

Issue 361083004: Tab and TabCloseButton should implement MaskedTargeterDelegate (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: re-upload Created 6 years, 5 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
« no previous file with comments | « chrome/browser/ui/views/tabs/tab.h ('k') | chrome/browser/ui/views/tabs/tab_strip_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 2b4392ccd588810ba7dd052c5d4aa19c003d030d..1db349eaea78a8fb36fc99b6b16de9605a3597a6 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -45,6 +45,7 @@
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/rect_based_targeting_utils.h"
+#include "ui/views/view_targeter.h"
#include "ui/views/widget/tooltip_manager.h"
#include "ui/views/widget/widget.h"
#include "ui/views/window/non_client_view.h"
@@ -231,12 +232,19 @@ class Tab::FaviconCrashAnimation : public gfx::LinearAnimation,
//
// This is a Button subclass that causes middle clicks to be forwarded to the
// parent View by explicitly not handling them in OnMousePressed.
-class Tab::TabCloseButton : public views::ImageButton {
+class Tab::TabCloseButton : public views::ImageButton,
+ public views::MaskedTargeterDelegate {
public:
- explicit TabCloseButton(Tab* tab) : views::ImageButton(tab), tab_(tab) {}
+ explicit TabCloseButton(Tab* tab)
+ : views::ImageButton(tab),
+ tab_(tab) {
+ SetEventTargeter(
+ scoped_ptr<views::ViewTargeter>(new views::ViewTargeter(this)));
+ }
+
virtual ~TabCloseButton() {}
- // Overridden from views::View.
+ // views::View:
virtual View* GetEventHandlerForRect(const gfx::Rect& rect) OVERRIDE {
if (!views::UsePointBasedTargeting(rect))
return View::GetEventHandlerForRect(rect);
@@ -252,7 +260,6 @@ class Tab::TabCloseButton : public views::ImageButton {
return contents_bounds.Intersects(rect) ? this : parent();
}
- // Overridden from views::View.
virtual View* GetTooltipHandlerForPoint(const gfx::Point& point) OVERRIDE {
// Tab close button has no children, so tooltip handler should be the same
// as the event handler.
@@ -289,26 +296,30 @@ class Tab::TabCloseButton : public views::ImageButton {
event->SetHandled();
}
- virtual bool HasHitTestMask() const OVERRIDE {
- return true;
+ virtual const char* GetClassName() const OVERRIDE {
+ return kTabCloseButtonName;
}
- virtual void GetHitTestMaskDeprecated(HitTestSource source,
- 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 hidden behind another tab.
+ private:
+ // Returns the rectangular bounds of parent tab's visible region in the
+ // local coordinate space of |this|.
+ gfx::Rect GetTabBounds() const {
gfx::Path tab_mask;
- tab_->GetHitTestMaskDeprecated(source, &tab_mask);
+ tab_->GetHitTestMask(&tab_mask);
- gfx::Rect button_bounds(GetContentsBounds());
- button_bounds.set_x(GetMirroredXForRect(button_bounds));
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);
+ return gfx::ToEnclosingRect(tab_bounds_f);
+ }
+
+ // Returns the rectangular bounds of the tab close button in the local
+ // coordinate space of |this|, not including clipped regions on the top
+ // or bottom of the button. |tab_bounds| is the rectangular bounds of
+ // the parent tab's visible region in the local coordinate space of |this|.
+ gfx::Rect GetTabCloseButtonBounds(const gfx::Rect& tab_bounds) const {
+ gfx::Rect button_bounds(GetContentsBounds());
+ button_bounds.set_x(GetMirroredXForRect(button_bounds));
- // If either the top or bottom of the tab close button is clipped,
- // do not consider these regions to be part of the button's bounds.
int top_overflow = tab_bounds.y() - button_bounds.y();
int bottom_overflow = button_bounds.bottom() - tab_bounds.bottom();
if (top_overflow > 0)
@@ -316,29 +327,52 @@ class Tab::TabCloseButton : public views::ImageButton {
else if (bottom_overflow > 0)
button_bounds.set_height(button_bounds.height() - bottom_overflow);
- // If the hit test request is in response to a gesture, |path| should be
- // empty unless the entire tab close button is visible to the user. Hit
- // test requests in response to a mouse event should always set |path|
- // to be the visible portion of the tab close button, even if it is
- // partially hidden behind another tab.
- path->reset();
+ return button_bounds;
+ }
+
+ // views:MaskedTargeterDelegate:
+ virtual bool GetHitTestMask(gfx::Path* mask) const OVERRIDE {
+ DCHECK(mask);
+ mask->reset();
+
+ // The parent tab may be partially occluded by another tab if we are
+ // in stacked tab mode, which means that the tab close button may also
+ // be partially occluded. Define the hit test mask of the tab close
+ // button to be the intersection of the parent tab's visible bounds
+ // and the bounds of the tab close button.
+ gfx::Rect tab_bounds(GetTabBounds());
+ gfx::Rect button_bounds(GetTabCloseButtonBounds(tab_bounds));
gfx::Rect intersection(gfx::IntersectRects(tab_bounds, button_bounds));
- if (!intersection.IsEmpty()) {
- // TODO(tdanderson): Consider always returning the intersection if
- // the non-rectangular shape of the tabs can be accounted for.
- if (source == HIT_TEST_SOURCE_TOUCH &&
- !tab_bounds.Contains(button_bounds))
- return;
- path->addRect(RectToSkRect(intersection));
+ if (!intersection.IsEmpty()) {
+ mask->addRect(RectToSkRect(intersection));
+ return true;
}
+
+ return false;
}
- virtual const char* GetClassName() const OVERRIDE {
- return kTabCloseButtonName;
+ virtual bool DoesIntersectRect(const View* target,
+ const gfx::Rect& rect) const OVERRIDE {
+ CHECK_EQ(target, this);
+
+ // If the request is not made in response to a gesture, use the
+ // default implementation.
+ if (views::UsePointBasedTargeting(rect))
+ return MaskedTargeterDelegate::DoesIntersectRect(target, rect);
+
+ // The hit test request is in response to a gesture. Return false if any
+ // part of the tab close button is hidden from the user.
+ // TODO(tdanderson): Consider always returning the intersection if the
+ // non-rectangular shape of the tab can be accounted for.
+ gfx::Rect tab_bounds(GetTabBounds());
+ gfx::Rect button_bounds(GetTabCloseButtonBounds(tab_bounds));
+ if (!tab_bounds.Contains(button_bounds))
+ return false;
+
+ return MaskedTargeterDelegate::DoesIntersectRect(target, rect);
}
- private:
Tab* tab_;
DISALLOW_COPY_AND_ASSIGN(TabCloseButton);
@@ -401,6 +435,9 @@ Tab::Tab(TabController* controller)
title_->SetText(CoreTabHelper::GetDefaultTitle());
AddChildView(title_);
+ SetEventTargeter(
+ scoped_ptr<views::ViewTargeter>(new views::ViewTargeter(this)));
+
// Add the Close Button.
close_button_ = new TabCloseButton(this);
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
@@ -655,6 +692,35 @@ void Tab::ShowContextMenuForView(views::View* source,
}
////////////////////////////////////////////////////////////////////////////////
+// Tab, views::MaskedTargeterDelegate overrides:
+
+bool Tab::GetHitTestMask(gfx::Path* mask) const {
+ DCHECK(mask);
+
+ // 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.
+ const views::Widget* widget = GetWidget();
+ bool include_top_shadow =
+ widget && (widget->IsMaximized() || widget->IsFullscreen());
+ TabResources::GetHitTestMask(width(), height(), include_top_shadow, mask);
+
+ // 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.
+ gfx::Rect clip;
+ controller_->ShouldPaintTab(this, &clip);
+ if (clip.size().GetArea()) {
+ SkRect intersection(mask->getBounds());
+ intersection.intersect(RectToSkRect(clip));
+ mask->reset();
+ mask->addRect(intersection);
+ }
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
// Tab, views::View overrides:
void Tab::OnPaint(gfx::Canvas* canvas) {
@@ -803,33 +869,6 @@ const char* Tab::GetClassName() const {
return kViewClassName;
}
-bool Tab::HasHitTestMask() const {
- return true;
-}
-
-void Tab::GetHitTestMaskDeprecated(HitTestSource source,
- gfx::Path* path) 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.
- const views::Widget* widget = GetWidget();
- 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.
- 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, base::string16* tooltip) const {
// Note: Anything that affects the tooltip text should be accounted for when
// calling TooltipTextChanged() from Tab::DataChanged().
« no previous file with comments | « chrome/browser/ui/views/tabs/tab.h ('k') | chrome/browser/ui/views/tabs/tab_strip_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698