diff options
author | Matthias Clasen <mclasen@redhat.com> | 2020-12-08 15:38:36 +0000 |
---|---|---|
committer | Matthias Clasen <mclasen@redhat.com> | 2020-12-08 15:38:36 +0000 |
commit | 1f141c19533f4b3f397c3959ade673ce243b6138 (patch) | |
tree | a789e257dfd8d6aed9ac0f6e7c6ba44ed2be3ec5 | |
parent | 1e14a91cb9307e039c7e2b5affb247f0f052272d (diff) | |
parent | 074b933ae4e866d092edd734fd43524e39033b5e (diff) | |
download | gtk+-1f141c19533f4b3f397c3959ade673ce243b6138.tar.gz |
Merge branch 'wip/surface-state-rework' into 'master'
Rework surface state and geometry computation
See merge request GNOME/gtk!2885
95 files changed, 1706 insertions, 2219 deletions
diff --git a/demos/gtk-demo/application.c b/demos/gtk-demo/application.c index a03e5c2c66..f1bca0523d 100644 --- a/demos/gtk-demo/application.c +++ b/demos/gtk-demo/application.c @@ -465,7 +465,7 @@ demo_application_window_size_allocate (GtkWidget *widget, baseline); if (!window->maximized && !window->fullscreen) - gtk_window_get_size (GTK_WINDOW (window), &window->width, &window->height); + gtk_window_get_default_size (GTK_WINDOW (window), &window->width, &window->height); } static void diff --git a/demos/gtk-demo/demo3widget.c b/demos/gtk-demo/demo3widget.c index 3a309927e8..7a13f698c4 100644 --- a/demos/gtk-demo/demo3widget.c +++ b/demos/gtk-demo/demo3widget.c @@ -97,9 +97,9 @@ demo3_widget_size_allocate (GtkWidget *widget, /* Since we are not using a layout manager (who would do this * for us), we need to allocate a size for our menu by calling - * gtk_native_check_resize(). + * gtk_popover_present(). */ - gtk_native_check_resize (GTK_NATIVE (self->menu)); + gtk_popover_present (GTK_POPOVER (self->menu)); } static void diff --git a/demos/gtk-demo/suggestionentry.c b/demos/gtk-demo/suggestionentry.c index a0a926979f..8a0b3aa082 100644 --- a/demos/gtk-demo/suggestionentry.c +++ b/demos/gtk-demo/suggestionentry.c @@ -474,7 +474,7 @@ suggestion_entry_size_allocate (GtkWidget *widget, gtk_widget_set_size_request (self->popup, gtk_widget_get_allocated_width (GTK_WIDGET (self)), -1); gtk_widget_queue_resize (self->popup); - gtk_native_check_resize (GTK_NATIVE (self->popup)); + gtk_popover_present (GTK_POPOVER (self->popup)); } static gboolean diff --git a/docs/reference/gdk/gdk4-sections.txt b/docs/reference/gdk/gdk4-sections.txt index 1680e9e3e5..f2e6fa3f3a 100644 --- a/docs/reference/gdk/gdk4-sections.txt +++ b/docs/reference/gdk/gdk4-sections.txt @@ -203,7 +203,6 @@ gdk_surface_get_cursor gdk_surface_set_input_region gdk_surface_get_width gdk_surface_get_height -gdk_surface_set_shadow_width gdk_surface_get_device_position GdkModifierType GDK_MODIFIER_MASK @@ -529,7 +528,6 @@ GDK_IS_EVENT gdk_event_get_type gdk_event_sequence_get_type gdk_button_event_get_type -gdk_configure_event_get_type gdk_crossing_event_get_type gdk_delete_event_get_type gdk_dnd_event_get_type diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt index c8e46d89a2..2bd4d33528 100644 --- a/docs/reference/gtk/gtk4-sections.txt +++ b/docs/reference/gtk/gtk4-sections.txt @@ -4592,6 +4592,7 @@ gtk_window_set_destroy_with_parent gtk_window_set_display gtk_window_is_active gtk_window_is_maximized +gtk_window_is_fullscreen gtk_window_get_toplevels gtk_window_list_toplevels gtk_window_get_focus @@ -4618,12 +4619,10 @@ gtk_window_get_default_size gtk_window_get_destroy_with_parent gtk_window_get_icon_name gtk_window_get_modal -gtk_window_get_size gtk_window_get_title gtk_window_get_transient_for gtk_window_get_group gtk_window_has_group -gtk_window_resize gtk_window_set_default_icon_name gtk_window_set_icon_name gtk_window_set_auto_startup_notification @@ -6116,6 +6115,7 @@ GtkPopover gtk_popover_new gtk_popover_popup gtk_popover_popdown +gtk_popover_present gtk_popover_set_child gtk_popover_get_child gtk_popover_set_pointing_to @@ -6973,7 +6973,6 @@ GtkNative gtk_native_get_for_surface gtk_native_get_surface gtk_native_get_renderer -gtk_native_check_resize gtk_native_get_surface_transform <SUBSECTION Private> diff --git a/docs/reference/gtk/migrating-3to4.md b/docs/reference/gtk/migrating-3to4.md index 8a4fc9f32e..c4024c9c2f 100644 --- a/docs/reference/gtk/migrating-3to4.md +++ b/docs/reference/gtk/migrating-3to4.md @@ -165,7 +165,7 @@ for this change. | ::key-release-event | #GtkEventControllerKey | | ::enter-notify-event | #GtkEventControllerMotion | | ::leave-notify-event | #GtkEventControllerMotion | -| ::configure-event | replaced by #GdkSurface::size-changed | +| ::configure-event | replaced by #GdkSurface::layout | | ::focus-in-event | #GtkEventControllerFocus | | ::focus-out-event | #GtkEventControllerFocus | | ::map-event | replaced by #GdkSurface:mapped | @@ -510,9 +510,14 @@ gtk_window_set_gravity(), gtk_window_move(), gtk_window_parse_geometry(), gtk_window_set_keep_above(), gtk_window_set_keep_below(), gtk_window_begin_resize_drag(), gtk_window_begin_move_drag(). Most likely, you should just stop using them. In some cases, you can -fall back to using the underlying #GdkToplevel APIS (for example, +fall back to using the underlying #GdkToplevel APIs (for example, gdk_toplevel_begin_resize()). +The APIs for controlling GtkWindow size have changed to be better aligned +with the way size changes are integrated in the frame cycle. gtk_window_resize() +and gtk_window_get_size() have been removed. Instead, use +gtk_window_set_default_size() and gtk_window_get_default_size(). + ### Adapt to GtkHeaderBar and GtkActionBar API changes The gtk_header_bar_set_show_close_button() function has been renamed to diff --git a/docs/sizing-test.txt b/docs/sizing-test.txt index 86183a2e83..bd98b0a977 100644 --- a/docs/sizing-test.txt +++ b/docs/sizing-test.txt @@ -12,13 +12,6 @@ gtk_widget_set_size_request(): we use 1x1 for implementation convenience) - causes notifies on width_request, height_request properties -gtk_window_resize(): - - causes a configure request in all cases if the window is mapped, - unless the new size is the same as the old size - - overrides the default size on map if the window is unmapped - - allows size of 0, equivalent to 1 - - clamped to geometry hints - gtk_window_set_default_size(): - has no effect after the window has been mapped the first time, unless the window has been unrealized in which case it should @@ -26,7 +19,6 @@ gtk_window_set_default_size(): - allows size of 0, equivalent to 1 - allows size of -1 to unset the default size - clamped to geometry hints - - gtk_window_resize() overrides it - causes notifies on default_width, default_height properties gtk_window_get_default_size(): diff --git a/gdk/broadway/gdkeventsource.c b/gdk/broadway/gdkeventsource.c index 3aab5583fa..bc332f9b79 100644 --- a/gdk/broadway/gdkeventsource.c +++ b/gdk/broadway/gdkeventsource.c @@ -280,12 +280,7 @@ _gdk_broadway_events_got_input (GdkDisplay *display, surface = g_hash_table_lookup (display_broadway->id_ht, GINT_TO_POINTER (message->configure_notify.id)); if (surface) { - event = gdk_configure_event_new (surface, - message->configure_notify.width, - message->configure_notify.height); - - node = _gdk_event_queue_append (display, event); - _gdk_windowing_got_event (display, node, event, message->base.serial); + gdk_surface_request_layout (surface); if (surface->resize_count >= 1) { diff --git a/gdk/broadway/gdksurface-broadway.c b/gdk/broadway/gdksurface-broadway.c index d9e45ad077..d44b2281f0 100644 --- a/gdk/broadway/gdksurface-broadway.c +++ b/gdk/broadway/gdksurface-broadway.c @@ -558,6 +558,7 @@ gdk_broadway_surface_layout_popup (GdkSurface *surface, int height, GdkPopupLayout *layout) { + GdkBroadwaySurface *impl = GDK_BROADWAY_SURFACE (surface); GdkMonitor *monitor; GdkRectangle bounds; GdkRectangle final_rect; @@ -570,6 +571,10 @@ gdk_broadway_surface_layout_popup (GdkSurface *surface, gdk_surface_layout_popup_helper (surface, width, height, + impl->shadow_left, + impl->shadow_right, + impl->shadow_top, + impl->shadow_bottom, monitor, &bounds, layout, @@ -596,7 +601,7 @@ gdk_broadway_surface_layout_popup (GdkSurface *surface, static void show_popup (GdkSurface *surface) { - gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_WITHDRAWN, 0); + gdk_surface_set_is_mapped (surface, TRUE); gdk_broadway_surface_show (surface, FALSE); gdk_surface_invalidate_rect (surface, NULL); } @@ -1516,7 +1521,7 @@ show_surface (GdkSurface *surface) was_mapped = GDK_SURFACE_IS_MAPPED (surface); if (!was_mapped) - gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_WITHDRAWN, 0); + gdk_surface_set_is_mapped (surface, TRUE); gdk_broadway_surface_show (surface, FALSE); @@ -1524,11 +1529,12 @@ show_surface (GdkSurface *surface) gdk_surface_invalidate_rect (surface, NULL); } -static gboolean +static void gdk_broadway_toplevel_present (GdkToplevel *toplevel, GdkToplevelLayout *layout) { GdkSurface *surface = GDK_SURFACE (toplevel); + GdkBroadwaySurface *impl = GDK_BROADWAY_SURFACE (surface); GdkDisplay *display = gdk_surface_get_display (surface); GdkMonitor *monitor; GdkToplevelSize size; @@ -1582,9 +1588,15 @@ gdk_broadway_toplevel_present (GdkToplevel *toplevel, else gdk_broadway_surface_unmaximize (surface); - show_surface (surface); + if (size.shadow.is_valid) + { + impl->shadow_left = size.shadow.left; + impl->shadow_right = size.shadow.right; + impl->shadow_top = size.shadow.top; + impl->shadow_bottom = size.shadow.bottom; + } - return TRUE; + show_surface (surface); } static gboolean diff --git a/gdk/broadway/gdksurface-broadway.h b/gdk/broadway/gdksurface-broadway.h index 0ca144fc80..95cb02ce6d 100644 --- a/gdk/broadway/gdksurface-broadway.h +++ b/gdk/broadway/gdksurface-broadway.h @@ -64,6 +64,11 @@ struct _GdkBroadwaySurface int root_x; int root_y; + + int shadow_left; + int shadow_right; + int shadow_top; + int shadow_bottom; }; struct _GdkBroadwaySurfaceClass diff --git a/gdk/gdk-private.h b/gdk/gdk-private.h index d2d185d57e..3df7d3215c 100644 --- a/gdk/gdk-private.h +++ b/gdk/gdk-private.h @@ -15,9 +15,6 @@ gboolean gdk_device_grab_info (GdkDisplay *display, void gdk_pre_parse (void); -void gdk_surface_freeze_toplevel_updates (GdkSurface *surface); -void gdk_surface_thaw_toplevel_updates (GdkSurface *surface); - gboolean gdk_surface_supports_edge_constraints (GdkSurface *surface); void gdk_display_set_double_click_time (GdkDisplay *display, diff --git a/gdk/gdkdeviceprivate.h b/gdk/gdkdeviceprivate.h index 79d24378a0..a4cfffc28b 100644 --- a/gdk/gdkdeviceprivate.h +++ b/gdk/gdkdeviceprivate.h @@ -54,12 +54,11 @@ typedef enum GDK_PROPERTY_CHANGE_MASK = 1 << 16, GDK_PROXIMITY_IN_MASK = 1 << 18, GDK_PROXIMITY_OUT_MASK = 1 << 19, - GDK_SUBSTRUCTURE_MASK = 1 << 20, - GDK_SCROLL_MASK = 1 << 21, - GDK_TOUCH_MASK = 1 << 22, - GDK_SMOOTH_SCROLL_MASK = 1 << 23, - GDK_TOUCHPAD_GESTURE_MASK = 1 << 24, - GDK_TABLET_PAD_MASK = 1 << 25, + GDK_SCROLL_MASK = 1 << 20, + GDK_TOUCH_MASK = 1 << 21, + GDK_SMOOTH_SCROLL_MASK = 1 << 22, + GDK_TOUCHPAD_GESTURE_MASK = 1 << 23, + GDK_TABLET_PAD_MASK = 1 << 24, GDK_ALL_EVENTS_MASK = 0x3FFFFFE } GdkEventMask; diff --git a/gdk/gdkevents.c b/gdk/gdkevents.c index 9cfefd0d39..30dee67dcd 100644 --- a/gdk/gdkevents.c +++ b/gdk/gdkevents.c @@ -430,7 +430,6 @@ static void gdk_event_init_types_once (void) { g_type_ensure (GDK_TYPE_BUTTON_EVENT); - g_type_ensure (GDK_TYPE_CONFIGURE_EVENT); g_type_ensure (GDK_TYPE_CROSSING_EVENT); g_type_ensure (GDK_TYPE_DELETE_EVENT); g_type_ensure (GDK_TYPE_DND_EVENT); @@ -1818,76 +1817,6 @@ gdk_key_event_get_match (GdkEvent *event, /* }}} */ -/* {{{ GdkConfigureEvent */ - -static gboolean -gdk_configure_event_get_position (GdkEvent *event, - double *x, - double *y) -{ - GdkConfigureEvent *self = (GdkConfigureEvent *) event; - - *x = self->x; - *y = self->y; - - return TRUE; -} - -static const GdkEventTypeInfo gdk_configure_event_info = { - sizeof (GdkConfigureEvent), - NULL, - NULL, - NULL, - gdk_configure_event_get_position, - NULL, - NULL, - NULL, -}; - -GDK_DEFINE_EVENT_TYPE (GdkConfigureEvent, gdk_configure_event, - &gdk_configure_event_info, - GDK_EVENT_TYPE_SLOT (GDK_CONFIGURE)) - -GdkEvent * -gdk_configure_event_new (GdkSurface *surface, - int width, - int height) -{ - GdkConfigureEvent *self; - - g_return_val_if_fail (width >= 0 && height >= 0, NULL); - - self = gdk_event_alloc (GDK_CONFIGURE, surface, NULL, GDK_CURRENT_TIME); - self->width = width; - self->height = height; - - return (GdkEvent *) self; -} - -/** - * gdk_configure_event_get_size: - * @event: (type GdkConfigureEvent): a configure event - * @width: (out): return location for surface width - * @height: (out): return location for surface height - * - * Extracts the surface size from a configure event. - */ -void -gdk_configure_event_get_size (GdkEvent *event, - int *width, - int *height) -{ - GdkConfigureEvent *self = (GdkConfigureEvent *) event; - - g_return_if_fail (GDK_IS_EVENT (event)); - g_return_if_fail (GDK_IS_EVENT_TYPE (event, GDK_CONFIGURE)); - - *width = self->width; - *height = self->height; -} - -/* }}} */ - /* {{{ GdkTouchEvent */ static void diff --git a/gdk/gdkevents.h b/gdk/gdkevents.h index 0ecd5a80df..2b87754eec 100644 --- a/gdk/gdkevents.h +++ b/gdk/gdkevents.h @@ -106,7 +106,6 @@ typedef struct _GdkEventSequence GdkEventSequence; typedef struct _GdkEvent GdkEvent; #define GDK_TYPE_BUTTON_EVENT (gdk_button_event_get_type()) -#define GDK_TYPE_CONFIGURE_EVENT (gdk_configure_event_get_type()) #define GDK_TYPE_CROSSING_EVENT (gdk_crossing_event_get_type()) #define GDK_TYPE_DELETE_EVENT (gdk_delete_event_get_type()) #define GDK_TYPE_DND_EVENT (gdk_dnd_event_get_type()) @@ -121,7 +120,6 @@ typedef struct _GdkEvent GdkEvent; #define GDK_TYPE_TOUCHPAD_EVENT (gdk_touchpad_event_get_type()) typedef struct _GdkButtonEvent GdkButtonEvent; -typedef struct _GdkConfigureEvent GdkConfigureEvent; typedef struct _GdkCrossingEvent GdkCrossingEvent; typedef struct _GdkDeleteEvent GdkDeleteEvent; typedef struct _GdkDNDEvent GdkDNDEvent; @@ -148,7 +146,6 @@ typedef struct _GdkTouchpadEvent GdkTouchpadEvent; * @GDK_ENTER_NOTIFY: the pointer has entered the surface. * @GDK_LEAVE_NOTIFY: the pointer has left the surface. * @GDK_FOCUS_CHANGE: the keyboard focus has entered or left the surface. - * @GDK_CONFIGURE: the size of the surface has changed. * @GDK_PROXIMITY_IN: an input device has moved into contact with a sensing * surface (e.g. a touchscreen or graphics tablet). * @GDK_PROXIMITY_OUT: an input device has moved out of contact with a sensing @@ -188,7 +185,6 @@ typedef enum GDK_ENTER_NOTIFY, GDK_LEAVE_NOTIFY, GDK_FOCUS_CHANGE, - GDK_CONFIGURE, GDK_PROXIMITY_IN, GDK_PROXIMITY_OUT, GDK_DRAG_ENTER, @@ -429,12 +425,6 @@ GdkNotifyType gdk_crossing_event_get_detail (GdkEvent *event); GDK_AVAILABLE_IN_ALL gboolean gdk_crossing_event_get_focus (GdkEvent *event); GDK_AVAILABLE_IN_ALL -GType gdk_configure_event_get_type (void) G_GNUC_CONST; -GDK_AVAILABLE_IN_ALL -void gdk_configure_event_get_size (GdkEvent *event, - int *width, - int *height); -GDK_AVAILABLE_IN_ALL GType gdk_touchpad_event_get_type (void) G_GNUC_CONST; GDK_AVAILABLE_IN_ALL GdkTouchpadGesturePhase diff --git a/gdk/gdkeventsprivate.h b/gdk/gdkeventsprivate.h index a521ca5ab5..c64598572e 100644 --- a/gdk/gdkeventsprivate.h +++ b/gdk/gdkeventsprivate.h @@ -323,25 +323,6 @@ struct _GdkFocusEvent }; /* - * GdkConfigureEvent: - * @x: the new x coordinate of the surface, relative to its parent. - * @y: the new y coordinate of the surface, relative to its parent. - * @width: the new width of the surface. - * @height: the new height of the surface. - * - * Generated when a surface size or position has changed. - */ -struct _GdkConfigureEvent -{ - GdkEvent parent_instance; - - int x; - int y; - int width; - int height; -}; - -/* * GdkProximityEvent: * @tool: the #GdkDeviceTool associated to the event * diff --git a/gdk/gdkframeclock.h b/gdk/gdkframeclock.h index a2eba246ad..f50512c150 100644 --- a/gdk/gdkframeclock.h +++ b/gdk/gdkframeclock.h @@ -50,7 +50,7 @@ typedef struct _GdkFrameClockClass GdkFrameClockClass; * @GDK_FRAME_CLOCK_PHASE_FLUSH_EVENTS: corresponds to GdkFrameClock::flush-events. Should not be handled by applications. * @GDK_FRAME_CLOCK_PHASE_BEFORE_PAINT: corresponds to GdkFrameClock::before-paint. Should not be handled by applications. * @GDK_FRAME_CLOCK_PHASE_UPDATE: corresponds to GdkFrameClock::update. - * @GDK_FRAME_CLOCK_PHASE_LAYOUT: corresponds to GdkFrameClock::layout. + * @GDK_FRAME_CLOCK_PHASE_LAYOUT: corresponds to GdkFrameClock::layout. Should not be handled by applicatiosn. * @GDK_FRAME_CLOCK_PHASE_PAINT: corresponds to GdkFrameClock::paint. * @GDK_FRAME_CLOCK_PHASE_RESUME_EVENTS: corresponds to GdkFrameClock::resume-events. Should not be handled by applications. * @GDK_FRAME_CLOCK_PHASE_AFTER_PAINT: corresponds to GdkFrameClock::after-paint. Should not be handled by applications. diff --git a/gdk/gdkpopup.c b/gdk/gdkpopup.c index 375a0fcb92..26b8fe55dd 100644 --- a/gdk/gdkpopup.c +++ b/gdk/gdkpopup.c @@ -38,15 +38,6 @@ G_DEFINE_INTERFACE (GdkPopup, gdk_popup, GDK_TYPE_SURFACE) -enum -{ - POPUP_LAYOUT_CHANGED, - - N_SIGNALS -}; - -static guint signals[N_SIGNALS] = { 0 }; - static gboolean gdk_popup_default_present (GdkPopup *popup, int width, @@ -101,25 +92,6 @@ gdk_popup_default_init (GdkPopupInterface *iface) P_("Whether to hide on outside clicks"), FALSE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS)); - - /** - * GdkPopup::popup-layout-changed - * @popup: the #GdkSurface that was laid out - * - * Emitted when the layout of a popup surface has changed, e.g. if the popup - * layout was reactive and after the parent moved causing the popover to end - * up partially off-screen. - */ - signals[POPUP_LAYOUT_CHANGED] = - g_signal_new (g_intern_static_string ("popup-layout-changed"), - GDK_TYPE_POPUP, - G_SIGNAL_RUN_FIRST, - 0, - NULL, - NULL, - NULL, - G_TYPE_NONE, - 0); } /** @@ -133,13 +105,16 @@ gdk_popup_default_init (GdkPopupInterface *iface) * If the popup was previously now showing, it will be showed, * otherwise it will change position according to @layout. * - * After calling this function, the result of the layout can be queried - * using gdk_popup_get_position_x(), gdk_popup_get_position_y(), - * gdk_surface_get_width(), gdk_surface_get_height(), - * gdk_popup_get_rect_anchor() and gdk_popup_get_surface_anchor(). + * After calling this function, the result should be handled in response + * to the #GdkSurface::layout signal being emitted. The resulting popup + * position can be queried using gdk_popup_get_position_x(), + * gdk_popup_get_position_y(), and the resulting size will be sent as + * parameters in the layout signal. Use gdk_popup_get_rect_anchor() and + * gdk_popup_get_surface_anchor() to get the resulting anchors. * - * Presenting may have fail, for example if it was immediately - * hidden if the @popup was set to autohide. + * Presenting may fail, for example if the @popup is set to autohide + * and is immediately hidden upon being presented. If presenting failed, + * the #GdkSurface::layout signal will not me emitted. * * Returns: %FALSE if it failed to be presented, otherwise %TRUE. */ @@ -164,7 +139,7 @@ gdk_popup_present (GdkPopup *popup, * Gets the current popup surface anchor. * * The value returned may change after calling gdk_popup_present(), - * or after the "popup-layout-changed" is emitted. + * or after the #GdkSurface::layout signal is emitted. * * Returns: the current surface anchor value of @popup */ @@ -183,7 +158,7 @@ gdk_popup_get_surface_anchor (GdkPopup *popup) * Gets the current popup rectangle anchor. * * The value returned may change after calling gdk_popup_present(), - * or after the "popup-layout-changed" is emitted. + * or after the #GdkSurface::layout signal is emitted. * * Returns: the current rectangle anchor value of @popup */ diff --git a/gdk/gdksurface.c b/gdk/gdksurface.c index 93e61d5c68..012864479a 100644 --- a/gdk/gdksurface.c +++ b/gdk/gdksurface.c @@ -76,8 +76,7 @@ */ enum { - POPUP_LAYOUT_CHANGED, - SIZE_CHANGED, + LAYOUT, RENDER, EVENT, ENTER_MONITOR, @@ -115,6 +114,9 @@ static void update_cursor (GdkDisplay *display, static void gdk_surface_set_frame_clock (GdkSurface *surface, GdkFrameClock *clock); +static void gdk_surface_queue_set_is_mapped (GdkSurface *surface, + gboolean is_mapped); + static guint signals[LAST_SIGNAL] = { 0 }; static GParamSpec *properties[LAST_PROP] = { NULL, }; @@ -285,6 +287,10 @@ void gdk_surface_layout_popup_helper (GdkSurface *surface, int width, int height, + int shadow_left, + int shadow_right, + int shadow_top, + int shadow_bottom, GdkMonitor *monitor, GdkRectangle *bounds, GdkPopupLayout *layout, @@ -315,8 +321,8 @@ gdk_surface_layout_popup_helper (GdkSurface *surface, gdk_popup_layout_get_offset (layout, &rect_anchor_dx, &rect_anchor_dy); anchor_hints = gdk_popup_layout_get_anchor_hints (layout); - final_rect.width = width - surface->shadow_left - surface->shadow_right; - final_rect.height = height - surface->shadow_top - surface->shadow_bottom; + final_rect.width = width - shadow_left - shadow_right; + final_rect.height = height - shadow_top - shadow_bottom; final_rect.x = maybe_flip_position (bounds->x, bounds->width, root_rect.x, @@ -380,10 +386,10 @@ gdk_surface_layout_popup_helper (GdkSurface *surface, final_rect.height = bounds->y + bounds->height - final_rect.y; } - final_rect.x -= surface->shadow_left; - final_rect.y -= surface->shadow_top; - final_rect.width += surface->shadow_left + surface->shadow_right; - final_rect.height += surface->shadow_top + surface->shadow_bottom; + final_rect.x -= shadow_left; + final_rect.y -= shadow_top; + final_rect.width += shadow_left + shadow_right; + final_rect.height += shadow_top + shadow_bottom; gdk_surface_get_origin (surface->parent, &x, &y); final_rect.x -= x; @@ -469,7 +475,7 @@ gdk_surface_init (GdkSurface *surface) { /* 0-initialization is good for all other fields. */ - surface->state = GDK_TOPLEVEL_STATE_WITHDRAWN; + surface->state = 0; surface->fullscreen_mode = GDK_FULLSCREEN_ON_CURRENT_MONITOR; surface->width = 1; surface->height = 1; @@ -548,18 +554,19 @@ gdk_surface_class_init (GdkSurfaceClass *klass) g_object_class_install_properties (object_class, LAST_PROP, properties); /** - * GdkSurface::size-changed: + * GdkSurface::layout: * @surface: the #GdkSurface - * @width: the new width - * @height: the new height + * @width: the current width + * @height: the current height * - * Emitted when the size of @surface is changed. + * Emitted when the size of @surface is changed, or when relayout should + * be performed. * * Surface size is reported in ”application pixels”, not * ”device pixels” (see gdk_surface_get_scale_factor()). */ - signals[SIZE_CHANGED] = - g_signal_new (g_intern_static_string ("size-changed"), + signals[LAYOUT] = + g_signal_new (g_intern_static_string ("layout"), G_OBJECT_CLASS_TYPE (object_class), G_SIGNAL_RUN_FIRST, 0, @@ -919,7 +926,10 @@ _gdk_surface_destroy_hierarchy (GdkSurface *surface, _gdk_surface_clear_update_area (surface); - surface->state |= GDK_TOPLEVEL_STATE_WITHDRAWN; + g_clear_handle_id (&surface->set_is_mapped_source_id, g_source_remove); + surface->is_mapped = FALSE; + surface->pending_is_mapped = FALSE; + surface->destroyed = TRUE; surface_remove_from_pointer_info (surface, surface->display); @@ -1264,7 +1274,7 @@ gdk_surface_schedule_update (GdkSurface *surface) if (surface->update_freeze_count || gdk_surface_is_toplevel_frozen (surface)) { - surface->pending_schedule_update = TRUE; + surface->pending_phases |= GDK_FRAME_CLOCK_PHASE_PAINT; return; } @@ -1318,6 +1328,50 @@ gdk_surface_process_updates_internal (GdkSurface *surface) } static void +gdk_surface_layout_on_clock (GdkFrameClock *clock, + void *data) +{ + GdkSurface *surface = GDK_SURFACE (data); + GdkSurfaceClass *class; + + g_return_if_fail (GDK_IS_SURFACE (surface)); + + if (GDK_SURFACE_DESTROYED (surface)) + return; + + if (!GDK_SURFACE_IS_MAPPED (surface)) + return; + + surface->pending_phases &= ~GDK_FRAME_CLOCK_PHASE_LAYOUT; + + class = GDK_SURFACE_GET_CLASS (surface); + if (class->compute_size) + { + if (class->compute_size (surface)) + return; + } + + g_signal_emit (surface, signals[LAYOUT], 0, surface->width, surface->height); +} + +void +gdk_surface_request_layout (GdkSurface *surface) +{ + GdkSurfaceClass *class; + GdkFrameClock *frame_clock; + + class = GDK_SURFACE_GET_CLASS (surface); + if (class->request_layout) + class->request_layout (surface); + + frame_clock = gdk_surface_get_frame_clock (surface); + g_return_if_fail (frame_clock); + + gdk_frame_clock_request_phase (frame_clock, + GDK_FRAME_CLOCK_PHASE_LAYOUT); +} + +static void gdk_surface_paint_on_clock (GdkFrameClock *clock, void *data) { @@ -1338,6 +1392,7 @@ gdk_surface_paint_on_clock (GdkFrameClock *clock, * do the update later when idle instead. */ !surface->in_update) { + surface->pending_phases &= ~GDK_FRAME_CLOCK_PHASE_PAINT; gdk_surface_process_updates_internal (surface); gdk_surface_remove_update_surface (surface); } @@ -1515,35 +1570,13 @@ gdk_surface_thaw_updates (GdkSurface *surface) if (--surface->update_freeze_count == 0) { - _gdk_frame_clock_inhibit_freeze (surface->frame_clock); - - if (surface->pending_schedule_update) - { - surface->pending_schedule_update = FALSE; - gdk_surface_schedule_update (surface); - } - } -} - -void -gdk_surface_freeze_toplevel_updates (GdkSurface *surface) -{ - g_return_if_fail (GDK_IS_SURFACE (surface)); - - surface->update_and_descendants_freeze_count++; - gdk_surface_freeze_updates (surface); -} + GdkFrameClock *frame_clock = surface->frame_clock; -void -gdk_surface_thaw_toplevel_updates (GdkSurface *surface) -{ - g_return_if_fail (GDK_IS_SURFACE (surface)); - g_return_if_fail (surface->update_and_descendants_freeze_count > 0); - - surface->update_and_descendants_freeze_count--; - gdk_surface_schedule_update (surface); - gdk_surface_thaw_updates (surface); + _gdk_frame_clock_inhibit_freeze (frame_clock); + if (surface->pending_phases) + gdk_frame_clock_request_phase (frame_clock, surface->pending_phases); + } } /* @@ -1669,8 +1702,7 @@ gdk_surface_hide (GdkSurface *surface) was_mapped = GDK_SURFACE_IS_MAPPED (surface); - if (GDK_SURFACE_IS_MAPPED (surface)) - gdk_synthesize_surface_state (surface, 0, GDK_TOPLEVEL_STATE_WITHDRAWN); + gdk_surface_queue_set_is_mapped (surface, FALSE); if (was_mapped) { @@ -2412,6 +2444,10 @@ gdk_surface_set_frame_clock (GdkSurface *surface, G_CALLBACK (gdk_surface_resume_events), surface); g_signal_connect (G_OBJECT (clock), + "layout", + G_CALLBACK (gdk_surface_layout_on_clock), + surface); + g_signal_connect (G_OBJECT (clock), "paint", G_CALLBACK (gdk_surface_paint_on_clock), surface); @@ -2432,6 +2468,9 @@ gdk_surface_set_frame_clock (GdkSurface *surface, G_CALLBACK (gdk_surface_resume_events), surface); g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock), + G_CALLBACK (gdk_surface_layout_on_clock), + surface); + g_signal_handlers_disconnect_by_func (G_OBJECT (surface->frame_clock), G_CALLBACK (gdk_surface_paint_on_clock), surface); @@ -2570,58 +2609,10 @@ gdk_surface_set_opaque_region (GdkSurface *surface, class->set_opaque_region (surface, region); } -/** - * gdk_surface_set_shadow_width: - * @surface: a #GdkSurface - * @left: The left extent - * @right: The right extent - * @top: The top extent - * @bottom: The bottom extent - * - * Newer GTK windows using client-side decorations use extra geometry - * around their frames for effects like shadows and invisible borders. - * Window managers that want to maximize windows or snap to edges need - * to know where the extents of the actual frame lie, so that users - * don’t feel like windows are snapping against random invisible edges. - * - * Note that this property is automatically updated by GTK, so this - * function should only be used by applications which do not use GTK - * to create toplevel surfaces. - */ -void -gdk_surface_set_shadow_width (GdkSurface *surface, - int left, - int right, - int top, - int bottom) -{ - GdkSurfaceClass *class; - - g_return_if_fail (GDK_IS_SURFACE (surface)); - g_return_if_fail (!GDK_SURFACE_DESTROYED (surface)); - g_return_if_fail (left >= 0 && right >= 0 && top >= 0 && bottom >= 0); - - if (surface->shadow_left == left && - surface->shadow_right == right && - surface->shadow_top == top && - surface->shadow_bottom == bottom) - return; - - surface->shadow_top = top; - surface->shadow_left = left; - surface->shadow_right = right; - surface->shadow_bottom = bottom; - - class = GDK_SURFACE_GET_CLASS (surface); - if (class->set_shadow_width) - class->set_shadow_width (surface, left, right, top, bottom); -} - void gdk_surface_set_state (GdkSurface *surface, GdkToplevelState new_state) { - gboolean was_mapped, mapped; gboolean was_sticky, sticky; g_return_if_fail (GDK_IS_SURFACE (surface)); @@ -2633,20 +2624,15 @@ gdk_surface_set_state (GdkSurface *surface, * inconsistent state to the user. */ - was_mapped = GDK_SURFACE_IS_MAPPED (surface); was_sticky = GDK_SURFACE_IS_STICKY (surface); surface->state = new_state; - mapped = GDK_SURFACE_IS_MAPPED (surface); sticky = GDK_SURFACE_IS_STICKY (surface); if (GDK_IS_TOPLEVEL (surface)) g_object_notify (G_OBJECT (surface), "state"); - if (was_mapped != mapped) - g_object_notify_by_pspec (G_OBJECT (surface), properties[PROP_MAPPED]); - if (was_sticky != sticky) g_object_notify (G_OBJECT (surface), "sticky"); } @@ -2659,6 +2645,94 @@ gdk_synthesize_surface_state (GdkSurface *surface, gdk_surface_set_state (surface, (surface->state | set_flags) & ~unset_flags); } +void +gdk_surface_queue_state_change (GdkSurface *surface, + GdkToplevelState unset_flags, + GdkToplevelState set_flags) +{ + surface->pending_unset_flags |= unset_flags; + surface->pending_set_flags &= ~unset_flags; + + surface->pending_set_flags |= set_flags; + surface->pending_unset_flags &= ~set_flags; +} + +void +gdk_surface_apply_state_change (GdkSurface *surface) +{ + if (!surface->pending_unset_flags && !surface->pending_set_flags) + return; + + gdk_synthesize_surface_state (surface, + surface->pending_unset_flags, + surface->pending_set_flags); + surface->pending_unset_flags = 0; + surface->pending_set_flags = 0; +} + +static gboolean +set_is_mapped_idle (gpointer user_data) +{ + GdkSurface *surface = GDK_SURFACE (user_data); + + surface->set_is_mapped_source_id = 0; + + g_return_val_if_fail (surface->pending_is_mapped != surface->is_mapped, + G_SOURCE_REMOVE); + + surface->is_mapped = surface->pending_is_mapped; + if (surface->is_mapped) + gdk_surface_invalidate_rect (surface, NULL); + + g_object_notify (G_OBJECT (surface), "mapped"); + + return G_SOURCE_REMOVE; +} + +void +gdk_surface_set_is_mapped (GdkSurface *surface, + gboolean is_mapped) +{ + gboolean was_mapped; + + if (surface->pending_is_mapped != surface->is_mapped) + g_clear_handle_id (&surface->set_is_mapped_source_id, g_source_remove); + + surface->pending_is_mapped = is_mapped; + + was_mapped = surface->is_mapped; + surface->is_mapped = is_mapped; + if (surface->is_mapped) + gdk_surface_invalidate_rect (surface, NULL); + + if (was_mapped != is_mapped) + g_object_notify (G_OBJECT (surface), "mapped"); +} + +static void +gdk_surface_queue_set_is_mapped (GdkSurface *surface, + gboolean is_mapped) +{ + if (surface->pending_is_mapped == is_mapped) + return; + + surface->pending_is_mapped = is_mapped; + + if (surface->is_mapped == surface->pending_is_mapped) + { + g_clear_handle_id (&surface->set_is_mapped_source_id, g_source_remove); + } + else + { + g_return_if_fail (!surface->set_is_mapped_source_id); + + surface->set_is_mapped_source_id = + g_idle_add_full (G_PRIORITY_HIGH - 10, + set_is_mapped_idle, + surface, NULL); + } +} + static gboolean check_autohide (GdkEvent *event) { @@ -2770,14 +2844,6 @@ add_event_mark (GdkEvent *event, break; } - case GDK_CONFIGURE: - { - int width, height; - gdk_configure_event_get_size (event, &width, &height); - message = g_strdup_printf ("%s {width=%d, height=%d}", kind, width, height); - break; - } - case GDK_ENTER_NOTIFY: case GDK_LEAVE_NOTIFY: case GDK_TOUCHPAD_SWIPE: @@ -2815,30 +2881,18 @@ add_event_mark (GdkEvent *event, gboolean gdk_surface_handle_event (GdkEvent *event) { + GdkSurface *surface = gdk_event_get_surface (event); gint64 begin_time = GDK_PROFILER_CURRENT_TIME; gboolean handled = FALSE; if (check_autohide (event)) return TRUE; - if (gdk_event_get_event_type (event) == GDK_CONFIGURE) - { - int width, height; - gdk_configure_event_get_size (event, &width, &height); - g_signal_emit (gdk_event_get_surface (event), signals[SIZE_CHANGED], 0, - width, height); - handled = TRUE; - } - else - { - GdkSurface *surface = gdk_event_get_surface (event); - - if (gdk_event_get_event_type (event) == GDK_MOTION_NOTIFY) - surface->request_motion = FALSE; + if (gdk_event_get_event_type (event) == GDK_MOTION_NOTIFY) + surface->request_motion = FALSE; - g_signal_emit (surface, signals[EVENT], 0, event, &handled); - } + g_signal_emit (surface, signals[EVENT], 0, event, &handled); if (GDK_PROFILER_IS_RUNNING) add_event_mark (event, begin_time, GDK_PROFILER_CURRENT_TIME); diff --git a/gdk/gdksurface.h b/gdk/gdksurface.h index 6b2cfcd03b..4e083ec07b 100644 --- a/gdk/gdksurface.h +++ b/gdk/gdksurface.h @@ -119,6 +119,9 @@ GDK_AVAILABLE_IN_ALL void gdk_surface_queue_render (GdkSurface *surface); GDK_AVAILABLE_IN_ALL +void gdk_surface_request_layout (GdkSurface *surface); + +GDK_AVAILABLE_IN_ALL GdkFrameClock* gdk_surface_get_frame_clock (GdkSurface *surface); GDK_AVAILABLE_IN_ALL @@ -126,13 +129,6 @@ void gdk_surface_set_opaque_region (GdkSurface *surface, cairo_region_t *region); GDK_AVAILABLE_IN_ALL -void gdk_surface_set_shadow_width (GdkSurface *surface, - int left, - int right, - int top, - int bottom); - -GDK_AVAILABLE_IN_ALL GdkCairoContext *gdk_surface_create_cairo_context(GdkSurface *surface); GDK_AVAILABLE_IN_ALL GdkGLContext * gdk_surface_create_gl_context (GdkSurface *surface, diff --git a/gdk/gdksurfaceprivate.h b/gdk/gdksurfaceprivate.h index f655d6c97f..27a3966fe7 100644 --- a/gdk/gdksurfaceprivate.h +++ b/gdk/gdksurfaceprivate.h @@ -44,6 +44,10 @@ struct _GdkSurface GdkSurface *parent; /* for popups */ GList *children; /* popups */ + guint set_is_mapped_source_id; + gboolean pending_is_mapped; + gboolean is_mapped; + gpointer widget; int x; @@ -53,13 +57,14 @@ struct _GdkSurface cairo_region_t *update_area; guint update_freeze_count; - gboolean pending_schedule_update; + GdkFrameClockPhase pending_phases; /* This is the update_area that was in effect when the current expose started. It may be smaller than the expose area if we'e painting more than we have to, but it represents the "true" damage. */ cairo_region_t *active_update_area; - GdkToplevelState old_state; + GdkToplevelState pending_set_flags; + GdkToplevelState pending_unset_flags; GdkToplevelState state; guint8 resize_count; @@ -83,10 +88,6 @@ struct _GdkSurface guint update_and_descendants_freeze_count; int width, height; - int shadow_top; - int shadow_left; - int shadow_right; - int shadow_bottom; GdkCursor *cursor; GHashTable *device_cursor; @@ -160,25 +161,24 @@ struct _GdkSurfaceClass void (* set_opaque_region) (GdkSurface *surface, cairo_region_t *region); - void (* set_shadow_width) (GdkSurface *surface, - int left, - int right, - int top, - int bottom); GdkGLContext *(*create_gl_context) (GdkSurface *surface, gboolean attached, GdkGLContext *share, GError **error); + void (* request_layout) (GdkSurface *surface); + gboolean (* compute_size) (GdkSurface *surface); }; #define GDK_SURFACE_DESTROYED(d) (((GdkSurface *)(d))->destroyed) -#define GDK_SURFACE_IS_MAPPED(surface) (((surface)->state & GDK_TOPLEVEL_STATE_WITHDRAWN) == 0) - +#define GDK_SURFACE_IS_MAPPED(surface) ((surface)->pending_is_mapped) void gdk_surface_set_state (GdkSurface *surface, GdkToplevelState new_state); +void gdk_surface_set_is_mapped (GdkSurface *surface, + gboolean is_mapped); + GdkMonitor * gdk_surface_get_layout_monitor (GdkSurface *surface, GdkPopupLayout *layout, void (*get_bounds) (GdkMonitor *monitor, @@ -187,6 +187,10 @@ GdkMonitor * gdk_surface_get_layout_monitor (GdkSurface *surface, void gdk_surface_layout_popup_helper (GdkSurface *surface, int width, int height, + int shadow_left, + int shadow_right, + int shadow_top, + int shadow_bottom, GdkMonitor *monitor, GdkRectangle *bounds, GdkPopupLayout *layout, @@ -326,9 +330,22 @@ void gdk_surface_constrain_size (GdkGeometry *geometry, int *new_width, int *new_height); +void gdk_surface_queue_state_change (GdkSurface *surface, + GdkToplevelState unset_flags, + GdkToplevelState set_flags); + +void gdk_surface_apply_state_change (GdkSurface *surface); + +void gdk_surface_emit_size_changed (GdkSurface *surface, + int width, + int height); + +void gdk_surface_request_compute_size (GdkSurface *surface); + GDK_AVAILABLE_IN_ALL void gdk_surface_request_motion (GdkSurface *surface); + G_END_DECLS #endif /* __GDK_SURFACE_PRIVATE_H__ */ diff --git a/gdk/gdktoplevel.c b/gdk/gdktoplevel.c index 34328db10d..13eb38cda1 100644 --- a/gdk/gdktoplevel.c +++ b/gdk/gdktoplevel.c @@ -51,11 +51,10 @@ enum static guint signals[N_SIGNALS] = { 0 }; -static gboolean +static void gdk_toplevel_default_present (GdkToplevel *toplevel, GdkToplevelLayout *layout) { - return FALSE; } static gboolean @@ -124,7 +123,7 @@ gdk_toplevel_default_init (GdkToplevelInterface *iface) g_param_spec_flags ("state", P_("State"), P_("State"), - GDK_TYPE_TOPLEVEL_STATE, GDK_TOPLEVEL_STATE_WITHDRAWN, + GDK_TYPE_TOPLEVEL_STATE, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); g_object_interface_install_property (iface, g_param_spec_string ("title", @@ -239,18 +238,17 @@ gdk_toplevel_install_properties (GObjectClass *object_class, * compute the preferred size of the toplevel surface. See * #GdkToplevel::compute-size for details. * - * Presenting may fail. - * - * Returns: %FALSE if @toplevel failed to be presented, otherwise %TRUE. + * Presenting is asynchronous and the specified layout parameters are not + * guaranteed to be respected. */ -gboolean +void gdk_toplevel_present (GdkToplevel *toplevel, GdkToplevelLayout *layout) { - g_return_val_if_fail (GDK_IS_TOPLEVEL (toplevel), FALSE); - g_return_val_if_fail (layout != NULL, FALSE); + g_return_if_fail (GDK_IS_TOPLEVEL (toplevel)); + g_return_if_fail (layout != NULL); - return GDK_TOPLEVEL_GET_IFACE (toplevel)->present (toplevel, layout); + GDK_TOPLEVEL_GET_IFACE (toplevel)->present (toplevel, layout); } /** diff --git a/gdk/gdktoplevel.h b/gdk/gdktoplevel.h index 05fafa4b5f..fb29315710 100644 --- a/gdk/gdktoplevel.h +++ b/gdk/gdktoplevel.h @@ -71,7 +71,6 @@ typedef enum /** * GdkToplevelState: - * @GDK_TOPLEVEL_STATE_WITHDRAWN: the surface is not shown * @GDK_TOPLEVEL_STATE_MINIMIZED: the surface is minimized * @GDK_TOPLEVEL_STATE_MAXIMIZED: the surface is maximized * @GDK_TOPLEVEL_STATE_STICKY: the surface is sticky @@ -98,23 +97,22 @@ typedef enum */ typedef enum { - GDK_TOPLEVEL_STATE_WITHDRAWN = 1 << 0, - GDK_TOPLEVEL_STATE_MINIMIZED = 1 << 1, - GDK_TOPLEVEL_STATE_MAXIMIZED = 1 << 2, - GDK_TOPLEVEL_STATE_STICKY = 1 << 3, - GDK_TOPLEVEL_STATE_FULLSCREEN = 1 << 4, - GDK_TOPLEVEL_STATE_ABOVE = 1 << 5, - GDK_TOPLEVEL_STATE_BELOW = 1 << 6, - GDK_TOPLEVEL_STATE_FOCUSED = 1 << 7, - GDK_TOPLEVEL_STATE_TILED = 1 << 8, - GDK_TOPLEVEL_STATE_TOP_TILED = 1 << 9, - GDK_TOPLEVEL_STATE_TOP_RESIZABLE = 1 << 10, - GDK_TOPLEVEL_STATE_RIGHT_TILED = 1 << 11, - GDK_TOPLEVEL_STATE_RIGHT_RESIZABLE = 1 << 12, - GDK_TOPLEVEL_STATE_BOTTOM_TILED = 1 << 13, - GDK_TOPLEVEL_STATE_BOTTOM_RESIZABLE = 1 << 14, - GDK_TOPLEVEL_STATE_LEFT_TILED = 1 << 15, - GDK_TOPLEVEL_STATE_LEFT_RESIZABLE = 1 << 16 + GDK_TOPLEVEL_STATE_MINIMIZED = 1 << 0, + GDK_TOPLEVEL_STATE_MAXIMIZED = 1 << 1, + GDK_TOPLEVEL_STATE_STICKY = 1 << 2, + GDK_TOPLEVEL_STATE_FULLSCREEN = 1 << 3, + GDK_TOPLEVEL_STATE_ABOVE = 1 << 4, + GDK_TOPLEVEL_STATE_BELOW = 1 << 5, + GDK_TOPLEVEL_STATE_FOCUSED = 1 << 6, + GDK_TOPLEVEL_STATE_TILED = 1 << 7, + GDK_TOPLEVEL_STATE_TOP_TILED = 1 << 8, + GDK_TOPLEVEL_STATE_TOP_RESIZABLE = 1 << 9, + GDK_TOPLEVEL_STATE_RIGHT_TILED = 1 << 10, + GDK_TOPLEVEL_STATE_RIGHT_RESIZABLE = 1 << 11, + GDK_TOPLEVEL_STATE_BOTTOM_TILED = 1 << 12, + GDK_TOPLEVEL_STATE_BOTTOM_RESIZABLE = 1 << 13, + GDK_TOPLEVEL_STATE_LEFT_TILED = 1 << 14, + GDK_TOPLEVEL_STATE_LEFT_RESIZABLE = 1 << 15 } GdkToplevelState; @@ -129,7 +127,7 @@ GDK_AVAILABLE_IN_ALL G_DECLARE_INTERFACE (GdkToplevel, gdk_toplevel, GDK, TOPLEVEL, GObject) GDK_AVAILABLE_IN_ALL -gboolean gdk_toplevel_present (GdkToplevel *toplevel, +void gdk_toplevel_present (GdkToplevel *toplevel, GdkToplevelLayout *layout); GDK_AVAILABLE_IN_ALL diff --git a/gdk/gdktoplevelprivate.h b/gdk/gdktoplevelprivate.h index 989ac29c46..52dcdca0ad 100644 --- a/gdk/gdktoplevelprivate.h +++ b/gdk/gdktoplevelprivate.h @@ -13,7 +13,7 @@ struct _GdkToplevelInterface { GTypeInterface g_iface; - gboolean (* present) (GdkToplevel *toplevel, + void (* present) (GdkToplevel *toplevel, GdkToplevelLayout *layout); gboolean (* minimize) (GdkToplevel *toplevel); gboolean (* lower) (GdkToplevel *toplevel); diff --git a/gdk/gdktoplevelsize.c b/gdk/gdktoplevelsize.c index e5802782d4..6932f6435b 100644 --- a/gdk/gdktoplevelsize.c +++ b/gdk/gdktoplevelsize.c @@ -118,18 +118,53 @@ gdk_toplevel_size_set_min_size (GdkToplevelSize *size, size->min_height = min_height; } +/** + * gdk_toplevel_size_set_shadow_width: + * @size: a #GdkToplevelSize + * @left: width of the left part of the shadow + * @right: width of the right part of the shadow + * @top: height of the top part of the shadow + * @bottom: height of the bottom part of the shadow + * + * The shadow width corresponds to the part of the computed surface size + * that would consist of the shadow margin surrounding the window, would + * there be any. + */ +void +gdk_toplevel_size_set_shadow_width (GdkToplevelSize *size, + int left, + int right, + int top, + int bottom) +{ + size->shadow.is_valid = TRUE; + size->shadow.left = left; + size->shadow.right = right; + size->shadow.top = top; + size->shadow.bottom = bottom; +} + void gdk_toplevel_size_validate (GdkToplevelSize *size) { + int geometry_width, geometry_height; + if (size->min_width > size->bounds_width || size->min_height > size->bounds_height) g_warning ("GdkToplevelSize: min_size (%d, %d) exceeds bounds (%d, %d)", size->min_width, size->min_height, size->bounds_width, size->bounds_height); - if (size->width > size->bounds_width || - size->height > size->bounds_height) - g_warning ("GdkToplevelSize: size (%d, %d) exceeds bounds (%d, %d)", + geometry_width = size->width; + geometry_height = size->height; + if (size->shadow.is_valid) + { + geometry_width -= size->shadow.left + size->shadow.right; + geometry_height -= size->shadow.top + size->shadow.bottom; + } + if (geometry_width > size->bounds_width || + geometry_height > size->bounds_height) + g_warning ("GdkToplevelSize: geometry size (%d, %d) exceeds bounds (%d, %d)", size->width, size->height, size->bounds_width, size->bounds_height); diff --git a/gdk/gdktoplevelsize.h b/gdk/gdktoplevelsize.h index 013a061ee9..69306d9413 100644 --- a/gdk/gdktoplevelsize.h +++ b/gdk/gdktoplevelsize.h @@ -54,6 +54,13 @@ void gdk_toplevel_size_set_min_size (GdkToplevelSize * int min_width, int min_height); +GDK_AVAILABLE_IN_ALL +void gdk_toplevel_size_set_shadow_width (GdkToplevelSize *size, + int left, + int right, + int top, + int bottom); + G_END_DECLS #endif /* __GDK_TOPLEVEL_SIZE_H__ */ diff --git a/gdk/gdktoplevelsizeprivate.h b/gdk/gdktoplevelsizeprivate.h index 3576513888..bba34cc7d7 100644 --- a/gdk/gdktoplevelsizeprivate.h +++ b/gdk/gdktoplevelsizeprivate.h @@ -30,6 +30,14 @@ struct _GdkToplevelSize int height; int min_width; int min_height; + + struct { + gboolean is_valid; + int left; + int right; + int top; + int bottom; + } shadow; }; void gdk_toplevel_size_init (GdkToplevelSize *size, diff --git a/gdk/macos/GdkMacosWindow.c b/gdk/macos/GdkMacosWindow.c index 46a97adcfc..dd762543d0 100644 --- a/gdk/macos/GdkMacosWindow.c +++ b/gdk/macos/GdkMacosWindow.c @@ -256,13 +256,7 @@ _gdk_surface_update_size (surface); - /* Synthesize a configure event */ - event = gdk_configure_event_new (surface, - content_rect.size.width, - content_rect.size.height); - node = _gdk_event_queue_append (display, event); - _gdk_windowing_got_event (display, node, event, - _gdk_display_get_next_serial (display)); + gdk_surface_request_layout (surface); _gdk_macos_surface_reposition_children (gdk_surface); diff --git a/gdk/macos/gdkmacospopupsurface.c b/gdk/macos/gdkmacospopupsurface.c index 48c2ca02b8..23c44a70a8 100644 --- a/gdk/macos/gdkmacospopupsurface.c +++ b/gdk/macos/gdkmacospopupsurface.c @@ -69,6 +69,10 @@ gdk_macos_popup_surface_layout (GdkMacosPopupSurface *self, gdk_surface_layout_popup_helper (GDK_SURFACE (self), width, height, + self->parent_instance.shadow_left, + self->parent_instance.shadow_right, + self->parent_instance.shadow_top, + self->parent_instance.shadow_bottom, monitor, &bounds, self->layout, diff --git a/gdk/macos/gdkmacossurface-private.h b/gdk/macos/gdkmacossurface-private.h index 074fd28854..9dd2a7ba52 100644 --- a/gdk/macos/gdkmacossurface-private.h +++ b/gdk/macos/gdkmacossurface-private.h @@ -125,6 +125,11 @@ void _gdk_macos_surface_set_opacity (GdkMacosSurface void _gdk_macos_surface_get_root_coords (GdkMacosSurface *self, int *x, int *y); +void _gdk_macos_surface_set_shadow_width (GdkSurface *surface, + int left, + int right, + int top, + int bottom); G_END_DECLS diff --git a/gdk/macos/gdkmacossurface.c b/gdk/macos/gdkmacossurface.c index 7c1c03f44d..5e528ca8e2 100644 --- a/gdk/macos/gdkmacossurface.c +++ b/gdk/macos/gdkmacossurface.c @@ -85,7 +85,7 @@ _gdk_macos_surface_reposition_children (GdkMacosSurface *self) } if (GDK_IS_POPUP (self) && self->did_initial_present) - g_signal_emit_by_name (self, "popup-layout-changed"); + gdk_surface_request_layout (GDK_SURFACE (self)); } static void @@ -139,7 +139,7 @@ gdk_macos_surface_get_scale_factor (GdkSurface *surface) return [self->window backingScaleFactor]; } -static void +void gdk_macos_surface_set_shadow_width (GdkSurface *surface, int left, int right, @@ -491,7 +491,6 @@ gdk_macos_surface_class_init (GdkMacosSurfaceClass *klass) surface_class->hide = gdk_macos_surface_hide; surface_class->set_input_region = gdk_macos_surface_set_input_region; surface_class->set_opaque_region = gdk_macos_surface_set_opaque_region; - surface_class->set_shadow_width = gdk_macos_surface_set_shadow_width; properties [PROP_NATIVE] = g_param_spec_pointer ("native", @@ -763,7 +762,7 @@ _gdk_macos_surface_show (GdkMacosSurface *self) was_mapped = GDK_SURFACE_IS_MAPPED (GDK_SURFACE (self)); if (!was_mapped) - gdk_synthesize_surface_state (GDK_SURFACE (self), GDK_TOPLEVEL_STATE_WITHDRAWN, 0); + gdk_surface_set_is_mapped (GDK_SURFACE (self), TRUE); _gdk_macos_display_clear_sorting (GDK_MACOS_DISPLAY (GDK_SURFACE (self)->display)); diff --git a/gdk/macos/gdkmacostoplevelsurface.c b/gdk/macos/gdkmacostoplevelsurface.c index 7af4725b35..63d924c3a2 100644 --- a/gdk/macos/gdkmacostoplevelsurface.c +++ b/gdk/macos/gdkmacostoplevelsurface.c @@ -155,6 +155,15 @@ _gdk_macos_toplevel_surface_present (GdkToplevel *toplevel, if (style_mask != [nswindow styleMask]) [nswindow setStyleMask:style_mask]; + if (size.shadow.is_valid) + { + _gdk_macos_surface_set_shadow_width (surface, + size.shadow.left, + size.shadow.right, + size.shadow.top, + size.shadow.bottom); + } + _gdk_macos_surface_set_geometry_hints (GDK_MACOS_SURFACE (self), &geometry, mask); gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height); _gdk_macos_surface_resize (GDK_MACOS_SURFACE (self), width, height); diff --git a/gdk/wayland/gdkdevice-wayland.c b/gdk/wayland/gdkdevice-wayland.c index 8671561175..c975c2069d 100644 --- a/gdk/wayland/gdkdevice-wayland.c +++ b/gdk/wayland/gdkdevice-wayland.c @@ -4502,7 +4502,7 @@ gdk_wayland_seat_grab (GdkSeat *seat, if (prepare_func) (prepare_func) (seat, surface, prepare_func_data); - if (!gdk_surface_get_mapped (surface)) + if (!gdk_wayland_surface_has_surface (surface)) { gdk_wayland_seat_set_grab_surface (wayland_seat, NULL); return GDK_GRAB_NOT_VIEWABLE; diff --git a/gdk/wayland/gdkprivate-wayland.h b/gdk/wayland/gdkprivate-wayland.h index 19a4e91c0b..eadacffbb9 100644 --- a/gdk/wayland/gdkprivate-wayland.h +++ b/gdk/wayland/gdkprivate-wayland.h @@ -96,6 +96,7 @@ void gdk_wayland_surface_sync (GdkSurface *surface); void gdk_wayland_surface_commit (GdkSurface *surface); void gdk_wayland_surface_notify_committed (GdkSurface *surface); void gdk_wayland_surface_request_frame (GdkSurface *surface); +gboolean gdk_wayland_surface_has_surface (GdkSurface *surface); void gdk_wayland_surface_attach_image (GdkSurface *surface, cairo_surface_t *cairo_surface, const cairo_region_t *damage); diff --git a/gdk/wayland/gdksurface-wayland.c b/gdk/wayland/gdksurface-wayland.c index 35378851c6..602d76b773 100644 --- a/gdk/wayland/gdksurface-wayland.c +++ b/gdk/wayland/gdksurface-wayland.c @@ -122,11 +122,11 @@ struct _GdkWaylandSurface gint64 pending_frame_counter; guint32 scale; - int margin_left; - int margin_right; - int margin_top; - int margin_bottom; - gboolean margin_dirty; + int shadow_left; + int shadow_right; + int shadow_top; + int shadow_bottom; + gboolean shadow_dirty; struct wl_output *initial_fullscreen_output; @@ -162,6 +162,7 @@ struct _GdkWaylandSurface int width; int height; GdkToplevelState state; + gboolean is_resizing; } toplevel; struct { @@ -179,6 +180,25 @@ struct _GdkWaylandSurface gboolean is_dirty; } pending; + struct { + GdkToplevelState unset_flags; + GdkToplevelState set_flags; + } initial_state; + + struct { + struct { + gboolean should_constrain; + gboolean size_is_fixed; + } toplevel; + struct { + int x; + int y; + } popup; + int configured_width; + int configured_height; + gboolean surface_geometry_dirty; + } next_layout; + uint32_t last_configure_serial; int state_freeze_count; @@ -264,12 +284,17 @@ static void gdk_wayland_surface_maybe_resize (GdkSurface *surface, int height, int scale); +static void gdk_wayland_surface_resize (GdkSurface *surface, + int width, + int height, + int scale); + static void gdk_wayland_surface_configure (GdkSurface *surface); static void maybe_set_gtk_surface_dbus_properties (GdkWaylandSurface *impl); static void maybe_set_gtk_surface_modal (GdkSurface *surface); -static void gdk_wayland_surface_sync_margin (GdkSurface *surface); +static void gdk_wayland_surface_sync_shadow (GdkSurface *surface); static void gdk_wayland_surface_sync_input_region (GdkSurface *surface); static void gdk_wayland_surface_sync_opaque_region (GdkSurface *surface); @@ -290,6 +315,8 @@ static void update_popup_layout_state (GdkSurface *surface, static gboolean gdk_wayland_surface_is_exported (GdkWaylandSurface *impl); +static void configure_toplevel_geometry (GdkSurface *surface); + static void gdk_wayland_surface_init (GdkWaylandSurface *impl) { @@ -336,8 +363,11 @@ _gdk_wayland_surface_save_size (GdkSurface *surface) GDK_TOPLEVEL_STATE_TILED)) return; - impl->saved_width = surface->width - impl->margin_left - impl->margin_right; - impl->saved_height = surface->height - impl->margin_top - impl->margin_bottom; + if (surface->width <= 1 || surface->height <= 1) + return; + + impl->saved_width = surface->width - impl->shadow_left - impl->shadow_right; + impl->saved_height = surface->height - impl->shadow_top - impl->shadow_bottom; } static void @@ -582,6 +612,59 @@ on_frame_clock_before_paint (GdkFrameClock *clock, */ timings->predicted_presentation_time = timings->frame_time + refresh_interval / 2 + refresh_interval; } + + gdk_surface_apply_state_change (surface); +} + +static void +configure_popup_geometry (GdkSurface *surface) +{ + GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); + + gdk_wayland_surface_move_resize (surface, + impl->next_layout.popup.x, + impl->next_layout.popup.y, + impl->next_layout.configured_width, + impl->next_layout.configured_height); +} + +static void +configure_drag_surface_geometry (GdkSurface *surface) +{ + GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); + + gdk_wayland_surface_resize (surface, + impl->next_layout.configured_width, + impl->next_layout.configured_height, + impl->scale); +} + +static gboolean +gdk_wayland_surface_compute_size (GdkSurface *surface) +{ + GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); + + if (impl->next_layout.surface_geometry_dirty) + { + if (GDK_IS_TOPLEVEL (impl)) + configure_toplevel_geometry (surface); + else if (GDK_IS_POPUP (impl)) + configure_popup_geometry (surface); + else if (GDK_IS_DRAG_SURFACE (impl)) + configure_drag_surface_geometry (surface); + + impl->next_layout.surface_geometry_dirty = FALSE; + } + + return FALSE; +} + +static void +gdk_wayland_surface_request_layout (GdkSurface *surface) +{ + GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); + + impl->next_layout.surface_geometry_dirty = TRUE; } void @@ -603,6 +686,14 @@ gdk_wayland_surface_request_frame (GdkSurface *surface) impl->awaiting_frame = TRUE; } +gboolean +gdk_wayland_surface_has_surface (GdkSurface *surface) +{ + GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); + + return !!impl->display_server.wl_surface; +} + void gdk_wayland_surface_commit (GdkSurface *surface) { @@ -801,7 +892,7 @@ gdk_wayland_surface_attach_image (GdkSurface *surface, void gdk_wayland_surface_sync (GdkSurface *surface) { - gdk_wayland_surface_sync_margin (surface); + gdk_wayland_surface_sync_shadow (surface); gdk_wayland_surface_sync_opaque_region (surface); gdk_wayland_surface_sync_input_region (surface); } @@ -910,16 +1001,6 @@ gdk_wayland_surface_resize (GdkSurface *surface, { gdk_wayland_surface_update_size (surface, width, height, scale); _gdk_surface_update_size (surface); - - if (is_realized_shell_surface (GDK_WAYLAND_SURFACE (surface))) - { - GdkDisplay *display; - GdkEvent *event; - - event = gdk_configure_event_new (surface, width, height); - display = gdk_surface_get_display (surface); - _gdk_wayland_display_deliver_event (display, event); - } } static void gdk_wayland_surface_show (GdkSurface *surface, @@ -1069,10 +1150,10 @@ gdk_wayland_surface_get_window_geometry (GdkSurface *surface, GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); *geometry = (GdkRectangle) { - .x = impl->margin_left, - .y = impl->margin_top, - .width = surface->width - (impl->margin_left + impl->margin_right), - .height = surface->height - (impl->margin_top + impl->margin_bottom) + .x = impl->shadow_left, + .y = impl->shadow_top, + .width = surface->width - (impl->shadow_left + impl->shadow_right), + .height = surface->height - (impl->shadow_top + impl->shadow_bottom) }; } @@ -1081,7 +1162,7 @@ static void gdk_wayland_surface_set_geometry_hints (GdkWaylandSurface *impl, GdkSurfaceHints geom_mask); static void -gdk_wayland_surface_sync_margin (GdkSurface *surface) +gdk_wayland_surface_sync_shadow (GdkSurface *surface) { GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); GdkWaylandDisplay *display_wayland = @@ -1255,7 +1336,7 @@ gdk_wayland_surface_create_surface (GdkSurface *surface) } static void -configure_surface_geometry (GdkSurface *surface) +configure_toplevel_geometry (GdkSurface *surface) { GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); GdkDisplay *display = gdk_surface_get_display (surface); @@ -1263,7 +1344,6 @@ configure_surface_geometry (GdkSurface *surface) GdkRectangle monitor_geometry; int bounds_width, bounds_height; GdkToplevelSize size; - int width, height; GdkToplevelLayout *layout; GdkGeometry geometry; GdkSurfaceHints mask; @@ -1276,10 +1356,8 @@ configure_surface_geometry (GdkSurface *surface) gdk_toplevel_size_init (&size, bounds_width, bounds_height); gdk_toplevel_notify_compute_size (GDK_TOPLEVEL (surface), &size); - width = size.width; - height = size.height; - g_warn_if_fail (width > 0); - g_warn_if_fail (height > 0); + g_warn_if_fail (size.width > 0); + g_warn_if_fail (size.height > 0); layout = impl->toplevel.layout; if (gdk_toplevel_layout_get_resizable (layout)) @@ -1290,13 +1368,71 @@ configure_surface_geometry (GdkSurface *surface) } else { - geometry.max_width = geometry.min_width = width; - geometry.max_height = geometry.min_height = height; + geometry.max_width = geometry.min_width = size.width; + geometry.max_height = geometry.min_height = size.height; mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE; } gdk_wayland_surface_set_geometry_hints (impl, &geometry, mask); - gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height); - gdk_wayland_surface_resize (surface, width, height, impl->scale); + + if (size.shadow.is_valid) + { + impl->shadow_left = size.shadow.left; + impl->shadow_right = size.shadow.right; + impl->shadow_top = size.shadow.top; + impl->shadow_bottom = size.shadow.bottom; + } + + if (impl->next_layout.configured_width > 0 && + impl->next_layout.configured_height > 0) + { + int width, height; + + width = impl->next_layout.configured_width + + impl->shadow_left + impl->shadow_right; + height = impl->next_layout.configured_height + + impl->shadow_top + impl->shadow_bottom; + + if (impl->next_layout.toplevel.should_constrain) + { + gdk_surface_constrain_size (&impl->geometry_hints, + impl->geometry_mask, + width, height, + &width, &height); + } + gdk_wayland_surface_resize (surface, width, height, impl->scale); + + if (!impl->next_layout.toplevel.size_is_fixed) + { + impl->next_layout.toplevel.should_constrain = FALSE; + impl->next_layout.configured_width = 0; + impl->next_layout.configured_height = 0; + } + } + else + { + int width, height; + + width = size.width; + height = size.height; + gdk_surface_constrain_size (&geometry, mask, + width, height, + &width, &height); + gdk_wayland_surface_resize (surface, width, height, impl->scale); + } +} + +static void +synthesize_initial_surface_state (GdkSurface *surface, + GdkToplevelState unset_flags, + GdkToplevelState set_flags) +{ + GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); + + impl->initial_state.unset_flags |= unset_flags; + impl->initial_state.set_flags &= ~unset_flags; + + impl->initial_state.set_flags |= set_flags; + impl->initial_state.unset_flags &= ~set_flags; } static void @@ -1307,16 +1443,21 @@ gdk_wayland_surface_configure_toplevel (GdkSurface *surface) GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface)); GdkToplevelState new_state; int width, height; + gboolean is_resizing; gboolean fixed_size; gboolean saved_size; new_state = impl->pending.toplevel.state; impl->pending.toplevel.state = 0; + is_resizing = impl->pending.toplevel.is_resizing; + impl->pending.toplevel.is_resizing = FALSE; + fixed_size = new_state & (GDK_TOPLEVEL_STATE_MAXIMIZED | GDK_TOPLEVEL_STATE_FULLSCREEN | - GDK_TOPLEVEL_STATE_TILED); + GDK_TOPLEVEL_STATE_TILED) || + is_resizing; width = impl->pending.toplevel.width; height = impl->pending.toplevel.height; @@ -1338,34 +1479,37 @@ gdk_wayland_surface_configure_toplevel (GdkSurface *surface) if (width > 0 && height > 0) { - GdkSurfaceHints geometry_mask = impl->geometry_mask; - if (!saved_size) { - /* Do not reapply constrains if we are restoring original size */ - gdk_surface_constrain_size (&impl->geometry_hints, - geometry_mask, - width + impl->margin_left + impl->margin_right, - height + impl->margin_top + impl->margin_bottom, - &width, - &height); + impl->next_layout.toplevel.should_constrain = TRUE; /* Save size for next time we get 0x0 */ _gdk_wayland_surface_save_size (surface); } + else if (is_resizing) + { + impl->next_layout.toplevel.should_constrain = TRUE; + } else { - width += impl->margin_left + impl->margin_right; - height += impl->margin_top + impl->margin_bottom; + impl->next_layout.toplevel.should_constrain = FALSE; } - gdk_wayland_surface_resize (surface, width, height, impl->scale); + impl->next_layout.toplevel.size_is_fixed = fixed_size; + impl->next_layout.configured_width = width; + impl->next_layout.configured_height = height; } else { - configure_surface_geometry (surface); + impl->next_layout.toplevel.should_constrain = FALSE; + impl->next_layout.toplevel.size_is_fixed = FALSE; + impl->next_layout.configured_width = 0; + impl->next_layout.configured_height = 0; } + impl->next_layout.surface_geometry_dirty = TRUE; + gdk_surface_request_layout (surface); + GDK_DISPLAY_NOTE (gdk_surface_get_display (surface), EVENTS, g_message ("configure, surface %p %dx%d,%s%s%s%s", surface, width, height, @@ -1374,7 +1518,7 @@ gdk_wayland_surface_configure_toplevel (GdkSurface *surface) (new_state & GDK_TOPLEVEL_STATE_FOCUSED) ? " focused" : "", (new_state & GDK_TOPLEVEL_STATE_TILED) ? " tiled" : "")); - gdk_surface_set_state (surface, new_state); + gdk_surface_queue_state_change (surface, ~0 & ~new_state, new_state); switch (display_wayland->shell_variant) { @@ -1395,6 +1539,7 @@ static void gdk_wayland_surface_configure_popup (GdkSurface *surface) { GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); + GdkWaylandSurface *parent_impl = GDK_WAYLAND_SURFACE (surface->parent); int x, y, width, height; if (impl->display_server.xdg_popup) @@ -1434,18 +1579,30 @@ gdk_wayland_surface_configure_popup (GdkSurface *surface) width = impl->pending.popup.width; height = impl->pending.popup.height; - gdk_wayland_surface_resize (surface, width, height, impl->scale); + x += parent_impl->shadow_left; + y += parent_impl->shadow_top; update_popup_layout_state (surface, x, y, width, height, impl->popup.layout); - if (!impl->pending.popup.has_repositioned_token && - !impl->pending.is_initial_configure) - g_signal_emit_by_name (surface, "popup-layout-changed"); + impl->next_layout.popup.x = x; + impl->next_layout.popup.y = y; + impl->next_layout.configured_width = width; + impl->next_layout.configured_height = height; + impl->next_layout.surface_geometry_dirty = TRUE; + gdk_surface_request_layout (surface); +} - gdk_surface_invalidate_rect (surface, NULL); +static void +maybe_notify_mapped (GdkSurface *surface) +{ + if (surface->destroyed) + return; + + if (!GDK_SURFACE_IS_MAPPED (surface)) + gdk_surface_set_is_mapped (surface, TRUE); } static void @@ -1458,6 +1615,7 @@ gdk_wayland_surface_configure (GdkSurface *surface) gdk_surface_thaw_updates (surface); impl->initial_configure_received = TRUE; impl->pending.is_initial_configure = TRUE; + maybe_notify_mapped (surface); } impl->has_uncommitted_ack_configure = TRUE; @@ -1539,9 +1697,12 @@ xdg_toplevel_configure (void *data, struct wl_array *states) { GdkSurface *surface = GDK_SURFACE (data); + GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); uint32_t *p; GdkToplevelState pending_state = 0; + impl->pending.toplevel.is_resizing = FALSE; + wl_array_for_each (p, states) { uint32_t state = *p; @@ -1558,6 +1719,7 @@ xdg_toplevel_configure (void *data, pending_state |= GDK_TOPLEVEL_STATE_FOCUSED; break; case XDG_TOPLEVEL_STATE_RESIZING: + impl->pending.toplevel.is_resizing = TRUE; break; default: /* Unknown state */ @@ -1628,9 +1790,12 @@ zxdg_toplevel_v6_configure (void *data, struct wl_array *states) { GdkSurface *surface = GDK_SURFACE (data); + GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); uint32_t *p; GdkToplevelState pending_state = 0; + impl->pending.toplevel.is_resizing = FALSE; + wl_array_for_each (p, states) { uint32_t state = *p; @@ -1647,6 +1812,7 @@ zxdg_toplevel_v6_configure (void *data, pending_state |= GDK_TOPLEVEL_STATE_FOCUSED; break; case ZXDG_TOPLEVEL_V6_STATE_RESIZING: + impl->pending.toplevel.is_resizing = TRUE; break; default: /* Unknown state */ @@ -1764,20 +1930,20 @@ gdk_wayland_surface_create_xdg_toplevel (GdkSurface *surface) switch (display_wayland->shell_variant) { case GDK_WAYLAND_SHELL_VARIANT_XDG_SHELL: - if (surface->state & GDK_TOPLEVEL_STATE_MAXIMIZED) + if (impl->initial_state.set_flags & GDK_TOPLEVEL_STATE_MAXIMIZED) xdg_toplevel_set_maximized (impl->display_server.xdg_toplevel); - if (surface->state & GDK_TOPLEVEL_STATE_MINIMIZED) + if (impl->initial_state.set_flags & GDK_TOPLEVEL_STATE_MINIMIZED) xdg_toplevel_set_minimized (impl->display_server.xdg_toplevel); - if (surface->state & GDK_TOPLEVEL_STATE_FULLSCREEN) + if (impl->initial_state.set_flags & GDK_TOPLEVEL_STATE_FULLSCREEN) xdg_toplevel_set_fullscreen (impl->display_server.xdg_toplevel, impl->initial_fullscreen_output); break; case GDK_WAYLAND_SHELL_VARIANT_ZXDG_SHELL_V6: - if (surface->state & GDK_TOPLEVEL_STATE_MAXIMIZED) + if (impl->initial_state.set_flags & GDK_TOPLEVEL_STATE_MAXIMIZED) zxdg_toplevel_v6_set_maximized (impl->display_server.zxdg_toplevel_v6); - if (surface->state & GDK_TOPLEVEL_STATE_MINIMIZED) + if (impl->initial_state.set_flags & GDK_TOPLEVEL_STATE_MINIMIZED) zxdg_toplevel_v6_set_minimized (impl->display_server.zxdg_toplevel_v6); - if (surface->state & GDK_TOPLEVEL_STATE_FULLSCREEN) + if (impl->initial_state.set_flags & GDK_TOPLEVEL_STATE_FULLSCREEN) zxdg_toplevel_v6_set_fullscreen (impl->display_server.zxdg_toplevel_v6, impl->initial_fullscreen_output); break; @@ -2098,9 +2264,9 @@ calculate_popup_rect (GdkSurface *surface, int x = 0, y = 0; width = (impl->popup.unconstrained_width - - (impl->margin_left + impl->margin_right)); + (impl->shadow_left + impl->shadow_right)); height = (impl->popup.unconstrained_height - - (impl->margin_top + impl->margin_bottom)); + (impl->shadow_top + impl->shadow_bottom)); anchor_rect = *gdk_popup_layout_get_anchor_rect (layout); gdk_popup_layout_get_offset (layout, &dx, &dy); @@ -2201,26 +2367,12 @@ update_popup_layout_state (GdkSurface *surface, int height, GdkPopupLayout *layout) { - int surface_x, surface_y; - int surface_width, surface_height; GdkRectangle best_rect; GdkRectangle flipped_rect; GdkGravity rect_anchor; GdkGravity surface_anchor; GdkAnchorHints anchor_hints; - x += surface->parent->shadow_left; - y += surface->parent->shadow_top; - - surface_x = x; - surface_y = y; - surface_width = width + surface->shadow_left + surface->shadow_right; - surface_height = height + surface->shadow_top + surface->shadow_bottom; - - gdk_wayland_surface_move_resize (surface, - surface_x, surface_y, - surface_width, surface_height); - rect_anchor = gdk_popup_layout_get_rect_anchor (layout); surface_anchor = gdk_popup_layout_get_surface_anchor (layout); anchor_hints = gdk_popup_layout_get_anchor_hints (layout); @@ -2300,6 +2452,7 @@ create_dynamic_positioner (GdkSurface *surface, { GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); GdkSurface *parent = surface->parent; + GdkWaylandSurface *parent_impl = GDK_WAYLAND_SURFACE (parent); GdkWaylandDisplay *display = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface)); GdkRectangle geometry; @@ -2314,15 +2467,15 @@ create_dynamic_positioner (GdkSurface *surface, GdkAnchorHints anchor_hints; geometry = (GdkRectangle) { - .x = impl->margin_left, - .y = impl->margin_top, - .width = width - (impl->margin_left + impl->margin_right), - .height = height - (impl->margin_top + impl->margin_bottom), + .x = impl->shadow_left, + .y = impl->shadow_top, + .width = width - (impl->shadow_left + impl->shadow_right), + .height = height - (impl->shadow_top + impl->shadow_bottom), }; anchor_rect = gdk_popup_layout_get_anchor_rect (layout); - real_anchor_rect_x = anchor_rect->x - parent->shadow_left; - real_anchor_rect_y = anchor_rect->y - parent->shadow_top; + real_anchor_rect_x = anchor_rect->x - parent_impl->shadow_left; + real_anchor_rect_y = anchor_rect->y - parent_impl->shadow_top; anchor_rect_width = MAX (anchor_rect->width, 1); anchor_rect_height = MAX (anchor_rect->height, 1); @@ -2381,14 +2534,13 @@ create_dynamic_positioner (GdkSurface *surface, xdg_positioner_get_version (positioner) >= XDG_POSITIONER_SET_PARENT_CONFIGURE_SINCE_VERSION) { - GdkWaylandSurface *parent_impl = GDK_WAYLAND_SURFACE (parent); int parent_width; int parent_height; - parent_width = parent->width - (parent_impl->margin_left + - parent_impl->margin_right); - parent_height = parent->height - (parent_impl->margin_top + - parent_impl->margin_bottom); + parent_width = parent->width - (parent_impl->shadow_left + + parent_impl->shadow_right); + parent_height = parent->height - (parent_impl->shadow_top + + parent_impl->shadow_bottom); xdg_positioner_set_parent_size (positioner, parent_width, @@ -2807,6 +2959,12 @@ gdk_wayland_surface_hide_surface (GdkSurface *surface) unset_transient_for_exported (surface); + impl->last_sent_window_geometry = (GdkRectangle) { 0 }; + impl->last_sent_min_width = 0; + impl->last_sent_min_height = 0; + impl->last_sent_max_width = 0; + impl->last_sent_max_height = 0; + _gdk_wayland_surface_clear_saved_size (surface); impl->mapped = FALSE; } @@ -2982,8 +3140,6 @@ gdk_wayland_surface_map_popup (GdkSurface *surface, impl->popup.unconstrained_width = width; impl->popup.unconstrained_height = height; impl->mapped = TRUE; - - gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_WITHDRAWN, 0); } static void @@ -3410,9 +3566,9 @@ gdk_wayland_surface_set_geometry_hints (GdkWaylandSurface *impl, if (geom_mask & GDK_HINT_MIN_SIZE) { min_width = MAX (0, (geometry->min_width - - (impl->margin_left + impl->margin_right))); + (impl->shadow_left + impl->shadow_right))); min_height = MAX (0, (geometry->min_height - - (impl->margin_top + impl->margin_bottom))); + (impl->shadow_top + impl->shadow_bottom))); } else { @@ -3423,9 +3579,9 @@ gdk_wayland_surface_set_geometry_hints (GdkWaylandSurface *impl, if (geom_mask & GDK_HINT_MAX_SIZE) { max_width = MAX (0, (geometry->max_width - - (impl->margin_left + impl->margin_right))); + (impl->shadow_left + impl->shadow_right))); max_height = MAX (0, (geometry->max_height - - (impl->margin_top + impl->margin_bottom))); + (impl->shadow_top + impl->shadow_bottom))); } else { @@ -3608,7 +3764,7 @@ gdk_wayland_surface_maximize (GdkSurface *surface) } else { - gdk_synthesize_surface_state (surface, 0, GDK_TOPLEVEL_STATE_MAXIMIZED); + synthesize_initial_surface_state (surface, 0, GDK_TOPLEVEL_STATE_MAXIMIZED); } } @@ -3639,7 +3795,7 @@ gdk_wayland_surface_unmaximize (GdkSurface *surface) } else { - gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_MAXIMIZED, 0); + synthesize_initial_surface_state (surface, GDK_TOPLEVEL_STATE_MAXIMIZED, 0); } } @@ -3676,7 +3832,7 @@ gdk_wayland_surface_fullscreen_on_monitor (GdkSurface *surface, } else { - gdk_synthesize_surface_state (surface, 0, GDK_TOPLEVEL_STATE_FULLSCREEN); + synthesize_initial_surface_state (surface, 0, GDK_TOPLEVEL_STATE_FULLSCREEN); impl->initial_fullscreen_output = output; } } @@ -3714,7 +3870,7 @@ gdk_wayland_surface_fullscreen (GdkSurface *surface) } else { - gdk_synthesize_surface_state (surface, 0, GDK_TOPLEVEL_STATE_FULLSCREEN); + synthesize_initial_surface_state (surface, 0, GDK_TOPLEVEL_STATE_FULLSCREEN); } } @@ -3747,7 +3903,7 @@ gdk_wayland_surface_unfullscreen (GdkSurface *surface) } else { - gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_FULLSCREEN, 0); + synthesize_initial_surface_state (surface, GDK_TOPLEVEL_STATE_FULLSCREEN, 0); } } @@ -3921,34 +4077,6 @@ gdk_wayland_surface_set_opaque_region (GdkSurface *surface, impl->opaque_region_dirty = TRUE; } -static void -gdk_wayland_surface_set_shadow_width (GdkSurface *surface, - int left, - int right, - int top, - int bottom) -{ - GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); - int new_width, new_height; - - if (GDK_SURFACE_DESTROYED (surface)) - return; - - /* Reconfigure surface to keep the same surface geometry */ - new_width = surface->width - - (impl->margin_left + impl->margin_right) + (left + right); - new_height = surface->height - - (impl->margin_top + impl->margin_bottom) + (top + bottom); - gdk_wayland_surface_maybe_resize (surface, - new_width, new_height, - impl->scale); - - impl->margin_left = left; - impl->margin_right = right; - impl->margin_top = top; - impl->margin_bottom = bottom; -} - static gboolean gdk_wayland_surface_show_window_menu (GdkSurface *surface, GdkEvent *event) @@ -4033,8 +4161,9 @@ gdk_wayland_surface_class_init (GdkWaylandSurfaceClass *klass) impl_class->drag_begin = _gdk_wayland_surface_drag_begin; impl_class->get_scale_factor = gdk_wayland_surface_get_scale_factor; impl_class->set_opaque_region = gdk_wayland_surface_set_opaque_region; - impl_class->set_shadow_width = gdk_wayland_surface_set_shadow_width; impl_class->create_gl_context = gdk_wayland_surface_create_gl_context; + impl_class->request_layout = gdk_wayland_surface_request_layout; + impl_class->compute_size = gdk_wayland_surface_compute_size; } void @@ -4736,98 +4865,94 @@ gdk_wayland_toplevel_class_init (GdkWaylandToplevelClass *class) gdk_toplevel_install_properties (object_class, 1); } -static void -show_surface (GdkSurface *surface) +static gboolean +did_maximize_layout_change (GdkToplevel *toplevel, + GdkToplevelLayout *layout) { - gboolean was_mapped; - - if (surface->destroyed) - return; - - was_mapped = GDK_SURFACE_IS_MAPPED (surface); + GdkSurface *surface = GDK_SURFACE (toplevel); + GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); - if (!was_mapped) - gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_WITHDRAWN, 0); + if (!impl->toplevel.layout) + return TRUE; - gdk_wayland_surface_show (surface, FALSE); + if (gdk_toplevel_layout_get_maximized (impl->toplevel.layout) != + gdk_toplevel_layout_get_maximized (layout) || + !!(surface->state & GDK_TOPLEVEL_STATE_MAXIMIZED) != + gdk_toplevel_layout_get_maximized (layout)) + return TRUE; - if (!was_mapped) - gdk_surface_invalidate_rect (surface, NULL); + return FALSE; } -static void -reconfigure_callback (void *data, - struct wl_callback *callback, - uint32_t time) +static gboolean +did_fullscreen_layout_change (GdkToplevel *toplevel, + GdkToplevelLayout *layout) { - gboolean *done = (gboolean *) data; + GdkSurface *surface = GDK_SURFACE (toplevel); + GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); - *done = TRUE; -} + if (!impl->toplevel.layout) + return TRUE; -static const struct wl_callback_listener reconfigure_listener = { - reconfigure_callback -}; + if (gdk_toplevel_layout_get_fullscreen (impl->toplevel.layout) != + gdk_toplevel_layout_get_fullscreen (layout) || + !!(surface->state & GDK_TOPLEVEL_STATE_FULLSCREEN) != + gdk_toplevel_layout_get_fullscreen (layout)) + return TRUE; -static gboolean + if (gdk_toplevel_layout_get_fullscreen_monitor (impl->toplevel.layout) != + gdk_toplevel_layout_get_fullscreen_monitor (layout)) + return TRUE; + + return FALSE; +} + +static void gdk_wayland_toplevel_present (GdkToplevel *toplevel, GdkToplevelLayout *layout) { GdkSurface *surface = GDK_SURFACE (toplevel); GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); - GdkWaylandDisplay *display_wayland; - struct wl_callback *callback; - gboolean done = FALSE; - int last_configure_serial = impl->last_configure_serial; - gboolean needs_reconfigure = TRUE; + gboolean pending_configure = FALSE; - if (gdk_toplevel_layout_get_maximized (layout)) + if (did_maximize_layout_change (toplevel, layout)) { - gdk_wayland_surface_maximize (surface); - needs_reconfigure = FALSE; - } - else - { - gdk_wayland_surface_unmaximize (surface); + if (gdk_toplevel_layout_get_maximized (layout)) + gdk_wayland_surface_maximize (surface); + else + gdk_wayland_surface_unmaximize (surface); + pending_configure = TRUE; } - if (gdk_toplevel_layout_get_fullscreen (layout)) + if (did_fullscreen_layout_change (toplevel, layout)) { - GdkMonitor *monitor = gdk_toplevel_layout_get_fullscreen_monitor (layout); - if (monitor) - gdk_wayland_surface_fullscreen_on_monitor (surface, monitor); + if (gdk_toplevel_layout_get_fullscreen (layout)) + { + GdkMonitor *monitor; + + monitor = gdk_toplevel_layout_get_fullscreen_monitor (layout); + if (monitor) + gdk_wayland_surface_fullscreen_on_monitor (surface, monitor); + else + gdk_wayland_surface_fullscreen (surface); + } else - gdk_wayland_surface_fullscreen (surface); - needs_reconfigure = FALSE; + { + gdk_wayland_surface_unfullscreen (surface); + } + pending_configure = TRUE; } - else - gdk_wayland_surface_unfullscreen (surface); g_clear_pointer (&impl->toplevel.layout, gdk_toplevel_layout_unref); impl->toplevel.layout = gdk_toplevel_layout_copy (layout); - show_surface (surface); - - display_wayland = GDK_WAYLAND_DISPLAY (gdk_surface_get_display (surface)); - callback = wl_display_sync (display_wayland->wl_display); - wl_proxy_set_queue ((struct wl_proxy *) callback, impl->event_queue); - wl_callback_add_listener (callback, - &reconfigure_listener, - &done); - while (is_realized_toplevel (impl) && - (!impl->initial_configure_received || !done)) - wl_display_dispatch_queue (display_wayland->wl_display, impl->event_queue); - - wl_callback_destroy (callback); - - if (needs_reconfigure && - last_configure_serial == impl->last_configure_serial && - !(surface->state & (GDK_TOPLEVEL_STATE_MAXIMIZED | - GDK_TOPLEVEL_STATE_FULLSCREEN | - GDK_TOPLEVEL_STATE_TILED))) - configure_surface_geometry (surface); + gdk_wayland_surface_show (surface, FALSE); - return TRUE; + if (!pending_configure) + { + impl->next_layout.surface_geometry_dirty = TRUE; + gdk_surface_request_layout (surface); + } } static gboolean @@ -4961,8 +5086,14 @@ gdk_wayland_drag_surface_present (GdkDragSurface *drag_surface, GdkSurface *surface = GDK_SURFACE (drag_surface); GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface); - gdk_wayland_surface_resize (surface, width, height, impl->scale); - show_surface (surface); + gdk_wayland_surface_show (surface, FALSE); + + impl->next_layout.configured_width = width; + impl->next_layout.configured_height = height; + impl->next_layout.surface_geometry_dirty = TRUE; + gdk_surface_request_layout (surface); + + maybe_notify_mapped (surface); return TRUE; } diff --git a/gdk/win32/gdkevents-win32.c b/gdk/win32/gdkevents-win32.c index b7488fbc1e..dbdcab2c43 100644 --- a/gdk/win32/gdkevents-win32.c +++ b/gdk/win32/gdkevents-win32.c @@ -562,7 +562,6 @@ event_mask_string (GdkEventMask mask) BIT (VISIBILITY_NOTIFY); BIT (PROXIMITY_IN); BIT (PROXIMITY_OUT); - BIT (SUBSTRUCTURE); BIT (SCROLL); #undef BIT @@ -1278,35 +1277,6 @@ _gdk_win32_get_window_rect (GdkSurface *window, return !impl->inhibit_configure; } -void -_gdk_win32_do_emit_configure_event (GdkSurface *surface, - RECT rect) -{ - GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface); - - impl->unscaled_width = rect.right - rect.left; - impl->unscaled_height = rect.bottom - rect.top; - surface->width = (impl->unscaled_width + impl->surface_scale - 1) / impl->surface_scale; - surface->height = (impl->unscaled_height + impl->surface_scale - 1) / impl->surface_scale; - surface->x = rect.left / impl->surface_scale; - surface->y = rect.top / impl->surface_scale; - - _gdk_surface_update_size (surface); - - g_signal_emit_by_name (surface, "size-changed", surface->width, surface->height); -} - -void -_gdk_win32_emit_configure_event (GdkSurface *surface) -{ - RECT rect; - - if (!_gdk_win32_get_window_rect (surface, &rect)) - return; - - _gdk_win32_do_emit_configure_event (surface, rect); -} - cairo_region_t * _gdk_win32_hrgn_to_region (HRGN hrgn, guint scale) @@ -2855,11 +2825,6 @@ gdk_event_translate (MSG *msg, set_bits = 0; unset_bits = 0; - if (IsWindowVisible (msg->hwnd)) - unset_bits |= GDK_TOPLEVEL_STATE_WITHDRAWN; - else - set_bits |= GDK_TOPLEVEL_STATE_WITHDRAWN; - if (IsIconic (msg->hwnd)) set_bits |= GDK_TOPLEVEL_STATE_MINIMIZED; else @@ -2870,6 +2835,7 @@ gdk_event_translate (MSG *msg, else unset_bits |= GDK_TOPLEVEL_STATE_MAXIMIZED; + gdk_surface_set_is_mapped (window, !!IsWindowVisible (msg->hwnd)); gdk_synthesize_surface_state (window, unset_bits, set_bits); new_state = window->state; @@ -2890,7 +2856,7 @@ gdk_event_translate (MSG *msg, { if (!IsIconic (msg->hwnd) && !GDK_SURFACE_DESTROYED (window)) - _gdk_win32_emit_configure_event (window); + gdk_surface_request_layout (window); } if ((windowpos->flags & SWP_HIDEWINDOW) && diff --git a/gdk/win32/gdkmain-win32.c b/gdk/win32/gdkmain-win32.c index 73d0420011..6d4e44cfc7 100644 --- a/gdk/win32/gdkmain-win32.c +++ b/gdk/win32/gdkmain-win32.c @@ -274,11 +274,6 @@ _gdk_win32_surface_state_to_string (GdkToplevelState state) if (state & GDK_TOPLEVEL_STATE_ ## x) \ (bufp += sprintf (bufp, "%s" #x, s), s = "|") - /* For clarity, also show the complement of WITHDRAWN, i.e. "MAPPED" */ - if (!(state & GDK_TOPLEVEL_STATE_WITHDRAWN)) - (bufp += sprintf (bufp, "MAPPED"), s = "|"); - - BIT (WITHDRAWN); BIT (MINIMIZED); BIT (MAXIMIZED); BIT (STICKY); diff --git a/gdk/win32/gdkprivate-win32.h b/gdk/win32/gdkprivate-win32.h index 6ed78b480b..d37866bcf3 100644 --- a/gdk/win32/gdkprivate-win32.h +++ b/gdk/win32/gdkprivate-win32.h @@ -407,7 +407,6 @@ GdkSurface *gdk_win32_display_get_root_window (GdkDisplay *display); /* Distributed display manager implementation */ GdkDisplay *_gdk_win32_display_open (const char *display_name); void _gdk_win32_append_event (GdkEvent *event); -void _gdk_win32_emit_configure_event (GdkSurface *window); guint32 _gdk_win32_keymap_get_decimal_mark (GdkWin32Keymap *keymap); diff --git a/gdk/win32/gdksurface-win32.c b/gdk/win32/gdksurface-win32.c index 1f76b5bbb3..263fcc6c60 100644 --- a/gdk/win32/gdksurface-win32.c +++ b/gdk/win32/gdksurface-win32.c @@ -1006,9 +1006,7 @@ gdk_win32_surface_hide (GdkSurface *window) _gdk_win32_surface_state_to_string (window->state))); if (GDK_SURFACE_IS_MAPPED (window)) - gdk_synthesize_surface_state (window, - 0, - GDK_TOPLEVEL_STATE_WITHDRAWN); + gdk_surface_set_is_mapped (window, FALSE); _gdk_surface_clear_update_area (window); @@ -1190,7 +1188,7 @@ gdk_win32_surface_move_resize_internal (GdkSurface *window, out: surface->inhibit_configure = FALSE; - _gdk_win32_emit_configure_event (window); + gdk_surface_request_layout (window); } void @@ -1217,6 +1215,7 @@ gdk_win32_surface_layout_popup (GdkSurface *surface, int height, GdkPopupLayout *layout) { + GdkWin32Surface *impl = GDK_WIN32_SURFACE (surface); GdkMonitor *monitor; GdkRectangle bounds; GdkRectangle final_rect; @@ -1229,6 +1228,10 @@ gdk_win32_surface_layout_popup (GdkSurface *surface, gdk_surface_layout_popup_helper (surface, width, height, + impl->margins.left, + impl->margins.right, + impl->margins.top, + impl->margins.bottom, monitor, &bounds, layout, @@ -1257,7 +1260,7 @@ static void show_popup (GdkSurface *surface) { gdk_win32_surface_raise (surface); - gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_WITHDRAWN, 0); + gdk_surface_set_is_mapped (surface, TRUE); show_window_internal (surface, FALSE, FALSE); gdk_surface_invalidate_rect (surface, NULL); } @@ -4013,7 +4016,7 @@ gdk_win32_surface_do_move_resize_drag (GdkSurface *window, rect.bottom != new_rect.bottom)) { context->native_move_resize_pending = TRUE; - _gdk_win32_do_emit_configure_event (window, new_rect); + gdk_surface_request_layout (window); } else if (context->op == GDK_WIN32_DRAGOP_MOVE && (rect.left != new_rect.left || @@ -4021,7 +4024,7 @@ gdk_win32_surface_do_move_resize_drag (GdkSurface *window, { context->native_move_resize_pending = FALSE; - _gdk_win32_do_emit_configure_event (window, new_rect); + gdk_surface_request_layout (window); if (impl->layered) { @@ -4615,8 +4618,6 @@ gdk_win32_surface_class_init (GdkWin32SurfaceClass *klass) //impl_class->beep = gdk_x11_surface_beep; - - impl_class->set_shadow_width = gdk_win32_surface_set_shadow_width; impl_class->destroy_notify = gdk_win32_surface_destroy_notify; impl_class->drag_begin = _gdk_win32_surface_drag_begin; impl_class->create_gl_context = _gdk_win32_surface_create_gl_context; @@ -4921,7 +4922,7 @@ show_surface (GdkSurface *surface) was_mapped = GDK_SURFACE_IS_MAPPED (surface); if (!was_mapped) - gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_WITHDRAWN, 0); + gdk_surface_set_is_mapped (surface, TRUE); gdk_win32_surface_show (surface, FALSE); @@ -4992,6 +4993,15 @@ gdk_win32_toplevel_present (GdkToplevel *toplevel, show_surface (surface); + if (size.shadow.is_valid) + { + gdk_win32_surface_set_shadow_width (surface, + size.shadow.left, + size.shadow.right, + size.shadow.top, + size.shadow.bottom); + } + return TRUE; } diff --git a/gdk/x11/gdkdisplay-x11.c b/gdk/x11/gdkdisplay-x11.c index b6a223d914..4350f2eef8 100644 --- a/gdk/x11/gdkdisplay-x11.c +++ b/gdk/x11/gdkdisplay-x11.c @@ -566,7 +566,7 @@ gdk_check_edge_constraints_changed (GdkSurface *surface) * messing around with shifts, just make the passed value and GDK's * enum values match by shifting to the first tiled state. */ - toplevel->edge_constraints = constraints[0] << 9; + toplevel->edge_constraints = constraints[0] << 8; XFree (constraints); } @@ -620,7 +620,6 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator, { Window xwindow; GdkSurface *surface; - gboolean is_substructure; GdkX11Surface *surface_impl = NULL; GdkX11Screen *x11_screen = NULL; GdkToplevelX11 *toplevel = NULL; @@ -629,18 +628,9 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator, event = NULL; - /* Find the GdkSurface that this event relates to. If that's - * not the same as the surface that the event was sent to, - * we are getting an event from SubstructureNotifyMask. - * We ignore such events for internal operation, but we - * need to report them to the application because of - * GDK_SUBSTRUCTURE_MASK (which should be removed at next - * opportunity.) The most likely reason for getting these - * events is when we are used in the Metacity or Mutter - * window managers. - */ xwindow = get_event_xwindow (xevent); - is_substructure = xwindow != xevent->xany.window; + if (xwindow != xevent->xany.window) + return NULL; surface = gdk_x11_surface_lookup_for_display (display, xwindow); if (surface) @@ -664,7 +654,7 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator, goto done; } - if (xevent->type == DestroyNotify && !is_substructure) + if (xevent->type == DestroyNotify) { x11_screen = GDK_X11_DISPLAY (display)->screen; @@ -793,14 +783,11 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator, g_message ("destroy notify:\twindow: %ld", xevent->xdestroywindow.window)); - if (!is_substructure) - { - if (surface) - event = gdk_delete_event_new (surface); + if (surface) + event = gdk_delete_event_new (surface); - if (surface && GDK_SURFACE_XID (surface) != x11_screen->xroot_window) - gdk_surface_destroy_notify (surface); - } + if (surface && GDK_SURFACE_XID (surface) != x11_screen->xroot_window) + gdk_surface_destroy_notify (surface); break; @@ -809,7 +796,7 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator, g_message ("unmap notify:\t\twindow: %ld", xevent->xmap.window)); - if (surface && !is_substructure) + if (surface) { /* If the WM supports the _NET_WM_STATE_HIDDEN hint, we do not want to * interpret UnmapNotify events as implying iconic state. @@ -852,7 +839,7 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator, g_message ("map notify:\t\twindow: %ld", xevent->xmap.window)); - if (surface && !is_substructure) + if (surface) { /* Unset minimized if it was set */ if (surface->state & GDK_TOPLEVEL_STATE_MINIMIZED) @@ -902,7 +889,7 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator, } #ifdef HAVE_XSYNC - if (!is_substructure && toplevel && display_x11->use_sync && toplevel->pending_counter_value != 0) + if (toplevel && display_x11->use_sync && toplevel->pending_counter_value != 0) { toplevel->configure_counter_value = toplevel->pending_counter_value; toplevel->configure_counter_value_is_extended = toplevel->pending_counter_value_is_extended; @@ -914,10 +901,16 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator, xevent->xconfigure.event == xevent->xconfigure.window) { int x, y; - int c_w = (xevent->xconfigure.width + surface_impl->surface_scale - 1) / surface_impl->surface_scale; - int c_h = (xevent->xconfigure.height + surface_impl->surface_scale - 1) / surface_impl->surface_scale; + int configured_width; + int configured_height; + int new_abs_x, new_abs_y; - event = gdk_configure_event_new (surface, c_w, c_h); + configured_width = + (xevent->xconfigure.width + surface_impl->surface_scale - 1) / + surface_impl->surface_scale; + configured_height = + (xevent->xconfigure.height + surface_impl->surface_scale - 1) / + surface_impl->surface_scale; if (!xevent->xconfigure.send_event && !xevent->xconfigure.override_redirect && @@ -946,47 +939,45 @@ gdk_x11_display_translate_event (GdkEventTranslator *translator, x = xevent->xconfigure.x / surface_impl->surface_scale; y = xevent->xconfigure.y / surface_impl->surface_scale; } - if (!is_substructure) - { - int new_abs_x, new_abs_y; - - new_abs_x = x; - new_abs_y = y; - surface_impl->abs_x = new_abs_x; - surface_impl->abs_y = new_abs_y; + new_abs_x = x; + new_abs_y = y; - if (surface->parent) - { - GdkX11Surface *parent_impl = - GDK_X11_SURFACE (surface->parent); + surface_impl->abs_x = new_abs_x; + surface_impl->abs_y = new_abs_y; - surface->x = new_abs_x - parent_impl->abs_x; - surface->y = new_abs_y - parent_impl->abs_y; - } + if (surface->parent) + { + GdkX11Surface *parent_impl = + GDK_X11_SURFACE (surface->parent); - if (surface_impl->unscaled_width != xevent->xconfigure.width || - surface_impl->unscaled_height != xevent->xconfigure.height) - { - surface_impl->unscaled_width = xevent->xconfigure.width; - surface_impl->unscaled_height = xevent->xconfigure.height; - gdk_configure_event_get_size (event, &surface->width, &surface->height); + surface->x = new_abs_x - parent_impl->abs_x; + surface->y = new_abs_y - parent_impl->abs_y; + } - _gdk_surface_update_size (surface); - _gdk_x11_surface_update_size (surface_impl); - } + if (surface_impl->unscaled_width != xevent->xconfigure.width || + surface_impl->unscaled_height != xevent->xconfigure.height) + { + surface_impl->unscaled_width = xevent->xconfigure.width; + surface_impl->unscaled_height = xevent->xconfigure.height; + + surface_impl->next_layout.configured_width = configured_width; + surface_impl->next_layout.configured_height = configured_height; + surface_impl->next_layout.surface_geometry_dirty = TRUE; + surface_impl->next_layout.configure_pending = TRUE; + gdk_surface_request_layout (surface); + } - if (surface->resize_count >= 1) - { - surface->resize_count -= 1; + if (surface->resize_count >= 1) + { + surface->resize_count -= 1; - if (surface->resize_count == 0) - _gdk_x11_moveresize_configure_done (display, surface); - } + if (surface->resize_count == 0) + _gdk_x11_moveresize_configure_done (display, surface); + } - gdk_x11_surface_update_popups (surface); - gdk_x11_surface_enter_leave_monitors (surface); - } + gdk_x11_surface_update_popups (surface); + gdk_x11_surface_enter_leave_monitors (surface); } break; diff --git a/gdk/x11/gdkdrag-x11.c b/gdk/x11/gdkdrag-x11.c index 8e40cab447..606cef0f0c 100644 --- a/gdk/x11/gdkdrag-x11.c +++ b/gdk/x11/gdkdrag-x11.c @@ -2036,7 +2036,7 @@ _gdk_x11_surface_drag_begin (GdkSurface *surface, if (gdk_x11_surface_get_group (surface)) gdk_x11_surface_set_group (x11_drag->ipc_surface, surface); - gdk_synthesize_surface_state (x11_drag->ipc_surface, GDK_TOPLEVEL_STATE_WITHDRAWN, 0); + gdk_surface_set_is_mapped (x11_drag->ipc_surface, TRUE); gdk_x11_surface_show (x11_drag->ipc_surface, FALSE); x11_drag->drag_surface = create_drag_surface (display); diff --git a/gdk/x11/gdkglcontext-x11.c b/gdk/x11/gdkglcontext-x11.c index a332773493..d83ef6aaad 100644 --- a/gdk/x11/gdkglcontext-x11.c +++ b/gdk/x11/gdkglcontext-x11.c @@ -463,7 +463,7 @@ on_surface_state_changed (GdkGLContext *context) { GdkSurface *surface = gdk_gl_context_get_surface (context); - if ((surface->state & GDK_TOPLEVEL_STATE_WITHDRAWN) == 0) + if (GDK_SURFACE_IS_MAPPED (surface)) return; /* If we're about to withdraw the surface, then we don't care if the frame is diff --git a/gdk/x11/gdksurface-x11.c b/gdk/x11/gdksurface-x11.c index 24b536cb96..293134371e 100644 --- a/gdk/x11/gdksurface-x11.c +++ b/gdk/x11/gdksurface-x11.c @@ -98,6 +98,14 @@ const int _gdk_x11_event_mask_table[21] = ButtonPressMask /* SCROLL; on X mouse wheel events is treated as mouse button 4/5 */ }; +typedef struct { + GdkX11Surface parent_instance; +} GdkX11Toplevel; + +typedef struct { + GdkX11SurfaceClass parent_class; +} GdkX11ToplevelClass; + const int _gdk_x11_event_mask_table_size = G_N_ELEMENTS (_gdk_x11_event_mask_table); /* Forward declarations */ @@ -111,6 +119,14 @@ static void gdk_x11_toplevel_state_callback (GdkSurface *surface); static gboolean gdk_x11_toplevel_event_callback (GdkSurface *surface, GdkEvent *gdk_event); +static void gdk_x11_surface_toplevel_resize (GdkSurface *surface, + int width, + int height); + +static void gdk_x11_surface_set_geometry_hints (GdkSurface *surface, + const GdkGeometry *geometry, + GdkSurfaceHints geom_mask); + /* Return whether time1 is considered later than time2 as far as xserver * time is concerned. Accounts for wraparound. */ @@ -192,6 +208,206 @@ gdk_x11_surface_get_unscaled_size (GdkSurface *surface, *unscaled_height = impl->unscaled_height; } +static void +update_shadow_size (GdkSurface *surface, + int shadow_left, + int shadow_right, + int shadow_top, + int shadow_bottom) +{ + GdkX11Surface *impl = GDK_X11_SURFACE (surface); + Atom frame_extents; + gulong data[4]; + + if (impl->shadow_left == shadow_left && + impl->shadow_right == shadow_right && + impl->shadow_top == shadow_top && + impl->shadow_bottom == shadow_bottom) + return; + + impl->shadow_left = shadow_left; + impl->shadow_right = shadow_right; + impl->shadow_top = shadow_top; + impl->shadow_bottom = shadow_bottom; + + data[0] = shadow_left * impl->surface_scale; + data[1] = shadow_right * impl->surface_scale; + data[2] = shadow_top * impl->surface_scale; + data[3] = shadow_bottom * impl->surface_scale; + + frame_extents = gdk_x11_get_xatom_by_name_for_display (gdk_surface_get_display (surface), + "_GTK_FRAME_EXTENTS"); + XChangeProperty (GDK_SURFACE_XDISPLAY (surface), + GDK_SURFACE_XID (surface), + frame_extents, XA_CARDINAL, + 32, PropModeReplace, + (guchar *) &data, 4); +} + +#define UPDATE_GEOMETRY TRUE +#define DONT_UPDATE_GEOMETRY FALSE + +static gboolean +compute_toplevel_size (GdkSurface *surface, + gboolean update_geometry, + int *width, + int *height) +{ + GdkX11Surface *impl = GDK_X11_SURFACE (surface); + GdkDisplay *display = gdk_surface_get_display (surface); + GdkMonitor *monitor; + GdkToplevelSize size; + int bounds_width, bounds_height; + + monitor = gdk_display_get_monitor_at_surface (display, surface); + if (monitor) + { + GdkRectangle workarea; + + gdk_x11_monitor_get_workarea (monitor, &workarea); + bounds_width = workarea.width; + bounds_height = workarea.height; + } + else + { + bounds_width = G_MAXINT; + bounds_height = G_MAXINT; + } + + gdk_toplevel_size_init (&size, bounds_width, bounds_height); + gdk_toplevel_notify_compute_size (GDK_TOPLEVEL (surface), &size); + + if (size.shadow.is_valid && update_geometry) + { + update_shadow_size (surface, + size.shadow.left, + size.shadow.right, + size.shadow.top, + size.shadow.bottom); + } + + if (update_geometry) + { + GdkGeometry geometry; + GdkSurfaceHints mask; + + if (gdk_toplevel_layout_get_resizable (impl->toplevel_layout)) + { + geometry.min_width = size.min_width; + geometry.min_height = size.min_height; + mask = GDK_HINT_MIN_SIZE; + } + else + { + geometry.max_width = geometry.min_width = size.width; + geometry.max_height = geometry.min_height = size.height; + mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE; + } + gdk_x11_surface_set_geometry_hints (surface, &geometry, mask); + } + + if (!(surface->state & (GDK_TOPLEVEL_STATE_FULLSCREEN | + GDK_TOPLEVEL_STATE_MAXIMIZED | + GDK_TOPLEVEL_STATE_TILED | + GDK_TOPLEVEL_STATE_TOP_TILED | + GDK_TOPLEVEL_STATE_RIGHT_TILED | + GDK_TOPLEVEL_STATE_BOTTOM_TILED | + GDK_TOPLEVEL_STATE_LEFT_TILED | + GDK_TOPLEVEL_STATE_MINIMIZED)) && + (!impl->next_layout.configure_pending || surface->resize_count > 0)) + { + GdkToplevelX11 *toplevel = _gdk_x11_surface_get_toplevel (surface); + GdkGeometry geometry; + GdkSurfaceHints mask; + + geometry = toplevel->last_geometry_hints; + mask = toplevel->last_geometry_hints_mask; + gdk_surface_constrain_size (&geometry, mask, + size.width, size.height, + &size.width, &size.height); + if ((impl->last_computed_width != size.width || + impl->last_computed_height != size.height) && + (impl->next_layout.configured_width != size.width || + impl->next_layout.configured_height != size.height)) + { + *width = size.width; + *height = size.height; + impl->last_computed_width = size.width; + impl->last_computed_height = size.height; + + return TRUE; + } + } + + return FALSE; +} + +static gboolean +compute_size_idle (gpointer user_data) +{ + GdkSurface *surface = user_data; + GdkX11Surface *impl = GDK_X11_SURFACE (surface); + int width, height; + + impl->compute_size_source_id = 0; + if (compute_toplevel_size (surface, UPDATE_GEOMETRY, &width, &height)) + gdk_x11_surface_toplevel_resize (surface, width, height); + + return G_SOURCE_REMOVE; +} + +static void +gdk_x11_surface_request_layout (GdkSurface *surface) +{ + GdkX11Surface *impl = GDK_X11_SURFACE (surface); + + if (!impl->compute_size_source_id && + GDK_IS_TOPLEVEL (surface)) + { + impl->compute_size_source_id = g_idle_add_full (G_PRIORITY_HIGH - 10, + compute_size_idle, + surface, + NULL); + } +} + +static gboolean +gdk_x11_surface_compute_size (GdkSurface *surface) +{ + GdkX11Surface *impl = GDK_X11_SURFACE (surface); + + if (GDK_IS_TOPLEVEL (surface)) + { + int width, height; + + if (compute_toplevel_size (surface, UPDATE_GEOMETRY, &width, &height)) + gdk_x11_surface_toplevel_resize (surface, width, height); + + if (surface->resize_count == 0) + { + surface->width = impl->next_layout.configured_width; + surface->height = impl->next_layout.configured_height; + _gdk_surface_update_size (surface); + _gdk_x11_surface_update_size (impl); + } + + impl->next_layout.surface_geometry_dirty = FALSE; + impl->next_layout.configure_pending = FALSE; + } + else + { + surface->width = impl->next_layout.configured_width; + surface->height = impl->next_layout.configured_height; + + _gdk_surface_update_size (surface); + _gdk_x11_surface_update_size (impl); + + impl->next_layout.surface_geometry_dirty = FALSE; + } + + return surface->resize_count > 0; +} + gboolean gdk_x11_surface_supports_edge_constraints (GdkSurface *surface) { @@ -838,6 +1054,19 @@ on_frame_clock_before_paint (GdkFrameClock *clock, } static void +on_frame_clock_after_update (GdkFrameClock *clock, + GdkSurface *surface) +{ + GdkX11Surface *impl = GDK_X11_SURFACE (surface); + + if (impl->compute_size_source_id) + { + g_clear_handle_id (&impl->compute_size_source_id, g_source_remove); + compute_size_idle (surface); + } +} + +static void on_frame_clock_after_paint (GdkFrameClock *clock, GdkSurface *surface) { @@ -859,6 +1088,8 @@ connect_frame_clock (GdkSurface *surface) g_signal_connect (frame_clock, "before-paint", G_CALLBACK (on_frame_clock_before_paint), surface); + g_signal_connect_after (frame_clock, "update", + G_CALLBACK (on_frame_clock_after_update), surface); g_signal_connect (frame_clock, "after-paint", G_CALLBACK (on_frame_clock_after_paint), surface); @@ -879,6 +1110,8 @@ disconnect_frame_clock (GdkSurface *surface) g_signal_handlers_disconnect_by_func (frame_clock, on_frame_clock_before_paint, surface); g_signal_handlers_disconnect_by_func (frame_clock, + on_frame_clock_after_update, surface); + g_signal_handlers_disconnect_by_func (frame_clock, on_frame_clock_after_paint, surface); impl->frame_clock_connected = FALSE; @@ -1168,7 +1401,7 @@ update_wm_hints (GdkSurface *surface, if (!force && !toplevel->is_leader && - surface->state & GDK_TOPLEVEL_STATE_WITHDRAWN) + !GDK_SURFACE_IS_MAPPED (surface)) return; wm_hints.flags = StateHint | InputHint; @@ -1375,9 +1608,7 @@ gdk_x11_surface_withdraw (GdkSurface *surface) if (!surface->destroyed) { if (GDK_SURFACE_IS_MAPPED (surface)) - gdk_synthesize_surface_state (surface, - 0, - GDK_TOPLEVEL_STATE_WITHDRAWN); + gdk_surface_set_is_mapped (surface, FALSE); g_assert (!GDK_SURFACE_IS_MAPPED (surface)); XWithdrawWindow (GDK_SURFACE_XDISPLAY (surface), @@ -1388,6 +1619,8 @@ gdk_x11_surface_withdraw (GdkSurface *surface) static void gdk_x11_surface_hide (GdkSurface *surface) { + GdkX11Surface *impl = GDK_X11_SURFACE (surface); + /* We'll get the unmap notify eventually, and handle it then, * but checking here makes things more consistent if we are * just doing stuff ourself. @@ -1395,6 +1628,9 @@ gdk_x11_surface_hide (GdkSurface *surface) _gdk_x11_surface_grab_check_unmap (surface, NextRequest (GDK_SURFACE_XDISPLAY (surface))); + g_clear_handle_id (&impl->compute_size_source_id, g_source_remove); + g_clear_pointer (&impl->toplevel_layout, gdk_toplevel_layout_unref); + gdk_x11_surface_withdraw (surface); } @@ -1424,6 +1660,9 @@ x11_surface_move (GdkSurface *surface, surface->x = x; surface->y = y; } + + impl->next_layout.surface_geometry_dirty = TRUE; + gdk_surface_request_layout (surface); } } @@ -1450,15 +1689,20 @@ x11_surface_resize (GdkSurface *surface, { impl->unscaled_width = width * impl->surface_scale; impl->unscaled_height = height * impl->surface_scale; - surface->width = width; - surface->height = height; - _gdk_surface_update_size (surface); - _gdk_x11_surface_update_size (GDK_X11_SURFACE (surface)); + impl->next_layout.configured_width = width; + impl->next_layout.configured_height = height; + impl->next_layout.surface_geometry_dirty = TRUE; + gdk_surface_request_layout (surface); } else { - if (width * impl->surface_scale != impl->unscaled_width || height * impl->surface_scale != impl->unscaled_height) - surface->resize_count += 1; + if (width * impl->surface_scale != impl->unscaled_width || + height * impl->surface_scale != impl->unscaled_height) + { + surface->resize_count++; + if (surface->resize_count == 1) + gdk_surface_freeze_updates (surface); + } } } @@ -1491,10 +1735,10 @@ x11_surface_move_resize (GdkSurface *surface, impl->unscaled_width = width * impl->surface_scale; impl->unscaled_height = height * impl->surface_scale; - surface->width = width; - surface->height = height; - - _gdk_x11_surface_update_size (GDK_X11_SURFACE (surface)); + impl->next_layout.configured_width = width; + impl->next_layout.configured_height = height; + impl->next_layout.surface_geometry_dirty = TRUE; + gdk_surface_request_layout (surface); if (surface->parent) { @@ -1509,8 +1753,13 @@ x11_surface_move_resize (GdkSurface *surface, } else { - if (width * impl->surface_scale != impl->unscaled_width || height * impl->surface_scale != impl->unscaled_height) - surface->resize_count += 1; + if (width * impl->surface_scale != impl->unscaled_width || + height * impl->surface_scale != impl->unscaled_height) + { + surface->resize_count++; + if (surface->resize_count == 1) + gdk_surface_freeze_updates (surface); + } } } @@ -1555,6 +1804,7 @@ gdk_x11_surface_layout_popup (GdkSurface *surface, int height, GdkPopupLayout *layout) { + GdkX11Surface *impl = GDK_X11_SURFACE (surface); GdkMonitor *monitor; GdkRectangle bounds; GdkRectangle final_rect; @@ -1567,6 +1817,10 @@ gdk_x11_surface_layout_popup (GdkSurface *surface, gdk_surface_layout_popup_helper (surface, width, height, + impl->shadow_left, + impl->shadow_right, + impl->shadow_top, + impl->shadow_bottom, monitor, &bounds, layout, @@ -1596,7 +1850,7 @@ static void show_popup (GdkSurface *surface) { gdk_x11_surface_raise (surface); - gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_WITHDRAWN, 0); + gdk_surface_set_is_mapped (surface, TRUE); gdk_x11_surface_show (surface, FALSE); gdk_surface_invalidate_rect (surface, NULL); } @@ -1721,10 +1975,6 @@ gdk_x11_surface_enter_leave_monitors (GdkSurface *surface) } } -static void gdk_x11_surface_set_geometry_hints (GdkSurface *surface, - const GdkGeometry *geometry, - GdkSurfaceHints geom_mask); - void _gdk_x11_surface_set_surface_scale (GdkSurface *surface, int scale) @@ -2815,31 +3065,6 @@ gdk_x11_surface_set_utf8_property (GdkSurface *surface, } } -static void -gdk_x11_surface_set_shadow_width (GdkSurface *surface, - int left, - int right, - int top, - int bottom) -{ - GdkX11Surface *impl = GDK_X11_SURFACE (surface); - Atom frame_extents; - gulong data[4] = { - left * impl->surface_scale, - right * impl->surface_scale, - top * impl->surface_scale, - bottom * impl->surface_scale - }; - - frame_extents = gdk_x11_get_xatom_by_name_for_display (gdk_surface_get_display (surface), - "_GTK_FRAME_EXTENTS"); - XChangeProperty (GDK_SURFACE_XDISPLAY (surface), - GDK_SURFACE_XID (surface), - frame_extents, XA_CARDINAL, - 32, PropModeReplace, - (guchar *) &data, 4); -} - /** * gdk_x11_surface_set_theme_variant: * @surface: (type GdkX11Surface): a #GdkSurface @@ -4095,6 +4320,9 @@ _gdk_x11_moveresize_configure_done (GdkDisplay *display, XEvent *tmp_event; MoveResizeData *mv_resize = get_move_resize_data (display, FALSE); + gdk_surface_thaw_updates (surface); + gdk_surface_request_layout (surface); + if (!mv_resize || surface != mv_resize->moveresize_surface) return FALSE; @@ -4565,9 +4793,10 @@ gdk_x11_surface_class_init (GdkX11SurfaceClass *klass) impl_class->drag_begin = _gdk_x11_surface_drag_begin; impl_class->get_scale_factor = gdk_x11_surface_get_scale_factor; impl_class->set_opaque_region = gdk_x11_surface_set_opaque_region; - impl_class->set_shadow_width = gdk_x11_surface_set_shadow_width; impl_class->create_gl_context = gdk_x11_surface_create_gl_context; impl_class->get_unscaled_size = gdk_x11_surface_get_unscaled_size; + impl_class->request_layout = gdk_x11_surface_request_layout; + impl_class->compute_size = gdk_x11_surface_compute_size; } #define LAST_PROP 1 @@ -4696,14 +4925,6 @@ gdk_x11_popup_iface_init (GdkPopupInterface *iface) iface->get_position_y = gdk_x11_popup_get_position_y; } -typedef struct { - GdkX11Surface parent_instance; -} GdkX11Toplevel; - -typedef struct { - GdkX11SurfaceClass parent_class; -} GdkX11ToplevelClass; - static void gdk_x11_toplevel_iface_init (GdkToplevelInterface *iface); G_DEFINE_TYPE_WITH_CODE (GdkX11Toplevel, gdk_x11_toplevel, GDK_TYPE_X11_SURFACE, @@ -4849,59 +5070,27 @@ gdk_x11_toplevel_class_init (GdkX11ToplevelClass *class) gdk_toplevel_install_properties (object_class, LAST_PROP); } -static gboolean +static void gdk_x11_toplevel_present (GdkToplevel *toplevel, GdkToplevelLayout *layout) { GdkSurface *surface = GDK_SURFACE (toplevel); - GdkDisplay *display = gdk_surface_get_display (surface); - GdkMonitor *monitor; - GdkToplevelSize size; - int bounds_width, bounds_height; + GdkX11Surface *impl = GDK_X11_SURFACE (surface); int width, height; - GdkGeometry geometry; - GdkSurfaceHints mask; gboolean was_mapped; - gdk_x11_surface_unminimize (surface); + if (surface->destroyed) + return; - monitor = gdk_display_get_monitor_at_surface (display, surface); - if (monitor) - { - GdkRectangle workarea; + was_mapped = GDK_SURFACE_IS_MAPPED (surface); - gdk_x11_monitor_get_workarea (monitor, &workarea); - bounds_width = workarea.width; - bounds_height = workarea.height; - } - else - { - bounds_width = G_MAXINT; - bounds_height = G_MAXINT; - } + gdk_x11_surface_unminimize (surface); - gdk_toplevel_size_init (&size, bounds_width, bounds_height); - gdk_toplevel_notify_compute_size (toplevel, &size); - g_warn_if_fail (size.width > 0); - g_warn_if_fail (size.height > 0); - width = size.width; - height = size.height; + g_clear_pointer (&impl->toplevel_layout, gdk_toplevel_layout_unref); + impl->toplevel_layout = gdk_toplevel_layout_copy (layout); - if (gdk_toplevel_layout_get_resizable (layout)) - { - geometry.min_width = size.min_width; - geometry.min_height = size.min_height; - mask = GDK_HINT_MIN_SIZE; - } - else - { - geometry.max_width = geometry.min_width = width; - geometry.max_height = geometry.min_height = height; - mask = GDK_HINT_MIN_SIZE | GDK_HINT_MAX_SIZE; - } - gdk_x11_surface_set_geometry_hints (surface, &geometry, mask); - gdk_surface_constrain_size (&geometry, mask, width, height, &width, &height); - gdk_x11_surface_toplevel_resize (surface, width, height); + if (compute_toplevel_size (surface, DONT_UPDATE_GEOMETRY, &width, &height)) + gdk_x11_surface_toplevel_resize (surface, width, height); if (gdk_toplevel_layout_get_maximized (layout)) gdk_x11_surface_maximize (surface); @@ -4921,20 +5110,16 @@ gdk_x11_toplevel_present (GdkToplevel *toplevel, else gdk_x11_surface_unfullscreen (surface); - if (surface->destroyed) - return TRUE; - - was_mapped = GDK_SURFACE_IS_MAPPED (surface); + impl->next_layout.surface_geometry_dirty = TRUE; + gdk_surface_request_layout (surface); if (!was_mapped) - gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_WITHDRAWN, 0); + gdk_surface_set_is_mapped (surface, TRUE); gdk_x11_surface_show (surface, was_mapped); if (!was_mapped) gdk_surface_invalidate_rect (surface, NULL); - - return TRUE; } static gboolean @@ -5100,7 +5285,7 @@ gdk_x11_drag_surface_present (GdkDragSurface *drag_surface, GdkSurface *surface = GDK_SURFACE (drag_surface); gdk_x11_surface_toplevel_resize (surface, width, height); - gdk_synthesize_surface_state (surface, GDK_TOPLEVEL_STATE_WITHDRAWN, 0); + gdk_surface_set_is_mapped (surface, TRUE); gdk_x11_surface_show (surface, FALSE); gdk_surface_invalidate_rect (surface, NULL); diff --git a/gdk/x11/gdksurface-x11.h b/gdk/x11/gdksurface-x11.h index eb23474afd..0830407dd0 100644 --- a/gdk/x11/gdksurface-x11.h +++ b/gdk/x11/gdksurface-x11.h @@ -59,6 +59,11 @@ struct _GdkX11Surface int surface_scale; + int shadow_left; + int shadow_right; + int shadow_top; + int shadow_bottom; + /* Width and height not divided by surface_scale - this matters in the * corner-case where the window manager assigns us a size that isn't * a multiple of surface_scale - for example for a maximized window @@ -67,6 +72,20 @@ struct _GdkX11Surface int unscaled_width; int unscaled_height; + int last_computed_width; + int last_computed_height; + + GdkToplevelLayout *toplevel_layout; + + struct { + int configured_width; + int configured_height; + gboolean configure_pending; + gboolean surface_geometry_dirty; + } next_layout; + + guint compute_size_source_id; + cairo_surface_t *cairo_surface; int abs_x; diff --git a/gtk/gtkcolorswatch.c b/gtk/gtkcolorswatch.c index 7addf913d3..a451fd827f 100644 --- a/gtk/gtkcolorswatch.c +++ b/gtk/gtkcolorswatch.c @@ -322,7 +322,7 @@ swatch_size_allocate (GtkWidget *widget, }, -1); if (swatch->popover) - gtk_native_check_resize (GTK_NATIVE (swatch->popover)); + gtk_popover_present (GTK_POPOVER (swatch->popover)); } static void diff --git a/gtk/gtkcolumnviewtitle.c b/gtk/gtkcolumnviewtitle.c index c76c8a9a8b..160b1b7604 100644 --- a/gtk/gtkcolumnviewtitle.c +++ b/gtk/gtkcolumnviewtitle.c @@ -144,7 +144,7 @@ gtk_column_view_title_size_allocate (GtkWidget *widget, } if (self->popup_menu) - gtk_native_check_resize (GTK_NATIVE (self->popup_menu)); + gtk_popover_present (GTK_POPOVER (self->popup_menu)); } static void diff --git a/gtk/gtkcombobox.c b/gtk/gtkcombobox.c index 30b4693078..0b2801e633 100644 --- a/gtk/gtkcombobox.c +++ b/gtk/gtkcombobox.c @@ -376,7 +376,7 @@ gtk_combo_box_size_allocate (GtkWidget *widget, gtk_widget_set_size_request (priv->popup_widget, MAX (width, menu_width), -1); - gtk_native_check_resize (GTK_NATIVE (priv->popup_widget)); + gtk_popover_present (GTK_POPOVER (priv->popup_widget)); } static void diff --git a/gtk/gtkdragicon.c b/gtk/gtkdragicon.c index 2348674951..6f31fd19cc 100644 --- a/gtk/gtkdragicon.c +++ b/gtk/gtkdragicon.c @@ -147,22 +147,22 @@ gtk_drag_icon_move_resize (GtkDragIcon *icon) } static void -gtk_drag_icon_native_check_resize (GtkNative *native) +gtk_drag_icon_present (GtkDragIcon *icon) { - GtkDragIcon *icon = GTK_DRAG_ICON (native); - GtkWidget *widget = GTK_WIDGET (native); + GtkWidget *widget = GTK_WIDGET (icon); if (!_gtk_widget_get_alloc_needed (widget)) gtk_widget_ensure_allocate (widget); else if (gtk_widget_get_visible (widget)) - { - gtk_drag_icon_move_resize (icon); - if (icon->surface) - gtk_widget_allocate (widget, - gdk_surface_get_width (icon->surface), - gdk_surface_get_height (icon->surface), - -1, NULL); - } + gtk_drag_icon_move_resize (icon); +} + +static void +gtk_drag_icon_native_layout (GtkNative *native, + int width, + int height) +{ + gtk_widget_allocate (GTK_WIDGET (native), width, height, -1, NULL); } static void @@ -171,7 +171,7 @@ gtk_drag_icon_native_init (GtkNativeInterface *iface) iface->get_surface = gtk_drag_icon_native_get_surface; iface->get_renderer = gtk_drag_icon_native_get_renderer; iface->get_surface_transform = gtk_drag_icon_native_get_surface_transform; - iface->check_resize = gtk_drag_icon_native_check_resize; + iface->layout = gtk_drag_icon_native_layout; } static gboolean @@ -197,6 +197,8 @@ gtk_drag_icon_realize (GtkWidget *widget) GTK_WIDGET_CLASS (gtk_drag_icon_parent_class)->realize (widget); icon->renderer = gsk_renderer_new_for_surface (icon->surface); + + gtk_native_realize (GTK_NATIVE (icon)); } static void @@ -204,6 +206,8 @@ gtk_drag_icon_unrealize (GtkWidget *widget) { GtkDragIcon *icon = GTK_DRAG_ICON (widget); + gtk_native_unrealize (GTK_NATIVE (icon)); + GTK_WIDGET_CLASS (gtk_drag_icon_parent_class)->unrealize (widget); gsk_renderer_unrealize (icon->renderer); @@ -279,7 +283,7 @@ gtk_drag_icon_show (GtkWidget *widget) _gtk_widget_set_visible_flag (widget, TRUE); gtk_css_node_validate (gtk_widget_get_css_node (widget)); gtk_widget_realize (widget); - gtk_drag_icon_native_check_resize (GTK_NATIVE (widget)); + gtk_drag_icon_present (GTK_DRAG_ICON (widget)); gtk_widget_map (widget); } @@ -414,7 +418,8 @@ gtk_drag_icon_get_for_drag (GdkDrag *drag) g_object_set_qdata_full (G_OBJECT (drag), drag_icon_quark, g_object_ref_sink (self), g_object_unref); - gtk_widget_show (self); + if (GTK_DRAG_ICON (self)->child != NULL) + gtk_widget_show (self); } return self; @@ -472,7 +477,10 @@ gtk_drag_icon_set_child (GtkDragIcon *self, self->child = child; if (self->child) - gtk_widget_set_parent (self->child, GTK_WIDGET (self)); + { + gtk_widget_set_parent (self->child, GTK_WIDGET (self)); + gtk_widget_show (GTK_WIDGET (self)); + } g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_CHILD]); } diff --git a/gtk/gtkdropdown.c b/gtk/gtkdropdown.c index 32e5c21c08..669305d539 100644 --- a/gtk/gtkdropdown.c +++ b/gtk/gtkdropdown.c @@ -383,7 +383,7 @@ gtk_drop_down_size_allocate (GtkWidget *widget, gtk_widget_set_size_request (self->popup, width, -1); gtk_widget_queue_resize (self->popup); - gtk_native_check_resize (GTK_NATIVE (self->popup)); + gtk_popover_present (GTK_POPOVER (self->popup)); } static gboolean diff --git a/gtk/gtkemojichooser.c b/gtk/gtkemojichooser.c index a41c4b49d5..11bf196e0a 100644 --- a/gtk/gtkemojichooser.c +++ b/gtk/gtkemojichooser.c @@ -113,7 +113,7 @@ gtk_emoji_chooser_child_size_allocate (GtkWidget *widget, GTK_WIDGET_CLASS (gtk_emoji_chooser_child_parent_class)->size_allocate (widget, width, height, baseline); if (child->variations) - gtk_native_check_resize (GTK_NATIVE (child->variations)); + gtk_popover_present (GTK_POPOVER (child->variations)); } static gboolean diff --git a/gtk/gtkentry.c b/gtk/gtkentry.c index a4cf3b30f8..e96fe4506f 100644 --- a/gtk/gtkentry.c +++ b/gtk/gtkentry.c @@ -181,7 +181,6 @@ struct _GtkEntryPrivate GtkWidget *text; GtkWidget *progress_widget; - GtkWidget *emoji_chooser; guint show_emoji_icon : 1; guint editing_canceled : 1; /* Only used by GtkCellRendererText */ @@ -1452,8 +1451,6 @@ gtk_entry_dispose (GObject *object) } g_clear_pointer (&priv->text, gtk_widget_unparent); - g_clear_pointer (&priv->emoji_chooser, gtk_widget_unparent); - G_OBJECT_CLASS (gtk_entry_parent_class)->dispose (object); } @@ -1803,9 +1800,6 @@ gtk_entry_size_allocate (GtkWidget *widget, if (completion) _gtk_entry_completion_resize_popup (completion); } - - if (priv->emoji_chooser) - gtk_native_check_resize (GTK_NATIVE (priv->emoji_chooser)); } static void diff --git a/gtk/gtkentrycompletion.c b/gtk/gtkentrycompletion.c index 6c197a4572..6092e036c5 100644 --- a/gtk/gtkentrycompletion.c +++ b/gtk/gtkentrycompletion.c @@ -1150,7 +1150,8 @@ _gtk_entry_completion_resize_popup (GtkEntryCompletion *completion) NULL, FALSE, 0.0, 0.0); gtk_tree_path_free (path); } - gtk_native_check_resize (GTK_NATIVE (completion->popup_window)); + + gtk_popover_present (GTK_POPOVER (completion->popup_window)); } static void diff --git a/gtk/gtkexpander.c b/gtk/gtkexpander.c index 647ee68428..bbe08fcced 100644 --- a/gtk/gtkexpander.c +++ b/gtk/gtkexpander.c @@ -727,23 +727,7 @@ gtk_expander_resize_toplevel (GtkExpander *expander) if (GTK_IS_WINDOW (toplevel) && gtk_widget_get_realized (toplevel)) - { - int toplevel_width, toplevel_height; - int child_height; - - gtk_widget_measure (child, GTK_ORIENTATION_VERTICAL, -1, - &child_height, NULL, NULL, NULL); - gtk_window_get_size (GTK_WINDOW (toplevel), &toplevel_width, &toplevel_height); - - if (expander->expanded) - toplevel_height += child_height; - else - toplevel_height -= child_height; - - gtk_window_resize (GTK_WINDOW (toplevel), - toplevel_width, - toplevel_height); - } + gtk_widget_queue_resize (GTK_WIDGET (expander)); } } diff --git a/gtk/gtkfilechooserdialog.c b/gtk/gtkfilechooserdialog.c index 6cff44ec93..b571a46f1e 100644 --- a/gtk/gtkfilechooserdialog.c +++ b/gtk/gtkfilechooserdialog.c @@ -628,7 +628,7 @@ save_dialog_geometry (GtkFileChooserDialog *dialog) window = GTK_WINDOW (dialog); - gtk_window_get_size (window, &width, &height); + gtk_window_get_default_size (window, &width, &height); g_settings_get (settings, SETTINGS_KEY_WINDOW_SIZE, "(ii)", &old_width, &old_height); if (old_width != width || old_height != height) diff --git a/gtk/gtkfilechooserwidget.c b/gtk/gtkfilechooserwidget.c index dd1cb284cf..18d4033892 100644 --- a/gtk/gtkfilechooserwidget.c +++ b/gtk/gtkfilechooserwidget.c @@ -7225,10 +7225,11 @@ gtk_file_chooser_widget_size_allocate (GtkWidget *widget, GtkFileChooserWidget *impl = GTK_FILE_CHOOSER_WIDGET (widget); GTK_WIDGET_CLASS (gtk_file_chooser_widget_parent_class)->size_allocate (widget, width, height, baseline); + if (impl->browse_files_popover) - gtk_native_check_resize (GTK_NATIVE (impl->browse_files_popover)); + gtk_popover_present (GTK_POPOVER (impl->browse_files_popover)); if (impl->rename_file_popover) - gtk_native_check_resize (GTK_NATIVE (impl->rename_file_popover)); + gtk_popover_present (GTK_POPOVER (impl->rename_file_popover)); } static void diff --git a/gtk/gtkheaderbar.c b/gtk/gtkheaderbar.c index 5ed128c4c2..1cb9e8185a 100644 --- a/gtk/gtkheaderbar.c +++ b/gtk/gtkheaderbar.c @@ -130,8 +130,6 @@ struct _GtkHeaderBar guint show_title_buttons : 1; guint track_default_decoration : 1; - - GdkToplevelState state; }; typedef struct _GtkHeaderBarClass GtkHeaderBarClass; @@ -613,7 +611,6 @@ gtk_header_bar_init (GtkHeaderBar *bar) bar->title_widget = NULL; bar->decoration_layout = NULL; bar->show_title_buttons = TRUE; - bar->state = GDK_TOPLEVEL_STATE_WITHDRAWN; bar->handle = gtk_window_handle_new (); gtk_widget_set_parent (bar->handle, GTK_WIDGET (bar)); diff --git a/gtk/gtklabel.c b/gtk/gtklabel.c index 7701422b62..9994d1a8fe 100644 --- a/gtk/gtklabel.c +++ b/gtk/gtklabel.c @@ -3276,7 +3276,7 @@ gtk_label_size_allocate (GtkWidget *widget, } if (self->popup_menu) - gtk_native_check_resize (GTK_NATIVE (self->popup_menu)); + gtk_popover_present (GTK_POPOVER (self->popup_menu)); } static void diff --git a/gtk/gtklayoutmanager.c b/gtk/gtklayoutmanager.c index d0e4037b2f..31ce041959 100644 --- a/gtk/gtklayoutmanager.c +++ b/gtk/gtklayoutmanager.c @@ -77,6 +77,9 @@ #include "gtklayoutchild.h" #include "gtkwidgetprivate.h" #include "gtknative.h" +#include "gtkpopover.h" +#include "gtktexthandleprivate.h" +#include "gtktooltipwindowprivate.h" #ifdef G_ENABLE_DEBUG #define LAYOUT_MANAGER_WARN_NOT_IMPLEMENTED(m,method) G_STMT_START { \ @@ -363,8 +366,15 @@ allocate_native_children (GtkWidget *widget) child != NULL; child = _gtk_widget_get_next_sibling (child)) { - if (GTK_IS_NATIVE (child)) - gtk_native_check_resize (GTK_NATIVE (child)); + if (GTK_IS_POPOVER (child)) + gtk_popover_present (GTK_POPOVER (child)); + else if (GTK_IS_TEXT_HANDLE (child)) + gtk_text_handle_present (GTK_TEXT_HANDLE (child)); + else if (GTK_IS_TOOLTIP_WINDOW (child)) + gtk_tooltip_window_present (GTK_TOOLTIP_WINDOW (child)); + else if (GTK_IS_NATIVE (child)) + g_warning ("Unable to present a to the layout manager unknown auxiliary child surface widget type %s", + G_OBJECT_TYPE_NAME (child)); } } diff --git a/gtk/gtkmenubutton.c b/gtk/gtkmenubutton.c index 93376641c0..d37ee47fc1 100644 --- a/gtk/gtkmenubutton.c +++ b/gtk/gtkmenubutton.c @@ -319,7 +319,7 @@ gtk_menu_button_size_allocate (GtkWidget *widget, &(GtkAllocation) { 0, 0, width, height }, baseline); if (self->popover) - gtk_native_check_resize (GTK_NATIVE (self->popover)); + gtk_popover_present (GTK_POPOVER (self->popover)); } static gboolean diff --git a/gtk/gtknative.c b/gtk/gtknative.c index 328d0c61fd..00dfd35820 100644 --- a/gtk/gtknative.c +++ b/gtk/gtknative.c @@ -24,6 +24,15 @@ #include "gdk/gdk-private.h" #include "gtkprivate.h" #include "gtkintl.h" +#include "gtkcssnodeprivate.h" + +typedef struct _GtkNativePrivate +{ + gulong update_handler_id; + gulong layout_handler_id; +} GtkNativePrivate; + +static GQuark quark_gtk_native_private; /** * SECTION:gtknative @@ -55,7 +64,9 @@ gtk_native_default_get_surface_transform (GtkNative *self, } static void -gtk_native_default_check_resize (GtkNative *self) +gtk_native_default_layout (GtkNative *self, + int width, + int height) { } @@ -64,7 +75,95 @@ gtk_native_default_init (GtkNativeInterface *iface) { iface->get_renderer = gtk_native_default_get_renderer; iface->get_surface_transform = gtk_native_default_get_surface_transform; - iface->check_resize = gtk_native_default_check_resize; + iface->layout = gtk_native_default_layout; + + quark_gtk_native_private = g_quark_from_static_string ("gtk-native-private"); +} + +static void +frame_clock_update_cb (GdkFrameClock *clock, + GtkNative *native) +{ + if (GTK_IS_ROOT (native)) + gtk_css_node_validate (gtk_widget_get_css_node (GTK_WIDGET (native))); +} + +static void +gtk_native_layout (GtkNative *self, + int width, + int height) +{ + return GTK_NATIVE_GET_IFACE (self)->layout (self, width, height); +} + +static void +surface_layout_cb (GdkSurface *surface, + int width, + int height, + GtkNative *native) +{ + gtk_native_layout (native, width, height); + + if (gtk_widget_needs_allocate (GTK_WIDGET (native))) + gtk_native_queue_relayout (native); +} + +static void +verify_priv_unrealized (gpointer user_data) +{ + GtkNativePrivate *priv = user_data; + + g_warn_if_fail (priv->update_handler_id == 0); + g_warn_if_fail (priv->layout_handler_id == 0); + + g_free (priv); +} + +void +gtk_native_realize (GtkNative *self) +{ + GdkSurface *surface; + GdkFrameClock *clock; + GtkNativePrivate *priv; + + g_return_if_fail (g_object_get_qdata (G_OBJECT (self), + quark_gtk_native_private) == NULL); + + surface = gtk_native_get_surface (self); + clock = gdk_surface_get_frame_clock (surface); + g_return_if_fail (clock != NULL); + + priv = g_new0 (GtkNativePrivate, 1); + priv->update_handler_id = g_signal_connect_after (clock, "update", + G_CALLBACK (frame_clock_update_cb), + self); + priv->layout_handler_id = g_signal_connect (surface, "layout", + G_CALLBACK (surface_layout_cb), + self); + g_object_set_qdata_full (G_OBJECT (self), + quark_gtk_native_private, + priv, + verify_priv_unrealized); +} + +void +gtk_native_unrealize (GtkNative *self) +{ + GtkNativePrivate *priv; + GdkSurface *surface; + GdkFrameClock *clock; + + priv = g_object_get_qdata (G_OBJECT (self), quark_gtk_native_private); + g_return_if_fail (priv != NULL); + + surface = gtk_native_get_surface (self); + clock = gdk_surface_get_frame_clock (surface); + g_return_if_fail (clock != NULL); + + g_clear_signal_handler (&priv->update_handler_id, clock); + g_clear_signal_handler (&priv->layout_handler_id, surface); + + g_object_set_qdata (G_OBJECT (self), quark_gtk_native_private, NULL); } /** @@ -121,23 +220,6 @@ gtk_native_get_surface_transform (GtkNative *self, } /** - * gtk_native_check_resize: - * @self: a #GtkNative - * - * Reposition and resize a #GtkNative. - * - * Widgets need to call this function on their attached - * native widgets when they receive a new size allocation. - */ -void -gtk_native_check_resize (GtkNative *self) -{ - g_return_if_fail (GTK_IS_NATIVE (self)); - - GTK_NATIVE_GET_IFACE (self)->check_resize (self); -} - -/** * gtk_native_get_for_surface: * @surface: a #GdkSurface * @@ -157,3 +239,19 @@ gtk_native_get_for_surface (GdkSurface *surface) return NULL; } + +void +gtk_native_queue_relayout (GtkNative *self) +{ + GtkWidget *widget = GTK_WIDGET (self); + GdkSurface *surface; + GdkFrameClock *clock; + + surface = gtk_widget_get_surface (widget); + clock = gtk_widget_get_frame_clock (widget); + if (clock == NULL) + return; + + gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_UPDATE); + gdk_surface_request_layout (surface); +} diff --git a/gtk/gtknative.h b/gtk/gtknative.h index c9372a60e9..18346f32fa 100644 --- a/gtk/gtknative.h +++ b/gtk/gtknative.h @@ -34,12 +34,14 @@ G_BEGIN_DECLS GDK_AVAILABLE_IN_ALL G_DECLARE_INTERFACE (GtkNative, gtk_native, GTK, NATIVE, GtkWidget) +GDK_AVAILABLE_IN_ALL +void gtk_native_realize (GtkNative *self); GDK_AVAILABLE_IN_ALL -GtkNative * gtk_native_get_for_surface (GdkSurface *surface); +void gtk_native_unrealize (GtkNative *self); GDK_AVAILABLE_IN_ALL -void gtk_native_check_resize (GtkNative *self); +GtkNative * gtk_native_get_for_surface (GdkSurface *surface); GDK_AVAILABLE_IN_ALL GdkSurface *gtk_native_get_surface (GtkNative *self); diff --git a/gtk/gtknativeprivate.h b/gtk/gtknativeprivate.h index 6b603361ff..df9b9ffaa6 100644 --- a/gtk/gtknativeprivate.h +++ b/gtk/gtknativeprivate.h @@ -23,9 +23,13 @@ struct _GtkNativeInterface double *x, double *y); - void (* check_resize) (GtkNative *self); + void (* layout) (GtkNative *self, + int width, + int height); }; +void gtk_native_queue_relayout (GtkNative *native); + G_END_DECLS #endif /* __GTK_NATIVE_PRIVATE_H__ */ diff --git a/gtk/gtkplacessidebar.c b/gtk/gtkplacessidebar.c index b90b748b85..41df790cc6 100644 --- a/gtk/gtkplacessidebar.c +++ b/gtk/gtkplacessidebar.c @@ -4076,10 +4076,10 @@ gtk_places_sidebar_size_allocate (GtkWidget *widget, baseline); if (sidebar->popover) - gtk_native_check_resize (GTK_NATIVE (sidebar->popover)); + gtk_popover_present (GTK_POPOVER (sidebar->popover)); if (sidebar->rename_popover) - gtk_native_check_resize (GTK_NATIVE (sidebar->rename_popover)); + gtk_popover_present (GTK_POPOVER (sidebar->rename_popover)); } static void diff --git a/gtk/gtkplacesviewrow.c b/gtk/gtkplacesviewrow.c index 8d8611bc1c..51af16c465 100644 --- a/gtk/gtkplacesviewrow.c +++ b/gtk/gtkplacesviewrow.c @@ -36,6 +36,7 @@ #include "gtkstack.h" #include "gtktypebuiltins.h" #include "gtknative.h" +#include "gtkpopover.h" #else #include <gtk/gtk.h> #endif @@ -319,7 +320,7 @@ gtk_places_view_row_size_allocate (GtkWidget *widget, GTK_WIDGET_CLASS (gtk_places_view_row_parent_class)->size_allocate (widget, width, height, baseline); if (menu) - gtk_native_check_resize (GTK_NATIVE (menu)); + gtk_popover_present (GTK_POPOVER (menu)); } static void diff --git a/gtk/gtkpopover.c b/gtk/gtkpopover.c index 504dcd6cc1..5d8a01266d 100644 --- a/gtk/gtkpopover.c +++ b/gtk/gtkpopover.c @@ -419,11 +419,6 @@ update_popover_layout (GtkPopover *popover, g_clear_pointer (&priv->arrow_render_node, gsk_render_node_unref); } - gtk_widget_allocate (GTK_WIDGET (popover), - gdk_surface_get_width (priv->surface), - gdk_surface_get_height (priv->surface), - -1, NULL); - gtk_widget_queue_draw (GTK_WIDGET (popover)); } @@ -582,10 +577,9 @@ present_popup (GtkPopover *popover) return FALSE; } -static void -gtk_popover_native_check_resize (GtkNative *native) +void +gtk_popover_present (GtkPopover *popover) { - GtkPopover *popover = GTK_POPOVER (native); GtkWidget *widget = GTK_WIDGET (popover); if (!_gtk_widget_get_alloc_needed (widget)) @@ -594,6 +588,61 @@ gtk_popover_native_check_resize (GtkNative *native) present_popup (popover); } +static void +maybe_request_motion_event (GtkPopover *popover) +{ + GtkWidget *widget = GTK_WIDGET (popover); + GtkRoot *root = gtk_widget_get_root (widget); + GdkSeat *seat; + GdkDevice *device; + GtkWidget *focus; + GdkSurface *focus_surface; + + seat = gdk_display_get_default_seat (gtk_widget_get_display (widget)); + if (!seat) + return; + + + device = gdk_seat_get_pointer (seat); + focus = gtk_window_lookup_pointer_focus_widget (GTK_WINDOW (root), + device, NULL); + if (!focus) + return; + + if (!gtk_widget_is_ancestor (focus, GTK_WIDGET (popover))) + return; + + focus_surface = gtk_native_get_surface (gtk_widget_get_native (focus)); + gdk_surface_request_motion (focus_surface); +} + +static void +gtk_popover_native_layout (GtkNative *native, + int width, + int height) +{ + GtkPopover *popover = GTK_POPOVER (native); + GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover); + GtkWidget *widget = GTK_WIDGET (popover); + + update_popover_layout (popover, gdk_popup_layout_ref (priv->layout)); + + if (gtk_widget_needs_allocate (widget)) + { + gtk_widget_allocate (widget, width, height, -1, NULL); + + /* This fake motion event is needed for getting up to date pointer focus + * and coordinates when tho pointer didn't move but the layout changed + * within the popover. + */ + maybe_request_motion_event (popover); + } + else + { + gtk_widget_ensure_allocate (widget); + } +} + static gboolean gtk_popover_has_mnemonic_modifier_pressed (GtkPopover *popover) { @@ -736,13 +785,6 @@ surface_mapped_changed (GtkWidget *widget) gtk_widget_set_visible (widget, gdk_surface_get_mapped (priv->surface)); } -static void -surface_size_changed (GtkWidget *widget, - guint width, - guint height) -{ -} - static gboolean surface_render (GdkSurface *surface, cairo_region_t *region, @@ -762,16 +804,6 @@ surface_event (GdkSurface *surface, } static void -popup_layout_changed (GdkSurface *surface, - GtkWidget *widget) -{ - GtkPopover *popover = GTK_POPOVER (widget); - GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover); - - update_popover_layout (popover, gdk_popup_layout_ref (priv->layout)); -} - -static void gtk_popover_activate_default (GtkPopover *popover) { GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover); @@ -887,14 +919,14 @@ gtk_popover_realize (GtkWidget *widget) gdk_surface_set_widget (priv->surface, widget); g_signal_connect_swapped (priv->surface, "notify::mapped", G_CALLBACK (surface_mapped_changed), widget); - g_signal_connect_swapped (priv->surface, "size-changed", G_CALLBACK (surface_size_changed), widget); g_signal_connect (priv->surface, "render", G_CALLBACK (surface_render), widget); g_signal_connect (priv->surface, "event", G_CALLBACK (surface_event), widget); - g_signal_connect (priv->surface, "popup-layout-changed", G_CALLBACK (popup_layout_changed), widget); GTK_WIDGET_CLASS (gtk_popover_parent_class)->realize (widget); priv->renderer = gsk_renderer_new_for_surface (priv->surface); + + gtk_native_realize (GTK_NATIVE (popover)); } static void @@ -903,16 +935,16 @@ gtk_popover_unrealize (GtkWidget *widget) GtkPopover *popover = GTK_POPOVER (widget); GtkPopoverPrivate *priv = gtk_popover_get_instance_private (popover); + gtk_native_unrealize (GTK_NATIVE (popover)); + GTK_WIDGET_CLASS (gtk_popover_parent_class)->unrealize (widget); gsk_renderer_unrealize (priv->renderer); g_clear_object (&priv->renderer); g_signal_handlers_disconnect_by_func (priv->surface, surface_mapped_changed, widget); - g_signal_handlers_disconnect_by_func (priv->surface, surface_size_changed, widget); g_signal_handlers_disconnect_by_func (priv->surface, surface_render, widget); g_signal_handlers_disconnect_by_func (priv->surface, surface_event, widget); - g_signal_handlers_disconnect_by_func (priv->surface, popup_layout_changed, widget); gdk_surface_set_widget (priv->surface, NULL); gdk_surface_destroy (priv->surface); g_clear_object (&priv->surface); @@ -1847,7 +1879,7 @@ gtk_popover_native_interface_init (GtkNativeInterface *iface) iface->get_surface = gtk_popover_native_get_surface; iface->get_renderer = gtk_popover_native_get_renderer; iface->get_surface_transform = gtk_popover_native_get_surface_transform; - iface->check_resize = gtk_popover_native_check_resize; + iface->layout = gtk_popover_native_layout; } static GtkBuildableIface *parent_buildable_iface; diff --git a/gtk/gtkpopover.h b/gtk/gtkpopover.h index 9cb1208761..1ecb8e57c3 100644 --- a/gtk/gtkpopover.h +++ b/gtk/gtkpopover.h @@ -121,6 +121,9 @@ GDK_AVAILABLE_IN_ALL void gtk_popover_set_default_widget (GtkPopover *popover, GtkWidget *widget); +GDK_AVAILABLE_IN_ALL +void gtk_popover_present (GtkPopover *popover); + G_END_DECLS diff --git a/gtk/gtkpopovermenubar.c b/gtk/gtkpopovermenubar.c index 455f21ef65..d0b17e6168 100644 --- a/gtk/gtkpopovermenubar.c +++ b/gtk/gtkpopovermenubar.c @@ -320,7 +320,7 @@ gtk_popover_menu_bar_item_size_allocate (GtkWidget *widget, &(GtkAllocation) { 0, 0, width, height }, baseline); - gtk_native_check_resize (GTK_NATIVE (item->popover)); + gtk_popover_present (GTK_POPOVER (item->popover)); } static void diff --git a/gtk/gtkroot.c b/gtk/gtkroot.c index 33000c28fc..16e1bef28c 100644 --- a/gtk/gtkroot.c +++ b/gtk/gtkroot.c @@ -21,6 +21,7 @@ #include "gtkrootprivate.h" #include "gtknative.h" +#include "gtknativeprivate.h" #include "gtkcssnodeprivate.h" #include "gtkwidgetprivate.h" #include "gdk/gdk-private.h" @@ -43,9 +44,6 @@ * The obvious example of a #GtkRoot is #GtkWindow. */ -static GQuark quark_restyle_pending; -static GQuark quark_resize_handler; - G_DEFINE_INTERFACE_WITH_CODE (GtkRoot, gtk_root, GTK_TYPE_WIDGET, g_type_interface_add_prerequisite (g_define_type_id, GTK_TYPE_NATIVE)) @@ -81,9 +79,6 @@ gtk_root_default_init (GtkRootInterface *iface) iface->get_constraint_solver = gtk_root_default_get_constraint_solver; iface->get_focus = gtk_root_default_get_focus; iface->set_focus = gtk_root_default_set_focus; - - quark_restyle_pending = g_quark_from_static_string ("gtk-root-restyle-pending"); - quark_resize_handler = g_quark_from_static_string ("gtk-root-resize-handler"); } /** @@ -161,117 +156,19 @@ gtk_root_get_focus (GtkRoot *self) return GTK_ROOT_GET_IFACE (self)->get_focus (self); } -static gboolean -gtk_root_needs_layout (GtkRoot *self) -{ - if (g_object_get_qdata (G_OBJECT (self), quark_restyle_pending)) - return TRUE; - - return gtk_widget_needs_allocate (GTK_WIDGET (self)); -} - -static void -gtk_root_layout_cb (GdkFrameClock *clock, - GtkRoot *self) -{ - GtkWidget *widget = GTK_WIDGET (self); - - /* We validate the style contexts in a single loop before even trying - * to handle resizes instead of doing validations inline. - * This is mostly necessary for compatibility reasons with old code, - * because both css_changed and size_allocate functions often change - * styles and so could cause infinite loops in this function. - * - * It's important to note that even an invalid style context returns - * sane values. So the result of an invalid style context will never be - * a program crash, but only a wrong layout or rendering. - */ - if (g_object_get_qdata (G_OBJECT (self), quark_restyle_pending)) - { - g_object_set_qdata (G_OBJECT (self), quark_restyle_pending, NULL); - gtk_css_node_validate (gtk_widget_get_css_node (widget)); - } - - /* we may be invoked with a container_resize_queue of NULL, because - * queue_resize could have been adding an extra idle function while - * the queue still got processed. we better just ignore such case - * than trying to explicitly work around them with some extra flags, - * since it doesn't cause any actual harm. - */ - if (gtk_widget_needs_allocate (widget)) - { - gtk_native_check_resize (GTK_NATIVE (self)); - if (GTK_IS_WINDOW (widget)) - { - GdkSeat *seat; - - seat = gdk_display_get_default_seat (gtk_widget_get_display (widget)); - if (seat) - { - GdkDevice *device; - GtkWidget *focus; - - device = gdk_seat_get_pointer (seat); - focus = gtk_window_lookup_pointer_focus_widget (GTK_WINDOW (widget), device, NULL); - if (focus) - gdk_surface_request_motion (gtk_native_get_surface (gtk_widget_get_native (focus))); - } - } - } - - if (!gtk_root_needs_layout (self)) - gtk_root_stop_layout (self); - else - gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_LAYOUT); -} - void gtk_root_start_layout (GtkRoot *self) { - GdkFrameClock *clock; - guint resize_handler; - - if (g_object_get_qdata (G_OBJECT (self), quark_resize_handler)) - return; - - if (!gtk_root_needs_layout (self)) - return; - - clock = gtk_widget_get_frame_clock (GTK_WIDGET (self)); - if (clock == NULL) - return; - - resize_handler = g_signal_connect (clock, "layout", - G_CALLBACK (gtk_root_layout_cb), self); - g_object_set_qdata (G_OBJECT (self), quark_resize_handler, GINT_TO_POINTER (resize_handler)); - - gdk_frame_clock_request_phase (clock, GDK_FRAME_CLOCK_PHASE_LAYOUT); + gtk_native_queue_relayout (GTK_NATIVE (self)); } void gtk_root_stop_layout (GtkRoot *self) { - GdkFrameClock *clock; - guint resize_handler; - - resize_handler = GPOINTER_TO_INT (g_object_get_qdata (G_OBJECT (self), quark_resize_handler)); - - if (resize_handler == 0) - return; - - clock = gtk_widget_get_frame_clock (GTK_WIDGET (self)); - g_signal_handler_disconnect (clock, resize_handler); - g_object_set_qdata (G_OBJECT (self), quark_resize_handler, NULL); } void gtk_root_queue_restyle (GtkRoot *self) { - if (g_object_get_qdata (G_OBJECT (self), quark_restyle_pending)) - return; - - g_object_set_qdata (G_OBJECT (self), quark_restyle_pending, GINT_TO_POINTER (1)); - gtk_root_start_layout (self); } - diff --git a/gtk/gtkscalebutton.c b/gtk/gtkscalebutton.c index bb39e7f19b..67c6044fc2 100644 --- a/gtk/gtkscalebutton.c +++ b/gtk/gtkscalebutton.c @@ -1001,5 +1001,5 @@ gtk_scale_button_size_allocate (GtkWidget *widget, &(GtkAllocation) { 0, 0, width, height }, baseline); - gtk_native_check_resize (GTK_NATIVE (priv->dock)); + gtk_popover_present (GTK_POPOVER (priv->dock)); } diff --git a/gtk/gtktext.c b/gtk/gtktext.c index 8452344f60..c39e007d61 100644 --- a/gtk/gtktext.c +++ b/gtk/gtktext.c @@ -2448,27 +2448,27 @@ gtk_text_size_allocate (GtkWidget *widget, chooser = g_object_get_data (G_OBJECT (self), "gtk-emoji-chooser"); if (chooser) - gtk_native_check_resize (GTK_NATIVE (chooser)); + gtk_popover_present (GTK_POPOVER (chooser)); gtk_text_update_handles (self); if (priv->emoji_completion) - gtk_native_check_resize (GTK_NATIVE (priv->emoji_completion)); + gtk_popover_present (GTK_POPOVER (priv->emoji_completion)); if (priv->magnifier_popover) - gtk_native_check_resize (GTK_NATIVE (priv->magnifier_popover)); + gtk_popover_present (GTK_POPOVER (priv->magnifier_popover)); if (priv->popup_menu) - gtk_native_check_resize (GTK_NATIVE (priv->popup_menu)); + gtk_popover_present (GTK_POPOVER (priv->popup_menu)); if (priv->selection_bubble) - gtk_native_check_resize (GTK_NATIVE (priv->selection_bubble)); + gtk_popover_present (GTK_POPOVER (priv->selection_bubble)); if (priv->text_handles[TEXT_HANDLE_CURSOR]) - gtk_native_check_resize (GTK_NATIVE (priv->text_handles[TEXT_HANDLE_CURSOR])); + gtk_text_handle_present (priv->text_handles[TEXT_HANDLE_CURSOR]); if (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND]) - gtk_native_check_resize (GTK_NATIVE (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND])); + gtk_text_handle_present (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND]); } static void diff --git a/gtk/gtktexthandle.c b/gtk/gtktexthandle.c index 47cceafa0e..73bd8d5bcc 100644 --- a/gtk/gtktexthandle.c +++ b/gtk/gtktexthandle.c @@ -162,18 +162,12 @@ gtk_text_handle_present_surface (GtkTextHandle *handle) MAX (req.height, 1), layout); gdk_popup_layout_unref (layout); - - gtk_widget_allocate (widget, - gdk_surface_get_width (handle->surface), - gdk_surface_get_height (handle->surface), - -1, NULL); } -static void -gtk_text_handle_native_check_resize (GtkNative *native) +void +gtk_text_handle_present (GtkTextHandle *handle) { - GtkTextHandle *handle = GTK_TEXT_HANDLE (native); - GtkWidget *widget = GTK_WIDGET (native); + GtkWidget *widget = GTK_WIDGET (handle); if (!_gtk_widget_get_alloc_needed (widget)) gtk_widget_ensure_allocate (widget); @@ -182,12 +176,25 @@ gtk_text_handle_native_check_resize (GtkNative *native) } static void +gtk_text_handle_native_layout (GtkNative *native, + int width, + int height) +{ + GtkWidget *widget = GTK_WIDGET (native); + + if (_gtk_widget_get_alloc_needed (widget)) + gtk_widget_allocate (widget, width, height, -1, NULL); + else + gtk_widget_ensure_allocate (widget); +} + +static void gtk_text_handle_native_interface_init (GtkNativeInterface *iface) { iface->get_surface = gtk_text_handle_native_get_surface; iface->get_renderer = gtk_text_handle_native_get_renderer; iface->get_surface_transform = gtk_text_handle_native_get_surface_transform; - iface->check_resize = gtk_text_handle_native_check_resize; + iface->layout = gtk_text_handle_native_layout; } static gboolean @@ -240,6 +247,8 @@ gtk_text_handle_realize (GtkWidget *widget) GTK_WIDGET_CLASS (gtk_text_handle_parent_class)->realize (widget); handle->renderer = gsk_renderer_new_for_surface (handle->surface); + + gtk_native_realize (GTK_NATIVE (handle)); } static void @@ -247,6 +256,8 @@ gtk_text_handle_unrealize (GtkWidget *widget) { GtkTextHandle *handle = GTK_TEXT_HANDLE (widget); + gtk_native_unrealize (GTK_NATIVE (handle)); + GTK_WIDGET_CLASS (gtk_text_handle_parent_class)->unrealize (widget); gsk_renderer_unrealize (handle->renderer); diff --git a/gtk/gtktexthandleprivate.h b/gtk/gtktexthandleprivate.h index 0a02eac12e..c01fedcd50 100644 --- a/gtk/gtktexthandleprivate.h +++ b/gtk/gtktexthandleprivate.h @@ -35,6 +35,8 @@ typedef enum GtkTextHandle * gtk_text_handle_new (GtkWidget *parent); +void gtk_text_handle_present (GtkTextHandle *handle); + void gtk_text_handle_set_role (GtkTextHandle *handle, GtkTextHandleRole role); GtkTextHandleRole gtk_text_handle_get_role (GtkTextHandle *handle); diff --git a/gtk/gtktextview.c b/gtk/gtktextview.c index 4816bef439..ce097cb586 100644 --- a/gtk/gtktextview.c +++ b/gtk/gtktextview.c @@ -4528,22 +4528,22 @@ gtk_text_view_size_allocate (GtkWidget *widget, chooser = g_object_get_data (G_OBJECT (text_view), "gtk-emoji-chooser"); if (chooser) - gtk_native_check_resize (GTK_NATIVE (chooser)); + gtk_popover_present (GTK_POPOVER (chooser)); if (priv->magnifier_popover) - gtk_native_check_resize (GTK_NATIVE (priv->magnifier_popover)); + gtk_popover_present (GTK_POPOVER (priv->magnifier_popover)); if (priv->popup_menu) - gtk_native_check_resize (GTK_NATIVE (priv->popup_menu)); + gtk_popover_present (GTK_POPOVER (priv->popup_menu)); if (priv->text_handles[TEXT_HANDLE_CURSOR]) - gtk_native_check_resize (GTK_NATIVE (priv->text_handles[TEXT_HANDLE_CURSOR])); + gtk_text_handle_present (priv->text_handles[TEXT_HANDLE_CURSOR]); if (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND]) - gtk_native_check_resize (GTK_NATIVE (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND])); + gtk_text_handle_present (priv->text_handles[TEXT_HANDLE_SELECTION_BOUND]); if (priv->selection_bubble) - gtk_native_check_resize (GTK_NATIVE (priv->selection_bubble)); + gtk_popover_present (GTK_POPOVER (priv->selection_bubble)); } static void diff --git a/gtk/gtktooltip.c b/gtk/gtktooltip.c index 392bd0620e..a192d1eb0d 100644 --- a/gtk/gtktooltip.c +++ b/gtk/gtktooltip.c @@ -1024,7 +1024,7 @@ gtk_tooltip_maybe_allocate (GtkNative *native) if (!tooltip || GTK_NATIVE (tooltip->native) != native) return; - gtk_native_check_resize (GTK_NATIVE (tooltip->window)); + gtk_tooltip_window_present (GTK_TOOLTIP_WINDOW (tooltip->window)); } void diff --git a/gtk/gtktooltipwindow.c b/gtk/gtktooltipwindow.c index 95b4333a9f..a3dbf83db4 100644 --- a/gtk/gtktooltipwindow.c +++ b/gtk/gtktooltipwindow.c @@ -47,7 +47,6 @@ struct _GtkTooltipWindow GdkSurface *surface; GskRenderer *renderer; - GdkToplevelState state; GtkWidget *relative_to; GdkRectangle rect; GdkGravity rect_anchor; @@ -139,11 +138,10 @@ gtk_tooltip_window_relayout (GtkTooltipWindow *window) gdk_popup_layout_unref (layout); } -static void -gtk_tooltip_window_native_check_resize (GtkNative *native) +void +gtk_tooltip_window_present (GtkTooltipWindow *window) { - GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (native); - GtkWidget *widget = GTK_WIDGET (native); + GtkWidget *widget = GTK_WIDGET (window); if (!_gtk_widget_get_alloc_needed (widget)) { @@ -152,39 +150,39 @@ gtk_tooltip_window_native_check_resize (GtkNative *native) else if (gtk_widget_get_visible (widget)) { gtk_tooltip_window_relayout (window); - if (window->surface) - gtk_widget_allocate (GTK_WIDGET (window), - gdk_surface_get_width (window->surface), - gdk_surface_get_height (window->surface), - -1, NULL); } } static void +gtk_tooltip_window_native_layout (GtkNative *native, + int width, + int height) +{ + GtkWidget *widget = GTK_WIDGET (native); + + if (gtk_widget_needs_allocate (widget)) + gtk_widget_allocate (widget, width, height, -1, NULL); + else + gtk_widget_ensure_allocate (widget); + +} + +static void gtk_tooltip_window_native_init (GtkNativeInterface *iface) { iface->get_surface = gtk_tooltip_window_native_get_surface; iface->get_renderer = gtk_tooltip_window_native_get_renderer; iface->get_surface_transform = gtk_tooltip_window_native_get_surface_transform; - iface->check_resize = gtk_tooltip_window_native_check_resize; + iface->layout = gtk_tooltip_window_native_layout; } static void -surface_state_changed (GtkWidget *widget) +mapped_changed (GdkSurface *surface, + GParamSpec *pspec, + GtkWidget *widget) { - GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (widget); - GdkToplevelState new_surface_state; - GdkToplevelState changed_mask; - - new_surface_state = gdk_toplevel_get_state (GDK_TOPLEVEL (window->surface)); - changed_mask = new_surface_state ^ window->state; - window->state = new_surface_state; - - if (changed_mask & GDK_TOPLEVEL_STATE_WITHDRAWN) - { - if (window->state & GDK_TOPLEVEL_STATE_WITHDRAWN) - gtk_widget_hide (widget); - } + if (!gdk_surface_get_mapped (surface)) + gtk_widget_hide (widget); } static gboolean @@ -216,13 +214,15 @@ gtk_tooltip_window_realize (GtkWidget *widget) gdk_surface_set_widget (window->surface, widget); - g_signal_connect_swapped (window->surface, "notify::state", G_CALLBACK (surface_state_changed), widget); + g_signal_connect (window->surface, "notify::mapped", G_CALLBACK (mapped_changed), widget); g_signal_connect (window->surface, "render", G_CALLBACK (surface_render), widget); g_signal_connect (window->surface, "event", G_CALLBACK (surface_event), widget); GTK_WIDGET_CLASS (gtk_tooltip_window_parent_class)->realize (widget); window->renderer = gsk_renderer_new_for_surface (window->surface); + + gtk_native_realize (GTK_NATIVE (window)); } static void @@ -230,12 +230,14 @@ gtk_tooltip_window_unrealize (GtkWidget *widget) { GtkTooltipWindow *window = GTK_TOOLTIP_WINDOW (widget); + gtk_native_unrealize (GTK_NATIVE (window)); + GTK_WIDGET_CLASS (gtk_tooltip_window_parent_class)->unrealize (widget); gsk_renderer_unrealize (window->renderer); g_clear_object (&window->renderer); - g_signal_handlers_disconnect_by_func (window->surface, surface_state_changed, widget); + g_signal_handlers_disconnect_by_func (window->surface, mapped_changed, widget); g_signal_handlers_disconnect_by_func (window->surface, surface_render, widget); g_signal_handlers_disconnect_by_func (window->surface, surface_event, widget); gdk_surface_set_widget (window->surface, NULL); @@ -340,7 +342,7 @@ gtk_tooltip_window_show (GtkWidget *widget) { _gtk_widget_set_visible_flag (widget, TRUE); gtk_widget_realize (widget); - gtk_tooltip_window_native_check_resize (GTK_NATIVE (widget)); + gtk_tooltip_window_present (GTK_TOOLTIP_WINDOW (widget)); gtk_widget_map (widget); } diff --git a/gtk/gtktooltipwindowprivate.h b/gtk/gtktooltipwindowprivate.h index 61e6b91864..651a3cf7c7 100644 --- a/gtk/gtktooltipwindowprivate.h +++ b/gtk/gtktooltipwindowprivate.h @@ -37,6 +37,8 @@ G_DECLARE_FINAL_TYPE (GtkTooltipWindow, gtk_tooltip_window, GTK, TOOLTIP_WINDOW, GtkWidget * gtk_tooltip_window_new (void); +void gtk_tooltip_window_present (GtkTooltipWindow *window); + void gtk_tooltip_window_set_label_markup (GtkTooltipWindow *window, const char *markup); void gtk_tooltip_window_set_label_text (GtkTooltipWindow *window, diff --git a/gtk/gtktreeview.c b/gtk/gtktreeview.c index def80e5776..dda21f82aa 100644 --- a/gtk/gtktreeview.c +++ b/gtk/gtktreeview.c @@ -2654,7 +2654,7 @@ gtk_tree_view_size_allocate (GtkWidget *widget, } if (priv->search_popover) - gtk_native_check_resize (GTK_NATIVE (priv->search_popover)); + gtk_popover_present (GTK_POPOVER (priv->search_popover)); } /* Grabs the focus and unsets the GTK_TREE_VIEW_DRAW_KEYFOCUS flag */ diff --git a/gtk/gtkwidget.c b/gtk/gtkwidget.c index b2636ffa58..a112309cdf 100644 --- a/gtk/gtkwidget.c +++ b/gtk/gtkwidget.c @@ -56,6 +56,7 @@ #include "gtkrenderbackgroundprivate.h" #include "gtkrenderborderprivate.h" #include "gtkrootprivate.h" +#include "gtknativeprivate.h" #include "gtkscrollable.h" #include "gtksettingsprivate.h" #include "gtkshortcut.h" @@ -3243,7 +3244,7 @@ gtk_widget_remove_surface_transform_changed_callback (GtkWidget *widget, } } -static GdkSurface * +GdkSurface * gtk_widget_get_surface (GtkWidget *widget) { GtkNative *native = gtk_widget_get_native (widget); @@ -10325,9 +10326,11 @@ gtk_widget_set_alloc_needed (GtkWidget *widget) if (!priv->visible) break; + if (GTK_IS_NATIVE (widget)) + gtk_native_queue_relayout (GTK_NATIVE (widget)); + if (!priv->parent && GTK_IS_ROOT (widget)) { - gtk_root_start_layout (GTK_ROOT (widget)); break; } diff --git a/gtk/gtkwidgetprivate.h b/gtk/gtkwidgetprivate.h index c024c6adf1..eb6959fe7c 100644 --- a/gtk/gtkwidgetprivate.h +++ b/gtk/gtkwidgetprivate.h @@ -229,6 +229,8 @@ void gtk_widget_ensure_resize (GtkWidget *widget); void gtk_widget_ensure_allocate (GtkWidget *widget); void _gtk_widget_scale_changed (GtkWidget *widget); +GdkSurface * gtk_widget_get_surface (GtkWidget *widget); + void gtk_widget_render (GtkWidget *widget, GdkSurface *surface, const cairo_region_t *region); diff --git a/gtk/gtkwindow.c b/gtk/gtkwindow.c index 996e09c64b..7e22e4bcbe 100644 --- a/gtk/gtkwindow.c +++ b/gtk/gtkwindow.c @@ -170,6 +170,9 @@ typedef struct GdkDisplay *display; GtkApplication *application; + int default_width; + int default_height; + char *startup_id; char *title; @@ -177,8 +180,6 @@ typedef struct guint32 initial_timestamp; - guint16 configure_request_count; - guint mnemonics_display_timeout_id; guint focus_visible_timeout; @@ -204,7 +205,6 @@ typedef struct guint need_default_size : 1; guint builder_visible : 1; - guint configure_notify_received : 1; guint decorated : 1; guint deletable : 1; guint destroy_with_parent : 1; @@ -238,6 +238,9 @@ typedef struct GtkConstraintSolver *constraint_solver; GdkToplevelLayout *layout; + int surface_width; + int surface_height; + GdkCursor *resize_cursor; } GtkWindowPrivate; @@ -281,7 +284,8 @@ enum { PROP_MNEMONICS_VISIBLE, PROP_FOCUS_VISIBLE, - PROP_IS_MAXIMIZED, + PROP_MAXIMIZED, + PROP_FULLSCREEN, LAST_ARG }; @@ -318,18 +322,6 @@ typedef struct { struct _GtkWindowGeometryInfo { - /* from last gtk_window_resize () - if > 0, indicates that - * we should resize to this size. - */ - int resize_width; - int resize_height; - - /* Default size - used only the FIRST time we map a window, - * only if > 0. - */ - int default_width; - int default_height; - GtkWindowLastGeometryInfo last; }; @@ -379,6 +371,10 @@ static int gtk_window_focus (GtkWidget *widget, static void gtk_window_move_focus (GtkWidget *widget, GtkDirectionType dir); +static void gtk_window_get_remembered_size (GtkWindow *window, + int *width, + int *height); + static void gtk_window_real_activate_default (GtkWindow *window); static void gtk_window_real_activate_focus (GtkWindow *window); static void gtk_window_keys_changed (GtkWindow *window); @@ -393,23 +389,6 @@ static void gtk_window_transient_parent_unrealized (GtkWidget *parent, static GtkWindowGeometryInfo* gtk_window_get_geometry_info (GtkWindow *window, gboolean create); -static void gtk_window_move_resize (GtkWindow *window); -static gboolean gtk_window_compare_hints (GdkGeometry *geometry_a, - guint flags_a, - GdkGeometry *geometry_b, - guint flags_b); -static void gtk_window_update_fixed_size (GtkWindow *window, - GdkGeometry *new_geometry, - int new_width, - int new_height); -static void gtk_window_compute_hints (GtkWindow *window, - GdkGeometry *new_geometry, - guint *new_flags); -static void gtk_window_compute_configure_request (GtkWindow *window, - GdkRectangle *request, - GdkGeometry *geometry, - guint *flags); - static void gtk_window_set_default_size_internal (GtkWindow *window, gboolean change_width, int width, @@ -495,6 +474,14 @@ static void gtk_window_native_interface_init (GtkNativeInterface * static void ensure_state_flag_backdrop (GtkWidget *widget); static void unset_titlebar (GtkWindow *window); +#define INCLUDE_CSD_SIZE 1 +#define EXCLUDE_CSD_SIZE -1 + +static void +gtk_window_update_csd_size (GtkWindow *window, + int *width, + int *height, + int apply); G_DEFINE_TYPE_WITH_CODE (GtkWindow, gtk_window, GTK_TYPE_WIDGET, G_ADD_PRIVATE (GtkWindow) @@ -756,17 +743,17 @@ gtk_window_class_init (GtkWindowClass *klass) window_props[PROP_DEFAULT_WIDTH] = g_param_spec_int ("default-width", P_("Default Width"), - P_("The default width of the window, used when initially showing the window"), + P_("The default width of the window"), -1, G_MAXINT, - -1, + 0, GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); window_props[PROP_DEFAULT_HEIGHT] = g_param_spec_int ("default-height", P_("Default Height"), - P_("The default height of the window, used when initially showing the window"), + P_("The default height of the window"), -1, G_MAXINT, - -1, + 0, GTK_PARAM_READWRITE|G_PARAM_EXPLICIT_NOTIFY); window_props[PROP_DESTROY_WITH_PARENT] = @@ -876,12 +863,19 @@ gtk_window_class_init (GtkWindowClass *klass) GTK_TYPE_WINDOW, GTK_PARAM_READWRITE|G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY); - window_props[PROP_IS_MAXIMIZED] = - g_param_spec_boolean ("is-maximized", + window_props[PROP_MAXIMIZED] = + g_param_spec_boolean ("maximized", P_("Is maximized"), P_("Whether the window is maximized"), FALSE, - GTK_PARAM_READABLE); + GTK_PARAM_READWRITE|G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY); + + window_props[PROP_FULLSCREEN] = + g_param_spec_boolean ("fullscreen", + P_("Is fullscreen"), + P_("Whether the window is fullscreen"), + FALSE, + GTK_PARAM_READWRITE|G_PARAM_CONSTRUCT|G_PARAM_EXPLICIT_NOTIFY); /** * GtkWindow:application: @@ -1107,6 +1101,9 @@ gtk_window_class_init (GtkWindowClass *klass) * immediately (or at all), as an effect of calling * gtk_window_maximize() or gtk_window_unmaximize(). * + * If the window isn't yet mapped, the value returned will whether the + * initial requested state is maximized. + * * Returns: whether the window has a maximized state. */ gboolean @@ -1116,7 +1113,40 @@ gtk_window_is_maximized (GtkWindow *window) g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); - return priv->maximized; + if (priv->surface && gdk_surface_get_mapped (priv->surface)) + return priv->maximized; + else + return priv->maximize_initially; +} + +/** + * gtk_window_is_fullscreen: + * @window: a #GtkWindow + * + * Retrieves the current fullscreen state of @window. + * + * Note that since fullscreening is ultimately handled by the window + * manager and happens asynchronously to an application request, you + * shouldn’t assume the return value of this function changing + * immediately (or at all), as an effect of calling + * gtk_window_fullscreen() or gtk_window_unfullscreen(). + * + * If the window isn't yet mapped, the value returned will whether the + * initial requested state is fullscreen. + * + * Returns: whether the window has a fullscreen state. + */ +gboolean +gtk_window_is_fullscreen (GtkWindow *window) +{ + GtkWindowPrivate *priv = gtk_window_get_instance_private (window); + + g_return_val_if_fail (GTK_IS_WINDOW (window), FALSE); + + if (priv->surface && gdk_surface_get_mapped (priv->surface)) + return priv->fullscreen; + else + return priv->fullscreen_initially; } void @@ -1467,15 +1497,13 @@ gtk_window_init (GtkWindow *window) priv->geometry_info = NULL; priv->focus_widget = NULL; priv->default_widget = NULL; - priv->configure_request_count = 0; priv->resizable = TRUE; - priv->configure_notify_received = FALSE; priv->need_default_size = TRUE; priv->modal = FALSE; priv->decorated = TRUE; priv->display = gdk_display_get_default (); - priv->state = GDK_TOPLEVEL_STATE_WITHDRAWN; + priv->state = 0; priv->deletable = TRUE; priv->startup_id = NULL; @@ -1588,11 +1616,13 @@ gtk_window_set_property (GObject *object, gtk_window_set_default_size_internal (window, TRUE, g_value_get_int (value), FALSE, -1); + gtk_widget_queue_resize (GTK_WIDGET (window)); break; case PROP_DEFAULT_HEIGHT: gtk_window_set_default_size_internal (window, FALSE, -1, TRUE, g_value_get_int (value)); + gtk_widget_queue_resize (GTK_WIDGET (window)); break; case PROP_DESTROY_WITH_PARENT: gtk_window_set_destroy_with_parent (window, g_value_get_boolean (value)); @@ -1627,6 +1657,18 @@ gtk_window_set_property (GObject *object, case PROP_FOCUS_VISIBLE: gtk_window_set_focus_visible (window, g_value_get_boolean (value)); break; + case PROP_MAXIMIZED: + if (g_value_get_boolean (value)) + gtk_window_maximize (window); + else + gtk_window_unmaximize (window); + break; + case PROP_FULLSCREEN: + if (g_value_get_boolean (value)) + gtk_window_fullscreen (window); + else + gtk_window_unfullscreen (window); + break; case PROP_FOCUS_WIDGET: gtk_window_set_focus (window, g_value_get_object (value)); break; @@ -1650,7 +1692,6 @@ gtk_window_get_property (GObject *object, switch (prop_id) { - GtkWindowGeometryInfo *info; case PROP_TITLE: g_value_set_string (value, priv->title); break; @@ -1661,18 +1702,10 @@ gtk_window_get_property (GObject *object, g_value_set_boolean (value, priv->modal); break; case PROP_DEFAULT_WIDTH: - info = gtk_window_get_geometry_info (window, FALSE); - if (!info) - g_value_set_int (value, -1); - else - g_value_set_int (value, info->default_width); + g_value_set_int (value, priv->default_width); break; case PROP_DEFAULT_HEIGHT: - info = gtk_window_get_geometry_info (window, FALSE); - if (!info) - g_value_set_int (value, -1); - else - g_value_set_int (value, info->default_height); + g_value_set_int (value, priv->default_height); break; case PROP_DESTROY_WITH_PARENT: g_value_set_boolean (value, priv->destroy_with_parent); @@ -1710,9 +1743,12 @@ gtk_window_get_property (GObject *object, case PROP_FOCUS_VISIBLE: g_value_set_boolean (value, priv->focus_visible); break; - case PROP_IS_MAXIMIZED: + case PROP_MAXIMIZED: g_value_set_boolean (value, gtk_window_is_maximized (window)); break; + case PROP_FULLSCREEN: + g_value_set_boolean (value, gtk_window_is_fullscreen (window)); + break; case PROP_FOCUS_WIDGET: g_value_set_object (value, gtk_window_get_focus (window)); break; @@ -1876,19 +1912,59 @@ gtk_window_native_get_surface_transform (GtkNative *native, } static void -gtk_window_native_check_resize (GtkNative *native) +gtk_window_native_layout (GtkNative *native, + int width, + int height) { + GtkWindow *window = GTK_WINDOW (native); + GtkWindowPrivate *priv = gtk_window_get_instance_private (window); GtkWidget *widget = GTK_WIDGET (native); - gint64 before G_GNUC_UNUSED; - before = GDK_PROFILER_CURRENT_TIME; + if (priv->surface_width != width || priv->surface_height != height) + { + surface_size_changed (widget, width, height); + priv->surface_width = width; + priv->surface_height = height; + } + + /* This fake motion event is needed for getting up to date pointer focus + * and coordinates when tho pointer didn't move but the layout changed + * within the window. + */ + if (gtk_widget_needs_allocate (widget)) + { + GdkSeat *seat; + + seat = gdk_display_get_default_seat (gtk_widget_get_display (widget)); + if (seat) + { + GdkDevice *device; + GtkWidget *focus; - if (!_gtk_widget_get_alloc_needed (widget)) - gtk_widget_ensure_allocate (widget); - else if (gtk_widget_get_visible (widget)) - gtk_window_move_resize (GTK_WINDOW (native)); + device = gdk_seat_get_pointer (seat); + focus = gtk_window_lookup_pointer_focus_widget (GTK_WINDOW (widget), + device, NULL); + if (focus) + { + GdkSurface *focus_surface = + gtk_native_get_surface (gtk_widget_get_native (focus)); + + gdk_surface_request_motion (focus_surface); + } + } + } - gdk_profiler_end_mark (before, "size allocation", ""); + if (gtk_widget_needs_allocate (widget)) + { + gtk_window_update_csd_size (window, + &width, &height, + EXCLUDE_CSD_SIZE); + gtk_widget_allocate (widget, width, height, -1, NULL); + } + else + { + gtk_widget_ensure_allocate (widget); + } } static void @@ -1906,7 +1982,7 @@ gtk_window_native_interface_init (GtkNativeInterface *iface) iface->get_surface = gtk_window_native_get_surface; iface->get_renderer = gtk_window_native_get_renderer; iface->get_surface_transform = gtk_window_native_get_surface_transform; - iface->check_resize = gtk_window_native_check_resize; + iface->layout = gtk_window_native_layout; } /** @@ -2698,10 +2774,6 @@ gtk_window_get_geometry_info (GtkWindow *window, { info = g_new0 (GtkWindowGeometryInfo, 1); - info->default_width = -1; - info->default_height = -1; - info->resize_width = -1; - info->resize_height = -1; info->last.configure_request.x = 0; info->last.configure_request.y = 0; info->last.configure_request.width = -1; @@ -3297,9 +3369,6 @@ gtk_window_get_default_icon_name (void) return default_icon_name; } -#define INCLUDE_CSD_SIZE 1 -#define EXCLUDE_CSD_SIZE -1 - static void gtk_window_update_csd_size (GtkWindow *window, int *width, @@ -3318,19 +3387,6 @@ gtk_window_update_csd_size (GtkWindow *window, w = *width + apply * (window_border.left + window_border.right); h = *height + apply * (window_border.top + window_border.bottom); - if (priv->title_box != NULL && - gtk_widget_get_visible (priv->title_box) && - gtk_widget_get_child_visible (priv->title_box)) - { - int minimum_height; - int natural_height; - - gtk_widget_measure (priv->title_box, GTK_ORIENTATION_VERTICAL, -1, - &minimum_height, &natural_height, - NULL, NULL); - h += apply * natural_height; - } - /* Make sure the size remains acceptable */ if (w < 1) w = 1; @@ -3351,48 +3407,32 @@ gtk_window_set_default_size_internal (GtkWindow *window, gboolean change_height, int height) { - GtkWindowGeometryInfo *info; + GtkWindowPrivate *priv = gtk_window_get_instance_private (window); g_return_if_fail (change_width == FALSE || width >= -1); g_return_if_fail (change_height == FALSE || height >= -1); - info = gtk_window_get_geometry_info (window, TRUE); - g_object_freeze_notify (G_OBJECT (window)); if (change_width) { - if (width == 0) - width = 1; - - if (width < 0) - width = -1; - - if (info->default_width != width) + if (priv->default_width != width) { - info->default_width = width; + priv->default_width = width; g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_DEFAULT_WIDTH]); } } if (change_height) { - if (height == 0) - height = 1; - - if (height < 0) - height = -1; - - if (info->default_height != height) + if (priv->default_height != height) { - info->default_height = height; + priv->default_height = height; g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_DEFAULT_HEIGHT]); } } g_object_thaw_notify (G_OBJECT (window)); - - gtk_widget_queue_resize (GTK_WIDGET (window)); } /** @@ -3412,11 +3452,6 @@ gtk_window_set_default_size_internal (GtkWindow *window, * again as they normally would. Setting a default size of -1 means to * use the “natural” default size (the size request of the window). * - * For some uses, gtk_window_resize() is a more appropriate function. - * gtk_window_resize() changes the current size of the window, rather - * than the size to be used on initial display. gtk_window_resize() always - * affects the window itself, not the geometry widget. - * * The default size of a window only affects the first time a window is * shown; if a window is hidden and re-shown, it will remember the size * it had prior to hiding, rather than using the default size. @@ -3439,6 +3474,7 @@ gtk_window_set_default_size (GtkWindow *window, g_return_if_fail (height >= -1); gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height); + gtk_widget_queue_resize (GTK_WIDGET (window)); } /** @@ -3447,7 +3483,7 @@ gtk_window_set_default_size (GtkWindow *window, * @width: (out) (allow-none): location to store the default width, or %NULL * @height: (out) (allow-none): location to store the default height, or %NULL * - * Gets the default size of the window. A value of -1 for the width or + * Gets the default size of the window. A value of 0 for the width or * height indicates that a default size has not been explicitly set * for that dimension, so the “natural” size of the window will be * used. @@ -3458,167 +3494,9 @@ gtk_window_get_default_size (GtkWindow *window, int *width, int *height) { - GtkWindowGeometryInfo *info; - g_return_if_fail (GTK_IS_WINDOW (window)); - info = gtk_window_get_geometry_info (window, FALSE); - - if (width) - *width = info ? info->default_width : -1; - - if (height) - *height = info ? info->default_height : -1; -} - -/** - * gtk_window_resize: - * @window: a #GtkWindow - * @width: width in pixels to resize the window to - * @height: height in pixels to resize the window to - * - * Resizes the window as if the user had done so, obeying geometry - * constraints. The default geometry constraint is that windows may - * not be smaller than their size request; to override this - * constraint, call gtk_widget_set_size_request() to set the window's - * request to a smaller value. - * - * If gtk_window_resize() is called before showing a window for the - * first time, it overrides any default size set with - * gtk_window_set_default_size(). - * - * Windows may not be resized smaller than 1 by 1 pixels. - * - * When using client side decorations, GTK will do its best to adjust - * the given size so that the resulting window size matches the - * requested size without the title bar, borders and shadows added for - * the client side decorations, but there is no guarantee that the - * result will be totally accurate because these widgets added for - * client side decorations depend on the theme and may not be realized - * or visible at the time gtk_window_resize() is issued. - * - * If the GtkWindow has a titlebar widget (see gtk_window_set_titlebar()), then - * typically, gtk_window_resize() will compensate for the height of the titlebar - * widget only if the height is known when the resulting GtkWindow configuration - * is issued. - * For example, if new widgets are added after the GtkWindow configuration - * and cause the titlebar widget to grow in height, this will result in a - * window content smaller that specified by gtk_window_resize() and not - * a larger window. - * - **/ -void -gtk_window_resize (GtkWindow *window, - int width, - int 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; - - gtk_widget_queue_resize (GTK_WIDGET (window)); -} - -/** - * gtk_window_get_size: - * @window: a #GtkWindow - * @width: (out) (optional): return location for width, or %NULL - * @height: (out) (optional): return location for height, or %NULL - * - * Obtains the current size of @window. - * - * If @window is not visible on screen, this function return the size GTK - * will suggest to the [window manager][gtk-X11-arch] for the initial window - * size (but this is not reliably the same as the size the window manager - * will actually select). See: gtk_window_set_default_size(). - * - * Depending on the windowing system and the window manager constraints, - * the size returned by this function may not match the size set using - * gtk_window_resize(); additionally, since gtk_window_resize() may be - * implemented as an asynchronous operation, GTK cannot guarantee in any - * way that this code: - * - * |[<!-- language="C" --> - * GtkWindow *window = GTK_WINDOW (gtk_window_new ()); - * int width = 500; - * int height = 300; - * gtk_window_resize (window, width, height); - * - * int new_width, new_height; - * gtk_window_get_size (window, &new_width, &new_height); - * ]| - * - * will result in `new_width` and `new_height` matching `width` and - * `height`, respectively. - * - * This function will return the logical size of the #GtkWindow, - * excluding the widgets used in client side decorations; there is, - * however, no guarantee that the result will be completely accurate - * because client side decoration may include widgets that depend on - * the user preferences and that may not be visible at the time you - * call this function. - * - * The dimensions returned by this function are suitable for being - * stored across sessions; use gtk_window_set_default_size() to - * restore them when before showing the window. - * - * |[<!-- language="C" --> - * static void - * on_size_allocate (GtkWidget *widget, - * const GtkAllocation *allocation, - * int baseline) - * { - * int new_width, new_height; - * - * gtk_window_get_size (GTK_WINDOW (widget), &new_width, &new_height); - * - * // ... - * } - * ]| - */ -void -gtk_window_get_size (GtkWindow *window, - int *width, - int *height) -{ - GtkWindowPrivate *priv = gtk_window_get_instance_private (window); - int w, h; - - g_return_if_fail (GTK_IS_WINDOW (window)); - - if (width == NULL && height == NULL) - return; - - if (_gtk_widget_get_mapped (GTK_WIDGET (window))) - { - w = gdk_surface_get_width (priv->surface); - h = gdk_surface_get_height (priv->surface); - } - else - { - GdkRectangle configure_request; - - gtk_window_compute_configure_request (window, - &configure_request, - NULL, NULL); - - w = configure_request.width; - h = configure_request.height; - } - - gtk_window_update_csd_size (window, &w, &h, EXCLUDE_CSD_SIZE); - - if (width) - *width = w; - if (height) - *height = h; + gtk_window_get_remembered_size (window, width, height); } static gboolean @@ -3794,7 +3672,7 @@ gtk_window_show (GtkWidget *widget) gtk_widget_realize (widget); - gtk_native_check_resize (GTK_NATIVE (window)); + gtk_window_present_toplevel (window); gtk_widget_map (widget); @@ -3856,7 +3734,8 @@ gtk_window_update_toplevel (GtkWindow *window) g_clear_pointer (&priv->layout, gdk_toplevel_layout_unref); priv->layout = gtk_window_compute_layout (window); - gdk_toplevel_present (GDK_TOPLEVEL (priv->surface), priv->layout); + if (_gtk_widget_get_mapped (GTK_WIDGET (window))) + gdk_toplevel_present (GDK_TOPLEVEL (priv->surface), priv->layout); } } @@ -3923,13 +3802,6 @@ gtk_window_unmap (GtkWidget *widget) GTK_WIDGET_CLASS (gtk_window_parent_class)->unmap (widget); gdk_surface_hide (priv->surface); - while (priv->configure_request_count > 0) - { - priv->configure_request_count--; - gdk_surface_thaw_toplevel_updates (priv->surface); - } - priv->configure_notify_received = FALSE; - state = gdk_toplevel_get_state (GDK_TOPLEVEL (priv->surface)); priv->minimize_initially = (state & GDK_TOPLEVEL_STATE_MINIMIZED) != 0; priv->maximize_initially = (state & GDK_TOPLEVEL_STATE_MAXIMIZED) != 0; @@ -3941,107 +3813,15 @@ gtk_window_unmap (GtkWidget *widget) gtk_widget_unmap (child); } -/* (Note: Replace "size" with "width" or "height". Also, the request - * mode is honoured.) - * For selecting the default window size, the following conditions - * should hold (in order of importance): - * - the size is not below the minimum size - * Windows cannot be resized below their minimum size, so we must - * ensure we don’t do that either. - * - the size is not above the natural size - * It seems weird to allocate more than this in an initial guess. - * - the size does not exceed that of a maximized window - * We want to see the whole window after all. - * (Note that this may not be possible to achieve due to imperfect - * information from the windowing system.) - */ - -static void -gtk_window_guess_default_size (GtkWindow *window, - int *width, - int *height) -{ - GtkWindowPrivate *priv = gtk_window_get_instance_private (window); - GtkWidget *widget; - GdkSurface *surface; - GdkDisplay *display; - GdkMonitor *monitor = NULL; - GdkRectangle geometry; - int minimum, natural; - - widget = GTK_WIDGET (window); - display = gtk_widget_get_display (widget); - surface = priv->surface; - - if (surface) - { - monitor = gdk_display_get_monitor_at_surface (display, surface); - if (monitor) - g_object_ref (monitor); - } - - if (!monitor) - monitor = g_list_model_get_item (gdk_display_get_monitors (display), 0); - - if (monitor) - { - gdk_monitor_get_geometry (monitor, &geometry); - g_object_unref (monitor); - } - else - { - geometry.width = G_MAXINT; - geometry.height = G_MAXINT; - } - - *width = geometry.width; - *height = geometry.height; - - if (gtk_widget_get_request_mode (widget) == GTK_SIZE_REQUEST_WIDTH_FOR_HEIGHT) - { - gtk_widget_measure (widget, GTK_ORIENTATION_VERTICAL, -1, - &minimum, &natural, - NULL, NULL); - *height = MAX (minimum, MIN (*height, natural)); - - gtk_widget_measure (widget, GTK_ORIENTATION_HORIZONTAL, - *height, - &minimum, &natural, - NULL, NULL); - *width = MAX (minimum, MIN (*width, natural)); - } - else /* GTK_SIZE_REQUEST_HEIGHT_FOR_WIDTH or CONSTANT_SIZE */ - { - gtk_widget_measure (widget, GTK_ORIENTATION_HORIZONTAL, -1, - &minimum, &natural, - NULL, NULL); - *width = MAX (minimum, MIN (*width, natural)); - - gtk_widget_measure (widget, GTK_ORIENTATION_VERTICAL, - *width, - &minimum, &natural, - NULL, NULL); - *height = MAX (minimum, MIN (*height, natural)); - } -} - static void gtk_window_get_remembered_size (GtkWindow *window, int *width, int *height) { - GtkWindowGeometryInfo *info; - - *width = 0; - *height = 0; + GtkWindowPrivate *priv = gtk_window_get_instance_private (window); - info = gtk_window_get_geometry_info (window, FALSE); - if (info) - { - /* MAX() works even if the last request is unset with -1 */ - *width = MAX (*width, info->last.configure_request.width); - *height = MAX (*height, info->last.configure_request.height); - } + *width = priv->default_width; + *height = priv->default_height; } static void @@ -4198,10 +3978,6 @@ update_realized_window_properties (GtkWindow *window) if (!priv->client_decorated) return; - if (priv->surface && priv->use_client_shadow) - gdk_surface_set_shadow_width (priv->surface, - shadow.left, shadow.right, shadow.top, shadow.bottom); - gtk_native_get_surface_transform (GTK_NATIVE (window), &native_x, &native_y); /* update the input shape, which makes it so that clicks @@ -4276,6 +4052,24 @@ gtk_window_compute_default_size (GtkWindow *window, } } +static gboolean +should_remember_size (GtkWindow *window) +{ + GtkWindowPrivate *priv = gtk_window_get_instance_private (window); + + if (!priv->resizable) + return FALSE; + + return !(priv->state & (GDK_TOPLEVEL_STATE_FULLSCREEN | + GDK_TOPLEVEL_STATE_MAXIMIZED | + GDK_TOPLEVEL_STATE_TILED | + GDK_TOPLEVEL_STATE_TOP_TILED | + GDK_TOPLEVEL_STATE_RIGHT_TILED | + GDK_TOPLEVEL_STATE_BOTTOM_TILED | + GDK_TOPLEVEL_STATE_LEFT_TILED | + GDK_TOPLEVEL_STATE_MINIMIZED)); +} + static void toplevel_compute_size (GdkToplevel *toplevel, GdkToplevelSize *size, @@ -4283,15 +4077,12 @@ toplevel_compute_size (GdkToplevel *toplevel, { GtkWindow *window = GTK_WINDOW (widget); GtkWindowPrivate *priv = gtk_window_get_instance_private (window); - GtkWindowGeometryInfo *info; int width, height; GtkBorder shadow; int bounds_width, bounds_height; int min_width, min_height; int nat_width, nat_height; - info = gtk_window_get_geometry_info (window, FALSE); - gdk_toplevel_size_get_bounds (size, &bounds_width, &bounds_height); gtk_window_compute_default_size (window, @@ -4299,78 +4090,42 @@ toplevel_compute_size (GdkToplevel *toplevel, &min_width, &min_height, &nat_width, &nat_height); - if (priv->need_default_size) - { - int remembered_width; - int remembered_height; + width = priv->default_width; + height = priv->default_height; - /* No longer use the default settings */ - priv->need_default_size = FALSE; + if (width <= 0) + width = nat_width; + if (height <= 0) + height = nat_height; - gtk_window_get_remembered_size (window, - &remembered_width, &remembered_height); - width = MAX (nat_width, remembered_width); - height = MAX (nat_height, remembered_height); + if (width < min_width) + width = min_width; + if (height < min_height) + height = min_height; - /* Override with default size */ - if (info) - { - /* Take width of shadows/headerbar into account. We want to set the - * default size of the content area and not the window area. - */ - int default_width_csd = info->default_width; - int default_height_csd = info->default_height; - gtk_window_update_csd_size (window, - &default_width_csd, &default_height_csd, - INCLUDE_CSD_SIZE); - - if (info->default_width > 0) - width = default_width_csd; - if (info->default_height > 0) - height = default_height_csd; - } - } - else - { - /* Default to keeping current size */ - gtk_window_get_remembered_size (window, &width, &height); - } - - /* Override any size with gtk_window_resize() values */ - if (priv->maximized || priv->fullscreen) - { - /* Unless we are maximized or fullscreen */ - gtk_window_get_remembered_size (window, &width, &height); - } - else if (info) - { - int resize_width_csd = info->resize_width; - int resize_height_csd = info->resize_height; - gtk_window_update_csd_size (window, - &resize_width_csd, &resize_height_csd, - INCLUDE_CSD_SIZE); + if (should_remember_size (window)) + gtk_window_set_default_size_internal (window, TRUE, width, TRUE, height); - if (info->resize_width > 0) - width = resize_width_csd; - if (info->resize_height > 0) - height = resize_height_csd; - } + gtk_window_update_csd_size (window, + &width, &height, + INCLUDE_CSD_SIZE); + gtk_window_update_csd_size (window, + &min_width, &min_height, + INCLUDE_CSD_SIZE); - /* Don't ever request zero width or height, it's not supported by - gdk. The size allocation code will round it to 1 anyway but if - we do it then the value returned from this function will is - not comparable to the size allocation read from the GtkWindow. */ - width = MAX (width, 1); - height = MAX (height, 1); + gdk_toplevel_size_set_min_size (size, min_width, min_height); gdk_toplevel_size_set_size (size, width, height); - get_shadow_width (window, &shadow); - - min_width = MIN (min_width + shadow.left + shadow.right, width); - min_height = MIN (min_height + shadow.top + shadow.bottom, height); + if (priv->use_client_shadow) + { + get_shadow_width (window, &shadow); + gdk_toplevel_size_set_shadow_width (size, + shadow.left, shadow.right, + shadow.top, shadow.bottom); + } - gdk_toplevel_size_set_min_size (size, min_width, min_height); + gtk_widget_ensure_resize (widget); } static void @@ -4410,7 +4165,7 @@ gtk_window_realize (GtkWidget *widget) priv->renderer = gsk_renderer_new_for_surface (surface); g_signal_connect_swapped (surface, "notify::state", G_CALLBACK (surface_state_changed), widget); - g_signal_connect_swapped (surface, "size-changed", G_CALLBACK (surface_size_changed), widget); + g_signal_connect_swapped (surface, "notify::mapped", G_CALLBACK (surface_state_changed), widget); g_signal_connect (surface, "render", G_CALLBACK (surface_render), widget); g_signal_connect (surface, "event", G_CALLBACK (surface_event), widget); g_signal_connect (surface, "compute-size", G_CALLBACK (toplevel_compute_size), widget); @@ -4470,6 +4225,8 @@ gtk_window_realize (GtkWidget *widget) gtk_window_realize_icon (window); check_scale_changed (window); + + gtk_native_realize (GTK_NATIVE (window)); } static void @@ -4480,6 +4237,8 @@ gtk_window_unrealize (GtkWidget *widget) GtkWindowGeometryInfo *info; GdkSurface *surface; + gtk_native_unrealize (GTK_NATIVE (window)); + /* On unrealize, we reset the size of the window such * that we will re-apply the default sizing stuff * next time we show the window. @@ -4490,8 +4249,6 @@ gtk_window_unrealize (GtkWidget *widget) info = gtk_window_get_geometry_info (window, FALSE); if (info) { - info->resize_width = -1; - info->resize_height = -1; info->last.configure_request.x = 0; info->last.configure_request.y = 0; info->last.configure_request.width = -1; @@ -4516,7 +4273,6 @@ gtk_window_unrealize (GtkWidget *widget) surface = priv->surface; g_signal_handlers_disconnect_by_func (surface, surface_state_changed, widget); - g_signal_handlers_disconnect_by_func (surface, surface_size_changed, widget); g_signal_handlers_disconnect_by_func (surface, surface_render, widget); g_signal_handlers_disconnect_by_func (surface, surface_event, widget); @@ -4717,6 +4473,8 @@ surface_state_changed (GtkWidget *widget) { priv->fullscreen = (new_surface_state & GDK_TOPLEVEL_STATE_FULLSCREEN) ? TRUE : FALSE; priv->fullscreen_initially = priv->fullscreen; + + g_object_notify_by_pspec (G_OBJECT (widget), window_props[PROP_FULLSCREEN]); } if (changed_mask & GDK_TOPLEVEL_STATE_MAXIMIZED) @@ -4724,7 +4482,7 @@ surface_state_changed (GtkWidget *widget) priv->maximized = (new_surface_state & GDK_TOPLEVEL_STATE_MAXIMIZED) ? TRUE : FALSE; priv->maximize_initially = priv->maximized; - g_object_notify_by_pspec (G_OBJECT (widget), window_props[PROP_IS_MAXIMIZED]); + g_object_notify_by_pspec (G_OBJECT (widget), window_props[PROP_MAXIMIZED]); } update_edge_constraints (window, new_surface_state); @@ -4749,55 +4507,25 @@ surface_size_changed (GtkWidget *widget, int width, int height) { - GtkWindowPrivate *priv = gtk_window_get_instance_private (GTK_WINDOW (widget)); + GtkWindow *window = GTK_WINDOW (widget); check_scale_changed (GTK_WINDOW (widget)); - if (!(priv->state & (GDK_TOPLEVEL_STATE_FULLSCREEN | - GDK_TOPLEVEL_STATE_MAXIMIZED | - GDK_TOPLEVEL_STATE_TILED | - GDK_TOPLEVEL_STATE_TOP_TILED | - GDK_TOPLEVEL_STATE_RIGHT_TILED | - GDK_TOPLEVEL_STATE_BOTTOM_TILED | - GDK_TOPLEVEL_STATE_LEFT_TILED | - GDK_TOPLEVEL_STATE_MINIMIZED))) - { - GtkWindowGeometryInfo *info; - - info = gtk_window_get_geometry_info (GTK_WINDOW (widget), TRUE); - info->last.configure_request.width = width; - info->last.configure_request.height = height; - } - - /* 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 - * 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 - * priv->configure_request_count notifies. - */ - - if (priv->configure_request_count > 0) + if (should_remember_size (window)) { - priv->configure_request_count -= 1; + int width_to_remember; + int height_to_remember; - gdk_surface_thaw_toplevel_updates (priv->surface); + width_to_remember = width; + height_to_remember = height; + gtk_window_update_csd_size (window, + &width_to_remember, &height_to_remember, + EXCLUDE_CSD_SIZE); + gtk_window_set_default_size_internal (window, + TRUE, width_to_remember, + TRUE, height_to_remember); } - /* - * If we do need to resize, we do that by: - * - setting configure_notify_received to TRUE - * for use in gtk_window_move_resize() - * - queueing a resize, leading to invocation of - * gtk_window_move_resize() in an idle handler - * - */ - priv->configure_notify_received = TRUE; - gtk_widget_queue_allocate (widget); } @@ -5280,535 +5008,6 @@ _gtk_window_unset_focus_and_default (GtkWindow *window, g_object_unref (window); } -/********************************* - * Functions related to resizing * - *********************************/ - -/* This function doesn't constrain to geometry hints */ -static void -gtk_window_compute_configure_request_size (GtkWindow *window, - guint flags, - int *width, - int *height) -{ - GtkWindowPrivate *priv = gtk_window_get_instance_private (window); - GtkWindowGeometryInfo *info; - int w, h; - - /* Preconditions: - * - we've done a size request - */ - info = gtk_window_get_geometry_info (window, FALSE); - - if (priv->need_default_size) - { - gtk_window_guess_default_size (window, width, height); - gtk_window_get_remembered_size (window, &w, &h); - *width = MAX (*width, w); - *height = MAX (*height, h); - - /* Override with default size */ - if (info) - { - /* Take width of shadows/headerbar into account. We want to set the - * default size of the content area and not the window area. - */ - int default_width_csd = info->default_width; - int default_height_csd = info->default_height; - gtk_window_update_csd_size (window, - &default_width_csd, &default_height_csd, - INCLUDE_CSD_SIZE); - - if (info->default_width > 0) - *width = default_width_csd; - if (info->default_height > 0) - *height = default_height_csd; - } - } - else - { - /* Default to keeping current size */ - gtk_window_get_remembered_size (window, width, height); - } - - /* Override any size with gtk_window_resize() values */ - if (priv->maximized || priv->fullscreen) - { - /* Unless we are maximized or fullscreen */ - gtk_window_get_remembered_size (window, width, height); - } - else if (info) - { - int resize_width_csd = info->resize_width; - int resize_height_csd = info->resize_height; - gtk_window_update_csd_size (window, - &resize_width_csd, &resize_height_csd, - INCLUDE_CSD_SIZE); - - if (info->resize_width > 0) - *width = resize_width_csd; - if (info->resize_height > 0) - *height = resize_height_csd; - } - - /* Don't ever request zero width or height, it's not supported by - gdk. The size allocation code will round it to 1 anyway but if - we do it then the value returned from this function will is - not comparable to the size allocation read from the GtkWindow. */ - *width = MAX (*width, 1); - *height = MAX (*height, 1); - -} - -static void -gtk_window_compute_configure_request (GtkWindow *window, - GdkRectangle *request, - GdkGeometry *geometry, - guint *flags) -{ - GdkGeometry new_geometry; - guint new_flags; - int w, h; - GtkWindowGeometryInfo *info; - int x, y; - - gtk_window_compute_hints (window, &new_geometry, &new_flags); - gtk_window_compute_configure_request_size (window, - new_flags, - &w, &h); - gtk_window_update_fixed_size (window, &new_geometry, w, h); - gdk_surface_constrain_size (&new_geometry, new_flags, - w, h, - &w, &h); - - info = gtk_window_get_geometry_info (window, FALSE); - - /* by default, don't change position requested */ - if (info) - { - x = info->last.configure_request.x; - y = info->last.configure_request.y; - } - else - { - x = 0; - y = 0; - } - - request->x = x; - request->y = y; - request->width = w; - request->height = h; - - if (geometry) - *geometry = new_geometry; - if (flags) - *flags = new_flags; -} - -static void -gtk_window_move_resize (GtkWindow *window) -{ - /* Overview: - * - * First we determine whether any information has changed that would - * cause us to revise our last configure request. If we would send - * a different configure request from last time, then - * configure_request_size_changed = TRUE or - * configure_request_pos_changed = TRUE. configure_request_size_changed - * may be true due to new hints, a gtk_window_resize(), or whatever. - * configure_request_pos_changed may be true due to gtk_window_set_position() - * or gtk_window_move(). - * - * If the configure request has changed, we send off a new one. To - * ensure GTK invariants are maintained (resize queue does what it - * should), we go ahead and size_allocate the requested size in this - * function. - * - * If the configure request has not changed, we don't ever resend - * it, because it could mean fighting the user or window manager. - * - * To prepare the configure request, we come up with a base size/pos: - * - the one from gtk_window_move()/gtk_window_resize() - * - else default_width, default_height if we haven't ever - * been mapped - * - else the size request if we haven't ever been mapped, - * as a substitute default size - * - else the current size of the window, as received from - * configure notifies (i.e. the current allocation) - */ - GtkWindowPrivate *priv = gtk_window_get_instance_private (window); - GtkWidget *widget; - GtkWindowGeometryInfo *info; - GdkGeometry new_geometry; - guint new_flags; - GdkRectangle new_request; - gboolean configure_request_size_changed; - gboolean configure_request_pos_changed; - gboolean hints_changed; /* do we need to send these again */ - GtkWindowLastGeometryInfo saved_last_info; - int current_width, current_height; - - widget = GTK_WIDGET (window); - - info = gtk_window_get_geometry_info (window, TRUE); - - configure_request_size_changed = FALSE; - configure_request_pos_changed = FALSE; - hints_changed = FALSE; - - gtk_window_compute_configure_request (window, &new_request, - &new_geometry, &new_flags); - - if (!(new_flags & GDK_HINT_MIN_SIZE)) - new_geometry.min_width = new_geometry.min_height = 1; - - g_clear_pointer (&priv->layout, gdk_toplevel_layout_unref); - priv->layout = gtk_window_compute_layout (window); - - /* This check implies the invariant that we never set info->last - * without setting the hints and sending off a configure request. - * - * If we change info->last without sending the request, we may - * miss a request. - */ - if (info->last.configure_request.x != new_request.x || - info->last.configure_request.y != new_request.y) - configure_request_pos_changed = TRUE; - - if ((info->last.configure_request.width != new_request.width || - info->last.configure_request.height != new_request.height)) - configure_request_size_changed = TRUE; - - if (!gtk_window_compare_hints (&info->last.geometry, info->last.flags, - &new_geometry, new_flags)) - hints_changed = TRUE; - -#if 0 - { - GtkAllocation alloc; - - gtk_widget_get_allocation (widget, &alloc); - - g_message ("--- %s ---\n" - "last : %d,%d\t%d x %d\n" - "this : %d,%d\t%d x %d\n" - "alloc : %d,%d\t%d x %d\n" - "resize: \t%d x %d\n" - "size_changed: %d pos_changed: %d hints_changed: %d\n" - "configure_notify_received: %d\n" - "configure_request_count: %d\n" - "position_constraints_changed: %d", - priv->title ? priv->title : "(no title)", - info->last.configure_request.x, - info->last.configure_request.y, - info->last.configure_request.width, - info->last.configure_request.height, - new_request.x, - new_request.y, - new_request.width, - new_request.height, - alloc.x, - alloc.y, - alloc.width, - alloc.height, - info->resize_width, - info->resize_height, - configure_request_size_changed, - configure_request_pos_changed, - hints_changed, - priv->configure_notify_received, - priv->configure_request_count, - info->position_constraints_changed); - } -#endif - - saved_last_info = info->last; - info->last.geometry = new_geometry; - info->last.flags = new_flags; - info->last.configure_request = new_request; - /* need to set PPosition so the WM will look at our position, - * but we don't want to count PPosition coming and going as a hints - * change for future iterations. So we saved info->last prior to - * this. - */ - - current_width = gdk_surface_get_width (priv->surface); - current_height = gdk_surface_get_height (priv->surface); - - /* handle resizing/moving and widget tree allocation - */ - if (priv->configure_notify_received) - { - GtkAllocation allocation; - GtkBorder shadow; - int min; - - /* If we have received a configure event since - * the last time in this function, we need to - * accept our new size and size_allocate child widgets. - * (see gtk_window_configure_event() for more details). - * - * 1 or more configure notifies may have been received. - * Also, configure_notify_received will only be TRUE - * if all expected configure notifies have been received - * (one per configure request), as an optimization. - * - */ - priv->configure_notify_received = FALSE; - - get_shadow_width (window, &shadow); - - allocation.x = shadow.left; - allocation.y = shadow.top; - - gtk_widget_measure (widget, GTK_ORIENTATION_HORIZONTAL, -1, - &min, NULL, NULL, NULL); - allocation.width = MAX (min, current_width - shadow.left - shadow.right); - gtk_widget_measure (widget, GTK_ORIENTATION_VERTICAL, allocation.width, - &min, NULL, NULL, NULL); - allocation.height = MAX (min, current_height - shadow.top - shadow.bottom); - - gtk_widget_size_allocate (widget, &allocation, -1); - - /* If the configure request changed, it means that - * we either: - * 1) coincidentally changed hints or widget properties - * impacting the configure request before getting - * a configure notify, or - * 2) some broken widget is changing its size request - * during size allocation, resulting in - * a false appearance of changed configure request. - * - * For 1), we could just go ahead and ask for the - * new size right now, but doing that for 2) - * might well be fighting the user (and can even - * trigger a loop). Since we really don't want to - * do that, we requeue a resize in hopes that - * by the time it gets handled, the child has seen - * the light and is willing to go along with the - * new size. (this happens for the zvt widget, since - * the size_allocate() above will have stored the - * requisition corresponding to the new size in the - * zvt widget) - * - * This doesn't buy us anything for 1), but it shouldn't - * hurt us too badly, since it is what would have - * happened if we had gotten the configure event before - * the new size had been set. - */ - - if (configure_request_size_changed || - configure_request_pos_changed) - { - /* Don't change the recorded last info after all, because we - * haven't actually updated to the new info yet - we decided - * to postpone our configure request until later. - */ - info->last = saved_last_info; - g_clear_pointer (&priv->layout, gdk_toplevel_layout_unref); - gtk_widget_queue_resize (widget); - } - - return; /* Bail out, we didn't really process the move/resize */ - } - else if ((configure_request_size_changed || hints_changed || configure_request_pos_changed) && - (current_width != new_request.width || current_height != new_request.height)) - { - /* We are in one of the following situations: - * A. configure_request_size_changed - * our requisition has changed and we need a different window size, - * so we request it from the window manager. - * B. !configure_request_size_changed && hints_changed - * the window manager rejects our size, but we have just changed the - * window manager hints, so there's a chance our request will - * be honoured this time, so we try again. - * - * However, if the new requisition is the same as the current allocation, - * we don't request it again, since we won't get a ConfigureNotify back from - * the window manager unless it decides to change our requisition. If - * we don't get the ConfigureNotify back, the resize queue will never be run. - */ - - /* Increment the number of have-not-yet-received-notify requests. - * This is done before gdk_surface[_move]_resize(), because - * that call might be synchronous (depending on which GDK backend - * is being used), so any preparations for its effects must - * be done beforehand. - */ - priv->configure_request_count += 1; - - gdk_surface_freeze_toplevel_updates (priv->surface); - - /* for GTK_RESIZE_QUEUE toplevels, we are now awaiting a new - * configure event in response to our resizing request. - * the configure event will cause a new resize with - * ->configure_notify_received=TRUE. - * until then, we want to - * - discard expose events - * - coalesce resizes for our children - * - defer any window resizes until the configure event arrived - * to achieve this, we queue a resize for the window, but remove its - * resizing handler, so resizing will not be handled from the next - * idle handler but when the configure event arrives. - * - * FIXME: we should also dequeue the pending redraws here, since - * we handle those ourselves upon ->configure_notify_received==TRUE. - */ - - /* Now send the configure request */ - if (configure_request_pos_changed) - g_warning ("configure request position changed. This should not happen. Ignoring the position"); - - gdk_toplevel_present (GDK_TOPLEVEL (priv->surface), priv->layout); - } - else - { - GtkAllocation allocation; - GtkBorder shadow; - int min_width, min_height; - - get_shadow_width (window, &shadow); - - allocation.x = shadow.left; - allocation.y = shadow.top; - - /* Handle any position changes. - */ - if (configure_request_pos_changed) - g_warning ("configure request position changed. This should not happen. Ignoring the position"); - - /* Our configure request didn't change size, but maybe some of - * our child widgets have. Run a size allocate with our current - * size to make sure that we re-layout our child widgets. */ - - gtk_widget_measure (widget, GTK_ORIENTATION_HORIZONTAL, current_height - shadow.top - shadow.bottom, - &min_width, NULL, NULL, NULL); - allocation.width = MAX (current_width - shadow.left - shadow.right, min_width); - - gtk_widget_measure (widget, GTK_ORIENTATION_VERTICAL, allocation.width, - &min_height, NULL, NULL, NULL); - allocation.height = MAX (current_height - shadow.top - shadow.bottom, min_height); - gtk_widget_size_allocate (widget, &allocation, -1); - } - - info->resize_width = -1; - info->resize_height = -1; -} - -/* Compare two sets of Geometry hints for equality. - */ -static gboolean -gtk_window_compare_hints (GdkGeometry *geometry_a, - guint flags_a, - GdkGeometry *geometry_b, - guint flags_b) -{ - if (flags_a != flags_b) - return FALSE; - - if ((flags_a & GDK_HINT_MIN_SIZE) && - (geometry_a->min_width != geometry_b->min_width || - geometry_a->min_height != geometry_b->min_height)) - return FALSE; - - if ((flags_a & GDK_HINT_MAX_SIZE) && - (geometry_a->max_width != geometry_b->max_width || - geometry_a->max_height != geometry_b->max_height)) - return FALSE; - - return TRUE; -} - -/* For non-resizable windows, make sure the given width/height fits - * in the geometry constrains and update the geometry hints to match - * the given width/height if not. - * This is to make sure that non-resizable windows get the default - * width/height if set, but can still grow if their content requires. - * - * Note: Fixed size windows with a default size set will not shrink - * smaller than the default size when their content requires less size. - */ -static void -gtk_window_update_fixed_size (GtkWindow *window, - GdkGeometry *new_geometry, - int new_width, - int new_height) -{ - GtkWindowPrivate *priv = gtk_window_get_instance_private (window); - GtkWindowGeometryInfo *info; - gboolean has_size_request; - - /* Adjust the geometry hints for non-resizable windows only */ - has_size_request = gtk_widget_has_size_request (GTK_WIDGET (window)); - if (priv->resizable || has_size_request) - return; - - info = gtk_window_get_geometry_info (window, FALSE); - if (info) - { - int default_width_csd = info->default_width; - int default_height_csd = info->default_height; - - gtk_window_update_csd_size (window, - &default_width_csd, &default_height_csd, - INCLUDE_CSD_SIZE); - - if (info->default_width > -1) - { - int w = MAX (MAX (default_width_csd, new_width), new_geometry->min_width); - new_geometry->min_width = w; - new_geometry->max_width = w; - } - - if (info->default_height > -1) - { - int h = MAX (MAX (default_height_csd, new_height), new_geometry->min_height); - new_geometry->min_height = h; - new_geometry->max_height = h; - } - } -} - -/* Compute the set of geometry hints and flags for a window - * based on the application set geometry, and requisition - * of the window. gtk_widget_get_preferred_size() must have been - * called first. - */ -static void -gtk_window_compute_hints (GtkWindow *window, - GdkGeometry *new_geometry, - guint *new_flags) -{ - GtkWindowPrivate *priv = gtk_window_get_instance_private (window); - GtkWidget *widget; - GtkRequisition requisition; - GtkBorder shadow; - - widget = GTK_WIDGET (window); - - /* Use a good size for unresizable widgets, otherwise the minimum one. */ - if (priv->resizable) - gtk_widget_get_preferred_size (widget, &requisition, NULL); - else - gtk_window_guess_default_size (window, &requisition.width, &requisition.height); - - *new_flags = 0; - - get_shadow_width (window, &shadow); - *new_flags |= GDK_HINT_MIN_SIZE; - new_geometry->min_width = requisition.width + shadow.left + shadow.right; - new_geometry->min_height = requisition.height + shadow.top + shadow.bottom; - - if (!priv->resizable) - { - *new_flags |= GDK_HINT_MAX_SIZE; - - new_geometry->max_width = new_geometry->min_width; - new_geometry->max_height = new_geometry->min_height; - } -} - #undef INCLUDE_CSD_SIZE #undef EXCLUDE_CSD_SIZE @@ -5869,8 +5068,6 @@ gtk_window_present_with_time (GtkWindow *window, g_assert (surface != NULL); - gtk_window_present_toplevel (window); - /* Translate a timestamp of GDK_CURRENT_TIME appropriately */ if (timestamp == GDK_CURRENT_TIME) { @@ -5972,19 +5169,28 @@ gtk_window_unminimize (GtkWindow *window) * initially. * * You can track the result of this operation via the #GdkToplevel:state - * property, or by listening to notifications on the #GtkWindow:is-maximized + * property, or by listening to notifications on the #GtkWindow:maximized * property. */ void gtk_window_maximize (GtkWindow *window) { GtkWindowPrivate *priv = gtk_window_get_instance_private (window); + gboolean was_maximized_initially; g_return_if_fail (GTK_IS_WINDOW (window)); + was_maximized_initially = priv->maximize_initially; priv->maximize_initially = TRUE; - gtk_window_update_toplevel (window); + if (priv->surface && gdk_surface_get_mapped (priv->surface)) + { + gtk_window_update_toplevel (window); + } + else if (!was_maximized_initially) + { + g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_MAXIMIZED]); + } } /** @@ -5999,19 +5205,26 @@ gtk_window_maximize (GtkWindow *window) * end up unmaximized. Just don’t write code that crashes if not. * * You can track the result of this operation via the #GdkToplevel:state - * property, or by listening to notifications on the #GtkWindow:is-maximized + * property, or by listening to notifications on the #GtkWindow:maximized * property. */ void gtk_window_unmaximize (GtkWindow *window) { GtkWindowPrivate *priv = gtk_window_get_instance_private (window); + gboolean was_maximized_initially; g_return_if_fail (GTK_IS_WINDOW (window)); + was_maximized_initially = priv->maximize_initially; priv->maximize_initially = FALSE; gtk_window_update_toplevel (window); + + if (priv->surface && gdk_surface_get_mapped (priv->surface)) + gtk_window_update_toplevel (window); + else if (was_maximized_initially) + g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_MAXIMIZED]); } /** @@ -6032,12 +5245,17 @@ void gtk_window_fullscreen (GtkWindow *window) { GtkWindowPrivate *priv = gtk_window_get_instance_private (window); + gboolean was_fullscreen_initially; g_return_if_fail (GTK_IS_WINDOW (window)); + was_fullscreen_initially = priv->fullscreen_initially; priv->fullscreen_initially = TRUE; - gtk_window_update_toplevel (window); + if (priv->surface && gdk_surface_get_mapped (priv->surface)) + gtk_window_update_toplevel (window); + else if (!was_fullscreen_initially) + g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_FULLSCREEN]); } static void @@ -6104,13 +5322,20 @@ void gtk_window_unfullscreen (GtkWindow *window) { GtkWindowPrivate *priv = gtk_window_get_instance_private (window); + gboolean was_fullscreen_initially; g_return_if_fail (GTK_IS_WINDOW (window)); + was_fullscreen_initially = priv->fullscreen_initially; unset_fullscreen_monitor (window); priv->fullscreen_initially = FALSE; gtk_window_update_toplevel (window); + + if (priv->surface && gdk_surface_get_mapped (priv->surface)) + gtk_window_update_toplevel (window); + else if (was_fullscreen_initially) + g_object_notify_by_pspec (G_OBJECT (window), window_props[PROP_FULLSCREEN]); } /** diff --git a/gtk/gtkwindow.h b/gtk/gtkwindow.h index 3a5638d1d3..06701f8313 100644 --- a/gtk/gtkwindow.h +++ b/gtk/gtkwindow.h @@ -215,14 +215,6 @@ GDK_AVAILABLE_IN_ALL void gtk_window_get_default_size (GtkWindow *window, int *width, int *height); -GDK_AVAILABLE_IN_ALL -void gtk_window_resize (GtkWindow *window, - int width, - int height); -GDK_AVAILABLE_IN_ALL -void gtk_window_get_size (GtkWindow *window, - int *width, - int *height); GDK_AVAILABLE_IN_ALL GtkWindowGroup *gtk_window_get_group (GtkWindow *window); @@ -252,6 +244,9 @@ GDK_AVAILABLE_IN_ALL gboolean gtk_window_is_maximized (GtkWindow *window); GDK_AVAILABLE_IN_ALL +gboolean gtk_window_is_fullscreen (GtkWindow *window); + +GDK_AVAILABLE_IN_ALL void gtk_window_destroy (GtkWindow *window); GDK_AVAILABLE_IN_ALL diff --git a/gtk/gtkwindowcontrols.c b/gtk/gtkwindowcontrols.c index 69dfe82534..c288c4ed75 100644 --- a/gtk/gtkwindowcontrols.c +++ b/gtk/gtkwindowcontrols.c @@ -377,7 +377,7 @@ window_notify_cb (GtkWindowControls *self, { if (pspec->name == I_("deletable") || pspec->name == I_("icon-name") || - pspec->name == I_("is-maximized") || + pspec->name == I_("maximized") || pspec->name == I_("modal") || pspec->name == I_("resizable") || pspec->name == I_("scale-factor") || diff --git a/gtk/tools/gtk-builder-tool-simplify.c b/gtk/tools/gtk-builder-tool-simplify.c index 868d0dc49a..add00fe833 100644 --- a/gtk/tools/gtk-builder-tool-simplify.c +++ b/gtk/tools/gtk-builder-tool-simplify.c @@ -455,6 +455,15 @@ value_is_default (Element *element, ret = g_value_get_boolean (&value) == default_value; } + else if (pspec->owner_type == GTK_TYPE_WINDOW && + (g_str_equal (pspec->name, "default-width") || + g_str_equal (pspec->name, "default-height"))) + { + int default_size; + + default_size = g_value_get_int (&value); + ret = default_size <= 0; + } else ret = g_param_value_defaults (pspec, &value); } diff --git a/tests/animated-resizing.c b/tests/animated-resizing.c index 9b5133a88d..bf7a0b68c4 100644 --- a/tests/animated-resizing.c +++ b/tests/animated-resizing.c @@ -123,17 +123,16 @@ on_frame (double progress) window_height = HEIGHT + jitter; } - gtk_window_resize (GTK_WINDOW (window), - window_width, window_height); + gtk_window_set_default_size (GTK_WINDOW (window), + window_width, window_height); gtk_widget_queue_draw (window); } static gboolean -tick_callback (GtkWidget *widget, - GdkFrameClock *frame_clock, - gpointer user_data) +resize_idle (gpointer user_data) { + GdkFrameClock *frame_clock = user_data; gint64 frame_time = gdk_frame_clock_get_frame_time (frame_clock); double scaled_time; @@ -143,6 +142,16 @@ tick_callback (GtkWidget *widget, scaled_time = (frame_time - start_frame_time) / (CYCLE_TIME * 1000000); on_frame (scaled_time - floor (scaled_time)); + return G_SOURCE_REMOVE; +} + +static gboolean +tick_callback (GtkWidget *widget, + GdkFrameClock *frame_clock, + gpointer user_data) +{ + g_idle_add (resize_idle, frame_clock); + return G_SOURCE_CONTINUE; } diff --git a/tests/showrendernode.c b/tests/showrendernode.c index 5fafd3c00e..43f99b5198 100644 --- a/tests/showrendernode.c +++ b/tests/showrendernode.c @@ -239,9 +239,9 @@ main (int argc, char **argv) } gsk_render_node_get_bounds (GTK_NODE_VIEW (nodeview)->node, &node_bounds); - gtk_window_resize (GTK_WINDOW (window), - MAX (600, node_bounds.size.width), - MAX (500, node_bounds.size.height)); + gtk_window_set_default_size (GTK_WINDOW (window), + MAX (600, node_bounds.size.width), + MAX (500, node_bounds.size.height)); g_signal_connect (window, "destroy", G_CALLBACK (quit_cb), &done); gtk_widget_show (window); diff --git a/tests/testgtk.c b/tests/testgtk.c index 188ecb0554..077d16136b 100644 --- a/tests/testgtk.c +++ b/tests/testgtk.c @@ -4531,8 +4531,6 @@ surface_state_callback (GdkSurface *window, new_state = gdk_toplevel_get_state (GDK_TOPLEVEL (window)); msg = g_strconcat ((const char *)g_object_get_data (G_OBJECT (label), "title"), ": ", - (new_state & GDK_TOPLEVEL_STATE_WITHDRAWN) ? - "withdrawn" : "not withdrawn", ", ", (new_state & GDK_TOPLEVEL_STATE_MINIMIZED) ? "minimized" : "not minimized", ", ", (new_state & GDK_TOPLEVEL_STATE_STICKY) ? @@ -4776,17 +4774,6 @@ get_ints (GtkWidget *window, } static void -set_size_callback (GtkWidget *widget, - gpointer data) -{ - int w, h; - - get_ints (data, &w, &h); - - gtk_window_resize (GTK_WINDOW (g_object_get_data (data, "target")), w, h); -} - -static void unset_default_size_callback (GtkWidget *widget, gpointer data) { @@ -4891,13 +4878,6 @@ window_controls (GtkWidget *window) G_CONNECT_SWAPPED); gtk_box_append (GTK_BOX (vbox), button); - button = gtk_button_new_with_label ("Resize"); - g_signal_connect (button, - "clicked", - G_CALLBACK (set_size_callback), - control_window); - gtk_box_append (GTK_BOX (vbox), button); - button = gtk_button_new_with_label ("Set default size"); g_signal_connect (button, "clicked", diff --git a/tests/testmenubutton.c b/tests/testmenubutton.c index a1f1c78a9d..4752cce214 100644 --- a/tests/testmenubutton.c +++ b/tests/testmenubutton.c @@ -46,7 +46,7 @@ int main (int argc, char **argv) gtk_init (); window = gtk_window_new (); - gtk_window_resize (GTK_WINDOW (window), 400, 300); + gtk_window_set_default_size (GTK_WINDOW (window), 400, 300); grid = gtk_grid_new (); gtk_grid_set_row_spacing (GTK_GRID (grid), 12); diff --git a/tests/testwindowsize.c b/tests/testwindowsize.c index e6539c7ae0..f61669b204 100644 --- a/tests/testwindowsize.c +++ b/tests/testwindowsize.c @@ -8,14 +8,27 @@ static GtkWidget *default_width_spin; static GtkWidget *default_height_spin; static GtkWidget *resizable_check; -static void -size_changed_cb (GdkSurface *surface, int width, int height, GtkLabel *label) +static gboolean +set_label_idle (gpointer user_data) { + GtkLabel *label = user_data; + GtkNative *native = gtk_widget_get_native (GTK_WIDGET (label)); + GdkSurface *surface = gtk_native_get_surface (native); char *str; - str = g_strdup_printf ("%d x %d", width, height); + str = g_strdup_printf ("%d x %d", + gdk_surface_get_width (surface), + gdk_surface_get_height (surface)); gtk_label_set_label (label, str); g_free (str); + + return G_SOURCE_REMOVE; +} + +static void +layout_cb (GdkSurface *surface, int width, int height, GtkLabel *label) +{ + g_idle_add (set_label_idle, label); } static void @@ -63,8 +76,8 @@ show_dialog (void) gtk_dialog_add_action_widget (GTK_DIALOG (dialog), label, GTK_RESPONSE_HELP); gtk_widget_realize (dialog); - g_signal_connect (gtk_native_get_surface (GTK_NATIVE (dialog)), "size-changed", - G_CALLBACK (size_changed_cb), label); + g_signal_connect (gtk_native_get_surface (GTK_NATIVE (dialog)), "layout", + G_CALLBACK (layout_cb), label); g_signal_connect (dialog, "response", G_CALLBACK (gtk_window_destroy), NULL); diff --git a/testsuite/gtk/filtermodel.c b/testsuite/gtk/filtermodel.c index 51728532be..2bf39ab0f3 100644 --- a/testsuite/gtk/filtermodel.c +++ b/testsuite/gtk/filtermodel.c @@ -4691,7 +4691,6 @@ specific_append_after_collapse (void) window = gtk_window_new (); tree_view = gtk_tree_view_new_with_model (sort); gtk_window_set_child (GTK_WINDOW (window), tree_view); - gtk_widget_realize (tree_view); while (g_main_context_pending (NULL)) g_main_context_iteration (NULL, TRUE); @@ -4811,7 +4810,6 @@ specific_sort_filter_remove_node (void) window = gtk_window_new (); tree_view = gtk_tree_view_new_with_model (filter); gtk_window_set_child (GTK_WINDOW (window), tree_view); - gtk_widget_realize (tree_view); while (g_main_context_pending (NULL)) g_main_context_iteration (NULL, TRUE); diff --git a/testsuite/gtk/notify.c b/testsuite/gtk/notify.c index 12ae9edb89..7809d4e915 100644 --- a/testsuite/gtk/notify.c +++ b/testsuite/gtk/notify.c @@ -524,7 +524,8 @@ test_type (gconstpointer data) g_str_equal (pspec->name, "has-default") || g_str_equal (pspec->name, "is-focus") || g_str_equal (pspec->name, "hexpand") || - g_str_equal (pspec->name, "vexpand"))) + g_str_equal (pspec->name, "vexpand") || + g_str_equal (pspec->name, "visible"))) continue; if (g_type_is_a (type, GTK_TYPE_ACCESSIBLE) && diff --git a/testsuite/gtk/window.c b/testsuite/gtk/window.c index 8ffc0645bf..c92c92e03f 100644 --- a/testsuite/gtk/window.c +++ b/testsuite/gtk/window.c @@ -148,69 +148,6 @@ test_default_size (void) } static void -test_resize (void) -{ - GtkWidget *window; - GtkWidget *da; - int w, h; - gboolean done; - - window = gtk_window_new (); - if (interactive) - { - GtkEventController *controller = gtk_event_controller_key_new (); - g_signal_connect (controller, "key-pressed", G_CALLBACK (on_keypress), window); - gtk_widget_add_controller (window, controller); - } - - da = gtk_drawing_area_new (); - gtk_drawing_area_set_draw_func (GTK_DRAWING_AREA (da), on_draw, NULL, NULL); - gtk_window_set_child (GTK_WINDOW (window), da); - - /* test that resize before show overrides default size */ - gtk_window_set_default_size (GTK_WINDOW (window), 500, 500); - - gtk_window_resize (GTK_WINDOW (window), 1, 1); - - gtk_window_get_size (GTK_WINDOW (window), &w, &h); - g_assert_cmpint (w, ==, 1); - g_assert_cmpint (h, ==, 1); - - gtk_window_resize (GTK_WINDOW (window), 400, 200); - - gtk_widget_show (window); - - done = FALSE; - if (!interactive) - g_timeout_add (200, stop_main, &done); - while (!done) - g_main_context_iteration (NULL, TRUE); - - /* test that resize before show works */ - gtk_window_get_size (GTK_WINDOW (window), &w, &h); - g_assert_cmpint (w, ==, 400); - g_assert_cmpint (h, ==, 200); - - /* test that resize after show works, both - * for making things bigger and for making things - * smaller - */ - gtk_window_resize (GTK_WINDOW (window), 200, 400); - - done = FALSE; - if (!interactive) - g_timeout_add (200, stop_main, &done); - while (!done) - g_main_context_iteration (NULL, TRUE); - - gtk_window_get_size (GTK_WINDOW (window), &w, &h); - g_assert_cmpint (w, ==, 200); - g_assert_cmpint (h, ==, 400); - - gtk_window_destroy (GTK_WINDOW (window)); -} - -static void test_resize_popup (void) { GtkWidget *window; @@ -220,7 +157,7 @@ test_resize_popup (void) /* testcase for the dnd window */ window = gtk_window_new (); gtk_window_set_decorated (GTK_WINDOW (window), FALSE); - gtk_window_resize (GTK_WINDOW (window), 1, 1); + gtk_window_set_default_size (GTK_WINDOW (window), 1, 1); gtk_window_get_size (GTK_WINDOW (window), &w, &h); g_assert_cmpint (w, ==, 1); g_assert_cmpint (h, ==, 1); @@ -304,7 +241,6 @@ main (int argc, char *argv[]) } g_test_add_func ("/window/default-size", test_default_size); - g_test_add_func ("/window/resize", test_resize); g_test_add_func ("/window/resize-popup", test_resize_popup); g_test_add_func ("/window/show-hide", test_show_hide); diff --git a/testsuite/reftests/meson.build b/testsuite/reftests/meson.build index 8df36fab93..a50b8f84df 100644 --- a/testsuite/reftests/meson.build +++ b/testsuite/reftests/meson.build @@ -439,8 +439,6 @@ testdata = [ 'window-default-size.ui', 'window-height-for-width.ref.ui', 'window-height-for-width.ui', - 'window-show-contents-on-map.ref.ui', - 'window-show-contents-on-map.ui', ] # These need to be fixed but the issue hasn't been tracked down. diff --git a/testsuite/reftests/textview-tags.ref.ui b/testsuite/reftests/textview-tags.ref.ui index 35a68abf20..c55837f484 100644 --- a/testsuite/reftests/textview-tags.ref.ui +++ b/testsuite/reftests/textview-tags.ref.ui @@ -37,6 +37,7 @@ <object class="GtkWindow" id="window1"> <child> <object class="GtkTextView" id="textview1"> + <property name="cursor_visible">false</property> <property name="buffer">textbuffer1</property> <signal name="map" handler="reftest:apply_tags_red_blue" swapped="no"/> </object> diff --git a/testsuite/reftests/textview-tags.ui b/testsuite/reftests/textview-tags.ui index 88da7b5493..4119eb4d47 100644 --- a/testsuite/reftests/textview-tags.ui +++ b/testsuite/reftests/textview-tags.ui @@ -37,6 +37,7 @@ <object class="GtkWindow" id="window1"> <child> <object class="GtkTextView" id="textview1"> + <property name="cursor_visible">false</property> <property name="buffer">textbuffer1</property> <signal name="map" handler="reftest:apply_tags_blue" swapped="no"/> </object> diff --git a/testsuite/reftests/window-show-contents-on-map.ref.ui b/testsuite/reftests/window-show-contents-on-map.ref.ui deleted file mode 100644 index f24540ed6b..0000000000 --- a/testsuite/reftests/window-show-contents-on-map.ref.ui +++ /dev/null @@ -1,16 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<interface> - <object class="GtkWindow" id="window1"> - <property name="width_request">200</property> - <property name="height_request">200</property> - <property name="decorated">0</property> - <child> - <object class="GtkLabel" id="label1"> - <property name="label" translatable="yes">This label is only shown when the window is mapped. So the window does its first size allocation without the label being visible and has to resize.</property> - <property name="wrap">1</property> - <property name="width_chars">20</property> - <property name="max_width_chars">20</property> - </object> - </child> - </object> -</interface> diff --git a/testsuite/reftests/window-show-contents-on-map.ui b/testsuite/reftests/window-show-contents-on-map.ui deleted file mode 100644 index 88e00d8e51..0000000000 --- a/testsuite/reftests/window-show-contents-on-map.ui +++ /dev/null @@ -1,15 +0,0 @@ -<?xml version="1.0" encoding="UTF-8"?> -<interface> - <object class="GtkWindow" id="window1"> - <property name="decorated">0</property> - <signal name="map" handler="gtk_widget_show" object="label1" after="yes" swapped="yes"/> - <child> - <object class="GtkLabel" id="label1"> - <property name="visible">0</property> - <property name="label" translatable="yes">This label is only shown when the window is mapped. So the window does its first size allocation without the label being visible and has to resize.</property> - <property name="width_chars">20</property> - <property name="wrap">1</property> - </object> - </child> - </object> -</interface> |