]> Pileus Git - ~andy/gtk/blobdiff - gtk/gtkwindow.c
small doc fixes.
[~andy/gtk] / gtk / gtkwindow.c
index b3682d184aac954a94832379a15e88b02f514059..1c12218f663d6178a9da3e81ee512eae80efc405 100644 (file)
@@ -1724,6 +1724,14 @@ gtk_window_transient_parent_unrealized (GtkWidget *parent,
                         gdk_atom_intern ("WM_TRANSIENT_FOR", FALSE));
 }
 
+static void
+gtk_window_transient_parent_screen_changed (GtkWindow  *parent,
+                                           GParamSpec  *pspec,
+                                           GtkWindow   *window)
+{
+  gtk_window_set_screen (window, parent->screen);
+}
+
 static void       
 gtk_window_unset_transient_for  (GtkWindow *window)
 {
@@ -1735,6 +1743,9 @@ gtk_window_unset_transient_for  (GtkWindow *window)
       g_signal_handlers_disconnect_by_func (window->transient_parent,
                                            gtk_window_transient_parent_unrealized,
                                            window);
+      g_signal_handlers_disconnect_by_func (window->transient_parent,
+                                           gtk_window_transient_parent_screen_changed,
+                                           window);
       g_signal_handlers_disconnect_by_func (window->transient_parent,
                                            gtk_widget_destroyed,
                                            &window->transient_parent);
@@ -1797,8 +1808,11 @@ gtk_window_set_transient_for  (GtkWindow *window,
       g_signal_connect (parent, "unrealize",
                        G_CALLBACK (gtk_window_transient_parent_unrealized),
                        window);
+      g_signal_connect (parent, "notify::screen",
+                       G_CALLBACK (gtk_window_transient_parent_screen_changed),
+                       window);
       
-      window->screen = parent->screen;
+      gtk_window_set_screen (window, parent->screen);
 
       if (window->destroy_with_parent)
         connect_parent_destroyed (window);
@@ -2116,7 +2130,9 @@ gtk_window_set_geometry_hints (GtkWindow       *window,
  * managers</link> allow GTK+ to disable these decorations, creating a
  * borderless window. If you set the decorated property to %FALSE
  * using this function, GTK+ will do its best to convince the window
- * manager not to decorate the window.
+ * manager not to decorate the window. Depending on the system, this
+ * function may not have any effect when called on a window that is
+ * already visible, so you should call it before calling gtk_window_show().
  *
  * On Windows, this function always works, since there's no window manager
  * policy involved.
@@ -2709,7 +2725,7 @@ gtk_window_set_default_icon_list (GList *list)
  *
  * Sets an icon to be used as fallback for windows that haven't
  * had gtk_window_set_icon_list() called on them from a file
- * on disk. Warns on failure if @error is %NULL.
+ * on disk. Warns on failure if @err is %NULL.
  *
  * Returns: %TRUE if setting the icon succeeded.
  **/
@@ -4417,6 +4433,89 @@ get_effective_position (GtkWindow *window)
   return pos;
 }
 
+static int
+get_center_monitor_of_window (GtkWindow *window)
+{
+  /* We could try to sort out the relative positions of the monitors and
+   * stuff, or we could just be losers and assume you have a row
+   * or column of monitors.
+   */
+  return gdk_screen_get_n_monitors (window->screen) / 2;
+}
+
+static int
+get_monitor_containing_pointer (GtkWindow *window)
+{
+  gint px, py;
+  gint monitor_num;
+  GdkScreen *pointer_screen;
+
+  gdk_display_get_pointer (gdk_screen_get_display (window->screen),
+                           &pointer_screen,
+                           &px, &py, NULL);
+
+  if (pointer_screen == window->screen)
+    monitor_num = gdk_screen_get_monitor_at_point (window->screen, px, py);
+  else
+    monitor_num = -1;
+
+  return monitor_num;
+}
+
+static void
+center_window_on_monitor (GtkWindow *window,
+                          gint       w,
+                          gint       h,
+                          gint      *x,
+                          gint      *y)
+{
+  GdkRectangle monitor;
+  int monitor_num;
+
+  monitor_num = get_monitor_containing_pointer (window);
+  
+  if (monitor_num == -1)
+    monitor_num = get_center_monitor_of_window (window);
+  
+  gdk_screen_get_monitor_geometry (window->screen, monitor_num, &monitor);
+  
+  *x = (monitor.width - w) / 2 + monitor.x;
+  *y = (monitor.height - h) / 2 + monitor.y;
+
+  /* Be sure we aren't off the monitor, ignoring _NET_WM_STRUT
+   * and WM decorations.
+   */
+  if (*x < monitor.x)
+    *x = monitor.x;
+  if (*y < monitor.y)
+    *y = monitor.y;
+}
+
+static void
+clamp_window_to_rectangle (gint               *x,
+                           gint               *y,
+                           gint                w,
+                           gint                h,
+                           const GdkRectangle *rect)
+{
+  gint outside_w, outside_h;
+  
+  outside_w = (*x + w) - (rect->x + rect->width);
+  if (outside_w > 0)
+    *x -= outside_w;
+
+  outside_h = (*y + h) - (rect->y + rect->height);
+  if (outside_h > 0)
+    *y -= outside_h; 
+
+  /* if larger than the screen, center on the screen. */
+  if (*x < rect->x)
+    *x += (rect->x - *x) / 2;
+  if (*y < rect->y)
+    *y += (rect->y - *y) / 2;
+}
+
+
 static void
 gtk_window_compute_configure_request (GtkWindow    *window,
                                       GdkRectangle *request,
@@ -4469,35 +4568,38 @@ gtk_window_compute_configure_request (GtkWindow    *window,
            */
         case GTK_WIN_POS_CENTER_ALWAYS:
         case GTK_WIN_POS_CENTER:
-          {
-           gint px, py, monitor_num;
-           GdkRectangle monitor;
-
-           gdk_window_get_pointer (gdk_screen_get_root_window (window->screen),
-                                   &px, &py, NULL);
-           
-           monitor_num = gdk_screen_get_monitor_at_point (window->screen, px, py);
-           if (monitor_num == -1)
-             monitor_num = 0;
-           
-           gdk_screen_get_monitor_geometry (window->screen, monitor_num, &monitor);
-           
-           x = (monitor.width - w) / 2 + monitor.x;
-           y = (monitor.height - h) / 2 + monitor.y;
-          }
+          center_window_on_monitor (window, w, h, &x, &y);
           break;
       
         case GTK_WIN_POS_CENTER_ON_PARENT:
           {
+            gint monitor_num;
+            GdkRectangle monitor;
             gint ox, oy;
             
             g_assert (GTK_WIDGET_MAPPED (parent_widget)); /* established earlier */
+
+            if (parent_widget->window != NULL)
+              monitor_num = gdk_screen_get_monitor_at_window (window->screen,
+                                                              parent_widget->window);
+            else
+              monitor_num = -1;
             
             gdk_window_get_origin (parent_widget->window,
                                    &ox, &oy);
             
             x = ox + (parent_widget->allocation.width - w) / 2;
             y = oy + (parent_widget->allocation.height - h) / 2;
+            
+            /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
+             * WM decorations. If parent wasn't on a monitor, just
+             * give up.
+             */
+            if (monitor_num >= 0)
+              {
+                gdk_screen_get_monitor_geometry (window->screen, monitor_num, &monitor);
+                clamp_window_to_rectangle (&x, &y, w, h, &monitor);
+              }
           }
           break;
 
@@ -4505,14 +4607,34 @@ gtk_window_compute_configure_request (GtkWindow    *window,
           {
             gint screen_width = gdk_screen_get_width (window->screen);
             gint screen_height = gdk_screen_get_height (window->screen);
-            int px, py;
+           gint monitor_num;
+           GdkRectangle monitor;
+            GdkScreen *pointer_screen;
+            gint px, py;
+            
+            gdk_display_get_pointer (gdk_screen_get_display (window->screen),
+                                     &pointer_screen,
+                                     &px, &py, NULL);
+
+            if (pointer_screen == window->screen)
+              monitor_num = gdk_screen_get_monitor_at_point (window->screen, px, py);
+            else
+              monitor_num = -1;
             
-            gdk_window_get_pointer (gdk_screen_get_root_window (window->screen),
-                                   &px, &py, NULL);
             x = px - w / 2;
             y = py - h / 2;
             x = CLAMP (x, 0, screen_width - w);
             y = CLAMP (y, 0, screen_height - h);
+
+            /* Clamp onto current monitor, ignoring _NET_WM_STRUT and
+             * WM decorations. Don't try to figure out what's going
+             * on if the mouse wasn't inside a monitor.
+             */
+            if (monitor_num >= 0)
+              {
+                gdk_screen_get_monitor_geometry (window->screen, monitor_num, &monitor);
+                clamp_window_to_rectangle (&x, &y, w, h, &monitor);
+              }
           }
           break;
 
@@ -4553,11 +4675,8 @@ gtk_window_constrain_position (GtkWindow    *window,
   if (window->position == GTK_WIN_POS_CENTER_ALWAYS)
     {
       gint center_x, center_y;
-      gint screen_width = gdk_screen_get_width (window->screen);
-      gint screen_height = gdk_screen_get_height (window->screen);
-      
-      center_x = (screen_width - new_width) / 2;
-      center_y = (screen_height - new_height) / 2;
+
+      center_window_on_monitor (window, new_width, new_height, &center_x, &center_y);
       
       *x = center_x;
       *y = center_y;