summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authordpolukhin@chromium.org <dpolukhin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-04 06:44:38 +0000
committerdpolukhin@chromium.org <dpolukhin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-02-04 06:44:38 +0000
commitfb6ce9a0cbf90c88f5820f1cc0dc2a9c091c80ee (patch)
treebdaa8f441172783639479ee62ad5938f29e1106b /chrome
parent0ede01dae033abeb7b0f4f38675b2bb3fe30df90 (diff)
downloadchromium_src-fb6ce9a0cbf90c88f5820f1cc0dc2a9c091c80ee.zip
chromium_src-fb6ce9a0cbf90c88f5820f1cc0dc2a9c091c80ee.tar.gz
chromium_src-fb6ce9a0cbf90c88f5820f1cc0dc2a9c091c80ee.tar.bz2
Move options dialog to the desktop of last active browser window.
Prevent moving options dialog out of monitor boundaries. BUG=1143 TEST=Tested on Linux with multiple desktops. Review URL: http://codereview.chromium.org/555151 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@38084 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/gtk/options/options_window_gtk.cc84
-rw-r--r--chrome/common/gtk_util.cc8
-rw-r--r--chrome/common/gtk_util.h5
-rw-r--r--chrome/common/x11_util.cc21
-rw-r--r--chrome/common/x11_util.h4
5 files changed, 85 insertions, 37 deletions
diff --git a/chrome/browser/gtk/options/options_window_gtk.cc b/chrome/browser/gtk/options/options_window_gtk.cc
index 709ee45..8d8e5ce 100644
--- a/chrome/browser/gtk/options/options_window_gtk.cc
+++ b/chrome/browser/gtk/options/options_window_gtk.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2006-2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -24,6 +24,7 @@
#include "chrome/common/pref_member.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/pref_service.h"
+#include "chrome/common/x11_util.h"
#include "grit/chromium_strings.h"
#include "grit/generated_resources.h"
@@ -80,6 +81,51 @@ class OptionsWindowGtk {
// The singleton options window object.
static OptionsWindowGtk* options_window = NULL;
+// Places |window| approximately over center of |parent|, it also moves window
+// to parent's desktop.
+// NOTE: It's better to use transient_for to center dialog but options dialog
+// is not modal so we don't want to set transient_for.
+static void CenterOverWindow(GtkWindow* window, GtkWindow* parent) {
+ gfx::Rect frame_bounds = gtk_util::GetWidgetScreenBounds(GTK_WIDGET(parent));
+ gfx::Point origin = frame_bounds.origin();
+ gfx::Size size = gtk_util::GetWidgetSize(GTK_WIDGET(window));
+ origin.Offset(
+ (frame_bounds.width() - size.width()) / 2,
+ (frame_bounds.height() - size.height()) / 2);
+
+ // Prevent moving window out of monitor bounds.
+ GdkScreen* screen = gtk_window_get_screen(parent);
+ if (screen) {
+ // It would be better to check against workarea for given monitor
+ // but getting workarea for particular monitor is tricky.
+ gint monitor = gdk_screen_get_monitor_at_window(screen,
+ GTK_WIDGET(parent)->window);
+ GdkRectangle rect;
+ gdk_screen_get_monitor_geometry(screen, monitor, &rect);
+
+ // Check the right bottom corner.
+ if (origin.x() > rect.x + rect.width - size.width())
+ origin.set_x(rect.x + rect.width - size.width());
+ if (origin.y() > rect.y + rect.height - size.height())
+ origin.set_y(rect.y + rect.height - size.height());
+
+ // Check the left top corner.
+ if (origin.x() < rect.x)
+ origin.set_x(rect.x);
+ if (origin.y() < rect.y)
+ origin.set_y(rect.y);
+ }
+
+ gtk_window_move(window, origin.x(), origin.y());
+
+ // Move to user expected desktop if window is already visible.
+ if (GTK_WIDGET(window)->window) {
+ x11_util::ChangeWindowDesktop(
+ x11_util::GetX11WindowFromGtkWidget(GTK_WIDGET(window)),
+ x11_util::GetX11WindowFromGtkWidget(GTK_WIDGET(parent)));
+ }
+}
+
///////////////////////////////////////////////////////////////////////////////
// OptionsWindowGtk, public:
@@ -155,14 +201,9 @@ OptionsWindowGtk::OptionsWindowGtk(Profile* profile)
gtk_notebook_get_n_pages(GTK_NOTEBOOK(notebook_)), OPTIONS_PAGE_COUNT);
if (Browser* b = BrowserList::GetLastActive()) {
- // Set temporary transient parent to align the windows before showing it.
- // gtk_widget_show_all below shows options dialog before ShowOptionsPage
- // is able to move the window to desired position. Therefor without
- // gtk_window_set_transient_for(), the window initially appears at 0,0
- // and then moves to the center. This trick eliminates blinking.
- gtk_window_set_transient_for(GTK_WINDOW(dialog_),
- b->window()->GetNativeHandle());
- gtk_window_set_position(GTK_WINDOW(dialog_), GTK_WIN_POS_CENTER_ON_PARENT);
+ // Show container content so that we can compute full dialog size.
+ gtk_widget_show_all(notebook_);
+ CenterOverWindow(GTK_WINDOW(dialog_), b->window()->GetNativeHandle());
}
// Need to show the notebook before connecting switch-page signal, otherwise
@@ -182,33 +223,10 @@ OptionsWindowGtk::OptionsWindowGtk(Profile* profile)
OptionsWindowGtk::~OptionsWindowGtk() {
}
-static gfx::Rect GetWindowBounds(GtkWindow* window) {
- gint x, y, width, height;
- gtk_window_get_position(window, &x, &y);
- gtk_window_get_size(window, &width, &height);
- return gfx::Rect(x, y, width, height);
-}
-
-static gfx::Size GetWindowSize(GtkWindow* window) {
- gint width, height;
- gtk_window_get_size(window, &width, &height);
- return gfx::Size(width, height);
-}
-
void OptionsWindowGtk::ShowOptionsPage(OptionsPage page,
OptionsGroup highlight_group) {
- // Remove transient parent to detach window since it doesn't belong to
- // any particular browser instance.
- gtk_window_set_transient_for(GTK_WINDOW(dialog_), NULL);
if (Browser* b = BrowserList::GetLastActive()) {
- // Move dialog to user expected position.
- gfx::Rect frame_bounds = GetWindowBounds(b->window()->GetNativeHandle());
- gfx::Point origin = frame_bounds.origin();
- gfx::Size size = GetWindowSize(GTK_WINDOW(dialog_));
- origin.Offset(
- (frame_bounds.width() - size.width()) / 2,
- (frame_bounds.height() - size.height()) / 2);
- gtk_window_move(GTK_WINDOW(dialog_), origin.x(), origin.y());
+ CenterOverWindow(GTK_WINDOW(dialog_), b->window()->GetNativeHandle());
}
// Bring options window to front if it already existed and isn't already
diff --git a/chrome/common/gtk_util.cc b/chrome/common/gtk_util.cc
index b8e7aeb..d989750 100644
--- a/chrome/common/gtk_util.cc
+++ b/chrome/common/gtk_util.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -274,6 +274,12 @@ gfx::Rect GetWidgetScreenBounds(GtkWidget* widget) {
widget->allocation.width, widget->allocation.height);
}
+gfx::Size GetWidgetSize(GtkWidget* widget) {
+ GtkRequisition size;
+ gtk_widget_size_request(widget, &size);
+ return gfx::Size(size.width, size.height);
+}
+
void ConvertWidgetPointToScreen(GtkWidget* widget, gfx::Point* p) {
DCHECK(widget);
DCHECK(p);
diff --git a/chrome/common/gtk_util.h b/chrome/common/gtk_util.h
index 149253b..ab0e538 100644
--- a/chrome/common/gtk_util.h
+++ b/chrome/common/gtk_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -106,6 +106,9 @@ gfx::Point GetWidgetScreenPosition(GtkWidget* widget);
// Returns the bounds of the specified widget in screen coordinates.
gfx::Rect GetWidgetScreenBounds(GtkWidget* widget);
+// Retuns size of the |widget| without window manager decorations.
+gfx::Size GetWidgetSize(GtkWidget* widget);
+
// Converts a point in a widget to screen coordinates. The point |p| is
// relative to the widget's top-left origin.
void ConvertWidgetPointToScreen(GtkWidget* widget, gfx::Point* p);
diff --git a/chrome/common/x11_util.cc b/chrome/common/x11_util.cc
index 12c9c6c..d857870 100644
--- a/chrome/common/x11_util.cc
+++ b/chrome/common/x11_util.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -632,4 +632,23 @@ void GrabWindowSnapshot(GtkWindow* gtk_window,
cairo_surface_destroy(surface);
}
+bool ChangeWindowDesktop(XID window, XID destination) {
+ int desktop;
+ if (!GetIntProperty(destination, "_NET_WM_DESKTOP", &desktop))
+ return false;
+
+ XEvent event;
+ event.xclient.type = ClientMessage;
+ event.xclient.window = window;
+ event.xclient.message_type = gdk_x11_get_xatom_by_name_for_display(
+ gdk_display_get_default(), "_NET_WM_DESKTOP");
+ event.xclient.format = 32;
+ event.xclient.data.l[0] = desktop;
+ event.xclient.data.l[1] = 1; // source indication
+
+ int result = XSendEvent(GetXDisplay(), GetX11RootWindow(), False,
+ SubstructureNotifyMask, &event);
+ return result == Success;
+}
+
} // namespace x11_util
diff --git a/chrome/common/x11_util.h b/chrome/common/x11_util.h
index c7a1b67..769f941 100644
--- a/chrome/common/x11_util.h
+++ b/chrome/common/x11_util.h
@@ -1,4 +1,4 @@
-// Copyright (c) 2009 The Chromium Authors. All rights reserved.
+// Copyright (c) 2010 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.
@@ -158,6 +158,8 @@ bool GetWindowManagerName(std::string* name);
void GrabWindowSnapshot(GtkWindow* gdk_window,
std::vector<unsigned char>* png_representation);
+// Change desktop for |window| to the desktop of |destination| window.
+bool ChangeWindowDesktop(XID window, XID destination);
} // namespace x11_util