X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkwindow.c;h=1c12218f663d6178a9da3e81ee512eae80efc405;hb=ec84d8d14dc490380194f9d958b8568f327b8b23;hp=6d3f419ae1c386a8beef12933039fae6fc960e13;hpb=203d7f660f2835c7a59295e7e043b9af00371998;p=~andy%2Fgtk diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 6d3f419ae..1c12218f6 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -1267,7 +1267,7 @@ gtk_window_remove_accel_group (GtkWindow *window, g_return_if_fail (GTK_IS_ACCEL_GROUP (accel_group)); g_signal_handlers_disconnect_by_func (accel_group, - (gpointer) gtk_window_notify_keys_changed, + gtk_window_notify_keys_changed, window); _gtk_accel_group_detach (accel_group, G_OBJECT (window)); } @@ -1628,7 +1628,7 @@ gtk_window_add_embedded_xid (GtkWindow *window, guint xid) g_object_set_data_full (G_OBJECT (window), "gtk-embedded", embedded_windows, embedded_windows ? - (GtkDestroyNotify) g_list_free : NULL); + (GDestroyNotify) g_list_free : NULL); } void @@ -1654,7 +1654,7 @@ gtk_window_remove_embedded_xid (GtkWindow *window, guint xid) g_object_set_data_full (G_OBJECT (window), "gtk-embedded", embedded_windows, embedded_windows ? - (GtkDestroyNotify) g_list_free : NULL); + (GDestroyNotify) g_list_free : NULL); } void @@ -1702,7 +1702,7 @@ disconnect_parent_destroyed (GtkWindow *window) if (window->transient_parent) { g_signal_handlers_disconnect_by_func (window->transient_parent, - G_CALLBACK (parent_destroyed_callback), + parent_destroyed_callback, window); } } @@ -1724,19 +1724,30 @@ 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) { if (window->transient_parent) { g_signal_handlers_disconnect_by_func (window->transient_parent, - G_CALLBACK (gtk_window_transient_parent_realized), + gtk_window_transient_parent_realized, window); g_signal_handlers_disconnect_by_func (window->transient_parent, - G_CALLBACK (gtk_window_transient_parent_unrealized), + gtk_window_transient_parent_unrealized, window); g_signal_handlers_disconnect_by_func (window->transient_parent, - G_CALLBACK (gtk_widget_destroyed), + gtk_window_transient_parent_screen_changed, + window); + g_signal_handlers_disconnect_by_func (window->transient_parent, + gtk_widget_destroyed, &window->transient_parent); if (window->destroy_with_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); @@ -2083,7 +2097,7 @@ gtk_window_set_geometry_hints (GtkWindow *window, if (info->widget) g_signal_handlers_disconnect_by_func (info->widget, - G_CALLBACK (gtk_widget_destroyed), + gtk_widget_destroyed, &info->widget); info->widget = geometry_widget; @@ -2116,7 +2130,9 @@ gtk_window_set_geometry_hints (GtkWindow *window, * managers 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. @@ -2619,13 +2635,15 @@ load_pixbuf_verbosely (const char *filename, /** * gtk_window_set_icon_from_file: * @window: a #GtkWindow - * @list: a list of #GdkPixbuf + * @filename: location of icon file * @err: location to store error, or %NULL. * - * Sets the icon for @wi - * had gtk_window_set_icon_list() called on them as a single file. + * Sets the icon for @window. * Warns on failure if @err is %NULL. * + * This function is equivalent to calling gtk_window_set_icon() + * with a pixbuf created by loading the image from @filename. + * * Returns: %TRUE if setting the icon succeeded. **/ gboolean @@ -2707,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. **/ @@ -3370,7 +3388,7 @@ gtk_window_finalize (GObject *object) { if (window->geometry_info->widget) g_signal_handlers_disconnect_by_func (window->geometry_info->widget, - G_CALLBACK (gtk_widget_destroyed), + gtk_widget_destroyed, &window->geometry_info->widget); g_free (window->geometry_info); } @@ -4415,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, @@ -4467,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; @@ -4503,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; @@ -4551,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, ¢er_x, ¢er_y); *x = center_x; *y = center_y;