diff options
Diffstat (limited to 'chrome/browser/gtk/tabs/tab_gtk.cc')
-rw-r--r-- | chrome/browser/gtk/tabs/tab_gtk.cc | 204 |
1 files changed, 127 insertions, 77 deletions
diff --git a/chrome/browser/gtk/tabs/tab_gtk.cc b/chrome/browser/gtk/tabs/tab_gtk.cc index 9966d0f..6db2595 100644 --- a/chrome/browser/gtk/tabs/tab_gtk.cc +++ b/chrome/browser/gtk/tabs/tab_gtk.cc @@ -5,15 +5,21 @@ #include "chrome/browser/gtk/tabs/tab_gtk.h" #include "app/resource_bundle.h" +#include "chrome/browser/gtk/custom_button.h" #include "chrome/browser/gtk/menu_gtk.h" #include "chrome/common/gfx/path.h" #include "chrome/common/l10n_util.h" #include "grit/generated_resources.h" #include "grit/theme_resources.h" -static const SkScalar kTabCapWidth = 15; -static const SkScalar kTabTopCurveWidth = 4; -static const SkScalar kTabBottomCurveWidth = 3; +namespace { + +// The targets available for drag n' drop. +GtkTargetEntry target_table[] = { + { const_cast<char*>("application/x-chrome-tab"), GTK_TARGET_SAME_APP, 0 } +}; + +} // namespace class TabGtk::ContextMenuController : public MenuGtk::Delegate { public: @@ -95,17 +101,38 @@ TabGtk::TabGtk(TabDelegate* delegate) : TabRendererGtk(), delegate_(delegate), closing_(false) { - ResourceBundle& rb = ResourceBundle::GetSharedInstance(); - SkBitmap* bitmap = rb.GetBitmapNamed(IDR_TAB_CLOSE); - - close_button_.reset(new TabButtonGtk(this)); - close_button_.get()->SetImage(TabButtonGtk::BS_NORMAL, bitmap); - close_button_.get()->SetImage(TabButtonGtk::BS_HOT, - rb.GetBitmapNamed(IDR_TAB_CLOSE_H)); - close_button_.get()->SetImage(TabButtonGtk::BS_PUSHED, - rb.GetBitmapNamed(IDR_TAB_CLOSE_P)); - close_button_.get()->set_bounds( - gfx::Rect(0, 0, bitmap->width(), bitmap->height())); + event_box_.Own(gtk_event_box_new()); + gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_.get()), FALSE); + gtk_drag_source_set(event_box_.get(), GDK_BUTTON1_MASK, + target_table, G_N_ELEMENTS(target_table), + GDK_ACTION_MOVE); + gtk_drag_dest_set(event_box_.get(), GTK_DEST_DEFAULT_DROP, + target_table, G_N_ELEMENTS(target_table), + GDK_ACTION_MOVE); + gtk_drag_dest_set_track_motion(event_box_.get(), true); + g_signal_connect(G_OBJECT(event_box_.get()), "button-press-event", + G_CALLBACK(OnMousePress), this); + g_signal_connect(G_OBJECT(event_box_.get()), "button-release-event", + G_CALLBACK(OnMouseRelease), this); + g_signal_connect(G_OBJECT(event_box_.get()), "enter-notify-event", + G_CALLBACK(OnEnterNotify), this); + g_signal_connect(G_OBJECT(event_box_.get()), "leave-notify-event", + G_CALLBACK(OnLeaveNotify), this); + g_signal_connect_after(G_OBJECT(event_box_.get()), "drag-begin", + G_CALLBACK(&OnDragBegin), this); + g_signal_connect_after(G_OBJECT(event_box_.get()), "drag-end", + G_CALLBACK(&OnDragEnd), this); + g_signal_connect_after(G_OBJECT(event_box_.get()), "drag-failed", + G_CALLBACK(&OnDragFailed), this); + g_signal_connect_after(G_OBJECT(event_box_.get()), "drag-motion", + G_CALLBACK(&OnDragMotion), this); + gtk_widget_add_events(event_box_.get(), + GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | + GDK_LEAVE_NOTIFY_MASK | GDK_LEAVE_NOTIFY_MASK); + gtk_container_add(GTK_CONTAINER(event_box_.get()), TabRendererGtk::widget()); + gtk_widget_show_all(event_box_.get()); + + close_button_.reset(MakeCloseButton()); } TabGtk::~TabGtk() { @@ -116,47 +143,84 @@ TabGtk::~TabGtk() { // Invoke this so that we hide the highlight. ContextMenuClosed(); } + + event_box_.Destroy(); } -bool TabGtk::IsPointInBounds(const gfx::Point& point) { - GdkRegion* region = MakeRegionForTab(); - bool in_bounds = (gdk_region_point_in(region, point.x(), point.y()) == TRUE); - gdk_region_destroy(region); - return in_bounds; +// static +gboolean TabGtk::OnMousePress(GtkWidget* widget, GdkEventButton* event, + TabGtk* tab) { + if (event->button == 1) { + // Store whether or not we were selected just now... we only want to be + // able to drag foreground tabs, so we don't start dragging the tab if + // it was in the background. + bool just_selected = !tab->IsSelected(); + if (just_selected) { + tab->delegate_->SelectTab(tab); + } + } + + return TRUE; } -bool TabGtk::OnMotionNotify(GdkEventMotion* event) { - gfx::Point point(event->x, event->y); - bool paint = false; +// static +gboolean TabGtk::OnMouseRelease(GtkWidget* widget, GdkEventButton* event, + TabGtk* tab) { + if (event->button == 2) { + tab->delegate_->CloseTab(tab); + } else if (event->button == 3) { + tab->ShowContextMenu(); + } - if (!(event->state & GDK_BUTTON1_MASK)) - paint = set_hovering(IsPointInBounds(point)); + return TRUE; +} - paint |= close_button_.get()->OnMotionNotify(event); - return paint; +// static +gboolean TabGtk::OnEnterNotify(GtkWidget* widget, GdkEventCrossing* event, + TabGtk* tab) { + tab->OnMouseEntered(); + return TRUE; } -bool TabGtk::OnMousePress(const gfx::Point& point) { - if (close_button_.get()->IsPointInBounds(point)) - return close_button_.get()->OnMousePress(); +// static +gboolean TabGtk::OnLeaveNotify(GtkWidget* widget, GdkEventCrossing* event, + TabGtk* tab) { + tab->OnMouseExited(); + return TRUE; +} - return false; +// static +void TabGtk::OnDragBegin(GtkWidget* widget, GdkDragContext* context, + TabGtk* tab) { + int x, y; + gdk_window_get_pointer(tab->event_box_.get()->window, &x, &y, NULL); + tab->delegate_->MaybeStartDrag(tab, gfx::Point(x, y)); } -void TabGtk::OnMouseRelease(GdkEventButton* event) { - close_button_.get()->OnMouseRelease(); +// static +void TabGtk::OnDragEnd(GtkWidget* widget, GdkDragContext* context, + TabGtk* tab) { + // Notify the drag helper that we're done with any potential drag operations. + // Clean up the drag helper, which is re-created on the next mouse press. + tab->delegate_->EndDrag(false); +} - if (event->button == 2) { - delegate_->CloseTab(this); - } else if (event->button == 3) { - ShowContextMenu(); - } +// static +gboolean TabGtk::OnDragMotion(GtkWidget* widget, + GdkDragContext* context, + guint x, guint y, + guint time, + TabGtk* tab) { + tab->delegate_->ContinueDrag(context); + return TRUE; } -bool TabGtk::OnLeaveNotify() { - bool paint = set_hovering(false); - paint |= close_button_.get()->OnLeaveNotify(); - return paint; +// static +gboolean TabGtk::OnDragFailed(GtkWidget* widget, GdkDragContext* context, + GtkDragResult result, + TabGtk* tab) { + tab->delegate_->EndDrag(true); + return TRUE; } /////////////////////////////////////////////////////////////////////////////// @@ -167,50 +231,23 @@ bool TabGtk::IsSelected() const { } void TabGtk::CloseButtonResized(const gfx::Rect& bounds) { - close_button_.get()->set_bounds(bounds); -} - -void TabGtk::Paint(ChromeCanvasPaint* canvas) { - TabRendererGtk::Paint(canvas); - close_button_.get()->Paint(canvas); + gtk_fixed_move(GTK_FIXED(TabRendererGtk::widget()), + close_button_.get()->widget(), bounds.x(), bounds.y()); } -//////////////////////////////////////////////////////////////////////////////// -// TabGtk, TabButtonGtk::Delegate implementation: +void TabGtk::Paint(GdkEventExpose* event) { + TabRendererGtk::Paint(event); -GdkRegion* TabGtk::MakeRegionForButton(const TabButtonGtk* button) const { - // Use the close button bounds for hit-testing. - return NULL; -} - -void TabGtk::OnButtonActivate(const TabButtonGtk* button) { - delegate_->CloseTab(this); + gtk_container_propagate_expose(GTK_CONTAINER(TabRendererGtk::widget()), + close_button_.get()->widget(), event); } /////////////////////////////////////////////////////////////////////////////// // TabGtk, private: -GdkRegion* TabGtk::MakeRegionForTab()const { - int w = width(); - int h = height(); - static const int kNumRegionPoints = 9; - - GdkPoint polygon[kNumRegionPoints] = { - { 0, h }, - { kTabBottomCurveWidth, h - kTabBottomCurveWidth }, - { kTabCapWidth - kTabTopCurveWidth, kTabTopCurveWidth }, - { kTabCapWidth, 0 }, - { w - kTabCapWidth, 0 }, - { w - kTabCapWidth - kTabTopCurveWidth, kTabTopCurveWidth }, - { w - kTabBottomCurveWidth, h - kTabBottomCurveWidth }, - { w, h }, - { 0, h }, - }; - - GdkRegion* region = gdk_region_polygon(polygon, kNumRegionPoints, - GDK_WINDING_RULE); - gdk_region_offset(region, x(), y()); - return region; +// static +void TabGtk::OnCloseButtonClicked(GtkWidget* widget, TabGtk* tab) { + tab->delegate_->CloseTab(tab); } void TabGtk::ShowContextMenu() { @@ -224,3 +261,16 @@ void TabGtk::ContextMenuClosed() { delegate()->StopAllHighlighting(); menu_controller_.reset(); } + +CustomDrawButton* TabGtk::MakeCloseButton() { + CustomDrawButton* button = new CustomDrawButton(IDR_TAB_CLOSE, + IDR_TAB_CLOSE_P, IDR_TAB_CLOSE_H, IDR_TAB_CLOSE); + + g_signal_connect(G_OBJECT(button->widget()), "clicked", + G_CALLBACK(OnCloseButtonClicked), this); + GTK_WIDGET_UNSET_FLAGS(button->widget(), GTK_CAN_FOCUS); + gtk_fixed_put(GTK_FIXED(TabRendererGtk::widget()), button->widget(), 0, 0); + gtk_widget_show(button->widget()); + + return button; +} |