From: Maxim Zakharov Date: Mon, 31 Jan 2022 00:30:32 +0000 (+1100) Subject: gdk/broadway: Implements modal hint for Broadway surface X-Git-Tag: archive/raspbian/4.12.3+ds-1+rpi1~1^2^2^2~22^2~8^2~45^2~1 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=2290c2bb2327a884b8eb61a3d7741da2afceb66b;p=gtk4.git gdk/broadway: Implements modal hint for Broadway surface Ensures modal window is raised above parent; does return focus to parent window when transient child window is closed. That solves problems with overlapped modal window and focus loss in complex multi window UI. --- diff --git a/gdk/broadway/broadway-protocol.h b/gdk/broadway/broadway-protocol.h index 9b56dff6df..875d6ac143 100644 --- a/gdk/broadway/broadway-protocol.h +++ b/gdk/broadway/broadway-protocol.h @@ -213,6 +213,7 @@ typedef enum { BROADWAY_REQUEST_RELEASE_TEXTURE, BROADWAY_REQUEST_SET_NODES, BROADWAY_REQUEST_ROUNDTRIP, + BROADWAY_REQUEST_SET_MODAL_HINT, } BroadwayRequestType; typedef struct { @@ -293,6 +294,12 @@ typedef struct { guint32 show_keyboard; } BroadwayRequestSetShowKeyboard; +typedef struct { + BroadwayRequestBase base; + guint32 id; + gboolean modal_hint; +} BroadwayRequestSetModalHint; + typedef union { BroadwayRequestBase base; BroadwayRequestNewSurface new_surface; @@ -312,6 +319,7 @@ typedef union { BroadwayRequestUploadTexture upload_texture; BroadwayRequestReleaseTexture release_texture; BroadwayRequestSetNodes set_nodes; + BroadwayRequestSetModalHint set_modal_hint; } BroadwayRequest; typedef enum { diff --git a/gdk/broadway/broadway-server.c b/gdk/broadway/broadway-server.c index b90c849f94..8c0be3818e 100644 --- a/gdk/broadway/broadway-server.c +++ b/gdk/broadway/broadway-server.c @@ -128,6 +128,7 @@ struct BroadwaySurface { gboolean visible; gint32 transient_for; guint32 texture; + gboolean modal_hint; BroadwayNode *nodes; GHashTable *node_lookup; }; @@ -425,6 +426,14 @@ update_event_state (BroadwayServer *server, { surface->x = message->configure_notify.x; surface->y = message->configure_notify.y; + + if (server->focused_surface_id != message->configure_notify.id && + server->pointer_grab_surface_id == -1 && surface->modal_hint) + { + broadway_server_surface_raise (server, message->configure_notify.id); + broadway_server_focus_surface (server, message->configure_notify.id); + broadway_server_flush (server); + } } break; case BROADWAY_EVENT_ROUNDTRIP_NOTIFY: @@ -1572,6 +1581,7 @@ broadway_server_destroy_surface (BroadwayServer *server, int id) { BroadwaySurface *surface; + gint32 transient_for = -1; if (server->mouse_in_surface_id == id) { @@ -1589,11 +1599,24 @@ broadway_server_destroy_surface (BroadwayServer *server, surface = broadway_server_lookup_surface (server, id); if (surface != NULL) { + if (server->focused_surface_id == id) + transient_for = surface->transient_for; + server->surfaces = g_list_remove (server->surfaces, surface); g_hash_table_remove (server->surface_id_hash, GINT_TO_POINTER (id)); broadway_surface_free (server, surface); } + + if (transient_for != -1) + { + surface = broadway_server_lookup_surface (server, transient_for); + if (surface != NULL) + { + broadway_server_focus_surface (server, transient_for); + broadway_server_flush (server); + } + } } gboolean @@ -1714,6 +1737,19 @@ broadway_server_surface_set_transient_for (BroadwayServer *server, } } +void +broadway_server_surface_set_modal_hint (BroadwayServer *server, + int id, gboolean modal_hint) +{ + BroadwaySurface *surface; + + surface = broadway_server_lookup_surface (server, id); + if (surface == NULL) + return; + + surface->modal_hint = modal_hint; +} + gboolean broadway_server_has_client (BroadwayServer *server) { diff --git a/gdk/broadway/broadway-server.h b/gdk/broadway/broadway-server.h index fd027a664e..1f7faad7ea 100644 --- a/gdk/broadway/broadway-server.h +++ b/gdk/broadway/broadway-server.h @@ -130,6 +130,9 @@ gboolean broadway_server_surface_move_resize (BroadwayServer * int height); void broadway_server_focus_surface (BroadwayServer *server, int new_focused_surface); +void broadway_server_surface_set_modal_hint (BroadwayServer *server, + int id, + gboolean modal_hint); #endif /* __BROADWAY_SERVER__ */ diff --git a/gdk/broadway/broadwayd.c b/gdk/broadway/broadwayd.c index 9cfa48f138..689ce72960 100644 --- a/gdk/broadway/broadwayd.c +++ b/gdk/broadway/broadwayd.c @@ -384,6 +384,11 @@ client_handle_request (BroadwayClient *client, case BROADWAY_REQUEST_SET_SHOW_KEYBOARD: broadway_server_set_show_keyboard (server, request->set_show_keyboard.show_keyboard); break; + case BROADWAY_REQUEST_SET_MODAL_HINT: + broadway_server_surface_set_modal_hint (server, + request->set_modal_hint.id, + request->set_modal_hint.modal_hint); + break; default: g_warning ("Unknown request of type %d", request->base.type); } diff --git a/gdk/broadway/gdkbroadway-server.c b/gdk/broadway/gdkbroadway-server.c index bd221f5442..133c7a50fa 100644 --- a/gdk/broadway/gdkbroadway-server.c +++ b/gdk/broadway/gdkbroadway-server.c @@ -561,6 +561,18 @@ _gdk_broadway_server_surface_set_transient_for (GdkBroadwayServer *server, BROADWAY_REQUEST_SET_TRANSIENT_FOR); } +void +_gdk_broadway_server_surface_set_modal_hint (GdkBroadwayServer *server, + int id, gboolean modal_hint) +{ + BroadwayRequestSetModalHint msg; + + msg.id = id; + msg.modal_hint = modal_hint; + gdk_broadway_server_send_message (server, msg, + BROADWAY_REQUEST_SET_MODAL_HINT); +} + static int open_shared_memory (void) { diff --git a/gdk/broadway/gdkbroadway-server.h b/gdk/broadway/gdkbroadway-server.h index d4557d556b..3fac98a75b 100644 --- a/gdk/broadway/gdkbroadway-server.h +++ b/gdk/broadway/gdkbroadway-server.h @@ -78,5 +78,8 @@ gboolean _gdk_broadway_server_surface_move_resize (GdkBroadwaySe int y, int width, int height); +void _gdk_broadway_server_surface_set_modal_hint (GdkBroadwayServer *server, + int id, + gboolean modal_hint); #endif /* __GDK_BROADWAY_SERVER__ */ diff --git a/gdk/broadway/gdkeventsource.c b/gdk/broadway/gdkeventsource.c index 9ae9022a41..17e934d48d 100644 --- a/gdk/broadway/gdkeventsource.c +++ b/gdk/broadway/gdkeventsource.c @@ -82,6 +82,26 @@ gdk_event_source_check (GSource *source) return retval; } +static void +handle_focus_change (GdkEvent *event) +{ + GdkSurface *surface = gdk_event_get_surface(event); + GdkEvent *focus_event; + gboolean focus_in = (gdk_event_get_event_type (event) == GDK_ENTER_NOTIFY); + + if (gdk_crossing_event_get_detail (event) == GDK_NOTIFY_INFERIOR) + return; + + if (!gdk_crossing_event_get_focus (event) ) + return; + + focus_event = gdk_focus_event_new (gdk_event_get_surface (event), + gdk_event_get_device (event), + focus_in); + gdk_display_put_event (gdk_event_get_display (event), focus_event); + gdk_event_unref (focus_event); +} + void _gdk_broadway_events_got_input (GdkDisplay *display, BroadwayInputMsg *message) @@ -110,6 +130,8 @@ _gdk_broadway_events_got_input (GdkDisplay *display, node = _gdk_event_queue_append (display, event); _gdk_windowing_got_event (display, node, event, message->base.serial); + + handle_focus_change (event); } break; case BROADWAY_EVENT_LEAVE: @@ -126,6 +148,8 @@ _gdk_broadway_events_got_input (GdkDisplay *display, message->crossing.mode, GDK_NOTIFY_ANCESTOR); + handle_focus_change (event); + node = _gdk_event_queue_append (display, event); _gdk_windowing_got_event (display, node, event, message->base.serial); } diff --git a/gdk/broadway/gdksurface-broadway.c b/gdk/broadway/gdksurface-broadway.c index d341303526..b3e5c235f0 100644 --- a/gdk/broadway/gdksurface-broadway.c +++ b/gdk/broadway/gdksurface-broadway.c @@ -709,6 +709,21 @@ gdk_broadway_surface_set_transient_for (GdkSurface *surface, _gdk_broadway_server_surface_set_transient_for (display->server, impl->id, impl->transient_for); } +static void +gdk_broadway_surface_set_modal_hint (GdkSurface *surface, + gboolean modal) + { + GdkBroadwayDisplay *display; + GdkBroadwaySurface *impl; + + impl = GDK_BROADWAY_SURFACE (surface); + + impl->modal_hint = modal; + + display = GDK_BROADWAY_DISPLAY (gdk_surface_get_display (surface)); + _gdk_broadway_server_surface_set_modal_hint (display->server, impl->id, impl->modal_hint); + } + static void gdk_broadway_surface_get_geometry (GdkSurface *surface, int *x, @@ -1433,6 +1448,8 @@ gdk_broadway_toplevel_set_property (GObject *object, break; case LAST_PROP + GDK_TOPLEVEL_PROP_MODAL: + gdk_broadway_surface_set_modal_hint (surface, g_value_get_boolean (value)); + g_object_notify_by_pspec (G_OBJECT (surface), pspec); break; case LAST_PROP + GDK_TOPLEVEL_PROP_ICON_LIST: @@ -1479,6 +1496,10 @@ gdk_broadway_toplevel_get_property (GObject *object, g_value_set_object (value, surface->transient_for); break; + case LAST_PROP + GDK_TOPLEVEL_PROP_MODAL: + g_value_set_boolean (value, surface->modal_hint); + break; + case LAST_PROP + GDK_TOPLEVEL_PROP_ICON_LIST: g_value_set_pointer (value, NULL); break; diff --git a/gdk/broadway/gdksurface-broadway.h b/gdk/broadway/gdksurface-broadway.h index f944306758..bdeb960162 100644 --- a/gdk/broadway/gdksurface-broadway.h +++ b/gdk/broadway/gdksurface-broadway.h @@ -54,6 +54,7 @@ struct _GdkBroadwaySurface gboolean dirty; gboolean last_synced; + gboolean modal_hint; GdkGeometry geometry_hints; GdkSurfaceHints geometry_hints_mask;