summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorbeng@google.com <beng@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-08-25 20:37:23 +0000
committerbeng@google.com <beng@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-08-25 20:37:23 +0000
commit050aa8004bdacfe680417f455b8723b693f92c66 (patch)
tree2498a52b71efcd2063887d4809d34f5b99fa4900 /chrome
parent4e676cc8c2c9de932162727b2e6a1a31ac176df9 (diff)
downloadchromium_src-050aa8004bdacfe680417f455b8723b693f92c66.zip
chromium_src-050aa8004bdacfe680417f455b8723b693f92c66.tar.gz
chromium_src-050aa8004bdacfe680417f455b8723b693f92c66.tar.bz2
Make tabs highlight and accept clicks based on the shape of the rendered tab, rather than the bounding box of the view that renders it. This allows for truer event handling.
B=656878 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@1327 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/tabs/tab.cc41
-rw-r--r--chrome/browser/tabs/tab.h7
-rw-r--r--chrome/browser/tabs/tab_strip.cc36
-rw-r--r--chrome/browser/tabs/tab_strip.h7
4 files changed, 91 insertions, 0 deletions
diff --git a/chrome/browser/tabs/tab.cc b/chrome/browser/tabs/tab.cc
index 4482079..f855701 100644
--- a/chrome/browser/tabs/tab.cc
+++ b/chrome/browser/tabs/tab.cc
@@ -6,6 +6,8 @@
#include "base/gfx/size.h"
#include "chrome/views/view_container.h"
+#include "chrome/common/gfx/chrome_canvas.h"
+#include "chrome/common/gfx/path.h"
#include "chrome/common/resource_bundle.h"
#include "chrome/views/chrome_menu.h"
#include "chrome/views/tooltip_manager.h"
@@ -13,6 +15,10 @@
const std::string Tab::kTabClassName = "browser/tabs/Tab";
+static const SkScalar kTabCapWidth = 15;
+static const SkScalar kTabTopCurveWidth = 4;
+static const SkScalar kTabBottomCurveWidth = 3;
+
class TabContextMenuController : public ChromeViews::MenuDelegate {
public:
explicit TabContextMenuController(Tab* tab)
@@ -120,6 +126,13 @@ bool Tab::IsSelected() const {
///////////////////////////////////////////////////////////////////////////////
// Tab, ChromeViews::View overrides:
+bool Tab::HitTest(const CPoint &l) const {
+ gfx::Path path;
+ MakePathForTab(&path);
+ ScopedHRGN rgn(path.CreateHRGN());
+ return !!PtInRegion(rgn, l.x, l.y);
+}
+
bool Tab::OnMousePressed(const ChromeViews::MouseEvent& event) {
if (event.IsOnlyLeftMouseButton()) {
// Store whether or not we were selected just now... we only want to be
@@ -198,3 +211,31 @@ void Tab::ButtonPressed(ChromeViews::BaseButton* sender) {
delegate_->CloseTab(this);
}
+///////////////////////////////////////////////////////////////////////////////
+// Tab, private:
+
+void Tab::MakePathForTab(gfx::Path* path) const {
+ DCHECK(path);
+
+ SkScalar h = SkIntToScalar(GetHeight());
+ SkScalar w = SkIntToScalar(GetWidth());
+
+ path->moveTo(0, h);
+
+ // Left end cap.
+ path->lineTo(kTabBottomCurveWidth, h - kTabBottomCurveWidth);
+ path->lineTo(kTabCapWidth - kTabTopCurveWidth, kTabTopCurveWidth);
+ path->lineTo(kTabCapWidth, 0);
+
+ // Connect to the right cap.
+ path->lineTo(w - kTabCapWidth, 0);
+
+ // Right end cap.
+ path->lineTo(w - kTabCapWidth - kTabTopCurveWidth, kTabTopCurveWidth);
+ path->lineTo(w - kTabBottomCurveWidth, h - kTabBottomCurveWidth);
+ path->lineTo(w, h);
+
+ // Close out the path.
+ path->lineTo(0, h);
+ path->close();
+}
diff --git a/chrome/browser/tabs/tab.h b/chrome/browser/tabs/tab.h
index 802156b..10346ef 100644
--- a/chrome/browser/tabs/tab.h
+++ b/chrome/browser/tabs/tab.h
@@ -10,6 +10,7 @@
#include "chrome/views/base_button.h"
namespace gfx {
+class Path;
class Point;
}
class TabContents;
@@ -83,6 +84,8 @@ class Tab : public TabRenderer,
// TabRenderer overrides:
virtual bool IsSelected() const;
+ // ChromeViews::View overrides:
+ virtual bool HitTest(const CPoint &l) const;
private:
// ChromeViews::View overrides:
virtual bool OnMousePressed(const ChromeViews::MouseEvent& event);
@@ -104,6 +107,10 @@ class Tab : public TabRenderer,
// ChromeViews::BaseButton::ButtonListener overrides:
virtual void ButtonPressed(ChromeViews::BaseButton* sender);
+ // Creates a path that contains the clickable region of the tab's visual
+ // representation. Used by GetViewForPoint for hit-testing.
+ void MakePathForTab(gfx::Path* path) const;
+
// An instance of a delegate object that can perform various actions based on
// user gestures.
TabDelegate* delegate_;
diff --git a/chrome/browser/tabs/tab_strip.cc b/chrome/browser/tabs/tab_strip.cc
index efb4763..aed87a1 100644
--- a/chrome/browser/tabs/tab_strip.cc
+++ b/chrome/browser/tabs/tab_strip.cc
@@ -689,6 +689,36 @@ void TabStrip::SetAccessibleName(const std::wstring& name) {
accessible_name_.assign(name);
}
+ChromeViews::View* TabStrip::GetViewForPoint(const CPoint& point) {
+ return GetViewForPoint(point, false);
+}
+
+ChromeViews::View* TabStrip::GetViewForPoint(const CPoint& point,
+ bool can_create_floating) {
+ // Return any view that isn't a Tab or this TabStrip immediately. We don't
+ // want to interfere.
+ ChromeViews::View* v = View::GetViewForPoint(point, can_create_floating);
+ if (v && v != this && v->GetClassName() != Tab::kTabClassName)
+ return v;
+
+ // The display order doesn't necessarily match the child list order, so we
+ // walk the display list hit-testing Tabs. Since the selected tab always
+ // renders on top of adjacent tabs, it needs to be hit-tested before any
+ // left-adjacent Tab, so we look ahead for it as we walk.
+ int tab_count = GetTabCount();
+ for (int i = 0; i < tab_count; ++i) {
+ Tab* next_tab = i < (tab_count - 1) ? GetTabAt(i + 1) : NULL;
+ if (next_tab && next_tab->IsSelected() && IsPointInTab(next_tab, point))
+ return next_tab;
+ Tab* tab = GetTabAt(i);
+ if (IsPointInTab(tab, point))
+ return tab;
+ }
+
+ // No need to do any floating view stuff, we don't use them in the TabStrip.
+ return this;
+}
+
///////////////////////////////////////////////////////////////////////////////
// TabStrip, TabStripModelObserver implementation:
@@ -1476,3 +1506,9 @@ int TabStrip::GetAvailableWidthForTabs(Tab* last_tab) const {
return last_tab->GetX() + last_tab->GetWidth();
}
+bool TabStrip::IsPointInTab(Tab* tab, const CPoint& point_in_tabstrip_coords) {
+ CPoint point_in_tab_coords(point_in_tabstrip_coords);
+ View::ConvertPointToView(this, tab, &point_in_tab_coords);
+ return tab->HitTest(point_in_tab_coords);
+}
+
diff --git a/chrome/browser/tabs/tab_strip.h b/chrome/browser/tabs/tab_strip.h
index 89151d8..ad14213 100644
--- a/chrome/browser/tabs/tab_strip.h
+++ b/chrome/browser/tabs/tab_strip.h
@@ -114,6 +114,9 @@ class TabStrip : public ChromeViews::View,
virtual bool GetAccessibleRole(VARIANT* role);
virtual bool GetAccessibleName(std::wstring* name);
virtual void SetAccessibleName(const std::wstring& name);
+ virtual ChromeViews::View* GetViewForPoint(const CPoint& point);
+ virtual ChromeViews::View* GetViewForPoint(const CPoint& point,
+ bool can_create_floating);
protected:
// TabStripModelObserver implementation:
@@ -268,6 +271,10 @@ class TabStrip : public ChromeViews::View,
// Calculates the available width for tabs, assuming a Tab is to be closed.
int GetAvailableWidthForTabs(Tab* last_tab) const;
+ // Returns true if the specified point in TabStrip coords is within the
+ // hit-test region of the specified Tab.
+ bool IsPointInTab(Tab* tab, const CPoint& point_in_tabstrip_coords);
+
// -- Member Variables ------------------------------------------------------
// Our model.