forked from AuroraMiddleware/gtk
Merge branch 'issue982' into 'master'
gdk: Add gdk_toplevel_inhibit_system_shortcuts API Closes #982 See merge request GNOME/gtk!1542
This commit is contained in:
commit
96f0c26306
@ -1499,6 +1499,9 @@ gdk_broadway_toplevel_set_property (GObject *object,
|
||||
case LAST_PROP + GDK_TOPLEVEL_PROP_DELETABLE:
|
||||
break;
|
||||
|
||||
case LAST_PROP + GDK_TOPLEVEL_PROP_SHORTCUTS_INHIBITED:
|
||||
break;
|
||||
|
||||
default:
|
||||
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
||||
break;
|
||||
@ -1541,6 +1544,10 @@ gdk_broadway_toplevel_get_property (GObject *object,
|
||||
case LAST_PROP + GDK_TOPLEVEL_PROP_DELETABLE:
|
||||
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;
|
||||
|
@ -181,6 +181,8 @@ void gdk_surface_get_unscaled_size (GdkSurface *surface,
|
||||
int *unscaled_width,
|
||||
int *unscaled_height);
|
||||
gboolean gdk_surface_handle_event (GdkEvent *event);
|
||||
GdkSeat * gdk_surface_get_seat_from_event (GdkSurface *surface,
|
||||
GdkEvent *event);
|
||||
|
||||
/*****************************************
|
||||
* Interfaces provided by windowing code *
|
||||
|
@ -3015,3 +3015,22 @@ gdk_surface_translate_coordinates (GdkSurface *from,
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
GdkSeat *
|
||||
gdk_surface_get_seat_from_event (GdkSurface *surface,
|
||||
GdkEvent *event)
|
||||
{
|
||||
if (event)
|
||||
{
|
||||
GdkDevice *device = gdk_event_get_device (event);
|
||||
GdkSeat *seat = NULL;
|
||||
|
||||
device = gdk_event_get_device (event);
|
||||
if (device)
|
||||
seat = gdk_device_get_seat (device);
|
||||
|
||||
if (seat)
|
||||
return seat;
|
||||
}
|
||||
return gdk_display_get_default_seat (surface->display);
|
||||
}
|
||||
|
@ -102,6 +102,9 @@ struct _GdkSurface
|
||||
GdkDrawContext *paint_context;
|
||||
|
||||
cairo_region_t *opaque_region;
|
||||
|
||||
guint shortcuts_inhibited : 1;
|
||||
GdkSeat *current_shortcuts_inhibited_seat;
|
||||
};
|
||||
|
||||
struct _GdkSurfaceClass
|
||||
|
@ -73,6 +73,17 @@ gdk_toplevel_default_supports_edge_constraints (GdkToplevel *toplevel)
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_toplevel_default_inhibit_system_shortcuts (GdkToplevel *toplevel,
|
||||
GdkEvent *event)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_toplevel_default_restore_system_shortcuts (GdkToplevel *toplevel)
|
||||
{
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_toplevel_default_init (GdkToplevelInterface *iface)
|
||||
{
|
||||
@ -82,6 +93,8 @@ gdk_toplevel_default_init (GdkToplevelInterface *iface)
|
||||
iface->focus = gdk_toplevel_default_focus;
|
||||
iface->show_window_menu = gdk_toplevel_default_show_window_menu;
|
||||
iface->supports_edge_constraints = gdk_toplevel_default_supports_edge_constraints;
|
||||
iface->inhibit_system_shortcuts = gdk_toplevel_default_inhibit_system_shortcuts;
|
||||
iface->restore_system_shortcuts = gdk_toplevel_default_restore_system_shortcuts;
|
||||
|
||||
g_object_interface_install_property (iface,
|
||||
g_param_spec_flags ("state",
|
||||
@ -137,6 +150,12 @@ gdk_toplevel_default_init (GdkToplevelInterface *iface)
|
||||
GDK_TYPE_FULLSCREEN_MODE,
|
||||
GDK_FULLSCREEN_ON_CURRENT_MONITOR,
|
||||
G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY));
|
||||
g_object_interface_install_property (iface,
|
||||
g_param_spec_boolean ("shortcuts-inhibited",
|
||||
"Shortcuts inhibited",
|
||||
"Whether keyboard shortcuts are inhibited",
|
||||
FALSE,
|
||||
G_PARAM_READABLE | G_PARAM_EXPLICIT_NOTIFY));
|
||||
}
|
||||
|
||||
guint
|
||||
@ -152,6 +171,7 @@ gdk_toplevel_install_properties (GObjectClass *object_class,
|
||||
g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_DECORATED, "decorated");
|
||||
g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_DELETABLE, "deletable");
|
||||
g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_FULLSCREEN_MODE, "fullscreen-mode");
|
||||
g_object_class_override_property (object_class, first_prop + GDK_TOPLEVEL_PROP_SHORTCUTS_INHIBITED, "shortcuts-inhibited");
|
||||
|
||||
return GDK_TOPLEVEL_NUM_PROPERTIES;
|
||||
}
|
||||
@ -439,3 +459,56 @@ gdk_toplevel_supports_edge_constraints (GdkToplevel *toplevel)
|
||||
|
||||
return GDK_TOPLEVEL_GET_IFACE (toplevel)->supports_edge_constraints (toplevel);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_toplevel_inhibit_system_shortcuts:
|
||||
* @toplevel: the #GdkToplevel requesting system keyboard shortcuts
|
||||
* @event: (nullable): the #GdkEvent that is triggering the inhibit
|
||||
* request, or %NULL if none is available.
|
||||
*
|
||||
* Requests that the @toplevel inhibit the system shortcuts, asking the
|
||||
* desktop environment/windowing system to let all keyboard events reach
|
||||
* the surface, as long as it is focused, instead of triggering system
|
||||
* actions.
|
||||
*
|
||||
* If granted, the rerouting remains active until the default shortcuts
|
||||
* processing is restored with gdk_toplevel_restore_system_shortcuts(),
|
||||
* or the request is revoked by the desktop enviroment, windowing system
|
||||
* or the user.
|
||||
*
|
||||
* A typical use case for this API is remote desktop or virtual machine
|
||||
* viewers which need to inhibit the default system keyboard shortcuts
|
||||
* so that the remote session or virtual host gets those instead of the
|
||||
* local environment.
|
||||
*
|
||||
* The windowing system or desktop environment may ask the user to grant
|
||||
* or deny the request or even choose to ignore the request entirely.
|
||||
*
|
||||
* The caller can be notified whenever the request is granted or revoked
|
||||
* by listening to the GdkToplevel::shortcuts-inhibited property.
|
||||
*
|
||||
*/
|
||||
void
|
||||
gdk_toplevel_inhibit_system_shortcuts (GdkToplevel *toplevel,
|
||||
GdkEvent *event)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
|
||||
|
||||
GDK_TOPLEVEL_GET_IFACE (toplevel)->inhibit_system_shortcuts (toplevel,
|
||||
event);
|
||||
}
|
||||
|
||||
/**
|
||||
* gdk_toplevel_restore_system_shortcuts:
|
||||
* @toplevel: a #GdkToplevel
|
||||
*
|
||||
* Restore default system keyboard shortcuts which were previously
|
||||
* requested to be inhibited by gdk_toplevel_inhibit_system_shortcuts().
|
||||
*/
|
||||
void
|
||||
gdk_toplevel_restore_system_shortcuts (GdkToplevel *toplevel)
|
||||
{
|
||||
g_return_if_fail (GDK_IS_TOPLEVEL (toplevel));
|
||||
|
||||
GDK_TOPLEVEL_GET_IFACE (toplevel)->restore_system_shortcuts (toplevel);
|
||||
}
|
||||
|
@ -24,6 +24,7 @@
|
||||
#error "Only <gdk/gdk.h> can be included directly."
|
||||
#endif
|
||||
|
||||
#include <gdk/gdkseat.h>
|
||||
#include <gdk/gdksurface.h>
|
||||
#include <gdk/gdktoplevellayout.h>
|
||||
|
||||
@ -87,6 +88,14 @@ void gdk_toplevel_set_deletable (GdkToplevel *toplevel,
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
gboolean gdk_toplevel_supports_edge_constraints (GdkToplevel *toplevel);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_toplevel_inhibit_system_shortcuts (GdkToplevel *toplevel,
|
||||
GdkEvent *event);
|
||||
|
||||
GDK_AVAILABLE_IN_ALL
|
||||
void gdk_toplevel_restore_system_shortcuts (GdkToplevel *toplevel);
|
||||
|
||||
|
||||
G_END_DECLS
|
||||
|
||||
#endif /* __GDK_TOPLEVEL_H__ */
|
||||
|
@ -21,6 +21,9 @@ struct _GdkToplevelInterface
|
||||
gboolean (* show_window_menu) (GdkToplevel *toplevel,
|
||||
GdkEvent *event);
|
||||
gboolean (* supports_edge_constraints) (GdkToplevel *toplevel);
|
||||
void (* inhibit_system_shortcuts) (GdkToplevel *toplevel,
|
||||
GdkEvent *event);
|
||||
void (* restore_system_shortcuts) (GdkToplevel *toplevel);
|
||||
};
|
||||
|
||||
typedef enum
|
||||
@ -34,6 +37,7 @@ typedef enum
|
||||
GDK_TOPLEVEL_PROP_DECORATED,
|
||||
GDK_TOPLEVEL_PROP_DELETABLE,
|
||||
GDK_TOPLEVEL_PROP_FULLSCREEN_MODE,
|
||||
GDK_TOPLEVEL_PROP_SHORTCUTS_INHIBITED,
|
||||
GDK_TOPLEVEL_NUM_PROPERTIES
|
||||
} GdkToplevelProperties;
|
||||
|
||||
|
@ -4112,9 +4112,9 @@ gdk_wayland_surface_set_transient_for_exported (GdkSurface *surface,
|
||||
|
||||
static struct zwp_keyboard_shortcuts_inhibitor_v1 *
|
||||
gdk_wayland_surface_get_inhibitor (GdkWaylandSurface *impl,
|
||||
struct wl_seat *seat)
|
||||
GdkSeat *gdk_seat)
|
||||
{
|
||||
return g_hash_table_lookup (impl->shortcuts_inhibitors, seat);
|
||||
return g_hash_table_lookup (impl->shortcuts_inhibitors, gdk_seat);
|
||||
}
|
||||
|
||||
void
|
||||
@ -4130,14 +4130,14 @@ gdk_wayland_surface_inhibit_shortcuts (GdkSurface *surface,
|
||||
if (display->keyboard_shortcuts_inhibit == NULL)
|
||||
return;
|
||||
|
||||
if (gdk_wayland_surface_get_inhibitor (impl, seat))
|
||||
return; /* Already inhibitted */
|
||||
if (gdk_wayland_surface_get_inhibitor (impl, gdk_seat))
|
||||
return; /* Already inhibited */
|
||||
|
||||
inhibitor =
|
||||
zwp_keyboard_shortcuts_inhibit_manager_v1_inhibit_shortcuts (
|
||||
display->keyboard_shortcuts_inhibit, wl_surface, seat);
|
||||
|
||||
g_hash_table_insert (impl->shortcuts_inhibitors, seat, inhibitor);
|
||||
g_hash_table_insert (impl->shortcuts_inhibitors, gdk_seat, inhibitor);
|
||||
}
|
||||
|
||||
void
|
||||
@ -4145,15 +4145,14 @@ gdk_wayland_surface_restore_shortcuts (GdkSurface *surface,
|
||||
GdkSeat *gdk_seat)
|
||||
{
|
||||
GdkWaylandSurface *impl = GDK_WAYLAND_SURFACE (surface);
|
||||
struct wl_seat *seat = gdk_wayland_seat_get_wl_seat (gdk_seat);
|
||||
struct zwp_keyboard_shortcuts_inhibitor_v1 *inhibitor;
|
||||
|
||||
inhibitor = gdk_wayland_surface_get_inhibitor (impl, seat);
|
||||
inhibitor = gdk_wayland_surface_get_inhibitor (impl, gdk_seat);
|
||||
if (inhibitor == NULL)
|
||||
return; /* Not inhibitted */
|
||||
|
||||
zwp_keyboard_shortcuts_inhibitor_v1_destroy (inhibitor);
|
||||
g_hash_table_remove (impl->shortcuts_inhibitors, seat);
|
||||
g_hash_table_remove (impl->shortcuts_inhibitors, gdk_seat);
|
||||
}
|
||||
|
||||
GdkSurface *
|
||||
@ -4360,6 +4359,9 @@ gdk_wayland_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;
|
||||
@ -4411,6 +4413,10 @@ gdk_wayland_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;
|
||||
@ -4534,6 +4540,70 @@ gdk_wayland_toplevel_supports_edge_constraints (GdkToplevel *toplevel)
|
||||
return gdk_wayland_surface_supports_edge_constraints (GDK_SURFACE (toplevel));
|
||||
}
|
||||
|
||||
static void
|
||||
inhibitor_active (void *data,
|
||||
struct zwp_keyboard_shortcuts_inhibitor_v1 *inhibitor)
|
||||
{
|
||||
GdkToplevel *toplevel = GDK_TOPLEVEL (data);
|
||||
GdkSurface *surface = GDK_SURFACE (toplevel);
|
||||
|
||||
surface->shortcuts_inhibited = TRUE;
|
||||
g_object_notify (G_OBJECT (toplevel), "shortcuts-inhibited");
|
||||
}
|
||||
|
||||
static void
|
||||
inhibitor_inactive (void *data,
|
||||
struct zwp_keyboard_shortcuts_inhibitor_v1 *inhibitor)
|
||||
{
|
||||
GdkToplevel *toplevel = GDK_TOPLEVEL (data);
|
||||
GdkSurface *surface = GDK_SURFACE (toplevel);
|
||||
|
||||
surface->shortcuts_inhibited = FALSE;
|
||||
g_object_notify (G_OBJECT (toplevel), "shortcuts-inhibited");
|
||||
}
|
||||
|
||||
static const struct zwp_keyboard_shortcuts_inhibitor_v1_listener
|
||||
zwp_keyboard_shortcuts_inhibitor_listener = {
|
||||
inhibitor_active,
|
||||
inhibitor_inactive,
|
||||
};
|
||||
|
||||
static void
|
||||
gdk_wayland_toplevel_inhibit_system_shortcuts (GdkToplevel *toplevel,
|
||||
GdkEvent *event)
|
||||
{
|
||||
struct zwp_keyboard_shortcuts_inhibitor_v1 *inhibitor;
|
||||
GdkSurface *surface = GDK_SURFACE (toplevel);
|
||||
GdkWaylandSurface *impl= GDK_WAYLAND_SURFACE (surface);
|
||||
GdkSeat *gdk_seat;
|
||||
|
||||
if (surface->shortcuts_inhibited)
|
||||
return;
|
||||
|
||||
gdk_seat = gdk_surface_get_seat_from_event (surface, event);
|
||||
gdk_wayland_surface_inhibit_shortcuts (surface, gdk_seat);
|
||||
|
||||
inhibitor = gdk_wayland_surface_get_inhibitor (impl, gdk_seat);
|
||||
if (!inhibitor)
|
||||
return;
|
||||
|
||||
surface->current_shortcuts_inhibited_seat = gdk_seat;
|
||||
zwp_keyboard_shortcuts_inhibitor_v1_add_listener
|
||||
(inhibitor, &zwp_keyboard_shortcuts_inhibitor_listener, toplevel);
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_toplevel_restore_system_shortcuts (GdkToplevel *toplevel)
|
||||
{
|
||||
GdkSurface *surface = GDK_SURFACE (toplevel);
|
||||
|
||||
gdk_wayland_surface_restore_shortcuts (surface,
|
||||
surface->current_shortcuts_inhibited_seat);
|
||||
surface->current_shortcuts_inhibited_seat = NULL;
|
||||
surface->shortcuts_inhibited = FALSE;
|
||||
g_object_notify (G_OBJECT (toplevel), "shortcuts-inhibited");
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_toplevel_iface_init (GdkToplevelInterface *iface)
|
||||
{
|
||||
@ -4543,6 +4613,8 @@ gdk_wayland_toplevel_iface_init (GdkToplevelInterface *iface)
|
||||
iface->focus = gdk_wayland_toplevel_focus;
|
||||
iface->show_window_menu = gdk_wayland_toplevel_show_window_menu;
|
||||
iface->supports_edge_constraints = gdk_wayland_toplevel_supports_edge_constraints;
|
||||
iface->inhibit_system_shortcuts = gdk_wayland_toplevel_inhibit_system_shortcuts;
|
||||
iface->restore_system_shortcuts = gdk_wayland_toplevel_restore_system_shortcuts;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
|
@ -4907,6 +4907,9 @@ gdk_win32_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;
|
||||
@ -4953,6 +4956,10 @@ gdk_win32_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;
|
||||
|
@ -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))
|
||||
@ -4552,10 +4560,10 @@ gdk_x11_popup_init (GdkX11Popup *popup)
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_popup_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
gdk_x11_popup_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkSurface *surface = GDK_SURFACE (object);
|
||||
|
||||
@ -4576,10 +4584,10 @@ gdk_wayland_popup_get_property (GObject *object,
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_popup_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
gdk_x11_popup_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkSurface *surface = GDK_SURFACE (object);
|
||||
|
||||
@ -4607,8 +4615,8 @@ gdk_x11_popup_class_init (GdkX11PopupClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->get_property = gdk_wayland_popup_get_property;
|
||||
object_class->set_property = gdk_wayland_popup_set_property;
|
||||
object_class->get_property = gdk_x11_popup_get_property;
|
||||
object_class->set_property = gdk_x11_popup_set_property;
|
||||
|
||||
gdk_popup_install_properties (object_class, 1);
|
||||
}
|
||||
@ -4675,10 +4683,10 @@ gdk_x11_toplevel_init (GdkX11Toplevel *toplevel)
|
||||
{
|
||||
}
|
||||
static void
|
||||
gdk_wayland_toplevel_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
gdk_x11_toplevel_set_property (GObject *object,
|
||||
guint prop_id,
|
||||
const GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkSurface *surface = GDK_SURFACE (object);
|
||||
|
||||
@ -4725,6 +4733,9 @@ gdk_wayland_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;
|
||||
@ -4732,10 +4743,10 @@ gdk_wayland_toplevel_set_property (GObject *object,
|
||||
}
|
||||
|
||||
static void
|
||||
gdk_wayland_toplevel_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
gdk_x11_toplevel_get_property (GObject *object,
|
||||
guint prop_id,
|
||||
GValue *value,
|
||||
GParamSpec *pspec)
|
||||
{
|
||||
GdkSurface *surface = GDK_SURFACE (object);
|
||||
|
||||
@ -4785,6 +4796,10 @@ gdk_wayland_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;
|
||||
@ -4796,8 +4811,8 @@ gdk_x11_toplevel_class_init (GdkX11ToplevelClass *class)
|
||||
{
|
||||
GObjectClass *object_class = G_OBJECT_CLASS (class);
|
||||
|
||||
object_class->get_property = gdk_wayland_toplevel_get_property;
|
||||
object_class->set_property = gdk_wayland_toplevel_set_property;
|
||||
object_class->get_property = gdk_x11_toplevel_get_property;
|
||||
object_class->set_property = gdk_x11_toplevel_set_property;
|
||||
|
||||
gdk_toplevel_install_properties (object_class, LAST_PROP);
|
||||
}
|
||||
@ -4908,6 +4923,63 @@ gdk_x11_toplevel_supports_edge_constraints (GdkToplevel *toplevel)
|
||||
return gdk_x11_surface_supports_edge_constraints (GDK_SURFACE (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)
|
||||
{
|
||||
@ -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 {
|
||||
|
@ -125,6 +125,7 @@ gtk_tests = [
|
||||
['testblur'],
|
||||
['testtexture'],
|
||||
['testwindowdrag'],
|
||||
['testinhibitshortcuts'],
|
||||
['testtexthistory', ['../gtk/gtktexthistory.c']],
|
||||
]
|
||||
|
||||
|
107
tests/testinhibitshortcuts.c
Normal file
107
tests/testinhibitshortcuts.c
Normal file
@ -0,0 +1,107 @@
|
||||
/* testinhibitshortcuts.c
|
||||
|
||||
Copyright (C) 2017 Red Hat
|
||||
Author: Olivier Fourdan <ofourdan@redhat.com>
|
||||
|
||||
This library is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Library General Public License as
|
||||
published by the Free Software Foundation; either version 2 of the
|
||||
License, or (at your option) any later version.
|
||||
|
||||
This library is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Library General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Library General Public
|
||||
License along with this library. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <gtk/gtk.h>
|
||||
|
||||
static void
|
||||
on_shortcuts_inhibit_change (GdkSurface *surface, GParamSpec *pspec, gpointer data)
|
||||
{
|
||||
GtkWidget *button = GTK_WIDGET (data);
|
||||
gboolean button_active;
|
||||
gboolean shortcuts_inhibited;
|
||||
|
||||
g_object_get (GDK_TOPLEVEL (surface), "shortcuts-inhibited", &shortcuts_inhibited, NULL);
|
||||
|
||||
gtk_check_button_set_inconsistent (GTK_CHECK_BUTTON (button), FALSE);
|
||||
|
||||
button_active = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button));
|
||||
|
||||
if (button_active != shortcuts_inhibited)
|
||||
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button), shortcuts_inhibited);
|
||||
}
|
||||
|
||||
static void
|
||||
on_button_toggle (GtkWidget *button, gpointer data)
|
||||
{
|
||||
GdkSurface *surface = GDK_SURFACE (data);
|
||||
GdkEvent *event;
|
||||
|
||||
if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)))
|
||||
{
|
||||
gdk_toplevel_restore_system_shortcuts (GDK_TOPLEVEL (surface));
|
||||
return;
|
||||
}
|
||||
|
||||
gtk_check_button_set_inconsistent (GTK_CHECK_BUTTON (button), TRUE);
|
||||
event = gtk_get_current_event ();
|
||||
gdk_toplevel_inhibit_system_shortcuts (GDK_TOPLEVEL (surface), event);
|
||||
}
|
||||
|
||||
static void
|
||||
quit_cb (GtkWidget *widget,
|
||||
gpointer user_data)
|
||||
{
|
||||
gboolean *done = user_data;
|
||||
|
||||
*done = TRUE;
|
||||
|
||||
g_main_context_wakeup (NULL);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
GdkSurface *surface;
|
||||
GtkWidget *window;
|
||||
GtkWidget *button;
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *text_view;
|
||||
gboolean done = FALSE;
|
||||
|
||||
gtk_init ();
|
||||
|
||||
window = gtk_window_new ();
|
||||
g_signal_connect (window, "destroy", G_CALLBACK (quit_cb), &done);
|
||||
gtk_widget_realize (window);
|
||||
surface = gtk_native_get_surface (gtk_widget_get_native (window));
|
||||
|
||||
vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 2);
|
||||
gtk_container_add (GTK_CONTAINER (window), vbox);
|
||||
|
||||
text_view = gtk_text_view_new ();
|
||||
gtk_widget_set_hexpand (text_view, TRUE);
|
||||
gtk_widget_set_vexpand (text_view, TRUE);
|
||||
gtk_container_add (GTK_CONTAINER (vbox), text_view);
|
||||
|
||||
button = gtk_check_button_new_with_label ("Inhibit system keyboard shorcuts");
|
||||
|
||||
gtk_container_add (GTK_CONTAINER (vbox), button);
|
||||
g_signal_connect (G_OBJECT (button), "toggled",
|
||||
G_CALLBACK (on_button_toggle), surface);
|
||||
|
||||
g_signal_connect (G_OBJECT (surface), "notify::shortcuts-inhibited",
|
||||
G_CALLBACK (on_shortcuts_inhibit_change), button);
|
||||
|
||||
gtk_widget_show (window);
|
||||
|
||||
while (!done)
|
||||
g_main_context_iteration (NULL, TRUE);
|
||||
|
||||
return 0;
|
||||
}
|
Loading…
Reference in New Issue
Block a user