diff options
Diffstat (limited to 'gdk/x11/gdksurface-x11.c')
-rw-r--r-- | gdk/x11/gdksurface-x11.c | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/gdk/x11/gdksurface-x11.c b/gdk/x11/gdksurface-x11.c index d4348a4e18..3607629819 100644 --- a/gdk/x11/gdksurface-x11.c +++ b/gdk/x11/gdksurface-x11.c @@ -109,6 +109,7 @@ static void set_wm_name (GdkDisplay *display, Window xwindow, const gchar *name); static void move_to_current_desktop (GdkSurface *surface); +static void gdk_x11_toplevel_state_callback (GdkSurface *surface); /* Return whether time1 is considered later than time2 as far as xserver * time is concerned. Accounts for wraparound. @@ -148,6 +149,9 @@ _gdk_x11_surface_get_toplevel (GdkSurface *surface) { impl->toplevel = g_new0 (GdkToplevelX11, 1); impl->toplevel->have_focused = FALSE; + g_signal_connect (surface, "notify::state", + G_CALLBACK (gdk_x11_toplevel_state_callback), + NULL); } return impl->toplevel; @@ -445,6 +449,10 @@ gdk_x11_surface_finalize (GObject *object) if (impl->toplevel->in_frame) unhook_surface_changed (GDK_SURFACE (impl)); + g_signal_handlers_disconnect_by_func (GDK_SURFACE (impl), + gdk_x11_toplevel_state_callback, + NULL); + _gdk_x11_surface_grab_check_destroy (GDK_SURFACE (impl)); if (!GDK_SURFACE_DESTROYED (impl)) @@ -4725,6 +4733,9 @@ gdk_x11_toplevel_set_property (GObject *object, g_object_notify_by_pspec (G_OBJECT (surface), pspec); break; + case LAST_PROP + GDK_TOPLEVEL_PROP_SHORTCUTS_INHIBITED: + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -4785,6 +4796,10 @@ gdk_x11_toplevel_get_property (GObject *object, g_value_set_enum (value, surface->fullscreen_mode); break; + case LAST_PROP + GDK_TOPLEVEL_PROP_SHORTCUTS_INHIBITED: + g_value_set_boolean (value, surface->shortcuts_inhibited); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -4909,6 +4924,63 @@ gdk_x11_toplevel_supports_edge_constraints (GdkToplevel *toplevel) } static void +gdk_x11_toplevel_inhibit_system_shortcuts (GdkToplevel *toplevel, + GdkEvent *gdk_event) +{ + GdkSurface *surface = GDK_SURFACE (toplevel); + GdkSeat *gdk_seat; + GdkGrabStatus status; + + if (surface->shortcuts_inhibited) + return; /* Already inhibited */ + + if (!(surface->state & GDK_SURFACE_STATE_FOCUSED)) + return; + + gdk_seat = gdk_surface_get_seat_from_event (surface, gdk_event); + + if (!(gdk_seat_get_capabilities (gdk_seat) & GDK_SEAT_CAPABILITY_KEYBOARD)) + return; + + status = gdk_seat_grab (gdk_seat, surface, GDK_SEAT_CAPABILITY_KEYBOARD, + TRUE, NULL, gdk_event, NULL, NULL); + + if (status != GDK_GRAB_SUCCESS) + return; + + surface->shortcuts_inhibited = TRUE; + surface->current_shortcuts_inhibited_seat = gdk_seat; + g_object_notify (G_OBJECT (toplevel), "shortcuts-inhibited"); +} + +static void +gdk_x11_toplevel_restore_system_shortcuts (GdkToplevel *toplevel) +{ + GdkSurface *surface = GDK_SURFACE (toplevel); + GdkSeat *gdk_seat; + + if (!surface->shortcuts_inhibited) + return; /* Not inhibited */ + + gdk_seat = surface->current_shortcuts_inhibited_seat; + gdk_seat_ungrab (gdk_seat); + surface->current_shortcuts_inhibited_seat = NULL; + + surface->shortcuts_inhibited = FALSE; + g_object_notify (G_OBJECT (toplevel), "shortcuts-inhibited"); +} + +static void +gdk_x11_toplevel_state_callback (GdkSurface *surface) +{ + if (surface->state & GDK_SURFACE_STATE_FOCUSED) + return; + + if (surface->shortcuts_inhibited) + gdk_x11_toplevel_restore_system_shortcuts (GDK_TOPLEVEL (surface)); +} + +static void gdk_x11_toplevel_iface_init (GdkToplevelInterface *iface) { iface->present = gdk_x11_toplevel_present; @@ -4917,6 +4989,8 @@ gdk_x11_toplevel_iface_init (GdkToplevelInterface *iface) iface->focus = gdk_x11_toplevel_focus; iface->show_window_menu = gdk_x11_toplevel_show_window_menu; iface->supports_edge_constraints = gdk_x11_toplevel_supports_edge_constraints; + iface->inhibit_system_shortcuts = gdk_x11_toplevel_inhibit_system_shortcuts; + iface->restore_system_shortcuts = gdk_x11_toplevel_restore_system_shortcuts; } typedef struct { |