summaryrefslogtreecommitdiffstats
path: root/chrome/browser/gtk
diff options
context:
space:
mode:
authorjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-03 21:49:35 +0000
committerjhawkins@chromium.org <jhawkins@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-06-03 21:49:35 +0000
commitd4ad1947465c74539226d34254537cfea9aa2e81 (patch)
tree357eb5b0bf8424e74f8bbdab2869badc04a6ba7b /chrome/browser/gtk
parent48f6a95841285ee0bf2d8c01568a5fc855dfb73b (diff)
downloadchromium_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.cc43
-rw-r--r--chrome/browser/gtk/browser_window_gtk.h21
-rw-r--r--chrome/browser/gtk/tabs/dragged_tab_controller_gtk.cc27
-rw-r--r--chrome/browser/gtk/tabs/dragged_tab_controller_gtk.h11
-rw-r--r--chrome/browser/gtk/tabs/dragged_tab_gtk.h2
-rw-r--r--chrome/browser/gtk/tabs/tab_strip_gtk.cc48
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) {