X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkwindow.c;h=99bab056658c3ea5bcecfee84dbb48b1a11b09d6;hb=2cfc56ced81d801669deb3a429a00e25769e5a70;hp=a4b9dd3898e840483206297ac990c0fab385f486;hpb=730765de9163934d9993b25a87f076f1b36ed271;p=~andy%2Fgtk diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index a4b9dd389..99bab0566 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -12,9 +12,7 @@ * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 59 Temple Place - Suite 330, - * Boston, MA 02111-1307, USA. + * License along with this library. If not, see . */ /* @@ -49,6 +47,7 @@ #include "gtkwidgetprivate.h" #include "gtkcontainerprivate.h" #include "gtkintl.h" +#include "gtkstylecontextprivate.h" #include "gtktypebuiltins.h" #include "a11y/gtkwindowaccessible.h" @@ -99,12 +98,15 @@ * */ +#define AUTO_MNEMONICS_DELAY 300 /* ms */ + typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo; struct _GtkWindowPrivate { GtkMnemonicHash *mnemonic_hash; + GtkWidget *attach_widget; GtkWidget *default_widget; GtkWidget *focus_widget; GtkWindow *transient_parent; @@ -116,8 +118,6 @@ struct _GtkWindowPrivate GdkModifierType mnemonic_modifier; GdkWindowTypeHint gdk_type_hint; - gdouble opacity; - GdkWindow *grip_window; gchar *startup_id; @@ -132,8 +132,7 @@ struct _GtkWindowPrivate guint16 configure_request_count; - GSettings *state_settings; - guint state_save_id; + guint auto_mnemonics_timeout_id; /* The following flags are initially TRUE (before a window is mapped). * They cause us to compute a configure request that involves @@ -165,7 +164,6 @@ struct _GtkWindowPrivate guint mnemonics_visible_set : 1; guint focus_visible : 1; guint modal : 1; - guint opacity_set : 1; guint position : 3; guint reset_type_hint : 1; guint resizable : 1; @@ -226,7 +224,7 @@ enum { PROP_DELETABLE, PROP_GRAVITY, PROP_TRANSIENT_FOR, - PROP_OPACITY, + PROP_ATTACHED_TO, PROP_HAS_RESIZE_GRIP, PROP_RESIZE_GRIP_VISIBLE, PROP_APPLICATION, @@ -424,9 +422,11 @@ static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window); static void gtk_window_free_key_hash (GtkWindow *window); static void gtk_window_on_composited_changed (GdkScreen *screen, GtkWindow *window); +#ifdef GDK_WINDOWING_X11 static void gtk_window_on_theme_variant_changed (GtkSettings *settings, GParamSpec *pspec, GtkWindow *window); +#endif static void gtk_window_set_theme_variant (GtkWindow *window); static GSList *toplevel_list = NULL; @@ -473,15 +473,7 @@ static void gtk_window_buildable_custom_finished (GtkBuildable *buildable, const gchar *tagname, gpointer user_data); - -static void gtk_window_get_preferred_width (GtkWidget *widget, - gint *minimum_size, - gint *natural_size); -static void gtk_window_get_preferred_height (GtkWidget *widget, - gint *minimum_size, - gint *natural_size); - -static void ensure_state_flag_window_unfocused (GtkWidget *widget); +static void ensure_state_flag_backdrop (GtkWidget *widget); G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN, G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, @@ -593,8 +585,6 @@ gtk_window_class_init (GtkWindowClass *klass) widget_class->focus = gtk_window_focus; widget_class->move_focus = gtk_window_move_focus; widget_class->draw = gtk_window_draw; - widget_class->get_preferred_width = gtk_window_get_preferred_width; - widget_class->get_preferred_height = gtk_window_get_preferred_height; widget_class->window_state_event = gtk_window_state_event; widget_class->direction_changed = gtk_window_direction_changed; widget_class->state_changed = gtk_window_state_changed; @@ -901,7 +891,7 @@ gtk_window_class_init (GtkWindowClass *klass) GTK_PARAM_READWRITE)); /** - * GtkWindow:has-resize-grip + * GtkWindow:has-resize-grip: * * Whether the window has a corner resize grip. * @@ -971,22 +961,25 @@ gtk_window_class_init (GtkWindowClass *klass) GTK_PARAM_READWRITE| G_PARAM_CONSTRUCT)); /** - * GtkWindow:opacity: + * GtkWindow:attached-to: * - * The requested opacity of the window. See gtk_window_set_opacity() for - * more details about window opacity. + * The widget to which this window is attached. + * See gtk_window_set_attached_to(). * - * Since: 2.12 + * Examples of places where specifying this relation is useful are + * for instance a #GtkMenu created by a #GtkComboBox, a completion + * popup window created by #GtkEntry or a typeahead search entry + * created by #GtkTreeView. + * + * Since: 3.4 */ g_object_class_install_property (gobject_class, - PROP_OPACITY, - g_param_spec_double ("opacity", - P_("Opacity for Window"), - P_("The opacity of the window, from 0 to 1"), - 0.0, - 1.0, - 1.0, - GTK_PARAM_READWRITE)); + PROP_ATTACHED_TO, + g_param_spec_object ("attached-to", + P_("Attached to Widget"), + P_("The widget where the window is attached"), + GTK_TYPE_WIDGET, + GTK_PARAM_READWRITE | G_PARAM_CONSTRUCT)); /* Style properties. */ @@ -1125,6 +1118,7 @@ gtk_window_class_init (GtkWindowClass *klass) static void gtk_window_init (GtkWindow *window) { + GtkStyleContext *context; GtkWindowPrivate *priv; window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window, @@ -1164,7 +1158,6 @@ gtk_window_init (GtkWindow *window) priv->focus_on_map = TRUE; priv->deletable = TRUE; priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL; - priv->opacity = 1.0; priv->startup_id = NULL; priv->initial_timestamp = GDK_CURRENT_TIME; priv->has_resize_grip = TRUE; @@ -1184,6 +1177,9 @@ gtk_window_init (GtkWindow *window) "notify::gtk-application-prefer-dark-theme", G_CALLBACK (gtk_window_on_theme_variant_changed), window); #endif + + context = gtk_widget_get_style_context (GTK_WIDGET (window)); + gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND); } static void @@ -1280,8 +1276,8 @@ gtk_window_set_property (GObject *object, case PROP_TRANSIENT_FOR: gtk_window_set_transient_for (window, g_value_get_object (value)); break; - case PROP_OPACITY: - gtk_window_set_opacity (window, g_value_get_double (value)); + case PROP_ATTACHED_TO: + gtk_window_set_attached_to (window, g_value_get_object (value)); break; case PROP_HAS_RESIZE_GRIP: gtk_window_set_has_resize_grip (window, g_value_get_boolean (value)); @@ -1401,8 +1397,8 @@ gtk_window_get_property (GObject *object, case PROP_TRANSIENT_FOR: g_value_set_object (value, gtk_window_get_transient_for (window)); break; - case PROP_OPACITY: - g_value_set_double (value, gtk_window_get_opacity (window)); + case PROP_ATTACHED_TO: + g_value_set_object (value, gtk_window_get_attached_to (window)); break; case PROP_HAS_RESIZE_GRIP: g_value_set_boolean (value, priv->has_resize_grip); @@ -1902,8 +1898,8 @@ _gtk_window_internal_set_focus (GtkWindow *window, * unsets the default widget for a #GtkWindow about. When setting * (rather than unsetting) the default widget it's generally easier to * call gtk_widget_grab_focus() on the widget. Before making a widget - * the default widget, you must set the #GTK_CAN_DEFAULT flag on the - * widget you'd like to make the default using GTK_WIDGET_SET_FLAGS(). + * the default widget, you must call gtk_widget_set_can_default() on the + * widget you'd like to make the default. **/ void gtk_window_set_default (GtkWindow *window, @@ -2378,6 +2374,20 @@ gtk_window_list_toplevels (void) return list; } +static void +remove_attach_widget (GtkWindow *window) +{ + GtkWindowPrivate *priv = window->priv; + + if (priv->attach_widget) + { + _gtk_widget_remove_attached_window (priv->attach_widget, window); + + g_object_unref (priv->attach_widget); + priv->attach_widget = NULL; + } +} + static void gtk_window_dispose (GObject *object) { @@ -2386,6 +2396,8 @@ gtk_window_dispose (GObject *object) gtk_window_set_focus (window, NULL); gtk_window_set_default (window, NULL); + remove_attach_widget (GTK_WINDOW (object)); + G_OBJECT_CLASS (gtk_window_parent_class)->dispose (object); } @@ -2576,6 +2588,82 @@ gtk_window_get_transient_for (GtkWindow *window) return window->priv->transient_parent; } +/** + * gtk_window_set_attached_to: + * @window: a #GtkWindow + * @attach_widget: (allow-none): a #GtkWidget, or %NULL + * + * Marks @window as attached to @attach_widget. This creates a logical binding + * between the window and the widget it belongs to, which is used by GTK+ to + * propagate information such as styling or accessibility to @window as if it + * was a children of @attach_widget. + * + * Examples of places where specifying this relation is useful are for instance + * a #GtkMenu created by a #GtkComboBox, a completion popup window + * created by #GtkEntry or a typeahead search entry created by #GtkTreeView. + * + * Note that this function should not be confused with + * gtk_window_set_transient_for(), which specifies a window manager relation + * between two toplevels instead. + * + * Passing %NULL for @attach_widget detaches the window. + * + * Since: 3.4 + **/ +void +gtk_window_set_attached_to (GtkWindow *window, + GtkWidget *attach_widget) +{ + GtkStyleContext *context; + GtkWindowPrivate *priv; + + g_return_if_fail (GTK_IS_WINDOW (window)); + g_return_if_fail (GTK_WIDGET (window) != attach_widget); + + priv = window->priv; + + if (priv->attach_widget == attach_widget) + return; + + remove_attach_widget (window); + + priv->attach_widget = attach_widget; + + if (priv->attach_widget) + { + _gtk_widget_add_attached_window (priv->attach_widget, window); + + g_object_ref (priv->attach_widget); + } + + /* Update the style, as the widget path might change. */ + context = gtk_widget_get_style_context (GTK_WIDGET (window)); + if (priv->attach_widget) + gtk_style_context_set_parent (context, gtk_widget_get_style_context (priv->attach_widget)); + else + gtk_style_context_set_parent (context, NULL); +} + +/** + * gtk_window_get_attached_to: + * @window: a #GtkWindow + * + * Fetches the attach widget for this window. See + * gtk_window_set_attached_to(). + * + * Return value: (transfer none): the widget where the window is attached, + * or %NULL if the window is not attached to any widget. + * + * Since: 3.4 + **/ +GtkWidget * +gtk_window_get_attached_to (GtkWindow *window) +{ + g_return_val_if_fail (GTK_IS_WINDOW (window), NULL); + + return window->priv->attach_widget; +} + /** * gtk_window_set_opacity: * @window: a #GtkWindow @@ -2592,28 +2680,13 @@ gtk_window_get_transient_for (GtkWindow *window) * shown causes it to flicker once on Windows. * * Since: 2.12 + * Deprecated: 3.8: Use gtk_widget_set_opacity instead. **/ void gtk_window_set_opacity (GtkWindow *window, gdouble opacity) { - GtkWindowPrivate *priv; - - g_return_if_fail (GTK_IS_WINDOW (window)); - - priv = window->priv; - - if (opacity < 0.0) - opacity = 0.0; - else if (opacity > 1.0) - opacity = 1.0; - - priv->opacity_set = TRUE; - priv->opacity = opacity; - - if (gtk_widget_get_realized (GTK_WIDGET (window))) - gdk_window_set_opacity (gtk_widget_get_window (GTK_WIDGET (window)), - priv->opacity); + gtk_widget_set_opacity (GTK_WIDGET (window), opacity); } /** @@ -2626,13 +2699,14 @@ gtk_window_set_opacity (GtkWindow *window, * Return value: the requested opacity for this window. * * Since: 2.12 + * Deprecated: 3.8: Use gtk_widget_get_opacity instead. **/ gdouble gtk_window_get_opacity (GtkWindow *window) { g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0); - return window->priv->opacity; + return gtk_widget_get_opacity (GTK_WIDGET (window)); } /** @@ -2703,6 +2777,9 @@ gtk_window_set_application (GtkWindow *window, gtk_application_add_window (priv->application, window); } + /* don't use a normal cast: application may be NULL */ + gtk_widget_insert_action_group (GTK_WIDGET (window), "app", (GActionGroup *) application); + g_object_notify (G_OBJECT (window), "application"); } } @@ -3284,7 +3361,7 @@ gtk_window_get_decorated (GtkWindow *window) * using this function, GTK+ will do its best to convince the window * manager not to show a close button. 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(). + * already visible, so you should call it before calling gtk_widget_show(). * * On Windows, this function always works, since there's no window manager * policy involved. @@ -4407,7 +4484,7 @@ gtk_window_move (GtkWindow *window, /** * gtk_window_get_position: * @window: a #GtkWindow - * @root_x: (out) (allow-none): eturn location for X coordinate of + * @root_x: (out) (allow-none): return location for X coordinate of * gravity-determined reference point, or %NULL * @root_y: (out) (allow-none): return location for Y coordinate of * gravity-determined reference point, or %NULL @@ -4593,40 +4670,6 @@ gtk_window_reshow_with_initial_size (GtkWindow *window) gtk_widget_show (widget); } -static gboolean -gtk_window_persistent_state_flush (gpointer user_data) -{ - GtkWindow *window = user_data; - GtkWidget *widget = user_data; - gboolean was_maximized; - gboolean is_maximized; - - was_maximized = g_settings_get_boolean (window->priv->state_settings, "is-maximized"); - is_maximized = gdk_window_get_state (gtk_widget_get_window (widget)) & GDK_WINDOW_STATE_MAXIMIZED; - - if (is_maximized != was_maximized) - g_settings_set_boolean (window->priv->state_settings, "is-maximized", is_maximized); - - if (!is_maximized) - { - gint old_width, old_height; - GtkAllocation size; - - G_STATIC_ASSERT (sizeof (size.width) == sizeof (int)); - - g_settings_get (window->priv->state_settings, "size", "(ii)", &old_width, &old_height); - gtk_widget_get_allocation (widget, &size); - - if (size.width != old_width || size.height != old_height) - g_settings_set (window->priv->state_settings, "size", "(ii)", size.width, size.height); - } - - g_source_remove (window->priv->state_save_id); - window->priv->state_save_id = 0; - - return G_SOURCE_REMOVE; -} - static void gtk_window_destroy (GtkWidget *widget) { @@ -4640,6 +4683,8 @@ gtk_window_destroy (GtkWidget *widget) if (priv->transient_parent) gtk_window_set_transient_for (window, NULL); + remove_attach_widget (GTK_WINDOW (widget)); + /* frees the icons */ gtk_window_set_icon_list (window, NULL); @@ -4695,6 +4740,12 @@ gtk_window_finalize (GObject *object) g_free (priv->startup_id); + if (priv->auto_mnemonics_timeout_id) + { + g_source_remove (priv->auto_mnemonics_timeout_id); + priv->auto_mnemonics_timeout_id = 0; + } + #ifdef GDK_WINDOWING_X11 g_signal_handlers_disconnect_by_func (gtk_settings_get_default (), gtk_window_on_theme_variant_changed, @@ -4710,6 +4761,7 @@ gtk_window_show (GtkWidget *widget) GtkWindow *window = GTK_WINDOW (widget); GtkWindowPrivate *priv = window->priv; GtkContainer *container = GTK_CONTAINER (window); + GtkBitmask *empty; gboolean need_resize; gboolean is_plug; @@ -4721,8 +4773,14 @@ gtk_window_show (GtkWidget *widget) _gtk_widget_set_visible_flag (widget, TRUE); - need_resize = _gtk_container_get_need_resize (container) || !gtk_widget_get_realized (widget); - _gtk_container_set_need_resize (container, FALSE); + need_resize = _gtk_widget_get_alloc_needed (widget) || !gtk_widget_get_realized (widget); + + empty = _gtk_bitmask_new (); + _gtk_style_context_validate (gtk_widget_get_style_context (widget), + g_get_monotonic_time (), + 0, + empty); + _gtk_bitmask_free (empty); if (need_resize) { @@ -4929,8 +4987,6 @@ gtk_window_map (GtkWidget *widget) gtk_window_set_focus_visible (window, gtk_window_get_focus_visible (priv->transient_parent)); else gtk_window_set_focus_visible (window, visible_focus == GTK_POLICY_ALWAYS); - - ensure_state_flag_window_unfocused (widget); } static gboolean @@ -5106,11 +5162,10 @@ gtk_window_realize (GtkWidget *widget) gdk_window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask); gtk_widget_set_window (widget, gdk_window); - gdk_window_set_user_data (gdk_window, widget); + gtk_widget_register_window (widget, gdk_window); gtk_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window); - gdk_window_enable_synchronized_configure (gdk_window); return; } @@ -5184,12 +5239,7 @@ gtk_window_realize (GtkWidget *widget) gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask); gtk_widget_set_window (widget, gdk_window); - if (priv->opacity_set) - gdk_window_set_opacity (gdk_window, priv->opacity); - - gdk_window_enable_synchronized_configure (gdk_window); - - gdk_window_set_user_data (gdk_window, window); + gtk_widget_register_window (widget, gdk_window); context = gtk_widget_get_style_context (widget); gtk_style_context_set_background (context, gdk_window); @@ -5252,8 +5302,6 @@ gtk_window_realize (GtkWidget *widget) } #endif - gtk_window_set_application (window, gtk_window_get_application (window)); - /* Icons */ gtk_window_realize_icon (window); @@ -5268,9 +5316,6 @@ gtk_window_unrealize (GtkWidget *widget) GtkWindowPrivate *priv = window->priv; GtkWindowGeometryInfo *info; - if (window->priv->state_save_id) - gtk_window_persistent_state_flush (window); - /* On unrealize, we reset the size of the window such * that we will re-apply the default sizing stuff * next time we show the window. @@ -5457,42 +5502,55 @@ set_grip_position (GtkWindow *window) rect.width, rect.height); } -static void -gtk_window_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) +/* _gtk_window_set_allocation: + * @window: a #GtkWindow + * @allocation: the new allocation + * + * This function is like gtk_widget_set_allocation() + * but does the necessary extra work to update + * the resize grip positioning, etc. + * + * Call this instead of gtk_widget_set_allocation() + * when overriding ::size_allocate in a GtkWindow + * subclass without chaining up. + */ +void +_gtk_window_set_allocation (GtkWindow *window, + GtkAllocation *allocation) { - GtkWindow *window = GTK_WINDOW (widget); - GtkAllocation child_allocation; - GtkWidget *child; - guint border_width; - - if (window->priv->state_settings) - { - if (window->priv->state_save_id) - g_source_remove (window->priv->state_save_id); - - window->priv->state_save_id = g_timeout_add (1000, gtk_window_persistent_state_flush, window); - } + GtkWidget *widget = (GtkWidget *)window; gtk_widget_set_allocation (widget, allocation); if (gtk_widget_get_realized (widget)) { - /* If it's not a toplevel we're embedded, we need to resize the window's - * window and skip the grip. + /* If it's not a toplevel we're embedded, we need to resize + * the window's window and skip the grip. */ if (!gtk_widget_is_toplevel (widget)) - { - gdk_window_move_resize (gtk_widget_get_window (widget), - allocation->x, allocation->y, - allocation->width, allocation->height); - } + { + gdk_window_move_resize (gtk_widget_get_window (widget), + allocation->x, allocation->y, + allocation->width, allocation->height); + } else - { - update_grip_visibility (window); - set_grip_position (window); - } + { + update_grip_visibility (window); + set_grip_position (window); + } } +} + +static void +gtk_window_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GtkWindow *window = GTK_WINDOW (widget); + GtkAllocation child_allocation; + GtkWidget *child; + guint border_width; + + _gtk_window_set_allocation (window, allocation); child = gtk_bin_get_child (&(window->bin)); if (child && gtk_widget_get_visible (child)) @@ -5500,10 +5558,8 @@ gtk_window_size_allocate (GtkWidget *widget, border_width = gtk_container_get_border_width (GTK_CONTAINER (window)); child_allocation.x = border_width; child_allocation.y = border_width; - child_allocation.width = - MAX (1, (gint)allocation->width - child_allocation.x * 2); - child_allocation.height = - MAX (1, (gint)allocation->height - child_allocation.y * 2); + child_allocation.width = MAX (1, allocation->width - border_width * 2); + child_allocation.height = MAX (1, allocation->height - border_width * 2); gtk_widget_size_allocate (child, &child_allocation); } @@ -5523,7 +5579,6 @@ gtk_window_configure_event (GtkWidget *widget, if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event) return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event); - gdk_window_configure_finished (gtk_widget_get_window (widget)); return FALSE; } @@ -5557,13 +5612,11 @@ gtk_window_configure_event (GtkWidget *widget, (allocation.width == event->width && allocation.height == event->height)) { - gdk_window_configure_finished (gtk_widget_get_window (widget)); return TRUE; } /* * If we do need to resize, we do that by: - * - filling in widget->allocation with the new size * - setting configure_notify_received to TRUE * for use in gtk_window_move_resize() * - queueing a resize, leading to invocation of @@ -5573,10 +5626,6 @@ gtk_window_configure_event (GtkWidget *widget, priv->configure_notify_received = TRUE; - allocation.width = event->width; - allocation.height = event->height; - gtk_widget_set_allocation (widget, &allocation); - gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE); // XXX - What was this for again? _gtk_container_queue_resize (GTK_CONTAINER (widget)); @@ -5591,7 +5640,7 @@ gtk_window_state_event (GtkWidget *widget, update_grip_visibility (GTK_WINDOW (widget)); if (event->changed_mask & GDK_WINDOW_STATE_FOCUSED) - ensure_state_flag_window_unfocused (widget); + ensure_state_flag_backdrop (widget); return FALSE; } @@ -5632,7 +5681,6 @@ gtk_window_style_updated (GtkWidget *widget) rect.width, rect.height); set_grip_shape (window); - gtk_widget_queue_resize (widget); } } @@ -5671,7 +5719,7 @@ resize_grip_create_window (GtkWindow *window) attributes_mask); gdk_window_set_background_rgba (priv->grip_window, &transparent); - gdk_window_set_user_data (priv->grip_window, widget); + gtk_widget_register_window (widget, priv->grip_window); gdk_window_raise (priv->grip_window); @@ -5684,7 +5732,7 @@ resize_grip_destroy_window (GtkWindow *window) { GtkWindowPrivate *priv = window->priv; - gdk_window_set_user_data (priv->grip_window, NULL); + gtk_widget_unregister_window (GTK_WIDGET (window), priv->grip_window); gdk_window_destroy (priv->grip_window); priv->grip_window = NULL; update_grip_visibility (window); @@ -5839,7 +5887,7 @@ gtk_window_get_has_resize_grip (GtkWindow *window) * Since: 3.0 */ gboolean -gtk_window_get_resize_grip_area (GtkWindow *window, +gtk_window_get_resize_grip_area (GtkWindow *window, GdkRectangle *rect) { GtkWidget *widget = GTK_WIDGET (window); @@ -6135,7 +6183,7 @@ maybe_set_mnemonics_visible (GtkWindow *window) NULL, &mask); if (window->priv->mnemonic_modifier == (mask & gtk_accelerator_get_default_mod_mask ())) { - gtk_window_set_mnemonics_visible (window, TRUE); + _gtk_window_set_auto_mnemonics_visible (window); break; } } @@ -6377,60 +6425,6 @@ gtk_window_real_set_focus (GtkWindow *window, } } - -static void -gtk_window_get_preferred_width (GtkWidget *widget, - gint *minimum_size, - gint *natural_size) -{ - GtkWindow *window; - GtkWidget *child; - guint border_width; - - window = GTK_WINDOW (widget); - child = gtk_bin_get_child (GTK_BIN (window)); - - border_width = gtk_container_get_border_width (GTK_CONTAINER (window)); - *minimum_size = border_width * 2; - *natural_size = border_width * 2; - - if (child && gtk_widget_get_visible (child)) - { - gint child_min, child_nat; - gtk_widget_get_preferred_width (child, &child_min, &child_nat); - - *minimum_size += child_min; - *natural_size += child_nat; - } -} - -static void -gtk_window_get_preferred_height (GtkWidget *widget, - gint *minimum_size, - gint *natural_size) -{ - GtkWindow *window; - GtkWidget *child; - guint border_width; - - window = GTK_WINDOW (widget); - child = gtk_bin_get_child (GTK_BIN (window)); - - border_width = gtk_container_get_border_width (GTK_CONTAINER (window)); - *minimum_size = border_width * 2; - *natural_size = border_width * 2; - - if (child && gtk_widget_get_visible (child)) - { - gint child_min, child_nat; - gtk_widget_get_preferred_height (child, &child_min, &child_nat); - - *minimum_size += child_min; - *natural_size += child_nat; - } -} - - /** * _gtk_window_unset_focus_and_default: * @window: a #GtkWindow @@ -6582,7 +6576,7 @@ gtk_window_compute_configure_request_size (GtkWindow *window, info->resize_height > 0 ? height : NULL); } - /* Don't ever request zero width or height, its not supported by + /* Don't ever request zero width or height, it's not supported by gdk. The size allocation code will round it to 1 anyway but if we do it then the value returned from this function will is not comparable to the size allocation read from the GtkWindow. */ @@ -7128,7 +7122,10 @@ gtk_window_move_resize (GtkWindow *window) &new_geometry, new_flags); - gtk_widget_get_allocation (widget, &allocation); + allocation.x = 0; + allocation.y = 0; + allocation.width = gdk_window_get_width (gdk_window); + allocation.height = gdk_window_get_height (gdk_window); /* handle resizing/moving and widget tree allocation */ @@ -7153,10 +7150,6 @@ gtk_window_move_resize (GtkWindow *window) set_grip_position (window); update_grip_visibility (window); - gdk_window_process_updates (gdk_window, TRUE); - - gdk_window_configure_finished (gdk_window); - /* If the configure request changed, it means that * we either: * 1) coincidentally changed hints or widget properties @@ -7563,27 +7556,14 @@ gtk_window_draw (GtkWidget *widget, context = gtk_widget_get_style_context (widget); - gtk_style_context_save (context); - if (!gtk_widget_get_app_paintable (widget) && gtk_cairo_should_draw_window (cr, gtk_widget_get_window (widget))) { - GtkStateFlags state; - - state = gtk_widget_get_state_flags (widget); - - if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget))) - state |= GTK_STATE_FLAG_FOCUSED; - - gtk_style_context_set_state (context, state); - gtk_style_context_add_class (context, GTK_STYLE_CLASS_BACKGROUND); gtk_render_background (context, cr, 0, 0, gtk_widget_get_allocated_width (widget), gtk_widget_get_allocated_height (widget)); } - gtk_style_context_restore (context); - if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw) ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr); @@ -7598,6 +7578,7 @@ gtk_window_draw (GtkWidget *widget, gtk_cairo_transform_to_window (cr, widget, priv->grip_window); gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect); + gtk_style_context_remove_class (context, GTK_STYLE_CLASS_BACKGROUND); gtk_style_context_add_class (context, GTK_STYLE_CLASS_GRIP); gtk_style_context_set_junction_sides (context, get_grip_junction (widget)); gtk_render_handle (context, cr, 0, 0, rect.width, rect.height); @@ -8114,7 +8095,7 @@ gtk_window_set_resizable (GtkWindow *window, if (priv->resizable != resizable) { - priv->resizable = (resizable != FALSE); + priv->resizable = resizable; update_grip_visibility (window); @@ -8357,6 +8338,7 @@ gtk_window_set_theme_variant (GtkWindow *window) #endif } +#ifdef GDK_WINDOWING_X11 static void gtk_window_on_theme_variant_changed (GtkSettings *settings, GParamSpec *pspec, @@ -8365,6 +8347,7 @@ gtk_window_on_theme_variant_changed (GtkSettings *settings, if (window->priv->type == GTK_WINDOW_TOPLEVEL) gtk_window_set_theme_variant (window); } +#endif static void gtk_window_on_composited_changed (GdkScreen *screen, @@ -9488,8 +9471,8 @@ _gtk_window_set_is_active (GtkWindow *window, * in-process, parented GtkPlug) * * Internal function used by #GtkPlug when it gets parented/unparented by a - * #GtkSocket. This keeps the @window's #GTK_TOPLEVEL flag in sync with the - * global list of toplevel windows. + * #GtkSocket. This keeps the @window's #GTK_WINDOW_TOPLEVEL flag in sync + * with the global list of toplevel windows. */ void _gtk_window_set_is_toplevel (GtkWindow *window, @@ -9667,9 +9650,39 @@ gtk_window_set_mnemonics_visible (GtkWindow *window, g_object_notify (G_OBJECT (window), "mnemonics-visible"); } + if (priv->auto_mnemonics_timeout_id) + { + g_source_remove (priv->auto_mnemonics_timeout_id); + priv->auto_mnemonics_timeout_id = 0; + } + priv->mnemonics_visible_set = TRUE; } +static gboolean +set_auto_mnemonics_visible_cb (gpointer data) +{ + GtkWindow *window = data; + + gtk_window_set_mnemonics_visible (window, TRUE); + + window->priv->auto_mnemonics_timeout_id = 0; + + return FALSE; +} + +void +_gtk_window_set_auto_mnemonics_visible (GtkWindow *window) +{ + g_return_if_fail (GTK_IS_WINDOW (window)); + + if (window->priv->auto_mnemonics_timeout_id) + return; + + window->priv->auto_mnemonics_timeout_id = + gdk_threads_add_timeout (AUTO_MNEMONICS_DELAY, set_auto_mnemonics_visible_cb, window); +} + /** * gtk_window_get_focus_visible: * @window: a #GtkWindow @@ -9734,7 +9747,7 @@ _gtk_window_get_wmclass (GtkWindow *window, * @setting: the new value * * Tells GTK+ whether to drop its extra reference to the window - * when gtk_window_destroy() is called. + * when gtk_widget_destroy() is called. * * This function is only exported for the benefit of language * bindings which may need to keep the window alive until their @@ -9753,7 +9766,7 @@ gtk_window_set_has_user_ref_count (GtkWindow *window, } static void -ensure_state_flag_window_unfocused (GtkWidget *widget) +ensure_state_flag_backdrop (GtkWidget *widget) { GdkWindow *window; gboolean window_focused = TRUE; @@ -9763,89 +9776,9 @@ ensure_state_flag_window_unfocused (GtkWidget *widget) window_focused = gdk_window_get_state (window) & GDK_WINDOW_STATE_FOCUSED; if (!window_focused) - gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_WINDOW_UNFOCUSED, FALSE); + gtk_widget_set_state_flags (widget, GTK_STATE_FLAG_BACKDROP, FALSE); else - gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_WINDOW_UNFOCUSED); + gtk_widget_unset_state_flags (widget, GTK_STATE_FLAG_BACKDROP); gtk_widget_queue_draw (widget); } - -/** - * gtk_window_setup_persistent_state: - * @window: a #GtkWindow - * @settings: a #GSettings object - * @child_name: the name of a child on @settings with schema - * 'org.gtk.WindowState' - * - * Sets up persistent window state using #GSettings. - * - * The size of the window and its maximized state is saved. - * - * At the time of the call, the values are read out of GSettings and - * applied to the window as the default size and maximized state. This - * must be done before the window is shown. - * - * When the size or maximized state of the window is changed, the - * updated values are stored back into GSettings (with an unspecified - * delay to prevent trashing). - * - * @child_name must be the name of a child of @settings (ie: - * g_settings_get_child() must succeed). The resulting #GSettings - * object must have the schema 'org.gtk.WindowState', which is installed - * by Gtk. - * - * Your application's schema should look something like this: - * - * |[ - * ... keys ... - * - * - * - * ]]>]| - * - * Then you should call this function like this: - * - * |[ - * GSettings *settings; - * - * settings = g_settings_new ("org.example.awesome"); - * gtk_window_setup_persistent_state (window, settings, "main-window-state"); - * ]| - * - * You may only call this function once per window. - * - * Since: 3.4 - **/ -void -gtk_window_setup_persistent_state (GtkWindow *window, - GSettings *settings, - const gchar *child_name) -{ - gint width, height; - GSList *node; - - g_return_if_fail (GTK_IS_WINDOW (window)); - g_return_if_fail (G_IS_SETTINGS (settings)); - g_return_if_fail (child_name != NULL); - g_return_if_fail (window->priv->state_settings == NULL); - - /* Force other windows to flush their state first. We may be sharing - * the same settings as they are and we want to see them up to date... - */ - for (node = toplevel_list; node; node = node->next) - { - GtkWindow *w = node->data; - - if (w->priv->state_save_id) - gtk_window_persistent_state_flush (w); - g_assert (w->priv->state_save_id == 0); - } - - window->priv->state_settings = g_settings_get_child (settings, child_name); - window->priv->maximize_initially = g_settings_get_boolean (window->priv->state_settings, "is-maximized"); - - g_settings_get (window->priv->state_settings, "size", "(ii)", &width, &height); - if (width > 0 && height > 0) - gtk_window_set_default_size (window, width, height); -}