diff --git a/gdk/broadway/broadway-protocol.h b/gdk/broadway/broadway-protocol.h index 0e82e94297..2573e9083a 100644 --- a/gdk/broadway/broadway-protocol.h +++ b/gdk/broadway/broadway-protocol.h @@ -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 { diff --git a/gdk/broadway/broadway-server.c b/gdk/broadway/broadway-server.c index b53f4edf12..14f7518e1f 100644 --- a/gdk/broadway/broadway-server.c +++ b/gdk/broadway/broadway-server.c @@ -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,16 @@ 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) + { + server->mouse_in_toplevel_id = message->configure_notify.id; + server->real_mouse_in_toplevel_id = message->configure_notify.id; + 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 +1446,7 @@ broadway_server_destroy_window (BroadwayServer *server, gint id) { BroadwayWindow *window; + gint transient_for = -1; if (server->mouse_in_toplevel_id == id) { @@ -1453,6 +1465,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 +1478,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 +1614,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) { diff --git a/gdk/broadway/broadway-server.h b/gdk/broadway/broadway-server.h index b5d319133a..d266685820 100644 --- a/gdk/broadway/broadway-server.h +++ b/gdk/broadway/broadway-server.h @@ -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__ */ diff --git a/gdk/broadway/broadwayd.c b/gdk/broadway/broadwayd.c index 84a9c3f3c1..90f4d3206b 100644 --- a/gdk/broadway/broadwayd.c +++ b/gdk/broadway/broadwayd.c @@ -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); } diff --git a/gdk/broadway/gdkbroadway-server.c b/gdk/broadway/gdkbroadway-server.c index 2aa98abfab..9398428857 100644 --- a/gdk/broadway/gdkbroadway-server.c +++ b/gdk/broadway/gdkbroadway-server.c @@ -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) { diff --git a/gdk/broadway/gdkbroadway-server.h b/gdk/broadway/gdkbroadway-server.h index 89a3076992..a961bb0358 100644 --- a/gdk/broadway/gdkbroadway-server.h +++ b/gdk/broadway/gdkbroadway-server.h @@ -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__ */ diff --git a/gdk/broadway/gdkeventsource.c b/gdk/broadway/gdkeventsource.c index e946778483..07c74f6d43 100644 --- a/gdk/broadway/gdkeventsource.c +++ b/gdk/broadway/gdkeventsource.c @@ -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); } diff --git a/gdk/broadway/gdkwindow-broadway.c b/gdk/broadway/gdkwindow-broadway.c index 32d1a0771c..39ef2ee353 100644 --- a/gdk/broadway/gdkwindow-broadway.c +++ b/gdk/broadway/gdkwindow-broadway.c @@ -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 diff --git a/gdk/broadway/gdkwindow-broadway.h b/gdk/broadway/gdkwindow-broadway.h index f6a9ec1c65..ce1b3f1019 100644 --- a/gdk/broadway/gdkwindow-broadway.h +++ b/gdk/broadway/gdkwindow-broadway.h @@ -73,6 +73,7 @@ struct _GdkWindowImplBroadway GdkGeometry geometry_hints; GdkWindowHints geometry_hints_mask; + gboolean modal_hint; }; struct _GdkWindowImplBroadwayClass