summaryrefslogtreecommitdiffstats
path: root/chrome/browser
diff options
context:
space:
mode:
Diffstat (limited to 'chrome/browser')
-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.