Merge branch 'gtk-3-24-focus-to-modal-parant-and-transient-for' into 'gtk-3-24'

Solution for focus loss problem for complex multi Window UI in Broadway backend

See merge request GNOME/gtk!3990
This commit is contained in:
Matthias Clasen 2023-02-10 11:37:49 +00:00
commit 4fcf3b3a7d
9 changed files with 100 additions and 1 deletions

View File

@ -157,7 +157,8 @@ typedef enum {
BROADWAY_REQUEST_GRAB_POINTER,
BROADWAY_REQUEST_UNGRAB_POINTER,
BROADWAY_REQUEST_FOCUS_WINDOW,
BROADWAY_REQUEST_SET_SHOW_KEYBOARD
BROADWAY_REQUEST_SET_SHOW_KEYBOARD,
BROADWAY_REQUEST_SET_MODAL_HINT
} BroadwayRequestType;
typedef struct {
@ -231,6 +232,12 @@ typedef struct {
guint32 show_keyboard;
} BroadwayRequestSetShowKeyboard;
typedef struct {
BroadwayRequestBase base;
guint32 id;
gboolean modal_hint;
} BroadwayRequestSetModalHint;
typedef union {
BroadwayRequestBase base;
BroadwayRequestNewWindow new_window;
@ -248,6 +255,7 @@ typedef union {
BroadwayRequestTranslate translate;
BroadwayRequestFocusWindow focus_window;
BroadwayRequestSetShowKeyboard set_show_keyboard;
BroadwayRequestSetModalHint set_modal_hint;
} BroadwayRequest;
typedef enum {

View File

@ -113,6 +113,7 @@ struct BroadwayWindow {
gboolean is_temp;
gboolean visible;
gint32 transient_for;
gboolean modal_hint;
BroadwayBuffer *buffer;
gboolean buffer_synced;
@ -276,6 +277,14 @@ update_event_state (BroadwayServer *server,
{
window->x = message->configure_notify.x;
window->y = message->configure_notify.y;
if (server->focused_window_id != message->configure_notify.id &&
server->pointer_grab_window_id == -1 && window->modal_hint)
{
broadway_server_window_raise (server, message->configure_notify.id);
broadway_server_focus_window (server, message->configure_notify.id);
broadway_server_flush (server);
}
}
break;
case BROADWAY_EVENT_DELETE_NOTIFY:
@ -1435,6 +1444,7 @@ broadway_server_destroy_window (BroadwayServer *server,
gint id)
{
BroadwayWindow *window;
gint transient_for = -1;
if (server->mouse_in_toplevel_id == id)
{
@ -1453,6 +1463,9 @@ broadway_server_destroy_window (BroadwayServer *server,
GINT_TO_POINTER (id));
if (window != NULL)
{
if (server->focused_window_id == id)
transient_for = window->transient_for;
server->toplevels = g_list_remove (server->toplevels, window);
g_hash_table_remove (server->id_ht,
GINT_TO_POINTER (id));
@ -1463,6 +1476,17 @@ broadway_server_destroy_window (BroadwayServer *server,
g_free (window);
}
if (transient_for != -1)
{
window = g_hash_table_lookup (server->id_ht,
GINT_TO_POINTER (transient_for));
if (window != NULL)
{
broadway_server_focus_window (server, transient_for);
broadway_server_flush (server);
}
}
}
gboolean
@ -1588,6 +1612,20 @@ broadway_server_window_set_transient_for (BroadwayServer *server,
}
}
void
broadway_server_window_set_modal_hint (BroadwayServer *server,
gint id, gboolean modal_hint)
{
BroadwayWindow *window;
window = g_hash_table_lookup (server->id_ht,
GINT_TO_POINTER (id));
if (window == NULL)
return;
window->modal_hint = modal_hint;
}
gboolean
broadway_server_has_client (BroadwayServer *server)
{

View File

@ -95,5 +95,8 @@ cairo_surface_t * broadway_server_open_surface (BroadwayServer *server,
char *name,
int width,
int height);
void broadway_server_window_set_modal_hint (BroadwayServer *server,
gint id,
gboolean modal_hint);
#endif /* __BROADWAY_SERVER__ */

View File

@ -301,6 +301,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_window_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);
}

View File

@ -523,6 +523,18 @@ _gdk_broadway_server_window_set_transient_for (GdkBroadwayServer *server,
BROADWAY_REQUEST_SET_TRANSIENT_FOR);
}
void
_gdk_broadway_server_window_set_modal_hint (GdkBroadwayServer *server,
gint 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 void *
map_named_shm (char *name, gsize size, gboolean *is_shm)
{

View File

@ -71,5 +71,8 @@ gboolean _gdk_broadway_server_window_move_resize (GdkBroadwaySer
int y,
int width,
int height);
void _gdk_broadway_server_window_set_modal_hint (GdkBroadwayServer *server,
gint id,
gboolean modal_hint);
#endif /* __GDK_BROADWAY_SERVER__ */

View File

@ -89,6 +89,24 @@ gdk_event_source_check (GSource *source)
return retval;
}
static void
handle_focus_change (GdkEventCrossing *event)
{
gboolean focus_in = (event->type != GDK_ENTER_NOTIFY);
GdkEvent *focus_event;
if (event->window->parent) {
focus_event = gdk_event_new (GDK_FOCUS_CHANGE);
focus_event->focus_change.window = g_object_ref (event->window->parent);
focus_event->focus_change.send_event = FALSE;
focus_event->focus_change.in = focus_in;
gdk_event_set_device (focus_event, gdk_event_get_device ((GdkEvent *) event));
gdk_event_put (focus_event);
gdk_event_free (focus_event);
}
}
void
_gdk_broadway_events_got_input (BroadwayInputMsg *message)
{
@ -160,6 +178,8 @@ _gdk_broadway_events_got_input (BroadwayInputMsg *message)
gdk_event_set_device (event, device_manager->core_pointer);
gdk_event_set_seat (event, gdk_device_get_seat (device_manager->core_pointer));
handle_focus_change (&event->crossing);
node = _gdk_event_queue_append (display, event);
_gdk_windowing_got_event (display, node, event, message->base.serial);
}

View File

@ -584,6 +584,15 @@ static void
gdk_broadway_window_set_modal_hint (GdkWindow *window,
gboolean modal)
{
GdkBroadwayDisplay *display;
GdkWindowImplBroadway *impl;
impl = GDK_WINDOW_IMPL_BROADWAY (window->impl);
impl->modal_hint = modal;
display = GDK_BROADWAY_DISPLAY (gdk_window_get_display (impl->wrapper));
_gdk_broadway_server_window_set_modal_hint (display->server, impl->id, impl->modal_hint);
}
static void

View File

@ -73,6 +73,7 @@ struct _GdkWindowImplBroadway
GdkGeometry geometry_hints;
GdkWindowHints geometry_hints_mask;
gboolean modal_hint;
};
struct _GdkWindowImplBroadwayClass