diff options
author | dpolukhin@chromium.org <dpolukhin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-04 06:44:38 +0000 |
---|---|---|
committer | dpolukhin@chromium.org <dpolukhin@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2010-02-04 06:44:38 +0000 |
commit | fb6ce9a0cbf90c88f5820f1cc0dc2a9c091c80ee (patch) | |
tree | bdaa8f441172783639479ee62ad5938f29e1106b /chrome | |
parent | 0ede01dae033abeb7b0f4f38675b2bb3fe30df90 (diff) | |
download | chromium_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.cc | 84 | ||||
-rw-r--r-- | chrome/common/gtk_util.cc | 8 | ||||
-rw-r--r-- | chrome/common/gtk_util.h | 5 | ||||
-rw-r--r-- | chrome/common/x11_util.cc | 21 | ||||
-rw-r--r-- | chrome/common/x11_util.h | 4 |
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 |