X-Git-Url: http://pileus.org/git/?a=blobdiff_plain;f=gtk%2Fgtkwindow.c;h=98b5c86dd0c381245350f9ec6adcd31dc166330e;hb=f91c04e2846de010871ee21389eb926dd18e065e;hp=95223601a6a2da124dda0ae071b65461c3695fe9;hpb=913cdf3be750a1e74c09b20edf55a57f9a919fcc;p=~andy%2Fgtk diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 95223601a..98b5c86dd 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -25,19 +25,18 @@ */ #include "config.h" + +#include "gtkwindow.h" + #include #include #include #include -#include "gdk/gdk.h" -#include "gdk/gdkkeysyms.h" - -#include "gtkintl.h" #include "gtkprivate.h" #include "gtkrc.h" -#include "gtkwindow.h" -#include "gtkwindow-decorate.h" +#include "gtkwindowprivate.h" +#include "gtkaccelgroupprivate.h" #include "gtkbindings.h" #include "gtkkeyhash.h" #include "gtkmain.h" @@ -48,7 +47,9 @@ #include "gtkmarshalers.h" #include "gtkplug.h" #include "gtkbuildable.h" -#include "gtksizerequest.h" +#include "gtkwidgetprivate.h" +#include "gtkintl.h" +#include "gtktypebuiltins.h" #ifdef GDK_WINDOWING_X11 #include "x11/gdkx.h" @@ -59,6 +60,16 @@ * @title: GtkWindow * @short_description: Toplevel which can contain other widgets * + * A GtkWindow is a toplevel window which can contain other widgets. + * Windows normally have decorations that are under the control + * of the windowing system and allow the user to manipulate the window + * (resize it, move it, close it,...). + * + * GTK+ also allows windows to have a resize grip (a small area in the lower + * right or left corner) which can be clicked to reszie the window. To + * control whether a window has a resize grip, use + * gtk_window_set_has_resize_grip(). + * * * GtkWindow as GtkBuildable * @@ -84,6 +95,90 @@ * * */ + +typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo; + +struct _GtkWindowPrivate +{ + GtkMnemonicHash *mnemonic_hash; + + GtkWidget *default_widget; + GtkWidget *focus_widget; + GtkWindow *transient_parent; + GtkWindowGeometryInfo *geometry_info; + GtkWindowGroup *group; + + GdkModifierType mnemonic_modifier; + GdkScreen *screen; + GdkWindowTypeHint gdk_type_hint; + + GtkApplication *application; + + gdouble opacity; + + GdkWindow *grip_window; + + gchar *startup_id; + gchar *title; + gchar *wmclass_class; + gchar *wmclass_name; + gchar *wm_role; + + guint keys_changed_handler; + + guint16 configure_request_count; + + /* The following flags are initially TRUE (before a window is mapped). + * They cause us to compute a configure request that involves + * default-only parameters. Once mapped, we set them to FALSE. + * Then we set them to TRUE again on unmap (for position) + * and on unrealize (for size). + */ + guint need_default_position : 1; + guint need_default_size : 1; + + guint above_initially : 1; + guint accept_focus : 1; + guint below_initially : 1; + guint builder_visible : 1; + guint configure_notify_received : 1; + guint decorated : 1; + guint deletable : 1; + guint destroy_with_parent : 1; + guint focus_on_map : 1; + guint fullscreen_initially : 1; + guint gravity : 5; /* GdkGravity */ + guint has_focus : 1; + guint has_user_ref_count : 1; + guint has_toplevel_focus : 1; + guint iconify_initially : 1; /* gtk_window_iconify() called before realization */ + guint is_active : 1; + guint maximize_initially : 1; + guint mnemonics_visible : 1; + guint mnemonics_visible_set : 1; + guint modal : 1; + guint opacity_set : 1; + guint position : 3; + guint reset_type_hint : 1; + guint resizable : 1; + guint skips_pager : 1; + guint skips_taskbar : 1; + guint stick_initially : 1; + guint transient_parent_group : 1; + guint type : 4; /* GtkWindowType */ + guint type_hint : 3; /* GdkWindowTypeHint if the hint is + * one of the original eight. If not, + * then it contains + * GDK_WINDOW_TYPE_HINT_NORMAL + */ + guint urgent : 1; + guint has_resize_grip : 1; + guint resize_grip_visible : 1; /* don't use, just for "resize- + * grip-visible" notification + */ + +}; + enum { SET_FOCUS, FRAME_EVENT, @@ -102,8 +197,6 @@ enum { /* Normal Props */ PROP_TITLE, PROP_ROLE, - PROP_ALLOW_SHRINK, - PROP_ALLOW_GROW, PROP_RESIZABLE, PROP_MODAL, PROP_WIN_POS, @@ -124,7 +217,9 @@ enum { PROP_GRAVITY, PROP_TRANSIENT_FOR, PROP_OPACITY, - + PROP_HAS_RESIZE_GRIP, + PROP_RESIZE_GRIP_VISIBLE, + PROP_APPLICATION, /* Readonly properties */ PROP_IS_ACTIVE, PROP_HAS_TOPLEVEL_FOCUS, @@ -140,8 +235,6 @@ enum { typedef struct { GList *icon_list; - GdkPixmap *icon_pixmap; - GdkPixmap *icon_mask; gchar *icon_name; guint realized : 1; guint using_default_icon : 1; @@ -186,51 +279,19 @@ struct _GtkWindowGeometryInfo */ guint position_constraints_changed : 1; - /* if true, default_width, height come from gtk_window_parse_geometry, - * and thus should be multiplied by the increments and affect the - * geometry widget only + /* if true, default_width, height should be multiplied by the + * increments and affect the geometry widget only */ guint default_is_geometry : 1; - - GtkWindowLastGeometryInfo last; -}; -#define GTK_WINDOW_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_WINDOW, GtkWindowPrivate)) -#define GTK_WINDOW_GROUP_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), GTK_TYPE_WINDOW_GROUP, GtkWindowGroupPrivate)) - -typedef struct _GtkWindowPrivate GtkWindowPrivate; - -struct _GtkWindowPrivate -{ - GtkMnemonicHash *mnemonic_hash; + /* if true, resize_width, height should be multiplied by the + * increments and affect the geometry widget only + */ + guint resize_is_geometry : 1; - guint above_initially : 1; - guint below_initially : 1; - guint fullscreen_initially : 1; - guint skips_taskbar : 1; - guint skips_pager : 1; - guint urgent : 1; - guint accept_focus : 1; - guint focus_on_map : 1; - guint deletable : 1; - guint transient_parent_group : 1; - - guint reset_type_hint : 1; - guint opacity_set : 1; - guint builder_visible : 1; - - guint mnemonics_visible : 1; - guint mnemonics_visible_set : 1; - - GdkWindowTypeHint type_hint; - - gdouble opacity; - - gchar *startup_id; + GtkWindowLastGeometryInfo last; }; -typedef struct _GtkDeviceGrabInfo GtkDeviceGrabInfo; -typedef struct _GtkWindowGroupPrivate GtkWindowGroupPrivate; struct _GtkDeviceGrabInfo { @@ -241,12 +302,13 @@ struct _GtkDeviceGrabInfo struct _GtkWindowGroupPrivate { + GSList *grabs; GSList *device_grabs; }; static void gtk_window_dispose (GObject *object); -static void gtk_window_destroy (GtkObject *object); static void gtk_window_finalize (GObject *object); +static void gtk_window_destroy (GtkWidget *widget); static void gtk_window_show (GtkWidget *widget); static void gtk_window_hide (GtkWidget *widget); static void gtk_window_map (GtkWidget *widget); @@ -255,18 +317,16 @@ static void gtk_window_realize (GtkWidget *widget); static void gtk_window_unrealize (GtkWidget *widget); static void gtk_window_size_allocate (GtkWidget *widget, GtkAllocation *allocation); -static gint gtk_window_event (GtkWidget *widget, - GdkEvent *event); static gboolean gtk_window_map_event (GtkWidget *widget, GdkEventAny *event); -static gboolean gtk_window_frame_event (GtkWindow *window, - GdkEvent *event); static gint gtk_window_configure_event (GtkWidget *widget, GdkEventConfigure *event); static gint gtk_window_key_press_event (GtkWidget *widget, GdkEventKey *event); static gint gtk_window_key_release_event (GtkWidget *widget, GdkEventKey *event); +static gint gtk_window_button_press_event (GtkWidget *widget, + GdkEventButton *event); static gint gtk_window_enter_notify_event (GtkWidget *widget, GdkEventCrossing *event); static gint gtk_window_leave_notify_event (GtkWidget *widget, @@ -275,23 +335,26 @@ static gint gtk_window_focus_in_event (GtkWidget *widget, GdkEventFocus *event); static gint gtk_window_focus_out_event (GtkWidget *widget, GdkEventFocus *event); -static gint gtk_window_client_event (GtkWidget *widget, - GdkEventClient *event); +static void gtk_window_style_updated (GtkWidget *widget); +static gboolean gtk_window_state_event (GtkWidget *widget, + GdkEventWindowState *event); static void gtk_window_check_resize (GtkContainer *container); static gint gtk_window_focus (GtkWidget *widget, GtkDirectionType direction); +static void gtk_window_move_focus (GtkWidget *widget, + GtkDirectionType dir); static void gtk_window_real_set_focus (GtkWindow *window, GtkWidget *focus); +static void gtk_window_direction_changed (GtkWidget *widget, + GtkTextDirection prev_dir); +static void gtk_window_state_changed (GtkWidget *widget, + GtkStateType previous_state); static void gtk_window_real_activate_default (GtkWindow *window); static void gtk_window_real_activate_focus (GtkWindow *window); -static void gtk_window_move_focus (GtkWindow *window, - GtkDirectionType dir); static void gtk_window_keys_changed (GtkWindow *window); -static void gtk_window_paint (GtkWidget *widget, - GdkRectangle *area); -static gint gtk_window_expose (GtkWidget *widget, - GdkEventExpose *event); +static gint gtk_window_draw (GtkWidget *widget, + cairo_t *cr); static void gtk_window_unset_transient_for (GtkWindow *window); static void gtk_window_transient_parent_realized (GtkWidget *parent, GtkWidget *window); @@ -341,6 +404,9 @@ static GList *icon_list_from_theme (GtkWidget *widget, const gchar *name); static void gtk_window_realize_icon (GtkWindow *window); static void gtk_window_unrealize_icon (GtkWindow *window); +static void resize_grip_create_window (GtkWindow *window); +static void resize_grip_destroy_window (GtkWindow *window); +static void update_grip_visibility (GtkWindow *window); static void gtk_window_notify_keys_changed (GtkWindow *window); static GtkKeyHash *gtk_window_get_key_hash (GtkWindow *window); @@ -358,7 +424,6 @@ static gboolean sent_startup_notification = FALSE; static GQuark quark_gtk_embedded = 0; static GQuark quark_gtk_window_key_hash = 0; -static GQuark quark_gtk_window_default_icon_pixmap = 0; static GQuark quark_gtk_window_icon_info = 0; static GQuark quark_gtk_buildable_accels = 0; @@ -394,19 +459,16 @@ static void gtk_window_buildable_custom_finished (GtkBuildable *buildable, gpointer user_data); -static void gtk_window_size_request_init (GtkSizeRequestIface *iface); -static void gtk_window_get_width (GtkSizeRequest *widget, +static void gtk_window_get_preferred_width (GtkWidget *widget, gint *minimum_size, gint *natural_size); -static void gtk_window_get_height (GtkSizeRequest *widget, +static void gtk_window_get_preferred_height (GtkWidget *widget, gint *minimum_size, gint *natural_size); G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_BIN, G_IMPLEMENT_INTERFACE (GTK_TYPE_BUILDABLE, - gtk_window_buildable_interface_init) - G_IMPLEMENT_INTERFACE (GTK_TYPE_SIZE_REQUEST, - gtk_window_size_request_init)) + gtk_window_buildable_interface_init)) static void add_tab_bindings (GtkBindingSet *binding_set, @@ -456,9 +518,10 @@ extract_time_from_startup_id (const gchar* startup_id) /* Skip past the "_TIME" part */ timestr += 5; + end = NULL; errno = 0; - timestamp = strtoul (timestr, &end, 0); - if (end != timestr && errno == 0) + timestamp = g_ascii_strtoull (timestr, &end, 0); + if (errno == 0 && end != timestr) retval = timestamp; } @@ -475,18 +538,15 @@ static void gtk_window_class_init (GtkWindowClass *klass) { GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - GtkObjectClass *object_class; GtkWidgetClass *widget_class; GtkContainerClass *container_class; GtkBindingSet *binding_set; - - object_class = (GtkObjectClass*) klass; + widget_class = (GtkWidgetClass*) klass; container_class = (GtkContainerClass*) klass; quark_gtk_embedded = g_quark_from_static_string ("gtk-embedded"); quark_gtk_window_key_hash = g_quark_from_static_string ("gtk-window-key-hash"); - quark_gtk_window_default_icon_pixmap = g_quark_from_static_string ("gtk-window-default-icon-pixmap"); quark_gtk_window_icon_info = g_quark_from_static_string ("gtk-window-icon-info"); quark_gtk_buildable_accels = g_quark_from_static_string ("gtk-window-buildable-accels"); @@ -495,9 +555,8 @@ gtk_window_class_init (GtkWindowClass *klass) gobject_class->set_property = gtk_window_set_property; gobject_class->get_property = gtk_window_get_property; - - object_class->destroy = gtk_window_destroy; + widget_class->destroy = gtk_window_destroy; widget_class->show = gtk_window_show; widget_class->hide = gtk_window_hide; widget_class->map = gtk_window_map; @@ -512,23 +571,28 @@ gtk_window_class_init (GtkWindowClass *klass) widget_class->enter_notify_event = gtk_window_enter_notify_event; widget_class->leave_notify_event = gtk_window_leave_notify_event; widget_class->focus_in_event = gtk_window_focus_in_event; + widget_class->button_press_event = gtk_window_button_press_event; widget_class->focus_out_event = gtk_window_focus_out_event; - widget_class->client_event = gtk_window_client_event; widget_class->focus = gtk_window_focus; - widget_class->expose_event = gtk_window_expose; + 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; + widget_class->style_updated = gtk_window_style_updated; container_class->check_resize = gtk_window_check_resize; klass->set_focus = gtk_window_real_set_focus; - klass->frame_event = gtk_window_frame_event; klass->activate_default = gtk_window_real_activate_default; klass->activate_focus = gtk_window_real_activate_focus; - klass->move_focus = gtk_window_move_focus; klass->keys_changed = gtk_window_keys_changed; - + g_type_class_add_private (gobject_class, sizeof (GtkWindowPrivate)); - + /* Construct */ g_object_class_install_property (gobject_class, PROP_TYPE, @@ -773,6 +837,41 @@ gtk_window_class_init (GtkWindowClass *klass) TRUE, GTK_PARAM_READWRITE)); + /** + * GtkWindow:has-resize-grip + * + * Whether the window has a corner resize grip. + * + * Note that the resize grip is only shown if the window is + * actually resizable and not maximized. Use + * #GtkWindow:resize-grip-visible to find out if the resize + * grip is currently shown. + * + * Since: 3.0 + */ + g_object_class_install_property (gobject_class, + PROP_HAS_RESIZE_GRIP, + g_param_spec_boolean ("has-resize-grip", + P_("Resize grip"), + P_("Specifies whether the window should have a resize grip"), + TRUE, + GTK_PARAM_READWRITE)); + + /** + * GtkWindow:resize-grip-visible: + * + * Whether a corner resize grip is currently shown. + * + * Since: 3.0 + */ + g_object_class_install_property (gobject_class, + PROP_RESIZE_GRIP_VISIBLE, + g_param_spec_boolean ("resize-grip-visible", + P_("Resize grip is visible"), + P_("Specifies whether the window's resize grip is visible."), + FALSE, + GTK_PARAM_READABLE)); + /** * GtkWindow:gravity: @@ -826,6 +925,44 @@ gtk_window_class_init (GtkWindowClass *klass) 1.0, GTK_PARAM_READWRITE)); + /* Style properties. + */ + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("resize-grip-width", + P_("Width of resize grip"), + P_("Width of resize grip"), + 0, G_MAXINT, 16, GTK_PARAM_READWRITE)); + + gtk_widget_class_install_style_property (widget_class, + g_param_spec_int ("resize-grip-height", + P_("Height of resize grip"), + P_("Height of resize grip"), + 0, G_MAXINT, 16, GTK_PARAM_READWRITE)); + + + /** + * GtkWindow:application: + * + * The #GtkApplication associated with the window. + * + * The application will be kept alive for at least as long as it + * has any windows associated with it (see g_application_hold() + * for a way to keep it alive without windows). + * + * Normally, the connection between the application and the window + * will remain until the window is destroyed, but you can explicitly + * remove it by setting the ::application property to %NULL. + * + * Since: 3.0 + */ + g_object_class_install_property (gobject_class, + PROP_APPLICATION, + g_param_spec_object ("application", + P_("GtkApplication"), + P_("The GtkApplication for the window"), + GTK_TYPE_APPLICATION, + GTK_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); + window_signals[SET_FOCUS] = g_signal_new (I_("set-focus"), G_TYPE_FROM_CLASS (gobject_class), @@ -835,16 +972,6 @@ gtk_window_class_init (GtkWindowClass *klass) _gtk_marshal_VOID__OBJECT, G_TYPE_NONE, 1, GTK_TYPE_WIDGET); - - window_signals[FRAME_EVENT] = - g_signal_new (I_("frame-event"), - G_TYPE_FROM_CLASS (gobject_class), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET(GtkWindowClass, frame_event), - _gtk_boolean_handled_accumulator, NULL, - _gtk_marshal_BOOLEAN__BOXED, - G_TYPE_BOOLEAN, 1, - GDK_TYPE_EVENT); /** * GtkWindow::activate-focus: @@ -933,42 +1060,40 @@ gtk_window_class_init (GtkWindowClass *klass) static void gtk_window_init (GtkWindow *window) { - GdkColormap *colormap; - GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window); + GtkWindowPrivate *priv; + + window->priv = G_TYPE_INSTANCE_GET_PRIVATE (window, + GTK_TYPE_WINDOW, + GtkWindowPrivate); + priv = window->priv; gtk_widget_set_has_window (GTK_WIDGET (window), TRUE); _gtk_widget_set_is_toplevel (GTK_WIDGET (window), TRUE); - GTK_PRIVATE_SET_FLAG (window, GTK_ANCHORED); + _gtk_widget_set_anchored (GTK_WIDGET (window), TRUE); gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE); - window->title = NULL; - window->wmclass_name = g_strdup (g_get_prgname ()); - window->wmclass_class = g_strdup (gdk_get_program_class ()); - window->wm_role = NULL; - window->geometry_info = NULL; - window->type = GTK_WINDOW_TOPLEVEL; - window->focus_widget = NULL; - window->default_widget = NULL; - window->configure_request_count = 0; - window->resizable = TRUE; - window->configure_notify_received = FALSE; - window->position = GTK_WIN_POS_NONE; - window->need_default_size = TRUE; - window->need_default_position = TRUE; - window->modal = FALSE; - window->frame = NULL; - window->has_frame = FALSE; - window->frame_left = 0; - window->frame_right = 0; - window->frame_top = 0; - window->frame_bottom = 0; - window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL; - window->gravity = GDK_GRAVITY_NORTH_WEST; - window->decorated = TRUE; - window->mnemonic_modifier = GDK_MOD1_MASK; - window->screen = gdk_screen_get_default (); + priv->title = NULL; + priv->wmclass_name = g_strdup (g_get_prgname ()); + priv->wmclass_class = g_strdup (gdk_get_program_class ()); + priv->wm_role = NULL; + priv->geometry_info = NULL; + priv->type = GTK_WINDOW_TOPLEVEL; + priv->focus_widget = NULL; + priv->default_widget = NULL; + priv->configure_request_count = 0; + priv->resizable = TRUE; + priv->configure_notify_received = FALSE; + priv->position = GTK_WIN_POS_NONE; + priv->need_default_size = TRUE; + priv->need_default_position = TRUE; + priv->modal = FALSE; + priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL; + priv->gravity = GDK_GRAVITY_NORTH_WEST; + priv->decorated = TRUE; + priv->mnemonic_modifier = GDK_MOD1_MASK; + priv->screen = gdk_screen_get_default (); priv->accept_focus = TRUE; priv->focus_on_map = TRUE; @@ -976,20 +1101,16 @@ gtk_window_init (GtkWindow *window) priv->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL; priv->opacity = 1.0; priv->startup_id = NULL; + priv->has_resize_grip = TRUE; priv->mnemonics_visible = TRUE; - colormap = _gtk_widget_peek_colormap (); - if (colormap) - gtk_widget_set_colormap (GTK_WIDGET (window), colormap); - g_object_ref_sink (window); - window->has_user_ref_count = TRUE; + priv->has_user_ref_count = TRUE; toplevel_list = g_slist_prepend (toplevel_list, window); - gtk_decorated_window_init (window); - - g_signal_connect (window->screen, "composited-changed", - G_CALLBACK (gtk_window_on_composited_changed), window); + if (priv->screen) + g_signal_connect (priv->screen, "composited-changed", + G_CALLBACK (gtk_window_on_composited_changed), window); } static void @@ -998,17 +1119,13 @@ gtk_window_set_property (GObject *object, const GValue *value, GParamSpec *pspec) { - GtkWindow *window; - GtkWindowPrivate *priv; - - window = GTK_WINDOW (object); - - priv = GTK_WINDOW_GET_PRIVATE (window); + GtkWindow *window = GTK_WINDOW (object); + GtkWindowPrivate *priv = window->priv; switch (prop_id) { case PROP_TYPE: - window->type = g_value_get_enum (value); + priv->type = g_value_get_enum (value); break; case PROP_TITLE: gtk_window_set_title (window, g_value_get_string (value)); @@ -1018,10 +1135,9 @@ gtk_window_set_property (GObject *object, break; case PROP_STARTUP_ID: gtk_window_set_startup_id (window, g_value_get_string (value)); - break; + break; case PROP_RESIZABLE: - window->resizable = g_value_get_boolean (value); - gtk_widget_queue_resize (GTK_WIDGET (window)); + gtk_window_set_resizable (window, g_value_get_boolean (value)); break; case PROP_MODAL: gtk_window_set_modal (window, g_value_get_boolean (value)); @@ -1091,6 +1207,12 @@ gtk_window_set_property (GObject *object, case PROP_OPACITY: gtk_window_set_opacity (window, g_value_get_double (value)); break; + case PROP_HAS_RESIZE_GRIP: + gtk_window_set_has_resize_grip (window, g_value_get_boolean (value)); + break; + case PROP_APPLICATION: + gtk_window_set_application (window, g_value_get_object (value)); + break; case PROP_MNEMONICS_VISIBLE: gtk_window_set_mnemonics_visible (window, g_value_get_boolean (value)); break; @@ -1106,32 +1228,29 @@ gtk_window_get_property (GObject *object, GValue *value, GParamSpec *pspec) { - GtkWindow *window; - GtkWindowPrivate *priv; + GtkWindow *window = GTK_WINDOW (object); + GtkWindowPrivate *priv = window->priv; - window = GTK_WINDOW (object); - priv = GTK_WINDOW_GET_PRIVATE (window); - switch (prop_id) { GtkWindowGeometryInfo *info; case PROP_TYPE: - g_value_set_enum (value, window->type); + g_value_set_enum (value, priv->type); break; case PROP_ROLE: - g_value_set_string (value, window->wm_role); + g_value_set_string (value, priv->wm_role); break; case PROP_TITLE: - g_value_set_string (value, window->title); + g_value_set_string (value, priv->title); break; case PROP_RESIZABLE: - g_value_set_boolean (value, window->resizable); + g_value_set_boolean (value, priv->resizable); break; case PROP_MODAL: - g_value_set_boolean (value, window->modal); + g_value_set_boolean (value, priv->modal); break; case PROP_WIN_POS: - g_value_set_enum (value, window->position); + g_value_set_enum (value, priv->position); break; case PROP_DEFAULT_WIDTH: info = gtk_window_get_geometry_info (window, FALSE); @@ -1148,7 +1267,7 @@ gtk_window_get_property (GObject *object, g_value_set_int (value, info->default_height); break; case PROP_DESTROY_WITH_PARENT: - g_value_set_boolean (value, window->destroy_with_parent); + g_value_set_boolean (value, priv->destroy_with_parent); break; case PROP_ICON: g_value_set_object (value, gtk_window_get_icon (window)); @@ -1157,13 +1276,13 @@ gtk_window_get_property (GObject *object, g_value_set_string (value, gtk_window_get_icon_name (window)); break; case PROP_SCREEN: - g_value_set_object (value, window->screen); + g_value_set_object (value, priv->screen); break; case PROP_IS_ACTIVE: - g_value_set_boolean (value, window->is_active); + g_value_set_boolean (value, priv->is_active); break; case PROP_HAS_TOPLEVEL_FOCUS: - g_value_set_boolean (value, window->has_toplevel_focus); + g_value_set_boolean (value, priv->has_toplevel_focus); break; case PROP_TYPE_HINT: g_value_set_enum (value, priv->type_hint); @@ -1203,6 +1322,15 @@ gtk_window_get_property (GObject *object, case PROP_OPACITY: g_value_set_double (value, gtk_window_get_opacity (window)); break; + case PROP_HAS_RESIZE_GRIP: + g_value_set_boolean (value, priv->has_resize_grip); + break; + case PROP_RESIZE_GRIP_VISIBLE: + g_value_set_boolean (value, gtk_window_resize_grip_is_visible (window)); + break; + case PROP_APPLICATION: + g_value_set_object (value, gtk_window_get_application (window)); + break; case PROP_MNEMONICS_VISIBLE: g_value_set_boolean (value, priv->mnemonics_visible); break; @@ -1228,7 +1356,8 @@ gtk_window_buildable_set_buildable_property (GtkBuildable *buildable, const gchar *name, const GValue *value) { - GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (buildable); + GtkWindow *window = GTK_WINDOW (buildable); + GtkWindowPrivate *priv = window->priv; if (strcmp (name, "visible") == 0 && g_value_get_boolean (value)) priv->builder_visible = TRUE; @@ -1240,7 +1369,8 @@ static void gtk_window_buildable_parser_finished (GtkBuildable *buildable, GtkBuilder *builder) { - GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (buildable); + GtkWindow *window = GTK_WINDOW (buildable); + GtkWindowPrivate *priv = window->priv; GObject *object; GSList *accels, *l; @@ -1377,13 +1507,15 @@ gtk_window_buildable_custom_finished (GtkBuildable *buildable, GtkWidget* gtk_window_new (GtkWindowType type) { + GtkWindowPrivate *priv; GtkWindow *window; g_return_val_if_fail (type >= GTK_WINDOW_TOPLEVEL && type <= GTK_WINDOW_POPUP, NULL); window = g_object_new (GTK_TYPE_WINDOW, NULL); + priv = window->priv; - window->type = type; + priv->type = type; return GTK_WIDGET (window); } @@ -1407,23 +1539,23 @@ void gtk_window_set_title (GtkWindow *window, const gchar *title) { + GtkWindowPrivate *priv; GtkWidget *widget; char *new_title; g_return_if_fail (GTK_IS_WINDOW (window)); + priv = window->priv; widget = GTK_WIDGET (window); new_title = g_strdup (title); - g_free (window->title); - window->title = new_title; + g_free (priv->title); + priv->title = new_title; if (gtk_widget_get_realized (widget)) { gdk_window_set_title (gtk_widget_get_window (widget), - window->title); - - gtk_decorated_window_set_title (window, title); + priv->title); } g_object_notify (G_OBJECT (window), "title"); @@ -1444,7 +1576,7 @@ gtk_window_get_title (GtkWindow *window) { g_return_val_if_fail (GTK_IS_WINDOW (window), NULL); - return window->title; + return window->priv->title; } /** @@ -1468,13 +1600,17 @@ gtk_window_set_wmclass (GtkWindow *window, const gchar *wmclass_name, const gchar *wmclass_class) { + GtkWindowPrivate *priv; + g_return_if_fail (GTK_IS_WINDOW (window)); - g_free (window->wmclass_name); - window->wmclass_name = g_strdup (wmclass_name); + priv = window->priv; + + g_free (priv->wmclass_name); + priv->wmclass_name = g_strdup (wmclass_name); - g_free (window->wmclass_class); - window->wmclass_class = g_strdup (wmclass_class); + g_free (priv->wmclass_class); + priv->wmclass_class = g_strdup (wmclass_class); if (gtk_widget_get_realized (GTK_WIDGET (window))) g_warning ("gtk_window_set_wmclass: shouldn't set wmclass after window is realized!\n"); @@ -1503,17 +1639,20 @@ void gtk_window_set_role (GtkWindow *window, const gchar *role) { + GtkWindowPrivate *priv; char *new_role; g_return_if_fail (GTK_IS_WINDOW (window)); + priv = window->priv; + new_role = g_strdup (role); - g_free (window->wm_role); - window->wm_role = new_role; + g_free (priv->wm_role); + priv->wm_role = new_role; if (gtk_widget_get_realized (GTK_WIDGET (window))) gdk_window_set_role (gtk_widget_get_window (GTK_WIDGET (window)), - window->wm_role); + priv->wm_role); g_object_notify (G_OBJECT (window), "role"); } @@ -1545,7 +1684,7 @@ gtk_window_set_startup_id (GtkWindow *window, g_return_if_fail (GTK_IS_WINDOW (window)); - priv = GTK_WINDOW_GET_PRIVATE (window); + priv = window->priv; widget = GTK_WIDGET (window); g_free (priv->startup_id); @@ -1599,7 +1738,7 @@ gtk_window_get_role (GtkWindow *window) { g_return_val_if_fail (GTK_IS_WINDOW (window), NULL); - return window->wm_role; + return window->priv->wm_role; } /** @@ -1618,10 +1757,13 @@ void gtk_window_set_focus (GtkWindow *window, GtkWidget *focus) { + GtkWindowPrivate *priv; GtkWidget *parent; g_return_if_fail (GTK_IS_WINDOW (window)); + priv = window->priv; + if (focus) { g_return_if_fail (GTK_IS_WIDGET (focus)); @@ -1635,7 +1777,7 @@ gtk_window_set_focus (GtkWindow *window, /* Clear the existing focus chain, so that when we focus into * the window again, we start at the beginnning. */ - GtkWidget *widget = window->focus_widget; + GtkWidget *widget = priv->focus_widget; if (widget) { while ((parent = gtk_widget_get_parent (widget))) @@ -1653,9 +1795,13 @@ void _gtk_window_internal_set_focus (GtkWindow *window, GtkWidget *focus) { + GtkWindowPrivate *priv; + g_return_if_fail (GTK_IS_WINDOW (window)); - if ((window->focus_widget != focus) || + priv = window->priv; + + if ((priv->focus_widget != focus) || (focus && !gtk_widget_has_focus (focus))) g_signal_emit (window, window_signals[SET_FOCUS], 0, focus); } @@ -1678,36 +1824,42 @@ void gtk_window_set_default (GtkWindow *window, GtkWidget *default_widget) { + GtkWindowPrivate *priv; + g_return_if_fail (GTK_IS_WINDOW (window)); + priv = window->priv; + if (default_widget) g_return_if_fail (gtk_widget_get_can_default (default_widget)); - - if (window->default_widget != default_widget) + + if (priv->default_widget != default_widget) { GtkWidget *old_default_widget = NULL; if (default_widget) g_object_ref (default_widget); - - if (window->default_widget) + + if (priv->default_widget) { - old_default_widget = window->default_widget; - - if (window->focus_widget != window->default_widget || - !gtk_widget_get_receives_default (window->default_widget)) - _gtk_widget_set_has_default (window->default_widget, FALSE); - gtk_widget_queue_draw (window->default_widget); + old_default_widget = priv->default_widget; + + if (priv->focus_widget != priv->default_widget || + !gtk_widget_get_receives_default (priv->default_widget)) + _gtk_widget_set_has_default (priv->default_widget, FALSE); + + gtk_widget_queue_draw (priv->default_widget); } - window->default_widget = default_widget; + priv->default_widget = default_widget; - if (window->default_widget) + if (priv->default_widget) { - if (window->focus_widget == NULL || - !gtk_widget_get_receives_default (window->focus_widget)) - _gtk_widget_set_has_default (window->default_widget, TRUE); - gtk_widget_queue_draw (window->default_widget); + if (priv->focus_widget == NULL || + !gtk_widget_get_receives_default (priv->focus_widget)) + _gtk_widget_set_has_default (priv->default_widget, TRUE); + + gtk_widget_queue_draw (priv->default_widget); } if (old_default_widget) @@ -1728,7 +1880,7 @@ gtk_window_set_default (GtkWindow *window, * Returns the default widget for @window. See gtk_window_set_default() * for more details. * - * Returns: the default widget, or %NULL if there is none. + * Returns: (transfer none): the default widget, or %NULL if there is none. * * Since: 2.14 **/ @@ -1737,20 +1889,19 @@ gtk_window_get_default_widget (GtkWindow *window) { g_return_val_if_fail (GTK_IS_WINDOW (window), NULL); - return window->default_widget; + return window->priv->default_widget; } static gboolean handle_keys_changed (gpointer data) { - GtkWindow *window; - - window = GTK_WINDOW (data); + GtkWindow *window = GTK_WINDOW (data); + GtkWindowPrivate *priv = window->priv; - if (window->keys_changed_handler) + if (priv->keys_changed_handler) { - g_source_remove (window->keys_changed_handler); - window->keys_changed_handler = 0; + g_source_remove (priv->keys_changed_handler); + priv->keys_changed_handler = 0; } g_signal_emit (window, window_signals[KEYS_CHANGED], 0); @@ -1761,8 +1912,10 @@ handle_keys_changed (gpointer data) static void gtk_window_notify_keys_changed (GtkWindow *window) { - if (!window->keys_changed_handler) - window->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window); + GtkWindowPrivate *priv = window->priv; + + if (!priv->keys_changed_handler) + priv->keys_changed_handler = gdk_threads_add_idle (handle_keys_changed, window); } /** @@ -1813,10 +1966,11 @@ static GtkMnemonicHash * gtk_window_get_mnemonic_hash (GtkWindow *window, gboolean create) { - GtkWindowPrivate *private = GTK_WINDOW_GET_PRIVATE (window); + GtkWindowPrivate *private = window->priv; + if (!private->mnemonic_hash && create) private->mnemonic_hash = _gtk_mnemonic_hash_new (); - + return private->mnemonic_hash; } @@ -1876,9 +2030,13 @@ gtk_window_mnemonic_activate (GtkWindow *window, guint keyval, GdkModifierType modifier) { + GtkWindowPrivate *priv; + g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); - if (window->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ())) + priv = window->priv; + + if (priv->mnemonic_modifier == (modifier & gtk_accelerator_get_default_mod_mask ())) { GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE); if (mnemonic_hash) @@ -1900,10 +2058,14 @@ void gtk_window_set_mnemonic_modifier (GtkWindow *window, GdkModifierType modifier) { + GtkWindowPrivate *priv; + g_return_if_fail (GTK_IS_WINDOW (window)); g_return_if_fail ((modifier & ~GDK_MODIFIER_MASK) == 0); - window->mnemonic_modifier = modifier; + priv = window->priv; + + priv->mnemonic_modifier = modifier; gtk_window_notify_keys_changed (window); } @@ -1922,7 +2084,7 @@ gtk_window_get_mnemonic_modifier (GtkWindow *window) { g_return_val_if_fail (GTK_IS_WINDOW (window), 0); - return window->mnemonic_modifier; + return window->priv->mnemonic_modifier; } /** @@ -1938,10 +2100,14 @@ void gtk_window_set_position (GtkWindow *window, GtkWindowPosition position) { + GtkWindowPrivate *priv; + g_return_if_fail (GTK_IS_WINDOW (window)); + priv = window->priv; + if (position == GTK_WIN_POS_CENTER_ALWAYS || - window->position == GTK_WIN_POS_CENTER_ALWAYS) + priv->position == GTK_WIN_POS_CENTER_ALWAYS) { GtkWindowGeometryInfo *info; @@ -1956,7 +2122,7 @@ gtk_window_set_position (GtkWindow *window, gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window)); } - window->position = position; + priv->position = position; g_object_notify (G_OBJECT (window), "window-position"); } @@ -1972,10 +2138,14 @@ gtk_window_set_position (GtkWindow *window, gboolean gtk_window_activate_focus (GtkWindow *window) { + GtkWindowPrivate *priv; + g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); - if (window->focus_widget && gtk_widget_is_sensitive (window->focus_widget)) - return gtk_widget_activate (window->focus_widget); + priv = window->priv; + + if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget)) + return gtk_widget_activate (priv->focus_widget); return FALSE; } @@ -1997,7 +2167,7 @@ gtk_window_get_focus (GtkWindow *window) { g_return_val_if_fail (GTK_IS_WINDOW (window), NULL); - return window->focus_widget; + return window->priv->focus_widget; } /** @@ -2014,13 +2184,17 @@ gtk_window_get_focus (GtkWindow *window) gboolean gtk_window_activate_default (GtkWindow *window) { + GtkWindowPrivate *priv; + g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); - if (window->default_widget && gtk_widget_is_sensitive (window->default_widget) && - (!window->focus_widget || !gtk_widget_get_receives_default (window->focus_widget))) - return gtk_widget_activate (window->default_widget); - else if (window->focus_widget && gtk_widget_is_sensitive (window->focus_widget)) - return gtk_widget_activate (window->focus_widget); + priv = window->priv; + + if (priv->default_widget && gtk_widget_is_sensitive (priv->default_widget) && + (!priv->focus_widget || !gtk_widget_get_receives_default (priv->focus_widget))) + return gtk_widget_activate (priv->default_widget); + else if (priv->focus_widget && gtk_widget_is_sensitive (priv->focus_widget)) + return gtk_widget_activate (priv->focus_widget); return FALSE; } @@ -2043,21 +2217,24 @@ void gtk_window_set_modal (GtkWindow *window, gboolean modal) { + GtkWindowPrivate *priv; GtkWidget *widget; g_return_if_fail (GTK_IS_WINDOW (window)); + priv = window->priv; + modal = modal != FALSE; - if (window->modal == modal) + if (priv->modal == modal) return; - - window->modal = modal; + + priv->modal = modal; widget = GTK_WIDGET (window); /* adjust desired modality state */ if (gtk_widget_get_realized (widget)) { - if (window->modal) + if (priv->modal) gdk_window_set_modal_hint (gtk_widget_get_window (widget), TRUE); else gdk_window_set_modal_hint (gtk_widget_get_window (widget), FALSE); @@ -2065,7 +2242,7 @@ gtk_window_set_modal (GtkWindow *window, if (gtk_widget_get_visible (widget)) { - if (window->modal) + if (priv->modal) gtk_grab_add (widget); else gtk_grab_remove (widget); @@ -2088,7 +2265,7 @@ gtk_window_get_modal (GtkWindow *window) { g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); - return window->modal; + return window->priv->modal; } /** @@ -2115,50 +2292,6 @@ gtk_window_list_toplevels (void) return list; } -void -gtk_window_add_embedded_xid (GtkWindow *window, GdkNativeWindow xid) -{ - GList *embedded_windows; - - g_return_if_fail (GTK_IS_WINDOW (window)); - - embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded); - if (embedded_windows) - g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded); - embedded_windows = g_list_prepend (embedded_windows, - GUINT_TO_POINTER (xid)); - - g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded, - embedded_windows, - embedded_windows ? - (GDestroyNotify) g_list_free : NULL); -} - -void -gtk_window_remove_embedded_xid (GtkWindow *window, GdkNativeWindow xid) -{ - GList *embedded_windows; - GList *node; - - g_return_if_fail (GTK_IS_WINDOW (window)); - - embedded_windows = g_object_get_qdata (G_OBJECT (window), quark_gtk_embedded); - if (embedded_windows) - g_object_steal_qdata (G_OBJECT (window), quark_gtk_embedded); - - node = g_list_find (embedded_windows, GUINT_TO_POINTER (xid)); - if (node) - { - embedded_windows = g_list_remove_link (embedded_windows, node); - g_list_free_1 (node); - } - - g_object_set_qdata_full (G_OBJECT (window), quark_gtk_embedded, - embedded_windows, - embedded_windows ? - (GDestroyNotify) g_list_free : NULL); -} - static void gtk_window_dispose (GObject *object) { @@ -2179,9 +2312,11 @@ parent_destroyed_callback (GtkWindow *parent, GtkWindow *child) static void connect_parent_destroyed (GtkWindow *window) { - if (window->transient_parent) + GtkWindowPrivate *priv = window->priv; + + if (priv->transient_parent) { - g_signal_connect (window->transient_parent, + g_signal_connect (priv->transient_parent, "destroy", G_CALLBACK (parent_destroyed_callback), window); @@ -2191,9 +2326,11 @@ connect_parent_destroyed (GtkWindow *window) static void disconnect_parent_destroyed (GtkWindow *window) { - if (window->transient_parent) + GtkWindowPrivate *priv = window->priv; + + if (priv->transient_parent) { - g_signal_handlers_disconnect_by_func (window->transient_parent, + g_signal_handlers_disconnect_by_func (priv->transient_parent, parent_destroyed_callback, window); } @@ -2222,38 +2359,38 @@ gtk_window_transient_parent_screen_changed (GtkWindow *parent, GParamSpec *pspec, GtkWindow *window) { - gtk_window_set_screen (window, parent->screen); + gtk_window_set_screen (window, parent->priv->screen); } static void gtk_window_unset_transient_for (GtkWindow *window) { - GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window); - - if (window->transient_parent) + GtkWindowPrivate *priv = window->priv; + + if (priv->transient_parent) { - g_signal_handlers_disconnect_by_func (window->transient_parent, + g_signal_handlers_disconnect_by_func (priv->transient_parent, gtk_window_transient_parent_realized, window); - g_signal_handlers_disconnect_by_func (window->transient_parent, + g_signal_handlers_disconnect_by_func (priv->transient_parent, gtk_window_transient_parent_unrealized, window); - g_signal_handlers_disconnect_by_func (window->transient_parent, + g_signal_handlers_disconnect_by_func (priv->transient_parent, gtk_window_transient_parent_screen_changed, window); - g_signal_handlers_disconnect_by_func (window->transient_parent, + g_signal_handlers_disconnect_by_func (priv->transient_parent, gtk_widget_destroyed, - &window->transient_parent); + &priv->transient_parent); - if (window->destroy_with_parent) + if (priv->destroy_with_parent) disconnect_parent_destroyed (window); - - window->transient_parent = NULL; + + priv->transient_parent = NULL; if (priv->transient_parent_group) { priv->transient_parent_group = FALSE; - gtk_window_group_remove_window (window->group, + gtk_window_group_remove_window (priv->group, window); } } @@ -2282,31 +2419,31 @@ gtk_window_set_transient_for (GtkWindow *window, GtkWindow *parent) { GtkWindowPrivate *priv; - + g_return_if_fail (GTK_IS_WINDOW (window)); g_return_if_fail (parent == NULL || GTK_IS_WINDOW (parent)); g_return_if_fail (window != parent); - priv = GTK_WINDOW_GET_PRIVATE (window); + priv = window->priv; - if (window->transient_parent) + if (priv->transient_parent) { if (gtk_widget_get_realized (GTK_WIDGET (window)) && - gtk_widget_get_realized (GTK_WIDGET (window->transient_parent)) && + gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent)) && (!parent || !gtk_widget_get_realized (GTK_WIDGET (parent)))) - gtk_window_transient_parent_unrealized (GTK_WIDGET (window->transient_parent), + gtk_window_transient_parent_unrealized (GTK_WIDGET (priv->transient_parent), GTK_WIDGET (window)); gtk_window_unset_transient_for (window); } - window->transient_parent = parent; - + priv->transient_parent = parent; + if (parent) { g_signal_connect (parent, "destroy", G_CALLBACK (gtk_widget_destroyed), - &window->transient_parent); + &priv->transient_parent); g_signal_connect (parent, "realize", G_CALLBACK (gtk_window_transient_parent_realized), window); @@ -2316,10 +2453,10 @@ gtk_window_set_transient_for (GtkWindow *window, g_signal_connect (parent, "notify::screen", G_CALLBACK (gtk_window_transient_parent_screen_changed), window); - - gtk_window_set_screen (window, parent->screen); - if (window->destroy_with_parent) + gtk_window_set_screen (window, parent->priv->screen); + + if (priv->destroy_with_parent) connect_parent_destroyed (window); if (gtk_widget_get_realized (GTK_WIDGET (window)) && @@ -2327,9 +2464,9 @@ gtk_window_set_transient_for (GtkWindow *window, gtk_window_transient_parent_realized (GTK_WIDGET (parent), GTK_WIDGET (window)); - if (parent->group) + if (parent->priv->group) { - gtk_window_group_add_window (parent->group, window); + gtk_window_group_add_window (parent->priv->group, window); priv->transient_parent_group = TRUE; } } @@ -2350,7 +2487,7 @@ gtk_window_get_transient_for (GtkWindow *window) { g_return_val_if_fail (GTK_IS_WINDOW (window), NULL); - return window->transient_parent; + return window->priv->transient_parent; } /** @@ -2375,10 +2512,10 @@ gtk_window_set_opacity (GtkWindow *window, gdouble opacity) { GtkWindowPrivate *priv; - + g_return_if_fail (GTK_IS_WINDOW (window)); - priv = GTK_WINDOW_GET_PRIVATE (window); + priv = window->priv; if (opacity < 0.0) opacity = 0.0; @@ -2407,13 +2544,81 @@ gtk_window_set_opacity (GtkWindow *window, gdouble gtk_window_get_opacity (GtkWindow *window) { - GtkWindowPrivate *priv; - g_return_val_if_fail (GTK_IS_WINDOW (window), 0.0); - priv = GTK_WINDOW_GET_PRIVATE (window); + return window->priv->opacity; +} + +/** + * gtk_window_get_application: + * @window: a #GtkWindow + * + * Gets the #GtkApplication associated with the window (if any). + * + * Return value: (transfer none): a #GtkApplication, or %NULL + * + * Since: 3.0 + **/ +GtkApplication * +gtk_window_get_application (GtkWindow *window) +{ + g_return_val_if_fail (GTK_IS_WINDOW (window), NULL); + + return window->priv->application; +} + +static void +gtk_window_release_application (GtkWindow *window) +{ + if (window->priv->application) + { + GtkApplication *application; + + /* steal reference into temp variable */ + application = window->priv->application; + window->priv->application = NULL; + + gtk_application_remove_window (application, window); + g_object_unref (application); + } +} + +/** + * gtk_window_set_application: + * @window: a #GtkWindow + * @application: (allow-none): a #GtkApplication, or %NULL + * + * Sets or unsets the #GtkApplication associated with the window. + * + * The application will be kept alive for at least as long as the window + * is open. + * + * Since: 3.0 + **/ +void +gtk_window_set_application (GtkWindow *window, + GtkApplication *application) +{ + GtkWindowPrivate *priv; + + g_return_if_fail (GTK_IS_WINDOW (window)); + + priv = window->priv; + if (priv->application != application) + { + gtk_window_release_application (window); + + priv->application = application; + + if (priv->application != NULL) + { + g_object_ref (priv->application); + + gtk_application_add_window (priv->application, window); + } - return priv->opacity; + g_object_notify (G_OBJECT (window), "application"); + } } /** @@ -2440,12 +2645,12 @@ gtk_window_set_type_hint (GtkWindow *window, g_return_if_fail (GTK_IS_WINDOW (window)); g_return_if_fail (!gtk_widget_get_mapped (GTK_WIDGET (window))); - priv = GTK_WINDOW_GET_PRIVATE (window); + priv = window->priv; if (hint < GDK_WINDOW_TYPE_HINT_DROPDOWN_MENU) - window->type_hint = hint; + priv->gdk_type_hint = hint; else - window->type_hint = GDK_WINDOW_TYPE_HINT_NORMAL; + priv->gdk_type_hint = GDK_WINDOW_TYPE_HINT_NORMAL; priv->reset_type_hint = TRUE; priv->type_hint = hint; @@ -2462,13 +2667,9 @@ gtk_window_set_type_hint (GtkWindow *window, GdkWindowTypeHint gtk_window_get_type_hint (GtkWindow *window) { - GtkWindowPrivate *priv; - g_return_val_if_fail (GTK_IS_WINDOW (window), GDK_WINDOW_TYPE_HINT_NORMAL); - priv = GTK_WINDOW_GET_PRIVATE (window); - - return priv->type_hint; + return window->priv->type_hint; } /** @@ -2488,8 +2689,8 @@ gtk_window_set_skip_taskbar_hint (GtkWindow *window, GtkWindowPrivate *priv; g_return_if_fail (GTK_IS_WINDOW (window)); - - priv = GTK_WINDOW_GET_PRIVATE (window); + + priv = window->priv; setting = setting != FALSE; @@ -2516,13 +2717,9 @@ gtk_window_set_skip_taskbar_hint (GtkWindow *window, gboolean gtk_window_get_skip_taskbar_hint (GtkWindow *window) { - GtkWindowPrivate *priv; - g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); - - priv = GTK_WINDOW_GET_PRIVATE (window); - return priv->skips_taskbar; + return window->priv->skips_taskbar; } /** @@ -2545,8 +2742,8 @@ gtk_window_set_skip_pager_hint (GtkWindow *window, GtkWindowPrivate *priv; g_return_if_fail (GTK_IS_WINDOW (window)); - - priv = GTK_WINDOW_GET_PRIVATE (window); + + priv = window->priv; setting = setting != FALSE; @@ -2573,13 +2770,9 @@ gtk_window_set_skip_pager_hint (GtkWindow *window, gboolean gtk_window_get_skip_pager_hint (GtkWindow *window) { - GtkWindowPrivate *priv; - g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); - - priv = GTK_WINDOW_GET_PRIVATE (window); - return priv->skips_pager; + return window->priv->skips_pager; } /** @@ -2599,8 +2792,8 @@ gtk_window_set_urgency_hint (GtkWindow *window, GtkWindowPrivate *priv; g_return_if_fail (GTK_IS_WINDOW (window)); - - priv = GTK_WINDOW_GET_PRIVATE (window); + + priv = window->priv; setting = setting != FALSE; @@ -2627,13 +2820,9 @@ gtk_window_set_urgency_hint (GtkWindow *window, gboolean gtk_window_get_urgency_hint (GtkWindow *window) { - GtkWindowPrivate *priv; - g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); - - priv = GTK_WINDOW_GET_PRIVATE (window); - return priv->urgent; + return window->priv->urgent; } /** @@ -2653,8 +2842,8 @@ gtk_window_set_accept_focus (GtkWindow *window, GtkWindowPrivate *priv; g_return_if_fail (GTK_IS_WINDOW (window)); - - priv = GTK_WINDOW_GET_PRIVATE (window); + + priv = window->priv; setting = setting != FALSE; @@ -2681,13 +2870,9 @@ gtk_window_set_accept_focus (GtkWindow *window, gboolean gtk_window_get_accept_focus (GtkWindow *window) { - GtkWindowPrivate *priv; - g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); - - priv = GTK_WINDOW_GET_PRIVATE (window); - return priv->accept_focus; + return window->priv->accept_focus; } /** @@ -2708,8 +2893,8 @@ gtk_window_set_focus_on_map (GtkWindow *window, GtkWindowPrivate *priv; g_return_if_fail (GTK_IS_WINDOW (window)); - - priv = GTK_WINDOW_GET_PRIVATE (window); + + priv = window->priv; setting = setting != FALSE; @@ -2737,13 +2922,9 @@ gtk_window_set_focus_on_map (GtkWindow *window, gboolean gtk_window_get_focus_on_map (GtkWindow *window) { - GtkWindowPrivate *priv; - g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); - - priv = GTK_WINDOW_GET_PRIVATE (window); - return priv->focus_on_map; + return window->priv->focus_on_map; } /** @@ -2760,12 +2941,16 @@ void gtk_window_set_destroy_with_parent (GtkWindow *window, gboolean setting) { + GtkWindowPrivate *priv; + g_return_if_fail (GTK_IS_WINDOW (window)); - if (window->destroy_with_parent == (setting != FALSE)) + priv = window->priv; + + if (priv->destroy_with_parent == (setting != FALSE)) return; - if (window->destroy_with_parent) + if (priv->destroy_with_parent) { disconnect_parent_destroyed (window); } @@ -2773,8 +2958,8 @@ gtk_window_set_destroy_with_parent (GtkWindow *window, { connect_parent_destroyed (window); } - - window->destroy_with_parent = setting; + + priv->destroy_with_parent = setting; g_object_notify (G_OBJECT (window), "destroy-with-parent"); } @@ -2793,16 +2978,17 @@ gtk_window_get_destroy_with_parent (GtkWindow *window) { g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); - return window->destroy_with_parent; + return window->priv->destroy_with_parent; } static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window, gboolean create) { + GtkWindowPrivate *priv = window->priv; GtkWindowGeometryInfo *info; - info = window->geometry_info; + info = priv->geometry_info; if (!info && create) { info = g_new0 (GtkWindowGeometryInfo, 1); @@ -2822,7 +3008,7 @@ gtk_window_get_geometry_info (GtkWindow *window, info->last.configure_request.height = -1; info->widget = NULL; info->mask = 0; - window->geometry_info = info; + priv->geometry_info = info; } return info; @@ -2868,14 +3054,14 @@ gtk_window_set_geometry_hints (GtkWindow *window, if (geometry) info->geometry = *geometry; - /* We store gravity in window->gravity not in the hints. */ + /* We store gravity in priv->gravity not in the hints. */ info->mask = geom_mask & ~(GDK_HINT_WIN_GRAVITY); if (geom_mask & GDK_HINT_WIN_GRAVITY) { gtk_window_set_gravity (window, geometry->win_gravity); } - + gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window)); } @@ -2891,7 +3077,7 @@ gtk_window_set_geometry_hints (GtkWindow *window, * using this function, GTK+ will do its best to convince 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(). + * 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. @@ -2901,21 +3087,24 @@ void gtk_window_set_decorated (GtkWindow *window, gboolean setting) { + GtkWindowPrivate *priv; GdkWindow *gdk_window; g_return_if_fail (GTK_IS_WINDOW (window)); + priv = window->priv; + setting = setting != FALSE; - if (setting == window->decorated) + if (setting == priv->decorated) return; - window->decorated = setting; + priv->decorated = setting; gdk_window = gtk_widget_get_window (GTK_WIDGET (window)); if (gdk_window) { - if (window->decorated) + if (priv->decorated) gdk_window_set_decorations (gdk_window, GDK_DECOR_ALL); else @@ -2940,7 +3129,7 @@ gtk_window_get_decorated (GtkWindow *window) { g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE); - return window->decorated; + return window->priv->decorated; } /** @@ -2970,7 +3159,7 @@ gtk_window_set_deletable (GtkWindow *window, g_return_if_fail (GTK_IS_WINDOW (window)); - priv = GTK_WINDOW_GET_PRIVATE (window); + priv = window->priv; setting = setting != FALSE; @@ -3007,13 +3196,9 @@ gtk_window_set_deletable (GtkWindow *window, gboolean gtk_window_get_deletable (GtkWindow *window) { - GtkWindowPrivate *priv; - g_return_val_if_fail (GTK_IS_WINDOW (window), TRUE); - priv = GTK_WINDOW_GET_PRIVATE (window); - - return priv->deletable; + return window->priv->deletable; } static GtkWindowIconInfo* @@ -3049,157 +3234,6 @@ ensure_icon_info (GtkWindow *window) return info; } -typedef struct { - guint serial; - GdkPixmap *pixmap; - GdkPixmap *mask; -} ScreenIconInfo; - -static ScreenIconInfo * -get_screen_icon_info (GdkScreen *screen) -{ - ScreenIconInfo *info = g_object_get_qdata (G_OBJECT (screen), - quark_gtk_window_default_icon_pixmap); - if (!info) - { - info = g_slice_new0 (ScreenIconInfo); - g_object_set_qdata (G_OBJECT (screen), - quark_gtk_window_default_icon_pixmap, info); - } - - if (info->serial != default_icon_serial) - { - if (info->pixmap) - { - g_object_remove_weak_pointer (G_OBJECT (info->pixmap), (gpointer*)&info->pixmap); - info->pixmap = NULL; - } - - if (info->mask) - { - g_object_remove_weak_pointer (G_OBJECT (info->mask), (gpointer*)&info->mask); - info->mask = NULL; - } - - info->serial = default_icon_serial; - } - - return info; -} - -static void -get_pixmap_and_mask (GdkWindow *window, - GtkWindowIconInfo *parent_info, - gboolean is_default_list, - GList *icon_list, - GdkPixmap **pmap_return, - GdkBitmap **mask_return) -{ - GdkScreen *screen = gdk_drawable_get_screen (window); - ScreenIconInfo *default_icon_info = get_screen_icon_info (screen); - GdkPixbuf *best_icon; - GList *tmp_list; - int best_size; - - *pmap_return = NULL; - *mask_return = NULL; - - if (is_default_list && - default_icon_info->pixmap != NULL) - { - /* Use shared icon pixmap for all windows on this screen. - */ - if (default_icon_info->pixmap) - g_object_ref (default_icon_info->pixmap); - if (default_icon_info->mask) - g_object_ref (default_icon_info->mask); - - *pmap_return = default_icon_info->pixmap; - *mask_return = default_icon_info->mask; - } - else if (parent_info && parent_info->icon_pixmap) - { - if (parent_info->icon_pixmap) - g_object_ref (parent_info->icon_pixmap); - if (parent_info->icon_mask) - g_object_ref (parent_info->icon_mask); - - *pmap_return = parent_info->icon_pixmap; - *mask_return = parent_info->icon_mask; - } - else - { -#define IDEAL_SIZE 48 - - best_size = G_MAXINT; - best_icon = NULL; - tmp_list = icon_list; - while (tmp_list != NULL) - { - GdkPixbuf *pixbuf = tmp_list->data; - int this; - - /* average width and height - if someone passes in a rectangular - * icon they deserve what they get. - */ - this = gdk_pixbuf_get_width (pixbuf) + gdk_pixbuf_get_height (pixbuf); - this /= 2; - - if (best_icon == NULL) - { - best_icon = pixbuf; - best_size = this; - } - else - { - /* icon is better if it's 32 pixels or larger, and closer to - * the ideal size than the current best. - */ - if (this >= 32 && - (ABS (best_size - IDEAL_SIZE) < - ABS (this - IDEAL_SIZE))) - { - best_icon = pixbuf; - best_size = this; - } - } - - tmp_list = tmp_list->next; - } - - if (best_icon) - gdk_pixbuf_render_pixmap_and_mask_for_colormap (best_icon, - gdk_screen_get_system_colormap (screen), - pmap_return, - mask_return, - 128); - - /* Save pmap/mask for others to use if appropriate */ - if (parent_info) - { - parent_info->icon_pixmap = *pmap_return; - parent_info->icon_mask = *mask_return; - - if (parent_info->icon_pixmap) - g_object_ref (parent_info->icon_pixmap); - if (parent_info->icon_mask) - g_object_ref (parent_info->icon_mask); - } - else if (is_default_list) - { - default_icon_info->pixmap = *pmap_return; - default_icon_info->mask = *mask_return; - - if (default_icon_info->pixmap) - g_object_add_weak_pointer (G_OBJECT (default_icon_info->pixmap), - (gpointer*)&default_icon_info->pixmap); - if (default_icon_info->mask) - g_object_add_weak_pointer (G_OBJECT (default_icon_info->mask), - (gpointer*)&default_icon_info->mask); - } - } -} - static GList * icon_list_from_theme (GtkWidget *widget, const gchar *name) @@ -3242,6 +3276,7 @@ icon_list_from_theme (GtkWidget *widget, static void gtk_window_realize_icon (GtkWindow *window) { + GtkWindowPrivate *priv = window->priv; GtkWidget *widget; GtkWindowIconInfo *info; GdkWindow *gdk_window; @@ -3253,7 +3288,7 @@ gtk_window_realize_icon (GtkWindow *window) g_return_if_fail (gdk_window != NULL); /* no point setting an icon on override-redirect */ - if (window->type == GTK_WINDOW_POPUP) + if (priv->type == GTK_WINDOW_POPUP) return; icon_list = NULL; @@ -3263,9 +3298,6 @@ gtk_window_realize_icon (GtkWindow *window) if (info->realized) return; - g_return_if_fail (info->icon_pixmap == NULL); - g_return_if_fail (info->icon_mask == NULL); - info->using_default_icon = FALSE; info->using_parent_icon = FALSE; info->using_themed_icon = FALSE; @@ -3281,9 +3313,9 @@ gtk_window_realize_icon (GtkWindow *window) } /* Inherit from transient parent */ - if (icon_list == NULL && window->transient_parent) + if (icon_list == NULL && priv->transient_parent) { - icon_list = ensure_icon_info (window->transient_parent)->icon_list; + icon_list = ensure_icon_info (priv->transient_parent)->icon_list; if (icon_list) info->using_parent_icon = TRUE; } @@ -3304,24 +3336,9 @@ gtk_window_realize_icon (GtkWindow *window) info->using_themed_icon = TRUE; } - gdk_window_set_icon_list (gdk_window, icon_list); - - get_pixmap_and_mask (gdk_window, - info->using_parent_icon ? ensure_icon_info (window->transient_parent) : NULL, - info->using_default_icon, - icon_list, - &info->icon_pixmap, - &info->icon_mask); - - /* This is a slight ICCCM violation since it's a color pixmap not - * a bitmap, but everyone does it. - */ - gdk_window_set_icon (gdk_window, - NULL, - info->icon_pixmap, - info->icon_mask); - info->realized = TRUE; + + gdk_window_set_icon_list (gtk_widget_get_window (widget), icon_list); if (info->using_themed_icon) { @@ -3346,15 +3363,6 @@ gtk_window_unrealize_icon (GtkWindow *window) if (info == NULL) return; - if (info->icon_pixmap) - g_object_unref (info->icon_pixmap); - - if (info->icon_mask) - g_object_unref (info->icon_mask); - - info->icon_pixmap = NULL; - info->icon_mask = NULL; - if (info->using_themed_icon) { GtkIconTheme *icon_theme; @@ -3375,7 +3383,7 @@ gtk_window_unrealize_icon (GtkWindow *window) /** * gtk_window_set_icon_list: * @window: a #GtkWindow - * @list: (element-type GdkPixbuf) (transfer container): list of #GdkPixbuf + * @list: (element-type GdkPixbuf): list of #GdkPixbuf * * Sets up the icon representing a #GtkWindow. The icon is used when * the window is minimized (also known as iconified). Some window @@ -3635,7 +3643,7 @@ load_pixbuf_verbosely (const char *filename, /** * gtk_window_set_icon_from_file: * @window: a #GtkWindow - * @filename: location of icon file + * @filename: (type filename): location of icon file * @err: (allow-none): location to store error, or %NULL. * * Sets the icon for @window. @@ -3813,7 +3821,7 @@ gtk_window_get_default_icon_name (void) /** * gtk_window_set_default_icon_from_file: - * @filename: location of icon file + * @filename: (type filename): location of icon file * @err: (allow-none): location to store error, or %NULL. * * Sets an icon to be used as fallback for windows that haven't @@ -3954,6 +3962,30 @@ gtk_window_set_default_size (GtkWindow *window, gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, FALSE); } +/** + * gtk_window_set_default_geometry: + * @window: a #GtkWindow + * @width: width in resize increments, or -1 to unset the default width + * @height: height in resize increments, or -1 to unset the default height + * + * Like gtk_window_set_default_size(), but @width and @height are interpreted + * in terms of the base size and increment set with + * gtk_window_set_geometry_hints. + * + * Since: 3.0 + */ +void +gtk_window_set_default_geometry (GtkWindow *window, + gint width, + gint height) +{ + g_return_if_fail (GTK_IS_WINDOW (window)); + g_return_if_fail (width >= -1); + g_return_if_fail (height >= -1); + + gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height, TRUE); +} + /** * gtk_window_get_default_size: * @window: a #GtkWindow @@ -4018,6 +4050,39 @@ gtk_window_resize (GtkWindow *window, info->resize_width = width; info->resize_height = height; + info->resize_is_geometry = FALSE; + + gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window)); +} + +/** + * gtk_window_resize_to_geometry: + * @window: a #GtkWindow + * @width: width in resize increments to resize the window to + * @height: height in resize increments to resize the window to + * + * Like gtk_window_resize(), but @width and @height are interpreted + * in terms of the base size and increment set with + * gtk_window_set_geometry_hints. + * + * Since: 3.0 + */ +void +gtk_window_resize_to_geometry (GtkWindow *window, + gint width, + gint height) +{ + GtkWindowGeometryInfo *info; + + g_return_if_fail (GTK_IS_WINDOW (window)); + g_return_if_fail (width > 0); + g_return_if_fail (height > 0); + + info = gtk_window_get_geometry_info (window, TRUE); + + info->resize_width = width; + info->resize_height = height; + info->resize_is_geometry = TRUE; gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window)); } @@ -4088,8 +4153,8 @@ gtk_window_get_size (GtkWindow *window, if (gtk_widget_get_mapped (GTK_WIDGET (window))) { - gdk_drawable_get_size (gtk_widget_get_window (GTK_WIDGET (window)), - &w, &h); + w = gdk_window_get_width (gtk_widget_get_window (GTK_WIDGET (window))); + h = gdk_window_get_height (gtk_widget_get_window (GTK_WIDGET (window))); } else { @@ -4144,9 +4209,9 @@ gtk_window_get_size (GtkWindow *window, * gdk_screen_height () - window_height) (note that this * example does not take multi-head scenarios into account). * - * The Extended Window Manager Hints specification at - * http://www.freedesktop.org/Standards/wm-spec has a + * http://www.freedesktop.org/Standards/wm-spec has a * nice table of gravities in the "implementation notes" section. * * The gtk_window_get_position() documentation may also be relevant. @@ -4158,13 +4223,13 @@ gtk_window_move (GtkWindow *window, { GtkWindowGeometryInfo *info; GtkWidget *widget; - + g_return_if_fail (GTK_IS_WINDOW (window)); widget = GTK_WIDGET (window); info = gtk_window_get_geometry_info (window, TRUE); - + if (gtk_widget_get_mapped (widget)) { GtkAllocation allocation; @@ -4187,7 +4252,7 @@ gtk_window_move (GtkWindow *window, gtk_window_constrain_position (window, allocation.width, allocation.height, &x, &y); - + /* Note that this request doesn't go through our standard request * framework, e.g. doesn't increment configure_request_count, * doesn't set info->last, etc.; that's because @@ -4198,15 +4263,7 @@ gtk_window_move (GtkWindow *window, * the same as the position being changed by the window * manager. */ - - /* FIXME are we handling gravity properly for framed windows? */ - if (window->frame) - gdk_window_move (window->frame, - x - window->frame_left, - y - window->frame_top); - else - gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), - x, y); + gdk_window_move (gtk_widget_get_window (GTK_WIDGET (window)), x, y); } else { @@ -4267,15 +4324,17 @@ gtk_window_get_position (GtkWindow *window, gint *root_x, gint *root_y) { + GtkWindowPrivate *priv; GtkWidget *widget; GdkWindow *gdk_window; g_return_if_fail (GTK_IS_WINDOW (window)); + priv = window->priv; widget = GTK_WIDGET (window); gdk_window = gtk_widget_get_window (widget); - if (window->gravity == GDK_GRAVITY_STATIC) + if (priv->gravity == GDK_GRAVITY_STATIC) { if (gtk_widget_get_mapped (widget)) { @@ -4309,10 +4368,7 @@ gtk_window_get_position (GtkWindow *window, if (gtk_widget_get_mapped (widget)) { - if (window->frame) - gdk_window_get_frame_extents (window->frame, &frame_extents); - else - gdk_window_get_frame_extents (gdk_window, &frame_extents); + gdk_window_get_frame_extents (gdk_window, &frame_extents); x = frame_extents.x; y = frame_extents.y; gtk_window_get_size (window, &w, &h); @@ -4321,7 +4377,7 @@ gtk_window_get_position (GtkWindow *window, { /* We just say the frame has 0 size on all sides. * Not sure what else to do. - */ + */ gtk_window_compute_configure_request (window, &frame_extents, NULL, NULL); @@ -4331,7 +4387,7 @@ gtk_window_get_position (GtkWindow *window, h = frame_extents.height; } - switch (window->gravity) + switch (priv->gravity) { case GDK_GRAVITY_NORTH: case GDK_GRAVITY_CENTER: @@ -4354,7 +4410,7 @@ gtk_window_get_position (GtkWindow *window, break; } - switch (window->gravity) + switch (priv->gravity) { case GDK_GRAVITY_WEST: case GDK_GRAVITY_CENTER: @@ -4406,65 +4462,69 @@ gtk_window_reshow_with_initial_size (GtkWindow *window) } static void -gtk_window_destroy (GtkObject *object) +gtk_window_destroy (GtkWidget *widget) { - GtkWindow *window = GTK_WINDOW (object); - + GtkWindow *window = GTK_WINDOW (widget); + GtkWindowPrivate *priv = window->priv; + + gtk_window_release_application (window); + toplevel_list = g_slist_remove (toplevel_list, window); - if (window->transient_parent) + if (priv->transient_parent) gtk_window_set_transient_for (window, NULL); /* frees the icons */ gtk_window_set_icon_list (window, NULL); - - if (window->has_user_ref_count) + + if (priv->has_user_ref_count) { - window->has_user_ref_count = FALSE; + priv->has_user_ref_count = FALSE; g_object_unref (window); } - if (window->group) - gtk_window_group_remove_window (window->group, window); + if (priv->group) + gtk_window_group_remove_window (priv->group, window); gtk_window_free_key_hash (window); - GTK_OBJECT_CLASS (gtk_window_parent_class)->destroy (object); + GTK_WIDGET_CLASS (gtk_window_parent_class)->destroy (widget); } static void gtk_window_finalize (GObject *object) { GtkWindow *window = GTK_WINDOW (object); - GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window); + GtkWindowPrivate *priv = window->priv; GtkMnemonicHash *mnemonic_hash; - g_free (window->title); - g_free (window->wmclass_name); - g_free (window->wmclass_class); - g_free (window->wm_role); + g_free (priv->title); + g_free (priv->wmclass_name); + g_free (priv->wmclass_class); + g_free (priv->wm_role); + gtk_window_release_application (window); mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE); if (mnemonic_hash) _gtk_mnemonic_hash_free (mnemonic_hash); - if (window->geometry_info) + if (priv->geometry_info) { - if (window->geometry_info->widget) - g_signal_handlers_disconnect_by_func (window->geometry_info->widget, + if (priv->geometry_info->widget) + g_signal_handlers_disconnect_by_func (priv->geometry_info->widget, gtk_widget_destroyed, - &window->geometry_info->widget); - g_free (window->geometry_info); + &priv->geometry_info->widget); + g_free (priv->geometry_info); } - if (window->keys_changed_handler) + if (priv->keys_changed_handler) { - g_source_remove (window->keys_changed_handler); - window->keys_changed_handler = 0; + g_source_remove (priv->keys_changed_handler); + priv->keys_changed_handler = 0; } - if (window->screen) - g_signal_handlers_disconnect_by_func (window->screen, + if (priv->screen) + g_signal_handlers_disconnect_by_func (priv->screen, gtk_window_on_composited_changed, window); g_free (priv->startup_id); @@ -4476,10 +4536,18 @@ static void gtk_window_show (GtkWidget *widget) { GtkWindow *window = GTK_WINDOW (widget); + GtkWindowPrivate *priv = window->priv; GtkContainer *container = GTK_CONTAINER (window); gboolean need_resize; + gboolean is_plug; + + if (!gtk_widget_is_toplevel (GTK_WIDGET (widget))) + { + GTK_WIDGET_CLASS (gtk_window_parent_class)->show (widget); + return; + } - GTK_WIDGET_SET_FLAGS (widget, GTK_VISIBLE); + _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); @@ -4525,11 +4593,6 @@ gtk_window_show (GtkWidget *widget) was_realized = TRUE; } - /* Must be done after the windows are realized, - * so that the decorations can be read - */ - gtk_decorated_window_calculate_frame_size (window); - /* We only send configure request if we didn't just finish * creating the window; if we just created the window * then we created it with widget->allocation anyhow. @@ -4548,10 +4611,15 @@ gtk_window_show (GtkWidget *widget) /* Try to make sure that we have some focused widget */ - if (!window->focus_widget && !GTK_IS_PLUG (window)) - gtk_window_move_focus (window, GTK_DIR_TAB_FORWARD); +#ifdef GDK_WINDOWING_X11 + is_plug = GTK_IS_PLUG (window); +#else + is_plug = FALSE; +#endif + if (!priv->focus_widget && !is_plug) + gtk_window_move_focus (widget, GTK_DIR_TAB_FORWARD); - if (window->modal) + if (priv->modal) gtk_grab_add (widget); } @@ -4559,11 +4627,18 @@ static void gtk_window_hide (GtkWidget *widget) { GtkWindow *window = GTK_WINDOW (widget); + GtkWindowPrivate *priv = window->priv; + + if (!gtk_widget_is_toplevel (GTK_WIDGET (widget))) + { + GTK_WIDGET_CLASS (gtk_window_parent_class)->hide (widget); + return; + } - GTK_WIDGET_UNSET_FLAGS (widget, GTK_VISIBLE); + _gtk_widget_set_visible_flag (widget, FALSE); gtk_widget_unmap (widget); - if (window->modal) + if (priv->modal) gtk_grab_remove (widget); } @@ -4572,13 +4647,19 @@ gtk_window_map (GtkWidget *widget) { GtkWidget *child; GtkWindow *window = GTK_WINDOW (widget); - GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (window); + GtkWindowPrivate *priv = window->priv; GdkWindow *toplevel; GdkWindow *gdk_window; gboolean auto_mnemonics; gdk_window = gtk_widget_get_window (widget); + if (!gtk_widget_is_toplevel (GTK_WIDGET (widget))) + { + GTK_WIDGET_CLASS (gtk_window_parent_class)->map (widget); + return; + } + gtk_widget_set_mapped (widget, TRUE); child = gtk_bin_get_child (&(window->bin)); @@ -4587,22 +4668,19 @@ gtk_window_map (GtkWidget *widget) !gtk_widget_get_mapped (child)) gtk_widget_map (child); - if (window->frame) - toplevel = window->frame; - else - toplevel = gdk_window; + toplevel = gdk_window; - if (window->maximize_initially) + if (priv->maximize_initially) gdk_window_maximize (toplevel); else gdk_window_unmaximize (toplevel); - if (window->stick_initially) + if (priv->stick_initially) gdk_window_stick (toplevel); else gdk_window_unstick (toplevel); - if (window->iconify_initially) + if (priv->iconify_initially) gdk_window_iconify (toplevel); else gdk_window_deiconify (toplevel); @@ -4617,8 +4695,8 @@ gtk_window_map (GtkWidget *widget) gdk_window_set_keep_below (toplevel, priv->below_initially); /* No longer use the default settings */ - window->need_default_size = FALSE; - window->need_default_position = FALSE; + priv->need_default_size = FALSE; + priv->need_default_position = FALSE; if (priv->reset_type_hint) { @@ -4633,8 +4711,8 @@ gtk_window_map (GtkWidget *widget) gdk_window_show (gdk_window); - if (window->frame) - gdk_window_show (window->frame); + if (priv->grip_window) + gdk_window_show (priv->grip_window); if (!disable_startup_notification) { @@ -4686,27 +4764,31 @@ static void gtk_window_unmap (GtkWidget *widget) { GtkWindow *window = GTK_WINDOW (widget); - GtkWindowPrivate *priv = GTK_WINDOW_GET_PRIVATE (widget); - GtkWindowGeometryInfo *info; + GtkWindowPrivate *priv = window->priv; + GtkWidget *child; + GtkWindowGeometryInfo *info; GdkWindow *gdk_window; GdkWindowState state; + if (!gtk_widget_is_toplevel (GTK_WIDGET (widget))) + { + GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget); + return; + } + gdk_window = gtk_widget_get_window (widget); gtk_widget_set_mapped (widget, FALSE); - if (window->frame) - gdk_window_withdraw (window->frame); - else - gdk_window_withdraw (gdk_window); + gdk_window_withdraw (gdk_window); - window->configure_request_count = 0; - window->configure_notify_received = FALSE; + priv->configure_request_count = 0; + priv->configure_notify_received = FALSE; /* on unmap, we reset the default positioning of the window, * so it's placed again, but we don't reset the default * size of the window, so it's remembered. */ - window->need_default_position = TRUE; + priv->need_default_position = TRUE; info = gtk_window_get_geometry_info (window, FALSE); if (info) @@ -4716,11 +4798,15 @@ gtk_window_unmap (GtkWidget *widget) } state = gdk_window_get_state (gdk_window); - window->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0; - window->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0; - window->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0; + priv->iconify_initially = (state & GDK_WINDOW_STATE_ICONIFIED) != 0; + priv->maximize_initially = (state & GDK_WINDOW_STATE_MAXIMIZED) != 0; + priv->stick_initially = (state & GDK_WINDOW_STATE_STICKY) != 0; priv->above_initially = (state & GDK_WINDOW_STATE_ABOVE) != 0; priv->below_initially = (state & GDK_WINDOW_STATE_BELOW) != 0; + + child = gtk_bin_get_child (&(window->bin)); + if (child) + gtk_widget_unmap (child); } static void @@ -4728,18 +4814,50 @@ gtk_window_realize (GtkWidget *widget) { GtkAllocation allocation; GtkWindow *window; - GtkStyle *style; GdkWindow *parent_window; GdkWindow *gdk_window; GdkWindowAttr attributes; gint attributes_mask; GtkWindowPrivate *priv; - + GtkStyleContext *context; + window = GTK_WINDOW (widget); - priv = GTK_WINDOW_GET_PRIVATE (window); + priv = window->priv; gtk_widget_get_allocation (widget, &allocation); + if (gtk_widget_get_parent_window (widget)) + { + gtk_container_set_resize_mode (GTK_CONTAINER (widget), GTK_RESIZE_PARENT); + + gtk_widget_set_realized (widget, TRUE); + + attributes.x = allocation.x; + attributes.y = allocation.y; + attributes.width = allocation.width; + attributes.height = allocation.height; + attributes.window_type = GDK_WINDOW_CHILD; + + attributes.event_mask = gtk_widget_get_events (widget) | GDK_EXPOSURE_MASK | GDK_STRUCTURE_MASK; + + attributes.visual = gtk_widget_get_visual (widget); + attributes.wclass = GDK_INPUT_OUTPUT; + + attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL; + + 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_style_context_set_background (gtk_widget_get_style_context (widget), gdk_window); + + gdk_window_enable_synchronized_configure (gdk_window); + return; + } + + gtk_container_set_resize_mode (GTK_CONTAINER (window), GTK_RESIZE_QUEUE); + /* ensure widget tree is properly size allocated */ if (allocation.x == -1 && allocation.y == -1 && @@ -4747,9 +4865,13 @@ gtk_window_realize (GtkWidget *widget) allocation.height == 1) { GtkRequisition requisition; - GtkAllocation allocation = { 0, 0, 200, 200 }; - gtk_widget_size_request (widget, &requisition); + allocation.x = 0; + allocation.y = 0; + allocation.width = 200; + allocation.height = 200; + + gtk_widget_get_preferred_size (widget, &requisition, NULL); if (requisition.width || requisition.height) { /* non-empty window */ @@ -4765,7 +4887,7 @@ gtk_window_realize (GtkWidget *widget) gtk_widget_set_realized (widget, TRUE); - switch (window->type) + switch (priv->type) { case GTK_WINDOW_TOPLEVEL: attributes.window_type = GDK_WINDOW_TOPLEVEL; @@ -4774,61 +4896,18 @@ gtk_window_realize (GtkWidget *widget) attributes.window_type = GDK_WINDOW_TEMP; break; default: - g_warning (G_STRLOC": Unknown window type %d!", window->type); + g_warning (G_STRLOC": Unknown window type %d!", priv->type); break; } - - attributes.title = window->title; - attributes.wmclass_name = window->wmclass_name; - attributes.wmclass_class = window->wmclass_class; + + attributes.title = priv->title; + attributes.wmclass_name = priv->wmclass_name; + attributes.wmclass_class = priv->wmclass_class; attributes.wclass = GDK_INPUT_OUTPUT; attributes.visual = gtk_widget_get_visual (widget); - attributes.colormap = gtk_widget_get_colormap (widget); - - if (window->has_frame) - { - gtk_widget_get_allocation (widget, &allocation); - attributes.width = allocation.width + window->frame_left + window->frame_right; - attributes.height = allocation.height + window->frame_top + window->frame_bottom; - attributes.event_mask = (GDK_EXPOSURE_MASK | - GDK_KEY_PRESS_MASK | - GDK_ENTER_NOTIFY_MASK | - GDK_LEAVE_NOTIFY_MASK | - GDK_FOCUS_CHANGE_MASK | - GDK_STRUCTURE_MASK | - GDK_BUTTON_MOTION_MASK | - GDK_POINTER_MOTION_HINT_MASK | - GDK_BUTTON_PRESS_MASK | - GDK_BUTTON_RELEASE_MASK); - - attributes_mask = GDK_WA_VISUAL | GDK_WA_COLORMAP; - - window->frame = gdk_window_new (gtk_widget_get_root_window (widget), - &attributes, attributes_mask); - - if (priv->opacity_set) - gdk_window_set_opacity (window->frame, priv->opacity); - - gdk_window_set_user_data (window->frame, widget); - - attributes.window_type = GDK_WINDOW_CHILD; - attributes.x = window->frame_left; - attributes.y = window->frame_top; - - attributes_mask = GDK_WA_X | GDK_WA_Y; - parent_window = window->frame; - - g_signal_connect (window, - "event", - G_CALLBACK (gtk_window_event), - NULL); - } - else - { - attributes_mask = 0; - parent_window = gtk_widget_get_root_window (widget); - } + attributes_mask = 0; + parent_window = gtk_widget_get_root_window (widget); gtk_widget_get_allocation (widget, &allocation); attributes.width = allocation.width; @@ -4843,94 +4922,91 @@ gtk_window_realize (GtkWidget *widget) GDK_STRUCTURE_MASK); attributes.type_hint = priv->type_hint; - attributes_mask |= GDK_WA_VISUAL | GDK_WA_COLORMAP | GDK_WA_TYPE_HINT; - attributes_mask |= (window->title ? GDK_WA_TITLE : 0); - attributes_mask |= (window->wmclass_name ? GDK_WA_WMCLASS : 0); + attributes_mask |= GDK_WA_VISUAL | GDK_WA_TYPE_HINT; + attributes_mask |= (priv->title ? GDK_WA_TITLE : 0); + attributes_mask |= (priv->wmclass_name ? GDK_WA_WMCLASS : 0); gdk_window = gdk_window_new (parent_window, &attributes, attributes_mask); gtk_widget_set_window (widget, gdk_window); - if (!window->has_frame && priv->opacity_set) + 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_style_attach (widget); - style = gtk_widget_get_style (widget); - gtk_style_set_background (style, gdk_window, GTK_STATE_NORMAL); - if (window->frame) - gtk_style_set_background (style, window->frame, GTK_STATE_NORMAL); + context = gtk_widget_get_style_context (widget); + gtk_style_context_set_background (context, gdk_window); - /* This is a bad hack to set the window background. */ - gtk_window_paint (widget, NULL); - - if (window->transient_parent && - gtk_widget_get_realized (GTK_WIDGET (window->transient_parent))) - gdk_window_set_transient_for (gdk_window, - gtk_widget_get_window (GTK_WIDGET (window->transient_parent))); - if (window->wm_role) - gdk_window_set_role (gdk_window, window->wm_role); + if (priv->transient_parent && + gtk_widget_get_realized (GTK_WIDGET (priv->transient_parent))) + gdk_window_set_transient_for (gdk_window, + gtk_widget_get_window (GTK_WIDGET (priv->transient_parent))); - if (!window->decorated) + if (priv->wm_role) + gdk_window_set_role (gdk_window, priv->wm_role); + + if (!priv->decorated) gdk_window_set_decorations (gdk_window, 0); - + if (!priv->deletable) gdk_window_set_functions (gdk_window, GDK_FUNC_ALL | GDK_FUNC_CLOSE); - + if (gtk_window_get_skip_pager_hint (window)) gdk_window_set_skip_pager_hint (gdk_window, TRUE); - + if (gtk_window_get_skip_taskbar_hint (window)) gdk_window_set_skip_taskbar_hint (gdk_window, TRUE); - + if (gtk_window_get_accept_focus (window)) gdk_window_set_accept_focus (gdk_window, TRUE); else gdk_window_set_accept_focus (gdk_window, FALSE); - + if (gtk_window_get_focus_on_map (window)) gdk_window_set_focus_on_map (gdk_window, TRUE); else gdk_window_set_focus_on_map (gdk_window, FALSE); - - if (window->modal) + + if (priv->modal) gdk_window_set_modal_hint (gdk_window, TRUE); else gdk_window_set_modal_hint (gdk_window, FALSE); - + if (priv->startup_id) { #ifdef GDK_WINDOWING_X11 guint32 timestamp = extract_time_from_startup_id (priv->startup_id); if (timestamp != GDK_CURRENT_TIME) - gdk_x11_window_set_user_time (gdk_window, timestamp); + gdk_x11_window_set_user_time (gdk_window, timestamp); #endif if (!startup_id_is_fake (priv->startup_id)) - gdk_window_set_startup_id (gdk_window, priv->startup_id); + gdk_window_set_startup_id (gdk_window, priv->startup_id); } - + /* Icons */ gtk_window_realize_icon (window); + + if (priv->has_resize_grip) + resize_grip_create_window (window); } static void gtk_window_unrealize (GtkWidget *widget) { - GtkWindow *window; + GtkWindow *window = GTK_WINDOW (widget); + GtkWindowPrivate *priv = window->priv; GtkWindowGeometryInfo *info; - window = GTK_WINDOW (widget); - /* 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. * * Default positioning is reset on unmap, instead of unrealize. */ - window->need_default_size = TRUE; + priv->need_default_size = TRUE; info = gtk_window_get_geometry_info (window, FALSE); if (info) { @@ -4943,111 +5019,215 @@ gtk_window_unrealize (GtkWidget *widget) /* be sure we reset geom hints on re-realize */ info->last.flags = 0; } - - if (window->frame) - { - gdk_window_set_user_data (window->frame, NULL); - gdk_window_destroy (window->frame); - window->frame = NULL; - } /* Icons */ gtk_window_unrealize_icon (window); + if (priv->grip_window != NULL) + resize_grip_destroy_window (window); + GTK_WIDGET_CLASS (gtk_window_parent_class)->unrealize (widget); } -static void -gtk_window_size_allocate (GtkWidget *widget, - GtkAllocation *allocation) +static GtkJunctionSides +get_grip_junction (GtkWidget *widget) { - GtkWindow *window; - GtkAllocation child_allocation; - GtkWidget *child; - guint border_width; + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) + return GTK_JUNCTION_CORNER_BOTTOMRIGHT; + else + return GTK_JUNCTION_CORNER_BOTTOMLEFT; +} - window = GTK_WINDOW (widget); - gtk_widget_set_allocation (widget, allocation); +static gboolean +get_drag_edge (GtkWidget *widget, + GdkWindowEdge *edge) +{ + GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv; + gboolean hresizable; + gboolean vresizable; + GtkTextDirection dir; + GtkWindowGeometryInfo *info; - child = gtk_bin_get_child (&(window->bin)); - if (child && gtk_widget_get_visible (child)) + hresizable = TRUE; + vresizable = TRUE; + + info = priv->geometry_info; + if (info) { - 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); + GdkWindowHints flags = info->last.flags; + GdkGeometry *geometry = &info->last.geometry; - gtk_widget_size_allocate (child, &child_allocation); + if ((flags & GDK_HINT_MIN_SIZE) && (flags & GDK_HINT_MAX_SIZE)) + { + hresizable = geometry->min_width < geometry->max_width; + vresizable = geometry->min_height < geometry->max_height; + } } - if (gtk_widget_get_realized (widget) && window->frame) - { - gdk_window_resize (window->frame, - allocation->width + window->frame_left + window->frame_right, - allocation->height + window->frame_top + window->frame_bottom); - } + dir = gtk_widget_get_direction (widget); + + if (hresizable && vresizable) + *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_SOUTH_EAST : GDK_WINDOW_EDGE_SOUTH_WEST; + else if (hresizable) + *edge = dir == GTK_TEXT_DIR_LTR ? GDK_WINDOW_EDGE_EAST : GDK_WINDOW_EDGE_WEST; + else if (vresizable) + *edge = GDK_WINDOW_EDGE_SOUTH; + else + return FALSE; + + return TRUE; } -static gint -gtk_window_event (GtkWidget *widget, GdkEvent *event) +static void +set_grip_cursor (GtkWindow *window) { - GtkWindow *window; - gboolean return_val; + GtkWidget *widget = GTK_WIDGET (window); + GtkWindowPrivate *priv = window->priv; - window = GTK_WINDOW (widget); + if (priv->grip_window == NULL) + return; - if (window->frame && (event->any.window == window->frame)) + if (gtk_widget_is_sensitive (widget)) { - if ((event->type != GDK_KEY_PRESS) && - (event->type != GDK_KEY_RELEASE) && - (event->type != GDK_FOCUS_CHANGE)) - { - g_signal_stop_emission_by_name (widget, "event"); - return_val = FALSE; - g_signal_emit (widget, window_signals[FRAME_EVENT], 0, event, &return_val); - return TRUE; - } - else - { - g_object_unref (event->any.window); - event->any.window = g_object_ref (gtk_widget_get_window (widget)); - } + GdkWindowEdge edge; + GdkDisplay *display; + GdkCursorType cursor_type; + GdkCursor *cursor; + + cursor_type = GDK_LEFT_PTR; + + if (get_drag_edge (widget, &edge)) + { + switch (edge) + { + case GDK_WINDOW_EDGE_EAST: + cursor_type = GDK_RIGHT_SIDE; + break; + case GDK_WINDOW_EDGE_SOUTH_EAST: + cursor_type = GDK_BOTTOM_RIGHT_CORNER; + break; + case GDK_WINDOW_EDGE_SOUTH: + cursor_type = GDK_BOTTOM_SIDE; + break; + case GDK_WINDOW_EDGE_SOUTH_WEST: + cursor_type = GDK_BOTTOM_LEFT_CORNER; + break; + case GDK_WINDOW_EDGE_WEST: + cursor_type = GDK_LEFT_SIDE; + break; + default: ; + } + } + + display = gtk_widget_get_display (widget); + cursor = gdk_cursor_new_for_display (display, cursor_type); + gdk_window_set_cursor (priv->grip_window, cursor); + g_object_unref (cursor); } + else + gdk_window_set_cursor (priv->grip_window, NULL); +} - return FALSE; +static void +set_grip_shape (GtkWindow *window) +{ + GtkWindowPrivate *priv = window->priv; + cairo_region_t *region; + cairo_surface_t *surface; + cairo_t *cr; + double width, height; + + if (priv->grip_window == NULL) + return; + + width = gdk_window_get_width (priv->grip_window); + height = gdk_window_get_height (priv->grip_window); + surface = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height); + + cr = cairo_create (surface); + cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 0.0); + cairo_paint (cr); + cairo_set_source_rgba (cr, 0.0, 0.0, 0.0, 1.0); + if (get_grip_junction (GTK_WIDGET (window)) & GTK_JUNCTION_CORNER_BOTTOMRIGHT) + { + cairo_move_to (cr, width, 0.0); + cairo_line_to (cr, width, height); + cairo_line_to (cr, 0.0, height); + } + else + { + cairo_move_to (cr, 0.0, 0.0); + cairo_line_to (cr, width, height); + cairo_line_to (cr, 0.0, height); + } + cairo_close_path (cr); + cairo_fill (cr); + cairo_destroy (cr); + region = gdk_cairo_region_create_from_surface (surface); + cairo_surface_destroy (surface); + + gdk_window_shape_combine_region (priv->grip_window, region, 0, 0); + cairo_region_destroy (region); } -static gboolean -gtk_window_frame_event (GtkWindow *window, GdkEvent *event) +static void +set_grip_position (GtkWindow *window) { - GdkEventConfigure *configure_event; + GtkWindowPrivate *priv = window->priv; GdkRectangle rect; - switch (event->type) + if (priv->grip_window == NULL) + return; + + gtk_window_get_resize_grip_area (window, &rect); + gdk_window_raise (priv->grip_window); + gdk_window_move_resize (priv->grip_window, + rect.x, rect.y, + rect.width, rect.height); +} + +static void +gtk_window_size_allocate (GtkWidget *widget, + GtkAllocation *allocation) +{ + GtkWindow *window = GTK_WINDOW (widget); + GtkAllocation child_allocation; + GtkWidget *child; + guint border_width; + + gtk_widget_set_allocation (widget, allocation); + + if (gtk_widget_get_realized (widget)) { - case GDK_CONFIGURE: - configure_event = (GdkEventConfigure *)event; - - /* Invalidate the decorations */ - rect.x = 0; - rect.y = 0; - rect.width = configure_event->width; - rect.height = configure_event->height; - - gdk_window_invalidate_rect (window->frame, &rect, FALSE); + /* 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); + } + else + { + update_grip_visibility (window); + set_grip_position (window); + } + } - /* Pass on the (modified) configure event */ - configure_event->width -= window->frame_left + window->frame_right; - configure_event->height -= window->frame_top + window->frame_bottom; - return gtk_window_configure_event (GTK_WIDGET (window), configure_event); - break; - default: - break; + child = gtk_bin_get_child (&(window->bin)); + if (child && gtk_widget_get_visible (child)) + { + 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); + + gtk_widget_size_allocate (child, &child_allocation); } - return FALSE; } static gint @@ -5056,23 +5236,33 @@ gtk_window_configure_event (GtkWidget *widget, { GtkAllocation allocation; GtkWindow *window = GTK_WINDOW (widget); - gboolean expected_reply = window->configure_request_count > 0; + GtkWindowPrivate *priv = window->priv; + gboolean expected_reply = priv->configure_request_count > 0; + + if (!gtk_widget_is_toplevel (GTK_WIDGET (widget))) + { + if (GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event) + return GTK_WIDGET_CLASS (gtk_window_parent_class)->configure_event (widget, event); - /* window->configure_request_count incremented for each + gdk_window_configure_finished (gtk_widget_get_window (widget)); + return FALSE; + } + + /* priv->configure_request_count incremented for each * configure request, and decremented to a min of 0 for * each configure notify. * * All it means is that we know we will get at least - * window->configure_request_count more configure notifies. + * priv->configure_request_count more configure notifies. * We could get more configure notifies than that; some * of the configure notifies we get may be unrelated to * the configure requests. But we will get at least - * window->configure_request_count notifies. + * priv->configure_request_count notifies. */ - if (window->configure_request_count > 0) + if (priv->configure_request_count > 0) { - window->configure_request_count -= 1; + priv->configure_request_count -= 1; gdk_window_thaw_toplevel_updates_libgtk_only (gtk_widget_get_window (widget)); } @@ -5102,17 +5292,307 @@ gtk_window_configure_event (GtkWidget *widget, * */ - window->configure_notify_received = TRUE; + 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)); return TRUE; } +static gboolean +gtk_window_state_event (GtkWidget *widget, + GdkEventWindowState *event) +{ + update_grip_visibility (GTK_WINDOW (widget)); + + return FALSE; +} + +static void +gtk_window_direction_changed (GtkWidget *widget, + GtkTextDirection prev_dir) +{ + GtkWindow *window = GTK_WINDOW (widget); + + set_grip_cursor (window); + set_grip_position (window); + set_grip_shape (window); +} + +static void +gtk_window_state_changed (GtkWidget *widget, + GtkStateType previous_state) +{ + GtkWindow *window = GTK_WINDOW (widget); + + update_grip_visibility (window); +} + +static void +gtk_window_style_updated (GtkWidget *widget) +{ + GtkWindow *window = GTK_WINDOW (widget); + GtkWindowPrivate *priv = window->priv; + GdkRectangle rect; + + GTK_WIDGET_CLASS (gtk_window_parent_class)->style_updated (widget); + + if (priv->grip_window != NULL && gtk_window_get_resize_grip_area (window, &rect)) + { + gdk_window_move_resize (priv->grip_window, + rect.x, rect.y, + rect.width, rect.height); + + set_grip_shape (window); + gtk_widget_queue_resize (widget); + } +} + +static void +resize_grip_create_window (GtkWindow *window) +{ + GtkWidget *widget; + GtkWindowPrivate *priv; + GdkWindowAttr attributes; + gint attributes_mask; + GdkRectangle rect; + + priv = window->priv; + widget = GTK_WIDGET (window); + + g_return_if_fail (gtk_widget_get_realized (widget)); + g_return_if_fail (priv->grip_window == NULL); + + gtk_window_get_resize_grip_area (window, &rect); + + attributes.x = rect.x; + attributes.y = rect.y; + attributes.width = rect.width; + attributes.height = rect.height; + attributes.window_type = GDK_WINDOW_CHILD; + attributes.wclass = GDK_INPUT_OUTPUT; + attributes.event_mask = gtk_widget_get_events (widget) | + GDK_EXPOSURE_MASK | + GDK_BUTTON_PRESS_MASK; + + attributes_mask = GDK_WA_X | GDK_WA_Y; + + priv->grip_window = gdk_window_new (gtk_widget_get_window (widget), + &attributes, + attributes_mask); + + gdk_window_set_user_data (priv->grip_window, widget); + + gdk_window_raise (priv->grip_window); + + set_grip_shape (window); + update_grip_visibility (window); +} + +static void +resize_grip_destroy_window (GtkWindow *window) +{ + GtkWindowPrivate *priv = window->priv; + + gdk_window_set_user_data (priv->grip_window, NULL); + gdk_window_destroy (priv->grip_window); + priv->grip_window = NULL; + update_grip_visibility (window); +} + +/** + * gtk_window_set_has_resize_grip: + * @window: a #GtkWindow + * @value: %TRUE to allow a resize grip + * + * Sets whether @window has a corner resize grip. + * + * Note that the resize grip is only shown if the window + * is actually resizable and not maximized. Use + * gtk_window_resize_grip_is_visible() to find out if the + * resize grip is currently shown. + * + * Since: 3.0 + */ +void +gtk_window_set_has_resize_grip (GtkWindow *window, + gboolean value) +{ + GtkWidget *widget = GTK_WIDGET (window); + GtkWindowPrivate *priv = window->priv; + + value = value != FALSE; + + if (value != priv->has_resize_grip) + { + priv->has_resize_grip = value; + gtk_widget_queue_draw (widget); + + if (gtk_widget_get_realized (widget) && + gtk_widget_is_toplevel (GTK_WIDGET (widget))) + { + if (priv->has_resize_grip && priv->grip_window == NULL) + resize_grip_create_window (window); + else if (!priv->has_resize_grip && priv->grip_window != NULL) + resize_grip_destroy_window (window); + } + + g_object_notify (G_OBJECT (window), "has-resize-grip"); + } +} + +static void +update_grip_visibility (GtkWindow *window) +{ + GtkWindowPrivate *priv = window->priv; + gboolean val; + + val = gtk_window_resize_grip_is_visible (window); + + if (priv->grip_window != NULL) + { + if (val) + { + gdk_window_show (priv->grip_window); + set_grip_cursor (window); + } + else + { + gdk_window_hide (priv->grip_window); + } + } + + if (priv->resize_grip_visible != val) + { + priv->resize_grip_visible = val; + + g_object_notify (G_OBJECT (window), "resize-grip-visible"); + } +} + +/** + * gtk_window_resize_grip_is_visible: + * @window: a #GtkWindow + * + * Determines whether a resize grip is visible for the specified window. + * + * Returns: %TRUE if a resize grip exists and is visible + * + * Since: 3.0 + */ +gboolean +gtk_window_resize_grip_is_visible (GtkWindow *window) +{ + GtkWidget *widget; + GtkWindowPrivate *priv; + GdkWindowEdge edge; + + g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); + + priv = window->priv; + widget = GTK_WIDGET (window); + + if (priv->type == GTK_WINDOW_POPUP) + return FALSE; + + if (!priv->resizable) + return FALSE; + + if (!gtk_widget_is_toplevel (GTK_WIDGET (widget))) + return FALSE; + + if (gtk_widget_get_realized (widget)) + { + GdkWindowState state; + + state = gdk_window_get_state (gtk_widget_get_window (widget)); + + if (state & GDK_WINDOW_STATE_MAXIMIZED || state & GDK_WINDOW_STATE_FULLSCREEN) + return FALSE; + } + + if (!get_drag_edge (widget, &edge)) + return FALSE; + + return window->priv->has_resize_grip; +} + +/** + * gtk_window_get_has_resize_grip: + * @window: a #GtkWindow + * + * Determines whether the window may have a resize grip. + * + * Returns: %TRUE if the window has a resize grip + * + * Since: 3.0 + */ +gboolean +gtk_window_get_has_resize_grip (GtkWindow *window) +{ + g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); + + return window->priv->has_resize_grip; +} + +/** + * gtk_window_get_resize_grip_area: + * @window: a #GtkWindow + * @rect: (out): a pointer to a #GdkRectangle which we should store + * the resize grip area + * + * If a window has a resize grip, this will retrieve the grip + * position, width and height into the specified #GdkRectangle. + * + * Returns: %TRUE if the resize grip's area was retrieved + * + * Since: 3.0 + */ +gboolean +gtk_window_get_resize_grip_area (GtkWindow *window, + GdkRectangle *rect) +{ + GtkWidget *widget = GTK_WIDGET (window); + GtkAllocation allocation; + gint grip_width; + gint grip_height; + + g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); + + if (!window->priv->has_resize_grip) + return FALSE; + + gtk_widget_get_allocation (widget, &allocation); + + gtk_widget_style_get (widget, + "resize-grip-width", &grip_width, + "resize-grip-height", &grip_height, + NULL); + + if (grip_width > allocation.width) + grip_width = allocation.width; + + if (grip_height > allocation.height) + grip_height = allocation.height; + + rect->width = grip_width; + rect->height = grip_height; + rect->y = allocation.y + allocation.height - grip_height; + + if (gtk_widget_get_direction (widget) == GTK_TEXT_DIR_LTR) + rect->x = allocation.x + allocation.width - grip_width; + else + rect->x = allocation.x; + + return TRUE; +} + /* the accel_key and accel_mods fields of the key have to be setup * upon calling this function. it'll then return whether that key * is at all used as accelerator, and if so will OR in the @@ -5123,8 +5603,12 @@ _gtk_window_query_nonaccels (GtkWindow *window, guint accel_key, GdkModifierType accel_mods) { + GtkWindowPrivate *priv; + g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); + priv = window->priv; + /* movement keys are considered locked accels */ if (!accel_mods) { @@ -5140,7 +5624,7 @@ _gtk_window_query_nonaccels (GtkWindow *window, } /* mnemonics are considered locked accels */ - if (accel_mods == window->mnemonic_modifier) + if (accel_mods == priv->mnemonic_modifier) { GtkMnemonicHash *mnemonic_hash = gtk_window_get_mnemonic_hash (window, FALSE); if (mnemonic_hash && _gtk_mnemonic_hash_lookup (mnemonic_hash, accel_key)) @@ -5170,13 +5654,16 @@ gboolean gtk_window_propagate_key_event (GtkWindow *window, GdkEventKey *event) { + GtkWindowPrivate *priv; gboolean handled = FALSE; GtkWidget *widget, *focus; g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); + priv = window->priv; widget = GTK_WIDGET (window); - focus = window->focus_widget; + + focus = priv->focus_widget; if (focus) g_object_ref (focus); @@ -5244,6 +5731,29 @@ gtk_window_key_release_event (GtkWidget *widget, return handled; } +static gint +gtk_window_button_press_event (GtkWidget *widget, + GdkEventButton *event) +{ + GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv; + GdkWindowEdge edge; + + if (event->window == priv->grip_window) + { + if (get_drag_edge (widget, &edge)) + gtk_window_begin_resize_drag (GTK_WINDOW (widget), + edge, + event->button, + event->x_root, + event->y_root, + event->time); + + return TRUE; + } + + return FALSE; +} + static void gtk_window_real_activate_default (GtkWindow *window) { @@ -5256,16 +5766,6 @@ gtk_window_real_activate_focus (GtkWindow *window) gtk_window_activate_focus (window); } -static void -gtk_window_move_focus (GtkWindow *window, - GtkDirectionType dir) -{ - gtk_widget_child_focus (GTK_WIDGET (window), dir); - - if (!gtk_container_get_focus_child (GTK_CONTAINER (window))) - gtk_window_set_focus (window, NULL); -} - static gint gtk_window_enter_notify_event (GtkWidget *widget, GdkEventCrossing *event) @@ -5300,7 +5800,7 @@ do_focus_change (GtkWidget *widget, GdkDevice *dev = d->data; GdkEvent *fevent; - if (dev->source != GDK_SOURCE_KEYBOARD) + if (gdk_device_get_source (dev) != GDK_SOURCE_KEYBOARD) continue; /* Skip non-master keyboards that haven't @@ -5368,66 +5868,14 @@ gtk_window_focus_out_event (GtkWidget *widget, return FALSE; } -static GdkAtom atom_rcfiles = GDK_NONE; -static GdkAtom atom_iconthemes = GDK_NONE; - -static void -send_client_message_to_embedded_windows (GtkWidget *widget, - GdkAtom message_type) -{ - GList *embedded_windows; - - embedded_windows = g_object_get_qdata (G_OBJECT (widget), quark_gtk_embedded); - if (embedded_windows) - { - GdkEvent *send_event = gdk_event_new (GDK_CLIENT_EVENT); - int i; - - for (i = 0; i < 5; i++) - send_event->client.data.l[i] = 0; - send_event->client.data_format = 32; - send_event->client.message_type = message_type; - - while (embedded_windows) - { - GdkNativeWindow xid = GDK_GPOINTER_TO_NATIVE_WINDOW(embedded_windows->data); - gdk_event_send_client_message_for_display (gtk_widget_get_display (widget), send_event, xid); - embedded_windows = embedded_windows->next; - } - - gdk_event_free (send_event); - } -} - -static gint -gtk_window_client_event (GtkWidget *widget, - GdkEventClient *event) -{ - if (!atom_rcfiles) - { - atom_rcfiles = gdk_atom_intern_static_string ("_GTK_READ_RCFILES"); - atom_iconthemes = gdk_atom_intern_static_string ("_GTK_LOAD_ICONTHEMES"); - } - - if (event->message_type == atom_rcfiles) - { - send_client_message_to_embedded_windows (widget, atom_rcfiles); - gtk_rc_reparse_all_for_settings (gtk_widget_get_settings (widget), FALSE); - } - - if (event->message_type == atom_iconthemes) - { - send_client_message_to_embedded_windows (widget, atom_iconthemes); - _gtk_icon_theme_check_reload (gtk_widget_get_display (widget)); - } - - return FALSE; -} - static void gtk_window_check_resize (GtkContainer *container) { - if (gtk_widget_get_visible (GTK_WIDGET (container))) + /* If the window is not toplevel anymore than it's embedded somewhere, + * so handle it like a normal window */ + if (!gtk_widget_is_toplevel (GTK_WIDGET (container))) + GTK_CONTAINER_CLASS (gtk_window_parent_class)->check_resize (container); + else if (gtk_widget_get_visible (GTK_WIDGET (container))) gtk_window_move_resize (GTK_WINDOW (container)); } @@ -5435,6 +5883,7 @@ static gboolean gtk_window_focus (GtkWidget *widget, GtkDirectionType direction) { + GtkWindowPrivate *priv; GtkBin *bin; GtkWindow *window; GtkContainer *container; @@ -5442,8 +5891,12 @@ gtk_window_focus (GtkWidget *widget, GtkWidget *old_focus_child; GtkWidget *parent; + if (!gtk_widget_is_toplevel (GTK_WIDGET (widget))) + return GTK_WIDGET_CLASS (gtk_window_parent_class)->focus (widget, direction); + container = GTK_CONTAINER (widget); window = GTK_WINDOW (widget); + priv = window->priv; bin = GTK_BIN (widget); old_focus_child = gtk_container_get_focus_child (container); @@ -5458,7 +5911,7 @@ gtk_window_focus (GtkWidget *widget, return TRUE; } - if (window->focus_widget) + if (priv->focus_widget) { if (direction == GTK_DIR_LEFT || direction == GTK_DIR_RIGHT || @@ -5469,7 +5922,7 @@ gtk_window_focus (GtkWidget *widget, } /* Wrapped off the end, clear the focus setting for the toplpevel */ - parent = gtk_widget_get_parent (window->focus_widget); + parent = gtk_widget_get_parent (priv->focus_widget); while (parent) { gtk_container_set_focus_child (GTK_CONTAINER (parent), NULL); @@ -5490,11 +5943,28 @@ gtk_window_focus (GtkWidget *widget, return FALSE; } +static void +gtk_window_move_focus (GtkWidget *widget, + GtkDirectionType dir) +{ + if (!gtk_widget_is_toplevel (GTK_WIDGET (widget))) + { + GTK_WIDGET_CLASS (gtk_window_parent_class)->move_focus (widget, dir); + return; + } + + gtk_widget_child_focus (widget, dir); + + if (! gtk_container_get_focus_child (GTK_CONTAINER (widget))) + gtk_window_set_focus (GTK_WINDOW (widget), NULL); +} + static void gtk_window_real_set_focus (GtkWindow *window, GtkWidget *focus) { - GtkWidget *old_focus = window->focus_widget; + GtkWindowPrivate *priv = window->priv; + GtkWidget *old_focus = priv->focus_widget; gboolean had_default = FALSE; gboolean focus_had_default = FALSE; gboolean old_focus_had_default = FALSE; @@ -5511,25 +5981,25 @@ gtk_window_real_set_focus (GtkWindow *window, g_object_freeze_notify (G_OBJECT (focus)); focus_had_default = gtk_widget_has_default (focus); } - - if (window->default_widget) - had_default = gtk_widget_has_default (window->default_widget); - - if (window->focus_widget) + + if (priv->default_widget) + had_default = gtk_widget_has_default (priv->default_widget); + + if (priv->focus_widget) { - if (gtk_widget_get_receives_default (window->focus_widget) && - (window->focus_widget != window->default_widget)) + if (gtk_widget_get_receives_default (priv->focus_widget) && + (priv->focus_widget != priv->default_widget)) { - _gtk_widget_set_has_default (window->focus_widget, FALSE); - gtk_widget_queue_draw (window->focus_widget); - - if (window->default_widget) - _gtk_widget_set_has_default (window->default_widget, TRUE); + _gtk_widget_set_has_default (priv->focus_widget, FALSE); + gtk_widget_queue_draw (priv->focus_widget); + + if (priv->default_widget) + _gtk_widget_set_has_default (priv->default_widget, TRUE); } - window->focus_widget = NULL; + priv->focus_widget = NULL; - if (window->has_focus) + if (priv->has_focus) do_focus_change (old_focus, FALSE); g_object_notify (G_OBJECT (old_focus), "is-focus"); @@ -5538,24 +6008,24 @@ gtk_window_real_set_focus (GtkWindow *window, /* The above notifications may have set a new focus widget, * if so, we don't want to override it. */ - if (focus && !window->focus_widget) + if (focus && !priv->focus_widget) { - window->focus_widget = focus; - - if (gtk_widget_get_receives_default (window->focus_widget) && - (window->focus_widget != window->default_widget)) + priv->focus_widget = focus; + + if (gtk_widget_get_receives_default (priv->focus_widget) && + (priv->focus_widget != priv->default_widget)) { - if (gtk_widget_get_can_default (window->focus_widget)) - _gtk_widget_set_has_default (window->focus_widget, TRUE); + if (gtk_widget_get_can_default (priv->focus_widget)) + _gtk_widget_set_has_default (priv->focus_widget, TRUE); - if (window->default_widget) - _gtk_widget_set_has_default (window->default_widget, FALSE); + if (priv->default_widget) + _gtk_widget_set_has_default (priv->default_widget, FALSE); } - if (window->has_focus) - do_focus_change (window->focus_widget, TRUE); + if (priv->has_focus) + do_focus_change (priv->focus_widget, TRUE); - g_object_notify (G_OBJECT (window->focus_widget), "is-focus"); + g_object_notify (G_OBJECT (priv->focus_widget), "is-focus"); } /* If the default widget changed, a redraw will have been queued @@ -5564,9 +6034,9 @@ gtk_window_real_set_focus (GtkWindow *window, * We'll sometimes queue a draw twice on the new widget but that * is harmless. */ - if (window->default_widget && - (had_default != gtk_widget_has_default (window->default_widget))) - gtk_widget_queue_draw (window->default_widget); + if (priv->default_widget && + (had_default != gtk_widget_has_default (priv->default_widget))) + gtk_widget_queue_draw (priv->default_widget); if (old_focus) { @@ -5587,18 +6057,10 @@ gtk_window_real_set_focus (GtkWindow *window, } -static void -gtk_window_size_request_init (GtkSizeRequestIface *iface) -{ - iface->get_width = gtk_window_get_width; - iface->get_height = gtk_window_get_height; -} - - static void -gtk_window_get_width (GtkSizeRequest *widget, - gint *minimum_size, - gint *natural_size) +gtk_window_get_preferred_width (GtkWidget *widget, + gint *minimum_size, + gint *natural_size) { GtkWindow *window; GtkWidget *child; @@ -5614,7 +6076,7 @@ gtk_window_get_width (GtkSizeRequest *widget, if (child && gtk_widget_get_visible (child)) { gint child_min, child_nat; - gtk_size_request_get_width (GTK_SIZE_REQUEST (child), &child_min, &child_nat); + gtk_widget_get_preferred_width (child, &child_min, &child_nat); *minimum_size += child_min; *natural_size += child_nat; @@ -5622,9 +6084,9 @@ gtk_window_get_width (GtkSizeRequest *widget, } static void -gtk_window_get_height (GtkSizeRequest *widget, - gint *minimum_size, - gint *natural_size) +gtk_window_get_preferred_height (GtkWidget *widget, + gint *minimum_size, + gint *natural_size) { GtkWindow *window; GtkWidget *child; @@ -5640,7 +6102,7 @@ gtk_window_get_height (GtkSizeRequest *widget, if (child && gtk_widget_get_visible (child)) { gint child_min, child_nat; - gtk_size_request_get_height (GTK_SIZE_REQUEST (child), &child_min, &child_nat); + gtk_widget_get_preferred_height (child, &child_min, &child_nat); *minimum_size += child_min; *natural_size += child_nat; @@ -5661,6 +6123,7 @@ _gtk_window_unset_focus_and_default (GtkWindow *window, GtkWidget *widget) { + GtkWindowPrivate *priv = window->priv; GtkWidget *child; GtkWidget *parent; @@ -5670,7 +6133,7 @@ _gtk_window_unset_focus_and_default (GtkWindow *window, parent = gtk_widget_get_parent (widget); if (gtk_container_get_focus_child (GTK_CONTAINER (parent)) == widget) { - child = window->focus_widget; + child = priv->focus_widget; while (child && child != widget) child = gtk_widget_get_parent (child); @@ -5679,7 +6142,7 @@ _gtk_window_unset_focus_and_default (GtkWindow *window, gtk_window_set_focus (GTK_WINDOW (window), NULL); } - child = window->default_widget; + child = priv->default_widget; while (child && child != widget) child = gtk_widget_get_parent (child); @@ -5695,12 +6158,50 @@ _gtk_window_unset_focus_and_default (GtkWindow *window, * Functions related to resizing * *********************************/ +static void +geometry_size_to_pixels (GdkGeometry *geometry, + guint flags, + guint *width, + guint *height) +{ + gint base_width = 0; + gint base_height = 0; + gint min_width = 0; + gint min_height = 0; + gint width_inc = 1; + gint height_inc = 1; + + if (flags & GDK_HINT_BASE_SIZE) + { + base_width = geometry->base_width; + base_height = geometry->base_height; + } + if (flags & GDK_HINT_MIN_SIZE) + { + min_width = geometry->min_width; + min_height = geometry->min_height; + } + if (flags & GDK_HINT_RESIZE_INC) + { + width_inc = geometry->width_inc; + height_inc = geometry->height_inc; + } + + if (width) + *width = MAX (*width * width_inc + base_width, min_width); + if (height) + *height = MAX (*height * height_inc + base_height, min_height); +} + /* This function doesn't constrain to geometry hints */ static void -gtk_window_compute_configure_request_size (GtkWindow *window, - guint *width, - guint *height) +gtk_window_compute_configure_request_size (GtkWindow *window, + GdkGeometry *geometry, + guint flags, + guint *width, + guint *height) { + GtkWindowPrivate *priv = window->priv; GtkRequisition requisition; GtkWindowGeometryInfo *info; GtkWidget *widget; @@ -5712,10 +6213,10 @@ gtk_window_compute_configure_request_size (GtkWindow *window, widget = GTK_WIDGET (window); info = gtk_window_get_geometry_info (window, FALSE); - - if (window->need_default_size) + + if (priv->need_default_size) { - gtk_widget_get_child_requisition (widget, &requisition); + gtk_widget_get_preferred_size (widget, &requisition, NULL); /* Default to requisition */ *width = requisition.width; @@ -5731,44 +6232,16 @@ gtk_window_compute_configure_request_size (GtkWindow *window, /* Override requisition with default size */ if (info) - { - gint base_width = 0; - gint base_height = 0; - gint min_width = 0; - gint min_height = 0; - gint width_inc = 1; - gint height_inc = 1; - - if (info->default_is_geometry && - (info->default_width > 0 || info->default_height > 0)) - { - GdkGeometry geometry; - guint flags; - - gtk_window_compute_hints (window, &geometry, &flags); - - if (flags & GDK_HINT_BASE_SIZE) - { - base_width = geometry.base_width; - base_height = geometry.base_height; - } - if (flags & GDK_HINT_MIN_SIZE) - { - min_width = geometry.min_width; - min_height = geometry.min_height; - } - if (flags & GDK_HINT_RESIZE_INC) - { - width_inc = geometry.width_inc; - height_inc = geometry.height_inc; - } - } - + { if (info->default_width > 0) - *width = MAX (info->default_width * width_inc + base_width, min_width); - + *width = info->default_width; if (info->default_height > 0) - *height = MAX (info->default_height * height_inc + base_height, min_height); + *height = info->default_height; + + if (info->default_is_geometry) + geometry_size_to_pixels (geometry, flags, + info->default_width > 0 ? width : NULL, + info->default_height > 0 ? height : NULL); } } else @@ -5786,10 +6259,14 @@ gtk_window_compute_configure_request_size (GtkWindow *window, if (info) { if (info->resize_width > 0) - *width = info->resize_width; - + *width = info->resize_width; if (info->resize_height > 0) - *height = info->resize_height; + *height = info->resize_height; + + if (info->resize_is_geometry) + geometry_size_to_pixels (geometry, flags, + info->resize_width > 0 ? width : NULL, + info->resize_height > 0 ? height : NULL); } /* Don't ever request zero width or height, its not supported by @@ -5803,11 +6280,12 @@ gtk_window_compute_configure_request_size (GtkWindow *window, static GtkWindowPosition get_effective_position (GtkWindow *window) { - GtkWindowPosition pos = window->position; + GtkWindowPrivate *priv = window->priv; + GtkWindowPosition pos = priv->position; if (pos == GTK_WIN_POS_CENTER_ON_PARENT && - (window->transient_parent == NULL || - !gtk_widget_get_mapped (GTK_WIDGET (window->transient_parent)))) + (priv->transient_parent == NULL || + !gtk_widget_get_mapped (GTK_WIDGET (priv->transient_parent)))) pos = GTK_WIN_POS_NONE; return pos; @@ -5839,9 +6317,9 @@ get_monitor_containing_pointer (GtkWindow *window) device_manager = gdk_display_get_device_manager (display); pointer = gdk_device_manager_get_client_pointer (device_manager); - gdk_display_get_device_state (display, pointer, - &pointer_screen, - &px, &py, NULL); + gdk_device_get_position (pointer, + &pointer_screen, + &px, &py); if (pointer_screen == window_screen) monitor_num = gdk_screen_get_monitor_at_point (pointer_screen, px, py); @@ -5925,34 +6403,33 @@ gtk_window_compute_configure_request (GtkWindow *window, GdkGeometry *geometry, guint *flags) { + GtkWindowPrivate *priv = window->priv; GdkGeometry new_geometry; guint new_flags; int w, h; - GtkWidget *widget; GtkWindowPosition pos; GtkWidget *parent_widget; GtkWindowGeometryInfo *info; GdkScreen *screen; - int x, y; - - widget = GTK_WIDGET (window); + int x, y; screen = gtk_window_check_screen (window); - - gtk_widget_size_request (widget, NULL); - gtk_window_compute_configure_request_size (window, (guint *)&w, (guint *)&h); - + gtk_window_compute_hints (window, &new_geometry, &new_flags); + gtk_window_compute_configure_request_size (window, + &new_geometry, new_flags, + (guint *)&w, (guint *)&h); + gtk_window_constrain_size (window, &new_geometry, new_flags, w, h, &w, &h); - parent_widget = (GtkWidget*) window->transient_parent; - + parent_widget = (GtkWidget*) priv->transient_parent; + pos = get_effective_position (window); info = gtk_window_get_geometry_info (window, FALSE); - + /* by default, don't change position requested */ if (info) { @@ -5966,7 +6443,7 @@ gtk_window_compute_configure_request (GtkWindow *window, } - if (window->need_default_position) + if (priv->need_default_position) { /* FIXME this all interrelates with window gravity. @@ -5974,7 +6451,6 @@ gtk_window_compute_configure_request (GtkWindow *window, * * Not sure how to go about that. */ - switch (pos) { /* here we are only handling CENTER_ALWAYS @@ -5985,7 +6461,7 @@ gtk_window_compute_configure_request (GtkWindow *window, case GTK_WIN_POS_CENTER: center_window_on_monitor (window, w, h, &x, &y); break; - + case GTK_WIN_POS_CENTER_ON_PARENT: { GtkAllocation allocation; @@ -5993,7 +6469,7 @@ gtk_window_compute_configure_request (GtkWindow *window, gint monitor_num; GdkRectangle monitor; gint ox, oy; - + g_assert (gtk_widget_get_mapped (parent_widget)); /* established earlier */ gdk_window = gtk_widget_get_window (parent_widget); @@ -6027,8 +6503,8 @@ gtk_window_compute_configure_request (GtkWindow *window, { gint screen_width = gdk_screen_get_width (screen); gint screen_height = gdk_screen_get_height (screen); - gint monitor_num; - GdkRectangle monitor; + gint monitor_num; + GdkRectangle monitor; GdkDisplay *display; GdkDeviceManager *device_manager; GdkDevice *pointer; @@ -6039,15 +6515,15 @@ gtk_window_compute_configure_request (GtkWindow *window, device_manager = gdk_display_get_device_manager (display); pointer = gdk_device_manager_get_client_pointer (device_manager); - gdk_display_get_device_state (display, pointer, - &pointer_screen, - &px, &py, NULL); + gdk_device_get_position (pointer, + &pointer_screen, + &px, &py); if (pointer_screen == screen) monitor_num = gdk_screen_get_monitor_at_point (screen, px, py); else monitor_num = -1; - + x = px - w / 2; y = py - h / 2; x = CLAMP (x, 0, screen_width - w); @@ -6068,16 +6544,16 @@ gtk_window_compute_configure_request (GtkWindow *window, default: break; } - } /* if (window->need_default_position) */ + } /* if (priv->need_default_position) */ - if (window->need_default_position && info && + if (priv->need_default_position && info && info->initial_pos_set) { x = info->initial_x; y = info->initial_y; gtk_window_constrain_position (window, w, h, &x, &y); } - + request->x = x; request->y = y; request->width = w; @@ -6096,10 +6572,12 @@ gtk_window_constrain_position (GtkWindow *window, gint *x, gint *y) { + GtkWindowPrivate *priv = window->priv; + /* See long comments in gtk_window_move_resize() * on when it's safe to call this function. */ - if (window->position == GTK_WIN_POS_CENTER_ALWAYS) + if (priv->position == GTK_WIN_POS_CENTER_ALWAYS) { gint center_x, center_y; @@ -6145,6 +6623,7 @@ gtk_window_move_resize (GtkWindow *window) * If GTK_WIN_POS_CENTER_ALWAYS is active, we constrain * the position request to be centered. */ + GtkWindowPrivate *priv = window->priv; GtkAllocation allocation; GtkWidget *widget; GtkContainer *container; @@ -6159,6 +6638,7 @@ gtk_window_move_resize (GtkWindow *window) GtkWindowLastGeometryInfo saved_last_info; widget = GTK_WIDGET (window); + gdk_window = gtk_widget_get_window (widget); container = GTK_CONTAINER (widget); info = gtk_window_get_geometry_info (window, TRUE); @@ -6256,7 +6736,7 @@ gtk_window_move_resize (GtkWindow *window) } #if 0 - if (window->type == GTK_WINDOW_TOPLEVEL) + if (priv->type == GTK_WINDOW_TOPLEVEL) { int notify_x, notify_y; @@ -6273,7 +6753,7 @@ gtk_window_move_resize (GtkWindow *window) "configure_notify_received: %d\n" "configure_request_count: %d\n" "position_constraints_changed: %d\n", - window->title ? window->title : "(no title)", + priv->title ? priv->title : "(no title)", info->last.configure_request.x, info->last.configure_request.y, info->last.configure_request.width, @@ -6292,8 +6772,8 @@ gtk_window_move_resize (GtkWindow *window) configure_request_pos_changed, configure_request_size_changed, hints_changed, - window->configure_notify_received, - window->configure_request_count, + priv->configure_notify_received, + priv->configure_request_count, info->position_constraints_changed); } #endif @@ -6320,7 +6800,7 @@ gtk_window_move_resize (GtkWindow *window) if ((configure_request_pos_changed || info->initial_pos_set || - (window->need_default_position && + (priv->need_default_position && get_effective_position (window) != GTK_WIN_POS_NONE)) && (new_flags & GDK_HINT_POS) == 0) { @@ -6339,7 +6819,7 @@ gtk_window_move_resize (GtkWindow *window) /* handle resizing/moving and widget tree allocation */ - if (window->configure_notify_received) + if (priv->configure_notify_received) { /* If we have received a configure event since * the last time in this function, we need to @@ -6352,11 +6832,14 @@ gtk_window_move_resize (GtkWindow *window) * (one per configure request), as an optimization. * */ - window->configure_notify_received = FALSE; + priv->configure_notify_received = FALSE; /* gtk_window_configure_event() filled in widget->allocation */ gtk_widget_size_allocate (widget, &allocation); + set_grip_position (window); + update_grip_visibility (window); + gdk_window_process_updates (gdk_window, TRUE); gdk_window_configure_finished (gdk_window); @@ -6423,33 +6906,18 @@ gtk_window_move_resize (GtkWindow *window) /* Now send the configure request */ if (configure_request_pos_changed) - { - if (window->frame) - { - gdk_window_move_resize (window->frame, - new_request.x - window->frame_left, - new_request.y - window->frame_top, - new_request.width + window->frame_left + window->frame_right, - new_request.height + window->frame_top + window->frame_bottom); - gdk_window_resize (gdk_window, - new_request.width, new_request.height); - } - else - gdk_window_move_resize (gdk_window, - new_request.x, new_request.y, - new_request.width, new_request.height); - } + { + gdk_window_move_resize (gdk_window, + new_request.x, new_request.y, + new_request.width, new_request.height); + } else /* only size changed */ - { - if (window->frame) - gdk_window_resize (window->frame, - new_request.width + window->frame_left + window->frame_right, - new_request.height + window->frame_top + window->frame_bottom); - gdk_window_resize (gdk_window, - new_request.width, new_request.height); - } - - if (window->type == GTK_WINDOW_POPUP) + { + gdk_window_resize (gdk_window, + new_request.width, new_request.height); + } + + if (priv->type == GTK_WINDOW_POPUP) { GtkAllocation allocation; @@ -6469,7 +6937,7 @@ gtk_window_move_resize (GtkWindow *window) else { /* Increment the number of have-not-yet-received-notify requests */ - window->configure_request_count += 1; + priv->configure_request_count += 1; gdk_window_freeze_toplevel_updates_libgtk_only (gdk_window); /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new @@ -6499,17 +6967,10 @@ gtk_window_move_resize (GtkWindow *window) /* Handle any position changes. */ if (configure_request_pos_changed) - { - if (window->frame) - { - gdk_window_move (window->frame, - new_request.x - window->frame_left, - new_request.y - window->frame_top); - } - else - gdk_window_move (gdk_window, - new_request.x, new_request.y); - } + { + gdk_window_move (gdk_window, + new_request.x, new_request.y); + } /* And run the resize queue. */ @@ -6577,11 +7038,14 @@ _gtk_window_constrain_size (GtkWindow *window, gint *new_width, gint *new_height) { + GtkWindowPrivate *priv; GtkWindowGeometryInfo *info; g_return_if_fail (GTK_IS_WINDOW (window)); - info = window->geometry_info; + priv = window->priv; + + info = priv->geometry_info; if (info) { GdkWindowHints flags = info->last.flags; @@ -6611,8 +7075,8 @@ gtk_window_constrain_size (GtkWindow *window, } /* Compute the set of geometry hints and flags for a window - * based on the application set geometry, and requisiition - * of the window. gtk_widget_size_request() must have been + * based on the application set geometry, and requisition + * of the window. gtk_widget_get_preferred_size() must have been * called first. */ static void @@ -6620,6 +7084,7 @@ gtk_window_compute_hints (GtkWindow *window, GdkGeometry *new_geometry, guint *new_flags) { + GtkWindowPrivate *priv = window->priv; GtkWidget *widget; gint extra_width = 0; gint extra_height = 0; @@ -6627,8 +7092,8 @@ gtk_window_compute_hints (GtkWindow *window, GtkRequisition requisition; widget = GTK_WIDGET (window); - - gtk_widget_get_child_requisition (widget, &requisition); + + gtk_widget_get_preferred_size (widget, &requisition, NULL); geometry_info = gtk_window_get_geometry_info (GTK_WINDOW (widget), FALSE); if (geometry_info) @@ -6643,26 +7108,52 @@ gtk_window_compute_hints (GtkWindow *window, if (geometry_info && geometry_info->widget) { - GtkRequisition requisition; - GtkRequisition child_requisition; - - /* FIXME: This really isn't right. It gets the min size wrong and forces - * callers to do horrible hacks like set a huge usize on the child requisition - * to get the base size right. We really want to find the answers to: - * - * - If the geometry widget was infinitely big, how much extra space - * would be needed for the stuff around it. + /* If the geometry widget is set, then the hints really apply to that + * widget. This is pretty much meaningless unless the window layout + * is such that the rest of the window adds fixed size borders to + * the geometry widget. Our job is to figure the size of the borders; + * We do that by asking how big the toplevel would be if the + * geometry widget was *really big*. * - * - If the geometry widget was infinitely small, how big would the - * window still have to be. + * +----------+ + * |AAAAAAAAA | At small sizes, the minimum sizes of widgets + * |GGGGG B| in the border can confuse things + * |GGGGG B| + * | B| + * +----------+ * - * Finding these answers would be a bit of a mess here. (Bug #68668) + * +-----------+ + * |AAAAAAAAA | When the geometry widget is large, things are + * |GGGGGGGGGGB| clearer. + * |GGGGGGGGGGB| + * |GGGGGGGGGG | + * +-----------+ */ - gtk_widget_get_child_requisition (geometry_info->widget, &child_requisition); +#define TEMPORARY_SIZE 10000 /* 10,000 pixels should be bigger than real widget sizes */ + GtkRequisition requisition; + int current_width, current_height; + + _gtk_widget_override_size_request (geometry_info->widget, + TEMPORARY_SIZE, TEMPORARY_SIZE, + ¤t_width, ¤t_height); + gtk_widget_get_preferred_size (widget, + &requisition, NULL); + _gtk_widget_restore_size_request (geometry_info->widget, + current_width, current_height); - gtk_size_request_get_size (GTK_SIZE_REQUEST (widget), &requisition, NULL); - extra_width = requisition.width - child_requisition.width; - extra_height = requisition.height - child_requisition.height; + extra_width = requisition.width - TEMPORARY_SIZE; + extra_height = requisition.height - TEMPORARY_SIZE; + + if (extra_width < 0 || extra_width < 0) + { + g_warning("Toplevel size doesn't seem to directly depend on the " + "size of the geometry widget from gtk_window_set_geometry_hints(). " + "The geometry widget might not be in the window, or it might not " + "be packed into the window appropriately"); + extra_width = MAX(extra_width, 0); + extra_height = MAX(extra_height, 0); + } +#undef TEMPORARY_SIZE } /* We don't want to set GDK_HINT_POS in here, we just set it @@ -6675,27 +7166,39 @@ gtk_window_compute_hints (GtkWindow *window, new_geometry->base_width += extra_width; new_geometry->base_height += extra_height; } - else if (!(*new_flags & GDK_HINT_MIN_SIZE) && - (*new_flags & GDK_HINT_RESIZE_INC) && - ((extra_width != 0) || (extra_height != 0))) + else { + /* For simplicity, we always set the base hint, even when we + * don't expect it to have any visible effect. + * (Note: geometry_size_to_pixels() depends on this.) + */ *new_flags |= GDK_HINT_BASE_SIZE; - + new_geometry->base_width = extra_width; new_geometry->base_height = extra_height; + + /* As for X, if BASE_SIZE is not set but MIN_SIZE is set, then the + * base size is the minimum size */ + if (*new_flags & GDK_HINT_MIN_SIZE) + { + if (new_geometry->min_width > 0) + new_geometry->base_width += new_geometry->min_width; + if (new_geometry->min_height > 0) + new_geometry->base_height += new_geometry->min_height; + } } - + if (*new_flags & GDK_HINT_MIN_SIZE) { if (new_geometry->min_width < 0) new_geometry->min_width = requisition.width; else - new_geometry->min_width += extra_width; + new_geometry->min_width = MAX (requisition.width, new_geometry->min_width + extra_width); if (new_geometry->min_height < 0) new_geometry->min_height = requisition.height; else - new_geometry->min_height += extra_height; + new_geometry->min_height = MAX (requisition.height, new_geometry->min_height + extra_height); } else { @@ -6717,7 +7220,7 @@ gtk_window_compute_hints (GtkWindow *window, else new_geometry->max_height += extra_height; } - else if (!window->resizable) + else if (!priv->resizable) { *new_flags |= GDK_HINT_MAX_SIZE; @@ -6726,137 +7229,66 @@ gtk_window_compute_hints (GtkWindow *window, } *new_flags |= GDK_HINT_WIN_GRAVITY; - new_geometry->win_gravity = window->gravity; + new_geometry->win_gravity = priv->gravity; } /*********************** * Redrawing functions * ***********************/ -static void -gtk_window_paint (GtkWidget *widget, - GdkRectangle *area) +static gboolean +gtk_window_draw (GtkWidget *widget, + cairo_t *cr) { - gtk_paint_flat_box (gtk_widget_get_style (widget), - gtk_widget_get_window (widget), - GTK_STATE_NORMAL, - GTK_SHADOW_NONE, area, widget, "base", 0, 0, -1, -1); -} + GtkWindowPrivate *priv = GTK_WINDOW (widget)->priv; + GtkStyleContext *context; + gboolean ret = FALSE; -static gint -gtk_window_expose (GtkWidget *widget, - GdkEventExpose *event) -{ - if (!gtk_widget_get_app_paintable (widget)) - gtk_window_paint (widget, &event->area); - - if (GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event) - return GTK_WIDGET_CLASS (gtk_window_parent_class)->expose_event (widget, event); + context = gtk_widget_get_style_context (widget); - return FALSE; -} + gtk_style_context_save (context); -/** - * gtk_window_set_has_frame: - * @window: a #GtkWindow - * @setting: a boolean - * - * (Note: this is a special-purpose function for the framebuffer port, - * that causes GTK+ to draw its own window border. For most applications, - * you want gtk_window_set_decorated() instead, which tells the window - * manager whether to draw the window border.) - * - * If this function is called on a window with setting of %TRUE, before - * it is realized or showed, it will have a "frame" window around - * @window->window, accessible in @window->frame. Using the signal - * frame_event you can receive all events targeted at the frame. - * - * This function is used by the linux-fb port to implement managed - * windows, but it could conceivably be used by X-programs that - * want to do their own window decorations. - * - **/ -void -gtk_window_set_has_frame (GtkWindow *window, - gboolean setting) -{ - g_return_if_fail (GTK_IS_WINDOW (window)); - g_return_if_fail (!gtk_widget_get_realized (GTK_WIDGET (window))); + if (!gtk_widget_get_app_paintable (widget)) + { + GtkStateFlags state; - window->has_frame = setting != FALSE; -} + state = gtk_widget_get_state_flags (widget); -/** - * gtk_window_get_has_frame: - * @window: a #GtkWindow - * - * Accessor for whether the window has a frame window exterior to - * @window->window. Gets the value set by gtk_window_set_has_frame (). - * - * Return value: %TRUE if a frame has been added to the window - * via gtk_window_set_has_frame(). - **/ -gboolean -gtk_window_get_has_frame (GtkWindow *window) -{ - g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); + if (gtk_window_has_toplevel_focus (GTK_WINDOW (widget))) + state |= GTK_STATE_FLAG_FOCUSED; - return window->has_frame; -} + 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_window_set_frame_dimensions: - * @window: a #GtkWindow that has a frame - * @left: The width of the left border - * @top: The height of the top border - * @right: The width of the right border - * @bottom: The height of the bottom border - * - * (Note: this is a special-purpose function intended for the framebuffer - * port; see gtk_window_set_has_frame(). It will have no effect on the - * window border drawn by the window manager, which is the normal - * case when using the X Window system.) - * - * For windows with frames (see gtk_window_set_has_frame()) this function - * can be used to change the size of the frame border. - **/ -void -gtk_window_set_frame_dimensions (GtkWindow *window, - gint left, - gint top, - gint right, - gint bottom) -{ - GtkAllocation allocation; - GtkWidget *widget; + gtk_style_context_restore (context); - g_return_if_fail (GTK_IS_WINDOW (window)); + if (GTK_WIDGET_CLASS (gtk_window_parent_class)->draw) + ret = GTK_WIDGET_CLASS (gtk_window_parent_class)->draw (widget, cr); - widget = GTK_WIDGET (window); + if (priv->grip_window != NULL && + gtk_cairo_should_draw_window (cr, priv->grip_window)) + { + GdkRectangle rect; - if (window->frame_left == left && - window->frame_top == top && - window->frame_right == right && - window->frame_bottom == bottom) - return; + gtk_style_context_save (context); + cairo_save (cr); - window->frame_left = left; - window->frame_top = top; - window->frame_right = right; - window->frame_bottom = bottom; + gtk_cairo_transform_to_window (cr, widget, priv->grip_window); + gtk_window_get_resize_grip_area (GTK_WINDOW (widget), &rect); - if (gtk_widget_get_realized (widget) && window->frame) - { - gtk_widget_get_allocation (widget, &allocation); + 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); - gint width = allocation.width + left + right; - gint height = allocation.height + top + bottom; - gdk_window_resize (window->frame, width, height); - gtk_decorated_window_move_resize_window (window, - left, top, - allocation.width, - allocation.height); + cairo_restore (cr); + gtk_style_context_restore (context); } + + return ret; } /** @@ -6962,19 +7394,18 @@ gtk_window_present_with_time (GtkWindow *window, void gtk_window_iconify (GtkWindow *window) { + GtkWindowPrivate *priv; GtkWidget *widget; GdkWindow *toplevel; g_return_if_fail (GTK_IS_WINDOW (window)); + priv = window->priv; widget = GTK_WIDGET (window); - window->iconify_initially = TRUE; + priv->iconify_initially = TRUE; - if (window->frame) - toplevel = window->frame; - else - toplevel = gtk_widget_get_window (widget); + toplevel = gtk_widget_get_window (widget); if (toplevel != NULL) gdk_window_iconify (toplevel); @@ -6996,19 +7427,18 @@ gtk_window_iconify (GtkWindow *window) void gtk_window_deiconify (GtkWindow *window) { + GtkWindowPrivate *priv; GtkWidget *widget; GdkWindow *toplevel; g_return_if_fail (GTK_IS_WINDOW (window)); + priv = window->priv; widget = GTK_WIDGET (window); - window->iconify_initially = FALSE; + priv->iconify_initially = FALSE; - if (window->frame) - toplevel = window->frame; - else - toplevel = gtk_widget_get_window (widget); + toplevel = gtk_widget_get_window (widget); if (toplevel != NULL) gdk_window_deiconify (toplevel); @@ -7035,19 +7465,18 @@ gtk_window_deiconify (GtkWindow *window) void gtk_window_stick (GtkWindow *window) { + GtkWindowPrivate *priv; GtkWidget *widget; GdkWindow *toplevel; g_return_if_fail (GTK_IS_WINDOW (window)); + priv = window->priv; widget = GTK_WIDGET (window); - window->stick_initially = TRUE; + priv->stick_initially = TRUE; - if (window->frame) - toplevel = window->frame; - else - toplevel = gtk_widget_get_window (widget); + toplevel = gtk_widget_get_window (widget); if (toplevel != NULL) gdk_window_stick (toplevel); @@ -7071,19 +7500,18 @@ gtk_window_stick (GtkWindow *window) void gtk_window_unstick (GtkWindow *window) { + GtkWindowPrivate *priv; GtkWidget *widget; GdkWindow *toplevel; g_return_if_fail (GTK_IS_WINDOW (window)); + priv = window->priv; widget = GTK_WIDGET (window); - window->stick_initially = FALSE; + priv->stick_initially = FALSE; - if (window->frame) - toplevel = window->frame; - else - toplevel = gtk_widget_get_window (widget); + toplevel = gtk_widget_get_window (widget); if (toplevel != NULL) gdk_window_unstick (toplevel); @@ -7112,19 +7540,18 @@ gtk_window_unstick (GtkWindow *window) void gtk_window_maximize (GtkWindow *window) { + GtkWindowPrivate *priv; GtkWidget *widget; GdkWindow *toplevel; g_return_if_fail (GTK_IS_WINDOW (window)); + priv = window->priv; widget = GTK_WIDGET (window); - window->maximize_initially = TRUE; + priv->maximize_initially = TRUE; - if (window->frame) - toplevel = window->frame; - else - toplevel = gtk_widget_get_window (widget); + toplevel = gtk_widget_get_window (widget); if (toplevel != NULL) gdk_window_maximize (toplevel); @@ -7148,19 +7575,18 @@ gtk_window_maximize (GtkWindow *window) void gtk_window_unmaximize (GtkWindow *window) { + GtkWindowPrivate *priv; GtkWidget *widget; GdkWindow *toplevel; g_return_if_fail (GTK_IS_WINDOW (window)); + priv = window->priv; widget = GTK_WIDGET (window); - window->maximize_initially = FALSE; + priv->maximize_initially = FALSE; - if (window->frame) - toplevel = window->frame; - else - toplevel = gtk_widget_get_window (widget); + toplevel = gtk_widget_get_window (widget); if (toplevel != NULL) gdk_window_unmaximize (toplevel); @@ -7186,21 +7612,18 @@ gtk_window_unmaximize (GtkWindow *window) void gtk_window_fullscreen (GtkWindow *window) { + GtkWindowPrivate *priv; GtkWidget *widget; GdkWindow *toplevel; - GtkWindowPrivate *priv; - + g_return_if_fail (GTK_IS_WINDOW (window)); + priv = window->priv; widget = GTK_WIDGET (window); - priv = GTK_WINDOW_GET_PRIVATE (window); - + priv->fullscreen_initially = TRUE; - if (window->frame) - toplevel = window->frame; - else - toplevel = gtk_widget_get_window (widget); + toplevel = gtk_widget_get_window (widget); if (toplevel != NULL) gdk_window_fullscreen (toplevel); @@ -7229,18 +7652,15 @@ gtk_window_unfullscreen (GtkWindow *window) GtkWidget *widget; GdkWindow *toplevel; GtkWindowPrivate *priv; - + g_return_if_fail (GTK_IS_WINDOW (window)); + priv = window->priv; widget = GTK_WIDGET (window); - priv = GTK_WINDOW_GET_PRIVATE (window); - + priv->fullscreen_initially = FALSE; - if (window->frame) - toplevel = window->frame; - else - toplevel = gtk_widget_get_window (widget); + toplevel = gtk_widget_get_window (widget); if (toplevel != NULL) gdk_window_unfullscreen (toplevel); @@ -7284,17 +7704,14 @@ gtk_window_set_keep_above (GtkWindow *window, g_return_if_fail (GTK_IS_WINDOW (window)); + priv = window->priv; widget = GTK_WIDGET (window); - priv = GTK_WINDOW_GET_PRIVATE (window); priv->above_initially = setting != FALSE; if (setting) priv->below_initially = FALSE; - if (window->frame) - toplevel = window->frame; - else - toplevel = gtk_widget_get_window (widget); + toplevel = gtk_widget_get_window (widget); if (toplevel != NULL) gdk_window_set_keep_above (toplevel, setting); @@ -7338,17 +7755,14 @@ gtk_window_set_keep_below (GtkWindow *window, g_return_if_fail (GTK_IS_WINDOW (window)); + priv = window->priv; widget = GTK_WIDGET (window); - priv = GTK_WINDOW_GET_PRIVATE (window); priv->below_initially = setting != FALSE; if (setting) priv->above_initially = FALSE; - if (window->frame) - toplevel = window->frame; - else - toplevel = gtk_widget_get_window (widget); + toplevel = gtk_widget_get_window (widget); if (toplevel != NULL) gdk_window_set_keep_below (toplevel, setting); @@ -7366,13 +7780,24 @@ void gtk_window_set_resizable (GtkWindow *window, gboolean resizable) { + GtkWindowPrivate *priv; + g_return_if_fail (GTK_IS_WINDOW (window)); - window->resizable = (resizable != FALSE); + priv = window->priv; - g_object_notify (G_OBJECT (window), "resizable"); + resizable = (resizable != FALSE); - gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window)); + if (priv->resizable != resizable) + { + priv->resizable = (resizable != FALSE); + + update_grip_visibility (window); + + gtk_widget_queue_resize_no_redraw (GTK_WIDGET (window)); + + g_object_notify (G_OBJECT (window), "resizable"); + } } /** @@ -7388,7 +7813,7 @@ gtk_window_get_resizable (GtkWindow *window) { g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); - return window->resizable; + return window->priv->resizable; } /** @@ -7408,11 +7833,15 @@ void gtk_window_set_gravity (GtkWindow *window, GdkGravity gravity) { + GtkWindowPrivate *priv; + g_return_if_fail (GTK_IS_WINDOW (window)); - if (gravity != window->gravity) + priv = window->priv; + + if (gravity != priv->gravity) { - window->gravity = gravity; + priv->gravity = gravity; /* gtk_window_move_resize() will adapt gravity */ @@ -7435,7 +7864,7 @@ gtk_window_get_gravity (GtkWindow *window) { g_return_val_if_fail (GTK_IS_WINDOW (window), 0); - return window->gravity; + return window->priv->gravity; } /** @@ -7465,15 +7894,12 @@ gtk_window_begin_resize_drag (GtkWindow *window, { GtkWidget *widget; GdkWindow *toplevel; - + g_return_if_fail (GTK_IS_WINDOW (window)); widget = GTK_WIDGET (window); g_return_if_fail (gtk_widget_get_visible (widget)); - - if (window->frame) - toplevel = window->frame; - else - toplevel = gtk_widget_get_window (widget); + + toplevel = gtk_widget_get_window (widget); gdk_window_begin_resize_drag (toplevel, edge, button, @@ -7481,44 +7907,6 @@ gtk_window_begin_resize_drag (GtkWindow *window, timestamp); } -/** - * gtk_window_get_frame_dimensions: - * @window: a #GtkWindow - * @left: (out) (allow-none): location to store the width of the frame at the left, or %NULL - * @top: (out) (allow-none): location to store the height of the frame at the top, or %NULL - * @right: (out) (allow-none): location to store the width of the frame at the returns, or %NULL - * @bottom: (out) (allow-none): location to store the height of the frame at the bottom, or %NULL - * - * (Note: this is a special-purpose function intended for the - * framebuffer port; see gtk_window_set_has_frame(). It will not - * return the size of the window border drawn by the window manager, which is the normal - * case when using a windowing system. See - * gdk_window_get_frame_extents() to get the standard window border - * extents.) - * - * Retrieves the dimensions of the frame window for this toplevel. - * See gtk_window_set_has_frame(), gtk_window_set_frame_dimensions(). - **/ -void -gtk_window_get_frame_dimensions (GtkWindow *window, - gint *left, - gint *top, - gint *right, - gint *bottom) -{ - g_return_if_fail (GTK_IS_WINDOW (window)); - - if (left) - *left = window->frame_left; - if (top) - *top = window->frame_top; - if (right) - *right = window->frame_right; - if (bottom) - *bottom = window->frame_bottom; -} - /** * gtk_window_begin_move_drag: * @window: a #GtkWindow @@ -7544,15 +7932,12 @@ gtk_window_begin_move_drag (GtkWindow *window, { GtkWidget *widget; GdkWindow *toplevel; - + g_return_if_fail (GTK_IS_WINDOW (window)); widget = GTK_WIDGET (window); g_return_if_fail (gtk_widget_get_visible (widget)); - - if (window->frame) - toplevel = window->frame; - else - toplevel = gtk_widget_get_window (widget); + + toplevel = gtk_widget_get_window (widget); gdk_window_begin_move_drag (toplevel, button, @@ -7560,7 +7945,7 @@ gtk_window_begin_move_drag (GtkWindow *window, timestamp); } -/** +/** * gtk_window_set_screen: * @window: a #GtkWindow. * @screen: a #GdkScreen. @@ -7575,36 +7960,40 @@ void gtk_window_set_screen (GtkWindow *window, GdkScreen *screen) { + GtkWindowPrivate *priv; GtkWidget *widget; GdkScreen *previous_screen; gboolean was_mapped; - + g_return_if_fail (GTK_IS_WINDOW (window)); g_return_if_fail (GDK_IS_SCREEN (screen)); - if (screen == window->screen) + priv = window->priv; + + if (screen == priv->screen) return; widget = GTK_WIDGET (window); - previous_screen = window->screen; + previous_screen = priv->screen; was_mapped = gtk_widget_get_mapped (widget); if (was_mapped) gtk_widget_unmap (widget); if (gtk_widget_get_realized (widget)) gtk_widget_unrealize (widget); - + gtk_window_free_key_hash (window); - window->screen = screen; + priv->screen = screen; gtk_widget_reset_rc_styles (widget); if (screen != previous_screen) { - g_signal_handlers_disconnect_by_func (previous_screen, - gtk_window_on_composited_changed, window); - g_signal_connect (screen, "composited-changed", - G_CALLBACK (gtk_window_on_composited_changed), window); - + if (previous_screen) + g_signal_handlers_disconnect_by_func (previous_screen, + gtk_window_on_composited_changed, window); + g_signal_connect (screen, "composited-changed", + G_CALLBACK (gtk_window_on_composited_changed), window); + _gtk_widget_propagate_screen_changed (widget, previous_screen); _gtk_widget_propagate_composited_changed (widget); } @@ -7626,8 +8015,10 @@ gtk_window_on_composited_changed (GdkScreen *screen, static GdkScreen * gtk_window_check_screen (GtkWindow *window) { - if (window->screen) - return window->screen; + GtkWindowPrivate *priv = window->priv; + + if (priv->screen) + return priv->screen; else { g_warning ("Screen for GtkWindow not set; you must always set\n" @@ -7636,7 +8027,7 @@ gtk_window_check_screen (GtkWindow *window) } } -/** +/** * gtk_window_get_screen: * @window: a #GtkWindow. * @@ -7650,8 +8041,8 @@ GdkScreen* gtk_window_get_screen (GtkWindow *window) { g_return_val_if_fail (GTK_IS_WINDOW (window), NULL); - - return window->screen; + + return window->priv->screen; } /** @@ -7675,7 +8066,7 @@ gtk_window_is_active (GtkWindow *window) { g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); - return window->is_active; + return window->priv->is_active; } /** @@ -7695,40 +8086,23 @@ gtk_window_has_toplevel_focus (GtkWindow *window) { g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); - return window->has_toplevel_focus; + return window->priv->has_toplevel_focus; } +G_DEFINE_TYPE (GtkWindowGroup, gtk_window_group, G_TYPE_OBJECT) + static void -gtk_window_group_class_init (GtkWindowGroupClass *klass) +gtk_window_group_init (GtkWindowGroup *group) { - g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate)); + group->priv = G_TYPE_INSTANCE_GET_PRIVATE (group, + GTK_TYPE_WINDOW_GROUP, + GtkWindowGroupPrivate); } -GType -gtk_window_group_get_type (void) +static void +gtk_window_group_class_init (GtkWindowGroupClass *klass) { - static GType window_group_type = 0; - - if (!window_group_type) - { - const GTypeInfo window_group_info = - { - sizeof (GtkWindowGroupClass), - NULL, /* base_init */ - NULL, /* base_finalize */ - (GClassInitFunc) gtk_window_group_class_init, - NULL, /* class_finalize */ - NULL, /* class_data */ - sizeof (GtkWindowGroup), - 0, /* n_preallocs */ - (GInstanceInitFunc) NULL, - }; - - window_group_type = g_type_register_static (G_TYPE_OBJECT, I_("GtkWindowGroup"), - &window_group_info, 0); - } - - return window_group_type; + g_type_class_add_private (klass, sizeof (GtkWindowGroupPrivate)); } /** @@ -7747,14 +8121,16 @@ gtk_window_group_new (void) static void window_group_cleanup_grabs (GtkWindowGroup *group, - GtkWindow *window) + GtkWindow *window) { GtkWindowGroupPrivate *priv; GtkDeviceGrabInfo *info; GSList *tmp_list; GSList *to_remove = NULL; - tmp_list = group->grabs; + priv = group->priv; + + tmp_list = priv->grabs; while (tmp_list) { if (gtk_widget_get_toplevel (tmp_list->data) == (GtkWidget*) window) @@ -7769,7 +8145,6 @@ window_group_cleanup_grabs (GtkWindowGroup *group, to_remove = g_slist_delete_link (to_remove, to_remove); } - priv = GTK_WINDOW_GROUP_GET_PRIVATE (group); tmp_list = priv->device_grabs; while (tmp_list) @@ -7802,20 +8177,24 @@ void gtk_window_group_add_window (GtkWindowGroup *window_group, GtkWindow *window) { + GtkWindowPrivate *priv; + g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group)); g_return_if_fail (GTK_IS_WINDOW (window)); - if (window->group != window_group) + priv = window->priv; + + if (priv->group != window_group) { g_object_ref (window); g_object_ref (window_group); - - if (window->group) - gtk_window_group_remove_window (window->group, window); + + if (priv->group) + gtk_window_group_remove_window (priv->group, window); else window_group_cleanup_grabs (gtk_window_get_group (NULL), window); - window->group = window_group; + priv->group = window_group; g_object_unref (window); } @@ -7832,15 +8211,18 @@ void gtk_window_group_remove_window (GtkWindowGroup *window_group, GtkWindow *window) { + GtkWindowPrivate *priv; + g_return_if_fail (GTK_IS_WINDOW_GROUP (window_group)); g_return_if_fail (GTK_IS_WINDOW (window)); - g_return_if_fail (window->group == window_group); + priv = window->priv; + g_return_if_fail (priv->group == window_group); g_object_ref (window); window_group_cleanup_grabs (window_group, window); - window->group = NULL; - + priv->group = NULL; + g_object_unref (window_group); g_object_unref (window); } @@ -7851,8 +8233,8 @@ gtk_window_group_remove_window (GtkWindowGroup *window_group, * * Returns a list of the #GtkWindows that belong to @window_group. * - * Returns: (element-type GtkWidget) (transfer container): A newly-allocated list of - * windows inside the group. + * Returns: (element-type GtkWindow) (transfer container): A + * newly-allocated list of windows inside the group. * * Since: 2.14 **/ @@ -7870,10 +8252,12 @@ gtk_window_group_list_windows (GtkWindowGroup *window_group) { GtkWindow *window = toplevel->data; - if (window_group == window->group) + if (window_group == window->priv->group) group_windows = g_list_prepend (group_windows, window); } + g_list_free (toplevels); + return g_list_reverse (group_windows); } @@ -7892,8 +8276,8 @@ gtk_window_group_list_windows (GtkWindowGroup *window_group) GtkWindowGroup * gtk_window_get_group (GtkWindow *window) { - if (window && window->group) - return window->group; + if (window && window->priv->group) + return window->priv->group; else { static GtkWindowGroup *default_group = NULL; @@ -7920,7 +8304,7 @@ gtk_window_has_group (GtkWindow *window) { g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); - return window->group != NULL; + return window->priv->group != NULL; } /** @@ -7930,7 +8314,7 @@ gtk_window_has_group (GtkWindow *window) * Gets the current grab widget of the given group, * see gtk_grab_add(). * - * Returns: the current grab widget of the group + * Returns: (transfer none): the current grab widget of the group * * Since: 2.22 */ @@ -7939,11 +8323,32 @@ gtk_window_group_get_current_grab (GtkWindowGroup *window_group) { g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL); - if (window_group->grabs) - return GTK_WIDGET (window_group->grabs->data); + if (window_group->priv->grabs) + return GTK_WIDGET (window_group->priv->grabs->data); return NULL; } +void +_gtk_window_group_add_grab (GtkWindowGroup *window_group, + GtkWidget *widget) +{ + GtkWindowGroupPrivate *priv; + + priv = window_group->priv; + priv->grabs = g_slist_prepend (priv->grabs, widget); +} + +void +_gtk_window_group_remove_grab (GtkWindowGroup *window_group, + GtkWidget *widget) +{ + GtkWindowGroupPrivate *priv; + + priv = window_group->priv; + priv->grabs = g_slist_remove (priv->grabs, widget); +} + + void _gtk_window_group_add_device_grab (GtkWindowGroup *window_group, GtkWidget *widget, @@ -7953,7 +8358,7 @@ _gtk_window_group_add_device_grab (GtkWindowGroup *window_group, GtkWindowGroupPrivate *priv; GtkDeviceGrabInfo *info; - priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group); + priv = window_group->priv; info = g_slice_new0 (GtkDeviceGrabInfo); info->widget = widget; @@ -7973,7 +8378,7 @@ _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group, GSList *list, *node = NULL; GdkDevice *other_device; - priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group); + priv = window_group->priv; other_device = gdk_device_get_associated_device (device); list = priv->device_grabs; @@ -8008,7 +8413,7 @@ _gtk_window_group_remove_device_grab (GtkWindowGroup *window_group, * * Returns the current grab widget for @device, or %NULL if none. * - * Returns: The grab widget, or %NULL + * Returns: (transfer none): The grab widget, or %NULL * * Since: 3.0 */ @@ -8024,7 +8429,7 @@ gtk_window_group_get_current_device_grab (GtkWindowGroup *window_group, g_return_val_if_fail (GTK_IS_WINDOW_GROUP (window_group), NULL); g_return_val_if_fail (GDK_IS_DEVICE (device), NULL); - priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group); + priv = window_group->priv; list = priv->device_grabs; other_device = gdk_device_get_associated_device (device); @@ -8051,7 +8456,7 @@ _gtk_window_group_widget_is_blocked_for_device (GtkWindowGroup *window_group, GdkDevice *other_device; GSList *list; - priv = GTK_WINDOW_GROUP_GET_PRIVATE (window_group); + priv = window_group->priv; other_device = gdk_device_get_associated_device (device); list = priv->device_grabs; @@ -8301,7 +8706,7 @@ gtk_XParseGeometry (const char *string, * gtk_init (&argc, &argv); * * window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - * vbox = gtk_vbox_new (FALSE, 0); + * vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, FALSE, 0); * * gtk_container_add (GTK_CONTAINER (window), vbox); * fill_with_content (vbox); @@ -8335,6 +8740,7 @@ gtk_window_parse_geometry (GtkWindow *window, { gint result, x = 0, y = 0; guint w, h; + GtkWidget *child; GdkGravity grav; gboolean size_set, pos_set; GdkScreen *screen; @@ -8342,6 +8748,12 @@ gtk_window_parse_geometry (GtkWindow *window, g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); g_return_val_if_fail (geometry != NULL, FALSE); + child = gtk_bin_get_child (GTK_BIN (window)); + if (!child || !gtk_widget_get_visible (child)) + g_warning ("gtk_window_parse_geometry() called on a window with no " + "visible children; the window should be set up before " + "gtk_window_parse_geometry() is called."); + screen = gtk_window_check_screen (window); result = gtk_XParseGeometry (geometry, &x, &y, &w, &h); @@ -8425,7 +8837,7 @@ gtk_window_mnemonic_hash_foreach (guint keyval, gpointer func_data; } *info = data; - (*info->func) (info->window, keyval, info->window->mnemonic_modifier, TRUE, info->func_data); + (*info->func) (info->window, keyval, info->window->priv->mnemonic_modifier, TRUE, info->func_data); } void @@ -8635,26 +9047,27 @@ gtk_window_activate_key (GtkWindow *window, static void window_update_has_focus (GtkWindow *window) { + GtkWindowPrivate *priv = window->priv; GtkWidget *widget = GTK_WIDGET (window); - gboolean has_focus = window->has_toplevel_focus && window->is_active; - - if (has_focus != window->has_focus) + gboolean has_focus = priv->has_toplevel_focus && priv->is_active; + + if (has_focus != priv->has_focus) { - window->has_focus = has_focus; - + priv->has_focus = has_focus; + if (has_focus) { - if (window->focus_widget && - window->focus_widget != widget && - !gtk_widget_has_focus (window->focus_widget)) - do_focus_change (window->focus_widget, TRUE); + if (priv->focus_widget && + priv->focus_widget != widget && + !gtk_widget_has_focus (priv->focus_widget)) + do_focus_change (priv->focus_widget, TRUE); } else { - if (window->focus_widget && - window->focus_widget != widget && - gtk_widget_has_focus (window->focus_widget)) - do_focus_change (window->focus_widget, FALSE); + if (priv->focus_widget && + priv->focus_widget != widget && + gtk_widget_has_focus (priv->focus_widget)) + do_focus_change (priv->focus_widget, FALSE); } } } @@ -8672,13 +9085,17 @@ void _gtk_window_set_is_active (GtkWindow *window, gboolean is_active) { + GtkWindowPrivate *priv; + g_return_if_fail (GTK_IS_WINDOW (window)); + priv = window->priv; + is_active = is_active != FALSE; - if (is_active != window->is_active) + if (is_active != priv->is_active) { - window->is_active = is_active; + priv->is_active = is_active; window_update_has_focus (window); g_object_notify (G_OBJECT (window), "is-active"); @@ -8689,7 +9106,7 @@ _gtk_window_set_is_active (GtkWindow *window, * _gtk_window_set_is_toplevel: * @window: a #GtkWindow * @is_toplevel: %TRUE if the window is still a real toplevel (nominally a - * parent of the root window); %FALSE if it is not (for example, for an + * child of the root window); %FALSE if it is not (for example, for an * in-process, parented GtkPlug) * * Internal function used by #GtkPlug when it gets parented/unparented by a @@ -8698,9 +9115,10 @@ _gtk_window_set_is_active (GtkWindow *window, */ void _gtk_window_set_is_toplevel (GtkWindow *window, - gboolean is_toplevel) + gboolean is_toplevel) { GtkWidget *widget; + GtkWidget *toplevel; widget = GTK_WIDGET (window); @@ -8714,13 +9132,45 @@ _gtk_window_set_is_toplevel (GtkWindow *window, if (is_toplevel) { + /* Pass through regular pathways of an embedded toplevel + * to go through unmapping and hiding the widget before + * becomming a toplevel again. + * + * We remain hidden after becomming toplevel in order to + * avoid problems during an embedded toplevel's dispose cycle + * (When a toplevel window is shown it tries to grab focus again, + * this causes problems while disposing). + */ + gtk_widget_hide (widget); + + /* Save the toplevel this widget was previously anchored into before + * propagating a hierarchy-changed. + * + * Usually this happens by way of gtk_widget_unparent() and we are + * already unanchored at this point, just adding this clause incase + * things happen differently. + */ + toplevel = gtk_widget_get_toplevel (widget); + if (!gtk_widget_is_toplevel (toplevel)) + toplevel = NULL; + _gtk_widget_set_is_toplevel (widget, TRUE); + + /* When a window becomes toplevel after being embedded and anchored + * into another window we need to unset its anchored flag so that + * the hierarchy changed signal kicks in properly. + */ + _gtk_widget_set_anchored (widget, FALSE); + _gtk_widget_propagate_hierarchy_changed (widget, toplevel); + toplevel_list = g_slist_prepend (toplevel_list, window); } else { _gtk_widget_set_is_toplevel (widget, FALSE); toplevel_list = g_slist_remove (toplevel_list, window); + + _gtk_widget_propagate_hierarchy_changed (widget, widget); } } @@ -8736,13 +9186,17 @@ void _gtk_window_set_has_toplevel_focus (GtkWindow *window, gboolean has_toplevel_focus) { + GtkWindowPrivate *priv; + g_return_if_fail (GTK_IS_WINDOW (window)); - + + priv = window->priv; + has_toplevel_focus = has_toplevel_focus != FALSE; - if (has_toplevel_focus != window->has_toplevel_focus) + if (has_toplevel_focus != priv->has_toplevel_focus) { - window->has_toplevel_focus = has_toplevel_focus; + priv->has_toplevel_focus = has_toplevel_focus; window_update_has_focus (window); g_object_notify (G_OBJECT (window), "has-toplevel-focus"); @@ -8786,7 +9240,7 @@ gtk_window_get_window_type (GtkWindow *window) { g_return_val_if_fail (GTK_IS_WINDOW (window), GTK_WINDOW_TOPLEVEL); - return window->type; + return window->priv->type; } /** @@ -8803,13 +9257,9 @@ gtk_window_get_window_type (GtkWindow *window) gboolean gtk_window_get_mnemonics_visible (GtkWindow *window) { - GtkWindowPrivate *priv; - g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); - priv = GTK_WINDOW_GET_PRIVATE (window); - - return priv->mnemonics_visible; + return window->priv->mnemonics_visible; } /** @@ -8829,7 +9279,7 @@ gtk_window_set_mnemonics_visible (GtkWindow *window, g_return_if_fail (GTK_IS_WINDOW (window)); - priv = GTK_WINDOW_GET_PRIVATE (window); + priv = window->priv; setting = setting != FALSE; @@ -8847,6 +9297,32 @@ _gtk_window_get_wmclass (GtkWindow *window, gchar **wmclass_name, gchar **wmclass_class) { - *wmclass_name = window->wmclass_name; - *wmclass_class = window->wmclass_class; + GtkWindowPrivate *priv = window->priv; + + *wmclass_name = priv->wmclass_name; + *wmclass_class = priv->wmclass_class; +} + +/** + * gtk_window_set_has_user_ref_count: + * @window: a #GtkWindow + * @setting: the new value + * + * Tells GTK+ whether to drop its extra reference to the window + * when gtk_window_destroy() is called. + * + * This function is only exported for the benefit of language + * bindings which may need to keep the window alive until their + * wrapper object is garbage collected. There is no justification + * for ever calling this function in an application. + * + * Since: 3.0 + */ +void +gtk_window_set_has_user_ref_count (GtkWindow *window, + gboolean setting) +{ + g_return_if_fail (GTK_IS_WINDOW (window)); + + window->priv->has_user_ref_count = setting; }