summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authormattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-13 03:49:13 +0000
committermattm@chromium.org <mattm@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2011-08-13 03:49:13 +0000
commit4845d5f6661bf58e556da21c36c1472125e81327 (patch)
tree9c0f3e674d66c4f1224447b64f8ea15f6a4376d2 /chrome
parenta3340f3d323f769460a1b269eb8198faf071e2a2 (diff)
downloadchromium_src-4845d5f6661bf58e556da21c36c1472125e81327.zip
chromium_src-4845d5f6661bf58e556da21c36c1472125e81327.tar.gz
chromium_src-4845d5f6661bf58e556da21c36c1472125e81327.tar.bz2
Gtk: Make click target of tabs match their appearance.
BUG=87856 TEST=See bug Review URL: http://codereview.chromium.org/7640004 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@96674 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/ui/gtk/gtk_input_event_box.cc159
-rw-r--r--chrome/browser/ui/gtk/gtk_input_event_box.h57
-rw-r--r--chrome/browser/ui/gtk/tabs/tab_gtk.cc23
-rw-r--r--chrome/browser/ui/gtk/tabs/tab_gtk.h3
-rw-r--r--chrome/browser/ui/gtk/tabs/tab_renderer_gtk.cc4
-rw-r--r--chrome/browser/ui/gtk/tabs/tab_strip_gtk.cc36
-rw-r--r--chrome/browser/ui/gtk/tabs/tab_strip_gtk.h12
-rw-r--r--chrome/browser/ui/tabs/tab_resources.cc44
-rw-r--r--chrome/browser/ui/tabs/tab_resources.h22
-rw-r--r--chrome/browser/ui/views/tabs/tab.cc30
-rw-r--r--chrome/chrome_browser.gypi5
11 files changed, 361 insertions, 34 deletions
diff --git a/chrome/browser/ui/gtk/gtk_input_event_box.cc b/chrome/browser/ui/gtk/gtk_input_event_box.cc
new file mode 100644
index 0000000..c554834
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_input_event_box.cc
@@ -0,0 +1,159 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/gtk/gtk_input_event_box.h"
+
+#include <gdk/gdkwindow.h>
+#include <gtk/gtk.h>
+#include <gtk/gtkwidget.h>
+#include <gtk/gtkbin.h>
+
+G_BEGIN_DECLS
+
+#define GTK_INPUT_EVENT_BOX_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
+ GTK_TYPE_INPUT_EVENT_BOX, \
+ GtkInputEventBoxPrivate))
+
+typedef struct _GtkInputEventBoxPrivate GtkInputEventBoxPrivate;
+
+struct _GtkInputEventBoxPrivate {
+ GdkWindow* event_window;
+};
+
+G_DEFINE_TYPE(GtkInputEventBox, gtk_input_event_box, GTK_TYPE_BIN)
+
+static void gtk_input_event_box_realize(GtkWidget* widget);
+static void gtk_input_event_box_unrealize(GtkWidget* widget);
+static void gtk_input_event_box_map(GtkWidget* widget);
+static void gtk_input_event_box_unmap(GtkWidget* widget);
+static void gtk_input_event_box_size_allocate(GtkWidget* widget,
+ GtkAllocation* allocation);
+static void gtk_input_event_box_size_request(GtkWidget* widget,
+ GtkRequisition* requisition);
+
+static void gtk_input_event_box_class_init(GtkInputEventBoxClass* klass) {
+ GtkWidgetClass* widget_class = reinterpret_cast<GtkWidgetClass*>(klass);
+ widget_class->realize = gtk_input_event_box_realize;
+ widget_class->unrealize = gtk_input_event_box_unrealize;
+ widget_class->map = gtk_input_event_box_map;
+ widget_class->unmap = gtk_input_event_box_unmap;
+ widget_class->size_allocate = gtk_input_event_box_size_allocate;
+ widget_class->size_request = gtk_input_event_box_size_request;
+
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ g_type_class_add_private(gobject_class, sizeof(GtkInputEventBoxPrivate));
+}
+
+static void gtk_input_event_box_init(GtkInputEventBox* widget) {
+ GtkInputEventBoxPrivate* priv = GTK_INPUT_EVENT_BOX_GET_PRIVATE(widget);
+ priv->event_window = NULL;
+}
+
+GtkWidget* gtk_input_event_box_new() {
+ return GTK_WIDGET(g_object_new(GTK_TYPE_INPUT_EVENT_BOX, NULL));
+}
+
+static void gtk_input_event_box_realize(GtkWidget* widget) {
+ g_return_if_fail(GTK_IS_INPUT_EVENT_BOX(widget));
+
+ GtkInputEventBoxPrivate* priv = GTK_INPUT_EVENT_BOX_GET_PRIVATE(widget);
+
+ GdkWindow* parent = gtk_widget_get_parent_window(widget);
+ GdkWindowAttr attributes;
+ GtkAllocation allocation;
+ gint attributes_mask = GDK_WA_X | GDK_WA_Y;
+
+ gtk_widget_get_allocation(widget, &allocation);
+
+ attributes.x = allocation.x;
+ attributes.y = allocation.y;
+ attributes.width = allocation.width;
+ attributes.height = allocation.height;
+
+ attributes.window_type = GDK_WINDOW_CHILD;
+ attributes.wclass = GDK_INPUT_ONLY;
+
+ attributes.event_mask = gtk_widget_get_events(widget)
+ | GDK_BUTTON_MOTION_MASK
+ | GDK_BUTTON_PRESS_MASK
+ | GDK_BUTTON_RELEASE_MASK
+ | GDK_EXPOSURE_MASK
+ | GDK_ENTER_NOTIFY_MASK
+ | GDK_LEAVE_NOTIFY_MASK;
+
+ priv->event_window = gdk_window_new(parent, &attributes, attributes_mask);
+ gdk_window_set_user_data(priv->event_window, widget);
+
+ GTK_WIDGET_CLASS(gtk_input_event_box_parent_class)->realize(widget);
+}
+
+static void gtk_input_event_box_unrealize(GtkWidget* widget) {
+ g_return_if_fail(GTK_IS_INPUT_EVENT_BOX(widget));
+
+ GtkInputEventBoxPrivate* priv = GTK_INPUT_EVENT_BOX_GET_PRIVATE(widget);
+ if (priv->event_window) {
+ gdk_window_set_user_data(priv->event_window, NULL);
+ gdk_window_destroy(priv->event_window);
+ priv->event_window = NULL;
+ }
+
+ GTK_WIDGET_CLASS(gtk_input_event_box_parent_class)->unrealize(widget);
+}
+
+static void gtk_input_event_box_map(GtkWidget* widget) {
+ g_return_if_fail(GTK_IS_INPUT_EVENT_BOX(widget));
+
+ GtkInputEventBoxPrivate* priv = GTK_INPUT_EVENT_BOX_GET_PRIVATE(widget);
+ if (priv->event_window)
+ gdk_window_show(priv->event_window);
+
+ GTK_WIDGET_CLASS(gtk_input_event_box_parent_class)->map(widget);
+}
+
+static void gtk_input_event_box_unmap(GtkWidget* widget) {
+ g_return_if_fail(GTK_IS_INPUT_EVENT_BOX(widget));
+
+ GtkInputEventBoxPrivate* priv = GTK_INPUT_EVENT_BOX_GET_PRIVATE(widget);
+ if (priv->event_window)
+ gdk_window_hide(priv->event_window);
+
+ GTK_WIDGET_CLASS(gtk_input_event_box_parent_class)->unmap(widget);
+}
+
+static void gtk_input_event_box_size_allocate(GtkWidget* widget,
+ GtkAllocation* allocation) {
+ g_return_if_fail(GTK_IS_INPUT_EVENT_BOX(widget));
+
+ widget->allocation = *allocation;
+
+ GtkInputEventBoxPrivate* priv = GTK_INPUT_EVENT_BOX_GET_PRIVATE(widget);
+ if (priv->event_window) {
+ gdk_window_move_resize(priv->event_window,
+ allocation->x,
+ allocation->y,
+ allocation->width,
+ allocation->height);
+ }
+
+ GtkWidget* child = gtk_bin_get_child(GTK_BIN(widget));
+ if (child)
+ gtk_widget_size_allocate(child, allocation);
+}
+
+static void gtk_input_event_box_size_request(GtkWidget* widget,
+ GtkRequisition* requisition) {
+
+ GtkWidget* child = gtk_bin_get_child(GTK_BIN(widget));
+ if (child)
+ gtk_widget_size_request(child, requisition);
+}
+
+GdkWindow* gtk_input_event_box_get_window(GtkInputEventBox* widget) {
+ g_return_val_if_fail(GTK_IS_INPUT_EVENT_BOX(widget), NULL);
+
+ GtkInputEventBoxPrivate* priv = GTK_INPUT_EVENT_BOX_GET_PRIVATE(widget);
+ return priv->event_window;
+}
+
+G_END_DECLS
diff --git a/chrome/browser/ui/gtk/gtk_input_event_box.h b/chrome/browser/ui/gtk/gtk_input_event_box.h
new file mode 100644
index 0000000..365dbb6
--- /dev/null
+++ b/chrome/browser/ui/gtk/gtk_input_event_box.h
@@ -0,0 +1,57 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_GTK_GTK_INPUT_EVENT_BOX_H_
+#define CHROME_BROWSER_UI_GTK_GTK_INPUT_EVENT_BOX_H_
+#pragma once
+
+#include <gdk/gdk.h>
+#include <gtk/gtk.h>
+
+// GtkInputEventBox is like GtkEventBox, but with the following differences:
+// 1. Only supports input (like gtk_event_box_set_visible_window(foo, FALSE).
+// 2. Provides a method to get the GdkWindow (gtk_input_event_box_get_window).
+// (The GdkWindow created by GtkEventBox cannot be retrieved unless you use it
+// in visible mode.)
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_INPUT_EVENT_BOX \
+ (gtk_input_event_box_get_type())
+#define GTK_INPUT_EVENT_BOX(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_INPUT_EVENT_BOX, \
+ GtkInputEventBox))
+#define GTK_INPUT_EVENT_BOX_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_INPUT_EVENT_BOX, \
+ GtkInputEventBoxClass))
+#define GTK_IS_INPUT_EVENT_BOX(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GTK_TYPE_INPUT_EVENT_BOX))
+#define GTK_IS_INPUT_EVENT_BOX_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), GTK_TYPE_INPUT_EVENT_BOX))
+#define GTK_INPUT_EVENT_BOX_GET_CLASS(obj) \
+ (G_TYPE_INSTANCE_GET_CLASS((obj), GTK_TYPE_INPUT_EVENT_BOX, \
+ GtkInputEventBoxClass))
+
+typedef struct _GtkInputEventBox GtkInputEventBox;
+typedef struct _GtkInputEventBoxClass GtkInputEventBoxClass;
+
+struct _GtkInputEventBox {
+ // Parent class.
+ GtkBin bin;
+};
+
+struct _GtkInputEventBoxClass {
+ GtkBinClass parent_class;
+};
+
+GType gtk_input_event_box_get_type();
+GtkWidget* gtk_input_event_box_new();
+
+// Get the GdkWindow |widget| uses for handling input events. Will be NULL if
+// the widget has not been realized yet.
+GdkWindow* gtk_input_event_box_get_window(GtkInputEventBox* widget);
+
+G_END_DECLS
+
+#endif // CHROME_BROWSER_UI_GTK_GTK_INPUT_EVENT_BOX_H_
diff --git a/chrome/browser/ui/gtk/tabs/tab_gtk.cc b/chrome/browser/ui/gtk/tabs/tab_gtk.cc
index c8e4a51..c4c6399 100644
--- a/chrome/browser/ui/gtk/tabs/tab_gtk.cc
+++ b/chrome/browser/ui/gtk/tabs/tab_gtk.cc
@@ -10,12 +10,15 @@
#include "base/utf_string_conversions.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/ui/gtk/accelerators_gtk.h"
+#include "chrome/browser/ui/gtk/gtk_input_event_box.h"
#include "chrome/browser/ui/gtk/menu_gtk.h"
#include "chrome/browser/ui/gtk/tabs/tab_strip_menu_controller.h"
#include "chrome/browser/ui/tabs/tab_menu_model.h"
+#include "chrome/browser/ui/tabs/tab_resources.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "ui/base/dragdrop/gtk_dnd_util.h"
+#include "ui/base/gtk/scoped_handle_gtk.h"
#include "ui/base/models/accelerator_gtk.h"
#include "ui/gfx/path.h"
@@ -62,8 +65,7 @@ TabGtk::TabGtk(TabDelegate* delegate)
title_width_(0),
ALLOW_THIS_IN_INITIALIZER_LIST(destroy_factory_(this)),
ALLOW_THIS_IN_INITIALIZER_LIST(drag_end_factory_(this)) {
- event_box_ = gtk_event_box_new();
- gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_), FALSE);
+ event_box_ = gtk_input_event_box_new();
g_signal_connect(event_box_, "button-press-event",
G_CALLBACK(OnButtonPressEventThunk), this);
g_signal_connect(event_box_, "button-release-event",
@@ -97,6 +99,12 @@ TabGtk::~TabGtk() {
}
}
+void TabGtk::Raise() const {
+ GdkWindow* window = gtk_input_event_box_get_window(
+ GTK_INPUT_EVENT_BOX(event_box_));
+ gdk_window_raise(window);
+}
+
gboolean TabGtk::OnButtonPressEvent(GtkWidget* widget, GdkEventButton* event) {
// Every button press ensures either a button-release-event or a drag-fail
// signal for |widget|.
@@ -257,6 +265,17 @@ void TabGtk::UpdateData(TabContents* contents, bool app, bool loading_only) {
void TabGtk::SetBounds(const gfx::Rect& bounds) {
TabRendererGtk::SetBounds(bounds);
+
+ if (gtk_input_event_box_get_window(GTK_INPUT_EVENT_BOX(event_box_))) {
+ gfx::Path mask;
+ TabResources::GetHitTestMask(bounds.width(), bounds.height(), &mask);
+ ui::ScopedRegion region(mask.CreateNativeRegion());
+ gdk_window_input_shape_combine_region(
+ gtk_input_event_box_get_window(GTK_INPUT_EVENT_BOX(event_box_)),
+ region.Get(),
+ 0, 0);
+ }
+
UpdateTooltipState();
}
diff --git a/chrome/browser/ui/gtk/tabs/tab_gtk.h b/chrome/browser/ui/gtk/tabs/tab_gtk.h
index bfa64e0..84df548 100644
--- a/chrome/browser/ui/gtk/tabs/tab_gtk.h
+++ b/chrome/browser/ui/gtk/tabs/tab_gtk.h
@@ -113,6 +113,9 @@ class TabGtk : public TabRendererGtk,
void set_dragging(bool dragging) { dragging_ = dragging; }
bool dragging() const { return dragging_; }
+ // Raise to top of Z-order.
+ void Raise() const;
+
// TabRendererGtk overrides:
virtual bool IsActive() const;
virtual bool IsSelected() const;
diff --git a/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.cc b/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.cc
index ad9e9681..6289ba2 100644
--- a/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.cc
+++ b/chrome/browser/ui/gtk/tabs/tab_renderer_gtk.cc
@@ -72,10 +72,6 @@ const double kMiniTitleChangeThrobOpacity = 0.75;
// Duration for when the title of an inactive mini-tab changes.
const int kMiniTitleChangeThrobDuration = 1000;
-const SkScalar kTabCapWidth = 15;
-const SkScalar kTabTopCurveWidth = 4;
-const SkScalar kTabBottomCurveWidth = 3;
-
// The vertical and horizontal offset used to position the close button
// in the tab. TODO(jhawkins): Ask pkasting what the Fuzz is about.
const int kCloseButtonVertFuzz = 0;
diff --git a/chrome/browser/ui/gtk/tabs/tab_strip_gtk.cc b/chrome/browser/ui/gtk/tabs/tab_strip_gtk.cc
index 142e4cb..d1eb188 100644
--- a/chrome/browser/ui/gtk/tabs/tab_strip_gtk.cc
+++ b/chrome/browser/ui/gtk/tabs/tab_strip_gtk.cc
@@ -750,6 +750,8 @@ void TabStripGtk::Init() {
-1 };
ui::SetDestTargetList(tabstrip_.get(), targets);
+ g_signal_connect(tabstrip_.get(), "map",
+ G_CALLBACK(OnMapThunk), this);
g_signal_connect(tabstrip_.get(), "expose-event",
G_CALLBACK(OnExposeThunk), this);
g_signal_connect(tabstrip_.get(), "size-allocate",
@@ -1006,6 +1008,8 @@ void TabStripGtk::TabInsertedAt(TabContentsWrapper* contents,
} else {
Layout();
}
+
+ ReStack();
}
void TabStripGtk::TabDetachedAt(TabContentsWrapper* contents, int index) {
@@ -1017,6 +1021,13 @@ void TabStripGtk::TabDetachedAt(TabContentsWrapper* contents, int index) {
GetTabAt(index)->set_closing(true);
}
+void TabStripGtk::ActiveTabChanged(TabContentsWrapper* old_contents,
+ TabContentsWrapper* new_contents,
+ int index,
+ bool user_gesture) {
+ ReStack();
+}
+
void TabStripGtk::TabSelectionChanged(const TabStripSelectionModel& old_model) {
// We have "tiny tabs" if the tabs are so tiny that the unselected ones are
// a different size to the selected ones.
@@ -1075,6 +1086,7 @@ void TabStripGtk::TabMoved(TabContentsWrapper* contents,
tab_data_.insert(tab_data_.begin() + to_index, data);
GenerateIdealBounds();
StartMoveTabAnimation(from_index, to_index);
+ ReStack();
}
void TabStripGtk::TabChangedAt(TabContentsWrapper* contents, int index,
@@ -1580,6 +1592,26 @@ bool TabStripGtk::IsCursorInTabStripZone() const {
return bds.Contains(cursor_point);
}
+void TabStripGtk::ReStack() {
+ if (!GTK_WIDGET_REALIZED(tabstrip_.get())) {
+ // If the window isn't realized yet, we can't stack them yet. It will be
+ // done by the OnMap signal handler.
+ return;
+ }
+ int tab_count = GetTabCount();
+ TabGtk* active_tab = NULL;
+ for (int i = tab_count - 1; i >= 0; --i) {
+ TabGtk* tab = GetTabAt(i);
+ if (tab->IsActive())
+ active_tab = tab;
+ else
+ tab->Raise();
+ }
+ if (active_tab)
+ active_tab->Raise();
+}
+
+
void TabStripGtk::AddMessageLoopObserver() {
if (!added_as_message_loop_observer_) {
MessageLoopForUI::current()->AddObserver(this);
@@ -1937,6 +1969,10 @@ void TabStripGtk::FinishAnimation(TabStripGtk::TabAnimation* animation,
Layout();
}
+void TabStripGtk::OnMap(GtkWidget* widget) {
+ ReStack();
+}
+
gboolean TabStripGtk::OnExpose(GtkWidget* widget, GdkEventExpose* event) {
if (gdk_region_empty(event->region))
return TRUE;
diff --git a/chrome/browser/ui/gtk/tabs/tab_strip_gtk.h b/chrome/browser/ui/gtk/tabs/tab_strip_gtk.h
index 98c7a85..c10e097 100644
--- a/chrome/browser/ui/gtk/tabs/tab_strip_gtk.h
+++ b/chrome/browser/ui/gtk/tabs/tab_strip_gtk.h
@@ -110,6 +110,10 @@ class TabStripGtk : public TabStripModelObserver,
virtual void TabMoved(TabContentsWrapper* contents,
int from_index,
int to_index);
+ virtual void ActiveTabChanged(TabContentsWrapper* old_contents,
+ TabContentsWrapper* new_contents,
+ int index,
+ bool user_gesture);
virtual void TabSelectionChanged(const TabStripSelectionModel& old_model);
virtual void TabChangedAt(TabContentsWrapper* contents, int index,
TabChangeType change_type);
@@ -228,6 +232,11 @@ class TabStripGtk : public TabStripModelObserver,
DISALLOW_COPY_AND_ASSIGN(DropInfo);
};
+ // Map signal handler that sets initial z-ordering. The widgets need to be
+ // realized before we can set the stacking. We use the "map" signal since the
+ // "realize" signal is called before the child widgets get realized.
+ CHROMEGTK_CALLBACK_0(TabStripGtk, void, OnMap);
+
// expose-event handler that redraws the tabstrip
CHROMEGTK_CALLBACK_1(TabStripGtk, gboolean, OnExpose, GdkEventExpose*);
@@ -321,6 +330,9 @@ class TabStripGtk : public TabStripModelObserver,
// which is defined as the region above the TabStrip and a bit below it.
bool IsCursorInTabStripZone() const;
+ // Reset the Z-ordering of tabs.
+ void ReStack();
+
// Ensure that the message loop observer used for event spying is added and
// removed appropriately so we can tell when to resize layout the tab strip.
void AddMessageLoopObserver();
diff --git a/chrome/browser/ui/tabs/tab_resources.cc b/chrome/browser/ui/tabs/tab_resources.cc
new file mode 100644
index 0000000..45f06c3
--- /dev/null
+++ b/chrome/browser/ui/tabs/tab_resources.cc
@@ -0,0 +1,44 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/ui/tabs/tab_resources.h"
+
+#include "base/logging.h"
+#include "ui/gfx/path.h"
+
+namespace {
+
+// Hit mask constants.
+const SkScalar kTabCapWidth = 15;
+const SkScalar kTabTopCurveWidth = 4;
+const SkScalar kTabBottomCurveWidth = 3;
+
+} // namespace
+
+// static
+void TabResources::GetHitTestMask(int width, int height, gfx::Path* path) {
+ DCHECK(path);
+
+ SkScalar h = SkIntToScalar(height);
+ SkScalar w = SkIntToScalar(width);
+
+ 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/ui/tabs/tab_resources.h b/chrome/browser/ui/tabs/tab_resources.h
new file mode 100644
index 0000000..975ccd0
--- /dev/null
+++ b/chrome/browser/ui/tabs/tab_resources.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2011 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_BROWSER_UI_TABS_TAB_RESOURCES_H_
+#define CHROME_BROWSER_UI_TABS_TAB_RESOURCES_H_
+#pragma once
+
+namespace gfx {
+class Path;
+}
+
+// Common resources for tab widgets. Currently this is used on Views and Gtk,
+// but not on Cocoa.
+class TabResources {
+ public:
+ // Return a |path| containing the region that matches the bitmap display of
+ // a tab of the given |width| and |height|, for input event hit testing.
+ static void GetHitTestMask(int width, int height, gfx::Path* path);
+};
+
+#endif // CHROME_BROWSER_UI_TABS_TAB_RESOURCES_H_
diff --git a/chrome/browser/ui/views/tabs/tab.cc b/chrome/browser/ui/views/tabs/tab.cc
index b675565..be385c3 100644
--- a/chrome/browser/ui/views/tabs/tab.cc
+++ b/chrome/browser/ui/views/tabs/tab.cc
@@ -9,6 +9,7 @@
#include "base/utf_string_conversions.h"
#include "chrome/browser/defaults.h"
#include "chrome/browser/themes/theme_service.h"
+#include "chrome/browser/ui/tabs/tab_resources.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "grit/theme_resources_standard.h"
@@ -84,11 +85,6 @@ static const SkColor kMiniTitleChangeGradientColor1 = SK_ColorWHITE;
static const SkColor kMiniTitleChangeGradientColor2 =
SkColorSetARGB(0, 255, 255, 255);
-// Hit mask constants.
-static const SkScalar kTabCapWidth = 15;
-static const SkScalar kTabTopCurveWidth = 4;
-static const SkScalar kTabBottomCurveWidth = 3;
-
// static
const char Tab::kViewClassName[] = "browser/tabs/Tab";
@@ -325,29 +321,7 @@ bool Tab::HasHitTestMask() const {
}
void Tab::GetHitTestMask(gfx::Path* path) const {
- DCHECK(path);
-
- SkScalar h = SkIntToScalar(height());
- SkScalar w = SkIntToScalar(width());
-
- 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();
+ TabResources::GetHitTestMask(width(), height(), path);
}
bool Tab::GetTooltipTextOrigin(const gfx::Point& p, gfx::Point* origin) {
diff --git a/chrome/chrome_browser.gypi b/chrome/chrome_browser.gypi
index f546423..076be2e 100644
--- a/chrome/chrome_browser.gypi
+++ b/chrome/chrome_browser.gypi
@@ -2874,6 +2874,8 @@
'browser/ui/gtk/gtk_expanded_container.h',
'browser/ui/gtk/gtk_floating_container.cc',
'browser/ui/gtk/gtk_floating_container.h',
+ 'browser/ui/gtk/gtk_input_event_box.cc',
+ 'browser/ui/gtk/gtk_input_event_box.h',
'browser/ui/gtk/gtk_theme_service.cc',
'browser/ui/gtk/gtk_theme_service.h',
'browser/ui/gtk/gtk_tree.cc',
@@ -3051,6 +3053,8 @@
'browser/ui/tabs/hover_tab_selector.h',
'browser/ui/tabs/tab_menu_model.cc',
'browser/ui/tabs/tab_menu_model.h',
+ 'browser/ui/tabs/tab_resources.cc',
+ 'browser/ui/tabs/tab_resources.h',
'browser/ui/toolbar/back_forward_menu_model.cc',
'browser/ui/toolbar/back_forward_menu_model.h',
'browser/ui/toolbar/encoding_menu_controller.cc',
@@ -4051,6 +4055,7 @@
'browser/ui/panels/panel_browser_view.cc',
'browser/ui/panels/panel_browser_view.h',
'browser/ui/tabs/dock_info.cc',
+ 'browser/ui/tabs/tab_resources.cc',
'browser/ui/views/extensions/extension_view.cc',
'browser/ui/views/extensions/extension_view.h',
],