diff options
author | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-03 21:49:35 +0000 |
---|---|---|
committer | jhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-06-03 21:49:35 +0000 |
commit | d4ad1947465c74539226d34254537cfea9aa2e81 (patch) | |
tree | 357eb5b0bf8424e74f8bbdab2869badc04a6ba7b /chrome/browser/gtk | |
parent | 48f6a95841285ee0bf2d8c01568a5fc855dfb73b (diff) | |
download | chromium_src-d4ad1947465c74539226d34254537cfea9aa2e81.zip chromium_src-d4ad1947465c74539226d34254537cfea9aa2e81.tar.gz chromium_src-d4ad1947465c74539226d34254537cfea9aa2e81.tar.bz2 |
Implement dragging a tab back into a tabstrip for gtk.
BUG=none
TEST=Open a browser window with two tabs. Drag one of those tabs in and out of the window's tabstrip many times. Open a new window and drag a tab into that window's tabstrip.
Review URL: http://codereview.chromium.org/118142
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@17542 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/gtk')
-rw-r--r-- | chrome/browser/gtk/browser_window_gtk.cc | 43 | ||||
-rw-r--r-- | chrome/browser/gtk/browser_window_gtk.h | 21 | ||||
-rw-r--r-- | chrome/browser/gtk/tabs/dragged_tab_controller_gtk.cc | 27 | ||||
-rw-r--r-- | chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h | 11 | ||||
-rw-r--r-- | chrome/browser/gtk/tabs/dragged_tab_gtk.h | 2 | ||||
-rw-r--r-- | chrome/browser/gtk/tabs/tab_strip_gtk.cc | 48 |
6 files changed, 138 insertions, 14 deletions
diff --git a/chrome/browser/gtk/browser_window_gtk.cc b/chrome/browser/gtk/browser_window_gtk.cc index 8cbf438..5c090d6 100644 --- a/chrome/browser/gtk/browser_window_gtk.cc +++ b/chrome/browser/gtk/browser_window_gtk.cc @@ -46,6 +46,8 @@ const int kLoadingAnimationFrameTimeMs = 30; const GdkColor kBorderColor = GDK_COLOR_RGB(0xbe, 0xc8, 0xd4); +const char* kBrowserWindowKey = "__BROWSER_WINDOW_GTK__"; + gboolean MainWindowConfigured(GtkWindow* window, GdkEventConfigure* event, BrowserWindowGtk* browser_win) { gfx::Rect bounds = gfx::Rect(event->x, event->y, event->width, event->height); @@ -273,6 +275,8 @@ gboolean OnFocusIn(GtkWidget* widget, GdkEventFocus* event, Browser* browser) { } // namespace +std::map<XID, GtkWindow*> BrowserWindowGtk::xid_map_; + // TODO(estade): Break up this constructor into helper functions to improve // readability. BrowserWindowGtk::BrowserWindowGtk(Browser* browser) @@ -283,7 +287,6 @@ BrowserWindowGtk::BrowserWindowGtk(Browser* browser) window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL)); SetWindowIcon(); SetGeometryHints(); - g_object_set_data(G_OBJECT(window_), "browser_window_gtk", this); g_signal_connect(window_, "delete-event", G_CALLBACK(MainWindowDeleteEvent), this); g_signal_connect(window_, "destroy", @@ -292,12 +295,17 @@ BrowserWindowGtk::BrowserWindowGtk(Browser* browser) G_CALLBACK(MainWindowConfigured), this); g_signal_connect(window_, "window-state-event", G_CALLBACK(MainWindowStateChanged), this); + g_signal_connect(window_, "map", + G_CALLBACK(MainWindowMapped), this); + g_signal_connect(window_, "unmap", + G_CALLBACK(MainWindowUnMapped), this); g_signal_connect(window_, "key-press-event", G_CALLBACK(OnKeyPress), browser_.get()); g_signal_connect(window_, "button-press-event", G_CALLBACK(OnButtonPressEvent), browser_.get()); g_signal_connect(window_, "focus-in-event", G_CALLBACK(OnFocusIn), browser_.get()); + g_object_set_data(G_OBJECT(window_), kBrowserWindowKey, this); ConnectAccelerators(); bounds_ = GetInitialWindowBounds(window_); @@ -741,6 +749,22 @@ void BrowserWindowGtk::AddFindBar(FindBarGtk* findbar) { gtk_box_reorder_child(GTK_BOX(render_area_vbox_), findbar->widget(), 0); } +// static +BrowserWindowGtk* BrowserWindowGtk::GetBrowserWindowForNativeWindow( + gfx::NativeWindow window) { + if (window) { + return static_cast<BrowserWindowGtk*>( + g_object_get_data(G_OBJECT(window), kBrowserWindowKey)); + } + + return NULL; +} + +// static +GtkWindow* BrowserWindowGtk::GetBrowserWindowForXID(XID xid) { + return BrowserWindowGtk::xid_map_.find(xid)->second; +} + void BrowserWindowGtk::SetGeometryHints() { // Allow the user to resize us arbitrarily small. GdkGeometry geometry; @@ -833,6 +857,23 @@ gboolean BrowserWindowGtk::OnGtkAccelerator(GtkAccelGroup* accel_group, return TRUE; } +// static +void BrowserWindowGtk::MainWindowMapped(GtkWidget* widget, + BrowserWindowGtk* window) { + // Map the X Window ID of the window to our window. + XID xid = x11_util::GetX11WindowFromGtkWidget(widget); + BrowserWindowGtk::xid_map_.insert( + std::pair<XID, GtkWindow*>(xid, GTK_WINDOW(widget))); +} + +// static +void BrowserWindowGtk::MainWindowUnMapped(GtkWidget* widget, + BrowserWindowGtk* window) { + // Unmap the X Window ID. + XID xid = x11_util::GetX11WindowFromGtkWidget(widget); + BrowserWindowGtk::xid_map_.erase(xid); +} + void BrowserWindowGtk::ExecuteBrowserCommand(int id) { if (browser_->command_updater()->IsCommandEnabled(id)) browser_->ExecuteCommand(id); diff --git a/chrome/browser/gtk/browser_window_gtk.h b/chrome/browser/gtk/browser_window_gtk.h index d2c0589..8e6dee5 100644 --- a/chrome/browser/gtk/browser_window_gtk.h +++ b/chrome/browser/gtk/browser_window_gtk.h @@ -7,12 +7,15 @@ #include <gtk/gtk.h> +#include <map> + #include "base/gfx/rect.h" #include "base/scoped_ptr.h" #include "base/timer.h" #include "chrome/browser/browser_window.h" #include "chrome/browser/tabs/tab_strip_model.h" #include "chrome/common/notification_registrar.h" +#include "chrome/common/x11_util.h" class BookmarkBarGtk; class BrowserToolbarGtk; @@ -94,6 +97,9 @@ class BrowserWindowGtk : public BrowserWindow, bool user_gesture); virtual void TabStripEmpty(); + // Accessor for the tab strip. + TabStripGtk* tabstrip() const { return tabstrip_.get(); } + void MaybeShowBookmarkBar(TabContents* contents); void UpdateUIForContents(TabContents* contents); @@ -109,6 +115,14 @@ class BrowserWindowGtk : public BrowserWindow, // Add the find bar widget to the window hierarchy. void AddFindBar(FindBarGtk* findbar); + // Returns the BrowserWindowGtk registered with |window|. + static BrowserWindowGtk* GetBrowserWindowForNativeWindow( + gfx::NativeWindow window); + + // Retrieves the GtkWindow associated with |xid|, which is the X Window + // ID of the top-level X window of this object. + static GtkWindow* GetBrowserWindowForXID(XID xid); + protected: virtual void DestroyBrowser(); // Top level window. @@ -154,6 +168,10 @@ class BrowserWindowGtk : public BrowserWindow, GdkModifierType modifier, BrowserWindowGtk* browser_window); + // Maps and Unmaps the xid of |widget| to |window|. + static void MainWindowMapped(GtkWidget* widget, BrowserWindowGtk* window); + static void MainWindowUnMapped(GtkWidget* widget, BrowserWindowGtk* window); + // A small shim for browser_->ExecuteCommand. void ExecuteBrowserCommand(int id); @@ -205,6 +223,9 @@ class BrowserWindowGtk : public BrowserWindow, // The timer used to update frames for the Loading Animation. base::RepeatingTimer<BrowserWindowGtk> loading_animation_timer_; + // A map which translates an X Window ID into its respective GtkWindow. + static std::map<XID, GtkWindow*> xid_map_; + DISALLOW_COPY_AND_ASSIGN(BrowserWindowGtk); }; diff --git a/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.cc b/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.cc index 96b4758..59c69ce 100644 --- a/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.cc +++ b/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.cc @@ -5,7 +5,7 @@ #include "chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h" #include "chrome/browser/browser.h" -#include "chrome/browser/browser_window.h" +#include "chrome/browser/gtk/browser_window_gtk.h" #include "chrome/browser/gtk/tabs/dragged_tab_gtk.h" #include "chrome/browser/gtk/tabs/tab_strip_gtk.h" #include "chrome/browser/tabs/tab_strip_model.h" @@ -75,6 +75,13 @@ bool DraggedTabControllerGtk::EndDrag(bool canceled) { return EndDragImpl(canceled ? CANCELED : NORMAL); } +TabGtk* DraggedTabControllerGtk::GetDragSourceTabForContents( + TabContents* contents) const { + if (attached_tabstrip_ == source_tabstrip_) + return contents == dragged_contents_ ? source_tab_ : NULL; + return NULL; +} + bool DraggedTabControllerGtk::IsDragSourceTab(TabGtk* tab) const { return source_tab_ == tab; } @@ -266,8 +273,22 @@ void DraggedTabControllerGtk::MoveTab(const gfx::Point& screen_point) { TabStripGtk* DraggedTabControllerGtk::GetTabStripForPoint( const gfx::Point& screen_point) { - // TODO(jhawkins): Actually get the correct tabstrip under |screen_point|. - return GetTabStripIfItContains(source_tabstrip_, screen_point); + GtkWidget* dragged_window = dragged_tab_->widget(); + dock_windows_.insert(dragged_window); + gfx::NativeWindow local_window = + DockInfo::GetLocalProcessWindowAtPoint(screen_point, dock_windows_); + dock_windows_.erase(dragged_window); + if (!local_window) + return NULL; + + BrowserWindowGtk* browser = + BrowserWindowGtk::GetBrowserWindowForNativeWindow(local_window); + if (!browser) + return NULL; + + TabStripGtk* other_tabstrip = browser->tabstrip(); + // TODO(jhawkins): Make sure the tabstrips are compatible. + return GetTabStripIfItContains(other_tabstrip, screen_point); } TabStripGtk* DraggedTabControllerGtk::GetTabStripIfItContains( diff --git a/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h b/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h index 08d656f..87ef243 100644 --- a/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h +++ b/chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h @@ -7,11 +7,14 @@ #include <gtk/gtk.h> +#include <set> + #include "base/scoped_ptr.h" #include "base/timer.h" #include "chrome/browser/dock_info.h" #include "chrome/browser/tab_contents/tab_contents_delegate.h" #include "chrome/common/notification_registrar.h" +#include "chrome/common/x11_util.h" class DraggedTabGtk; class TabGtk; @@ -39,6 +42,11 @@ class DraggedTabControllerGtk : public NotificationObserver, // begun. Returns whether the tab has been destroyed. bool EndDrag(bool canceled); + // Retrieve the source tab if the TabContents specified matches the one being + // dragged by this controller, or NULL if the specified TabContents is not + // the same as the one being dragged. + TabGtk* GetDragSourceTabForContents(TabContents* contents) const; + // Returns true if the specified tab matches the tab being dragged. bool IsDragSourceTab(TabGtk* tab) const; @@ -225,6 +233,9 @@ class DraggedTabControllerGtk : public NotificationObserver, // DockInfo for the tabstrip. DockInfo dock_info_; + typedef std::set<GtkWidget*> DockWindows; + DockWindows dock_windows_; + // Timer used to bring the window under the cursor to front. If the user // stops moving the mouse for a brief time over a browser window, it is // brought to front. diff --git a/chrome/browser/gtk/tabs/dragged_tab_gtk.h b/chrome/browser/gtk/tabs/dragged_tab_gtk.h index 3ff4231..fab68e1 100644 --- a/chrome/browser/gtk/tabs/dragged_tab_gtk.h +++ b/chrome/browser/gtk/tabs/dragged_tab_gtk.h @@ -49,6 +49,8 @@ class DraggedTabGtk : public AnimationDelegate { // to determine where to place the tab in the attached tabstrip. gfx::Size attached_tab_size() const { return attached_tab_size_; } + GtkWidget* widget() const { return container_; } + private: // Overridden from AnimationDelegate: virtual void AnimationProgressed(const Animation* animation); diff --git a/chrome/browser/gtk/tabs/tab_strip_gtk.cc b/chrome/browser/gtk/tabs/tab_strip_gtk.cc index 00f3fbf..57891f7 100644 --- a/chrome/browser/gtk/tabs/tab_strip_gtk.cc +++ b/chrome/browser/gtk/tabs/tab_strip_gtk.cc @@ -592,20 +592,48 @@ void TabStripGtk::TabInsertedAt(TabContents* contents, if (active_animation_.get()) active_animation_->Stop(); - TabGtk* tab = new TabGtk(this); + bool contains_tab = false; + TabGtk* tab = NULL; + // First see if this Tab is one that was dragged out of this TabStrip and is + // now being dragged back in. In this case, the DraggedTabController actually + // has the Tab already constructed and we can just insert it into our list + // again. + if (IsDragSessionActive()) { + tab = drag_controller_->GetDragSourceTabForContents(contents); + if (tab) { + // If the Tab was detached, it would have been animated closed but not + // removed, so we need to reset this property. + tab->set_closing(false); + tab->ValidateLoadingAnimation(TabRendererGtk::ANIMATION_NONE); + tab->SetVisible(true); + } + + // See if we're already in the list. We don't want to add ourselves twice. + std::vector<TabData>::const_iterator iter = tab_data_.begin(); + for (; iter != tab_data_.end() && !contains_tab; ++iter) { + if (iter->tab == tab) + contains_tab = true; + } + } + + if (!tab) + tab = new TabGtk(this); // Only insert if we're not already in the list. - if (index == TabStripModel::kNoTab) { - TabData d = { tab, gfx::Rect() }; - tab_data_.push_back(d); - tab->UpdateData(contents, false); - } else { - TabData d = { tab, gfx::Rect() }; - tab_data_.insert(tab_data_.begin() + index, d); - tab->UpdateData(contents, false); + if (!contains_tab) { + if (index == TabStripModel::kNoTab) { + TabData d = { tab, gfx::Rect() }; + tab_data_.push_back(d); + tab->UpdateData(contents, false); + } else { + TabData d = { tab, gfx::Rect() }; + tab_data_.insert(tab_data_.begin() + index, d); + tab->UpdateData(contents, false); + } } - gtk_fixed_put(GTK_FIXED(tabstrip_.get()), tab->widget(), 0, 0); + if (gtk_widget_get_parent(tab->widget()) != tabstrip_.get()) + gtk_fixed_put(GTK_FIXED(tabstrip_.get()), tab->widget(), 0, 0); // Don't animate the first tab; it looks weird. if (GetTabCount() > 1) { |