Compare commits

...

9 Commits

Author SHA1 Message Date
Matthias Clasen
8c4a81e16e wayland: Implement AccessX enabling shortcuts
These are the famous 'hold shift 8 seconds' and 'bang shift 5 times'
shortcuts for toggling slow keys and sticky keys.
2016-03-03 01:39:45 -05:00
Matthias Clasen
c15327f5e2 wayland: Implement sticky keys
A simple client-side implementation of the AccessX sticky keys
feature.
2016-03-03 00:52:14 -05:00
Matthias Clasen
2cdcae8473 wayland: implement toggle keys
A simple client-side implementation of the AccessX toggle keys
feature.
2016-03-03 00:52:08 -05:00
Matthias Clasen
1e9db1c9de wayland: implement bounce keys
A simple client-side implementation of the AccessX bounce keys
feature.
2016-03-02 22:26:48 -05:00
Matthias Clasen
3751aa50a9 wayland: implement slow keys
This is a simple client-side implementation of the AccessX
slow keys feature.
2016-03-02 21:43:04 -05:00
Matthias Clasen
38cd533159 wayland: Refactor key event processing
Split out the event translation and the key repeat handling
in subroutines.
2016-03-02 21:40:31 -05:00
Matthias Clasen
4bee19c0a8 wayland: Use libcanberra to implement beeping
The ability to beep in certain situations is a requirement
for some accessibility features. Since there is no Wayland
protocol for this (and it is not sure if there should be),
use libcanberra for this.

https://bugzilla.gnome.org/show_bug.cgi?id=763001
2016-03-02 21:40:31 -05:00
Matthias Clasen
345d41e6ac wayland: Add private api to get a ca_context
Make GdkWaylandScreen keep a ca_context and make
it available via private API. We also update the
context when sound-related settings change.

https://bugzilla.gnome.org/show_bug.cgi?id=763001
2016-03-02 21:40:31 -05:00
Matthias Clasen
ced14d4ebe wayland: Link against libcanberra
This will be used in the subsequent commits to implement
gdk_display_beep() for Wayland.

https://bugzilla.gnome.org/show_bug.cgi?id=763001
2016-03-02 21:40:31 -05:00
5 changed files with 689 additions and 38 deletions

View File

@@ -429,7 +429,7 @@ fi
PKG_PROG_PKG_CONFIG
WAYLAND_DEPENDENCIES="wayland-client >= wayland_required_version wayland-protocols >= wayland_protocols_required_version xkbcommon >= 0.2.0 wayland-cursor >= wayland_required_version wayland-egl"
WAYLAND_DEPENDENCIES="wayland-client >= wayland_required_version wayland-protocols >= wayland_protocols_required_version xkbcommon >= 0.2.0 wayland-cursor >= wayland_required_version wayland-egl libcanberra"
if test "$enable_wayland_backend" = "maybe" ; then
AC_PATH_PROG([WAYLAND_SCANNER],[wayland-scanner],[no])
PKG_CHECK_EXISTS($WAYLAND_DEPENDENCIES, [have_wayland_deps=yes], [have_wayland_deps=no])

View File

@@ -112,6 +112,19 @@ struct _GdkWaylandSeat
guint32 repeat_count;
GSettings *keyboard_settings;
guint32 slow_key_timer;
guint32 slow_key;
guint32 ignore_key_timer;
guint32 ignore_key;
uint32_t mods_depressed;
uint32_t mods_latched;
uint32_t mods_locked;
uint32_t group;
uint32_t shift_count;
uint32_t last_shift_time;
guint32 toggle_slow_keys_timer;
GSettings *a11y_settings;
guint cursor_timeout_id;
guint cursor_image_index;
guint cursor_image_delay;
@@ -177,6 +190,10 @@ struct _GdkWaylandDeviceManagerClass
GdkDeviceManagerClass parent_class;
};
static void process_key_event (GdkWaylandDeviceData *device,
uint32_t time_,
uint32_t key,
uint32_t state);
static void deliver_key_event (GdkWaylandDeviceData *device,
uint32_t time_,
uint32_t key,
@@ -1519,6 +1536,7 @@ keyboard_handle_enter (void *data,
}
static void stop_key_repeat (GdkWaylandDeviceData *device);
static void stop_slow_keys (GdkWaylandDeviceData *device);
static void
keyboard_handle_leave (void *data,
@@ -1539,6 +1557,7 @@ keyboard_handle_leave (void *data,
*/
stop_key_repeat (device);
stop_slow_keys (device);
_gdk_wayland_display_update_serial (display, serial);
@@ -1690,6 +1709,327 @@ get_key_repeat (GdkWaylandDeviceData *device,
return repeat;
}
static GSettings *
get_a11y_settings (GdkWaylandDeviceData *device)
{
if (!device->a11y_settings)
{
GSettingsSchemaSource *source;
GSettingsSchema *schema;
source = g_settings_schema_source_get_default ();
schema = g_settings_schema_source_lookup (source, "org.gnome.desktop.a11y.keyboard", FALSE);
if (schema != NULL)
{
device->a11y_settings = g_settings_new_full (schema, NULL, NULL);
g_settings_schema_unref (schema);
}
}
return device->a11y_settings;
}
static gboolean
get_slow_keys_enabled (GdkWaylandDeviceData *device)
{
GSettings *a11y_settings = get_a11y_settings (device);
if (a11y_settings)
return g_settings_get_boolean (a11y_settings, "slowkeys-enable");
return FALSE;
}
static void
set_slow_keys_enabled (GdkWaylandDeviceData *device,
gboolean enabled)
{
GSettings *a11y_settings = get_a11y_settings (device);
if (a11y_settings)
g_settings_set_boolean (a11y_settings, "slowkeys-enable", enabled);
}
static void
toggle_slow_keys_enabled (GdkWaylandDeviceData *device)
{
set_slow_keys_enabled (device, !get_slow_keys_enabled (device));
}
static gboolean
get_slow_keys_beep_on_press (GdkWaylandDeviceData *device)
{
GSettings *a11y_settings = get_a11y_settings (device);
if (a11y_settings)
return g_settings_get_boolean (a11y_settings, "slowkeys-beep-press");
return FALSE;
}
static gboolean
get_slow_keys_beep_on_accept (GdkWaylandDeviceData *device)
{
GSettings *a11y_settings = get_a11y_settings (device);
if (a11y_settings)
return g_settings_get_boolean (a11y_settings, "slowkeys-beep-accept");
return FALSE;
}
static gboolean
get_slow_keys_beep_on_reject (GdkWaylandDeviceData *device)
{
GSettings *a11y_settings = get_a11y_settings (device);
if (a11y_settings)
return g_settings_get_boolean (a11y_settings, "slowkeys-beep-reject");
return FALSE;
}
static gint
get_slow_keys_delay (GdkWaylandDeviceData *device)
{
GSettings *a11y_settings = get_a11y_settings (device);
if (a11y_settings)
return g_settings_get_int (a11y_settings, "slowkeys-delay");
return 100;
}
static gboolean
get_bounce_keys_enabled (GdkWaylandDeviceData *device)
{
GSettings *a11y_settings = get_a11y_settings (device);
if (a11y_settings)
return g_settings_get_boolean (a11y_settings, "bouncekeys-enable");
return FALSE;
}
static gboolean
get_bounce_keys_beep_on_reject (GdkWaylandDeviceData *device)
{
GSettings *a11y_settings = get_a11y_settings (device);
if (a11y_settings)
return g_settings_get_boolean (a11y_settings, "bouncekeys-beep-reject");
return FALSE;
}
static gint
get_bounce_keys_delay (GdkWaylandDeviceData *device)
{
GSettings *a11y_settings = get_a11y_settings (device);
if (a11y_settings)
return g_settings_get_int (a11y_settings, "bouncekeys-delay");
return 100;
}
static gboolean
get_toggle_keys_enabled (GdkWaylandDeviceData *device)
{
GSettings *a11y_settings = get_a11y_settings (device);
if (a11y_settings)
return g_settings_get_boolean (a11y_settings, "togglekeys-enable");
return FALSE;
}
static gboolean
get_sticky_keys_enabled (GdkWaylandDeviceData *device)
{
GSettings *a11y_settings = get_a11y_settings (device);
if (a11y_settings)
return g_settings_get_boolean (a11y_settings, "stickykeys-enable");
return FALSE;
}
static void
set_sticky_keys_enabled (GdkWaylandDeviceData *device,
gboolean enabled)
{
GSettings *a11y_settings = get_a11y_settings (device);
if (a11y_settings)
g_settings_set_boolean (a11y_settings, "stickykeys-enable", enabled);
}
static void
toggle_sticky_keys_enabled (GdkWaylandDeviceData *device)
{
set_sticky_keys_enabled (device, !get_sticky_keys_enabled (device));
}
static gboolean
get_sticky_keys_modifier_beep (GdkWaylandDeviceData *device)
{
GSettings *a11y_settings = get_a11y_settings (device);
if (a11y_settings)
return g_settings_get_boolean (a11y_settings, "stickykeys-modifier-beep");
return FALSE;
}
static gboolean
get_sticky_keys_two_key_off (GdkWaylandDeviceData *device)
{
GSettings *a11y_settings = get_a11y_settings (device);
if (a11y_settings)
return g_settings_get_boolean (a11y_settings, "stickykeys-two-key-off");
return FALSE;
}
static gboolean
get_access_keys_enabled (GdkWaylandDeviceData *device)
{
GSettings *a11y_settings = get_a11y_settings (device);
if (a11y_settings)
return g_settings_get_boolean (a11y_settings, "enable");
return FALSE;
}
static void start_key_repeat (GdkWaylandDeviceData *device,
uint32_t key);
static gboolean
slow_key (gpointer data)
{
GdkWaylandDeviceData *device = data;
uint32_t key;
key = device->slow_key;
if (key != 0)
deliver_key_event (device, device->time, key, 1);
device->slow_key = 0;
device->slow_key_timer = 0;
start_key_repeat (device, key);
return G_SOURCE_REMOVE;
}
static void
start_slow_keys (GdkWaylandDeviceData *device,
uint32_t key)
{
guint timeout;
timeout = get_slow_keys_delay (device);
device->slow_key = key;
device->slow_key_timer =
gdk_threads_add_timeout (timeout, slow_key, device);
g_source_set_name_by_id (device->slow_key_timer, "[gtk+] slow_key");
}
static void
stop_slow_keys (GdkWaylandDeviceData *device)
{
device->slow_key = 0;
if (device->slow_key_timer)
{
g_source_remove (device->slow_key_timer);
device->slow_key_timer = 0;
}
}
static gboolean
bounce_key (gpointer data)
{
GdkWaylandDeviceData *device = data;
device->ignore_key = 0;
device->ignore_key_timer = 0;
return G_SOURCE_REMOVE;
}
static void
start_bounce_keys (GdkWaylandDeviceData *device,
uint32_t key)
{
guint timeout;
timeout = get_bounce_keys_delay (device);
device->ignore_key = key;
device->ignore_key_timer =
gdk_threads_add_timeout (timeout, bounce_key, device);
g_source_set_name_by_id (device->ignore_key_timer, "[gtk+] bounce_key");
}
static void
stop_bounce_keys (GdkWaylandDeviceData *device)
{
device->ignore_key = 0;
if (device->ignore_key_timer)
{
g_source_remove (device->ignore_key_timer);
device->ignore_key_timer = 0;
}
}
static void
toggle_keys_apply (GdkWaylandDeviceData *device,
GdkModifierType from,
GdkModifierType to)
{
if (get_toggle_keys_enabled (device))
{
if ((from ^ to) & (GDK_LOCK_MASK | GDK_MOD4_MASK))
gdk_display_beep (device->display);
}
}
static void
start_key_repeat (GdkWaylandDeviceData *device,
uint32_t key)
{
struct xkb_keymap *xkb_keymap;
guint delay, interval, timeout;
xkb_keymap = _gdk_wayland_keymap_get_xkb_keymap (device->keymap);
if (!xkb_keymap_key_repeats (xkb_keymap, key))
return;
if (!get_key_repeat (device, &delay, &interval))
return;
device->repeat_key = key;
if (device->repeat_count == 0)
timeout = delay;
else
timeout = interval;
device->repeat_timer =
gdk_threads_add_timeout (timeout, keyboard_repeat, device);
g_source_set_name_by_id (device->repeat_timer, "[gtk+] keyboard_repeat");
}
static void
stop_key_repeat (GdkWaylandDeviceData *device)
{
@@ -1702,30 +2042,48 @@ stop_key_repeat (GdkWaylandDeviceData *device)
g_clear_pointer (&device->repeat_callback, wl_callback_destroy);
}
static gboolean
toggle_slow_keys (gpointer data)
{
GdkWaylandDeviceData *device = data;
toggle_slow_keys_enabled (device);
device->toggle_slow_keys_timer = 0;
return G_SOURCE_REMOVE;
}
static void
deliver_key_event (GdkWaylandDeviceData *device,
uint32_t time_,
uint32_t key,
uint32_t state)
start_toggle_slow_keys (GdkWaylandDeviceData *device)
{
device->toggle_slow_keys_timer =
gdk_threads_add_timeout (8000, toggle_slow_keys, device);
g_source_set_name_by_id (device->toggle_slow_keys_timer, "[gtk+] toggle_slow_keys");
}
static void
stop_toggle_slow_keys (GdkWaylandDeviceData *device)
{
if (device->toggle_slow_keys_timer)
{
g_source_remove (device->toggle_slow_keys_timer);
device->toggle_slow_keys_timer = 0;
}
}
static GdkEvent *
translate_key_event (GdkWaylandDeviceData *device,
uint32_t time_,
uint32_t key,
uint32_t state)
{
GdkEvent *event;
struct xkb_state *xkb_state;
struct xkb_keymap *xkb_keymap;
GdkKeymap *keymap;
xkb_keysym_t sym;
guint delay, interval, timeout;
stop_key_repeat (device);
keymap = device->keymap;
xkb_state = _gdk_wayland_keymap_get_xkb_state (keymap);
xkb_keymap = _gdk_wayland_keymap_get_xkb_keymap (keymap);
xkb_state = _gdk_wayland_keymap_get_xkb_state (device->keymap);
sym = xkb_state_key_get_one_sym (xkb_state, key);
device->time = time_;
device->key_modifiers = gdk_keymap_get_modifier_state (keymap);
event = gdk_event_new (state ? GDK_KEY_PRESS : GDK_KEY_RELEASE);
event->key.window = device->keyboard_focus ? g_object_ref (device->keyboard_focus) : NULL;
gdk_event_set_device (event, device->master_keyboard);
@@ -1736,38 +2094,177 @@ deliver_key_event (GdkWaylandDeviceData *device,
event->key.group = 0;
event->key.hardware_keycode = key;
event->key.keyval = sym;
event->key.is_modifier = _gdk_wayland_keymap_key_is_modifier (keymap, key);
event->key.is_modifier = _gdk_wayland_keymap_key_is_modifier (device->keymap, key);
translate_keyboard_string (&event->key);
return event;
}
static void
deliver_key_event (GdkWaylandDeviceData *device,
uint32_t time_,
uint32_t key,
uint32_t state)
{
GdkEvent *event;
struct xkb_state *xkb_state;
if (state == 1)
{
device->repeat_count++;
if (get_slow_keys_enabled (device) &&
get_slow_keys_beep_on_accept (device))
gdk_display_beep (device->display);
}
event = translate_key_event (device, time_, key, state);
_gdk_wayland_display_deliver_event (device->display, event);
if (state == 1)
{
if (get_sticky_keys_enabled (device) &&
!_gdk_wayland_keymap_key_is_modifier (device->keymap, key))
{
device->mods_latched = 0;
device->key_modifiers = device->mods_locked;
xkb_state = _gdk_wayland_keymap_get_xkb_state (device->keymap);
xkb_state_update_mask (xkb_state, 0, 0, device->mods_locked, device->group, 0, 0);
}
}
}
static void
process_key_event (GdkWaylandDeviceData *device,
uint32_t time_,
uint32_t key,
uint32_t state)
{
gboolean deliver = TRUE;
struct xkb_state *xkb_state;
device->time = time_;
device->key_modifiers = gdk_keymap_get_modifier_state (device->keymap);
GDK_NOTE (EVENTS,
g_message ("keyboard event, code %d, sym %d, "
"string %s, mods 0x%x",
event->key.hardware_keycode, event->key.keyval,
event->key.string, event->key.state));
g_message ("process key %s, code %d, modifiers 0x%x",
state ? "press" : "release",
key, device->key_modifiers));
if (state == 0)
return;
if (get_sticky_keys_enabled (device))
{
if (state && device->mods_depressed &&
get_sticky_keys_two_key_off (device))
{
set_sticky_keys_enabled (device, FALSE);
device->mods_depressed = 0;
device->mods_latched = 0;
device->mods_locked = 0;
if (!xkb_keymap_key_repeats (xkb_keymap, key))
return;
device->key_modifiers = 0;
xkb_state = _gdk_wayland_keymap_get_xkb_state (device->keymap);
xkb_state_update_mask (xkb_state, 0, 0, 0, device->group, 0, 0);
}
}
if (!get_key_repeat (device, &delay, &interval))
return;
if (get_access_keys_enabled (device))
{
xkb_keysym_t sym;
device->repeat_count++;
device->repeat_key = key;
xkb_state = _gdk_wayland_keymap_get_xkb_state (device->keymap);
sym = xkb_state_key_get_one_sym (xkb_state, key);
if (state)
{
if (sym == XKB_KEY_Shift_L || sym == XKB_KEY_Shift_R)
{
start_toggle_slow_keys (device);
if (!get_slow_keys_enabled (device))
{
if (time_ - device->last_shift_time > 15000)
device->shift_count = 1;
else
device->shift_count++;
device->last_shift_time = time_;
}
}
else
stop_toggle_slow_keys (device);
}
else
{
if (sym == XKB_KEY_Shift_L || sym == XKB_KEY_Shift_R)
{
stop_toggle_slow_keys (device);
if (device->shift_count >= 5)
{
toggle_sticky_keys_enabled (device);
device->shift_count = 0;
}
}
else
device->shift_count = 0;
}
}
if (device->repeat_count == 1)
timeout = delay;
else
timeout = interval;
if (get_slow_keys_enabled (device))
{
if (state)
{
if (device->slow_key == key)
return;
device->repeat_timer =
gdk_threads_add_timeout (timeout, keyboard_repeat, device);
g_source_set_name_by_id (device->repeat_timer, "[gtk+] keyboard_repeat");
if (device->repeat_count == 0 &&
get_slow_keys_beep_on_press (device))
gdk_display_beep (device->display);
start_slow_keys (device, key);
deliver = FALSE;
}
else
{
if (device->slow_key == key)
{
if (get_slow_keys_beep_on_reject (device))
gdk_display_beep (device->display);
deliver = FALSE;
}
stop_slow_keys (device);
}
}
if (get_bounce_keys_enabled (device))
{
if (state)
{
if (device->ignore_key == key)
{
if (get_bounce_keys_beep_on_reject (device))
gdk_display_beep (device->display);
deliver = FALSE;
}
}
else
{
if (device->ignore_key == key)
{
stop_bounce_keys (device);
deliver = FALSE;
}
start_bounce_keys (device, key);
}
}
stop_key_repeat (device);
if (!get_slow_keys_enabled (device))
{
if (state == 1)
start_key_repeat (device, key);
}
if (deliver)
deliver_key_event (device, time_, key, state);
}
static void
@@ -1780,6 +2277,7 @@ sync_after_repeat_callback (void *data,
g_clear_pointer (&device->repeat_callback, wl_callback_destroy);
deliver_key_event (device, device->time, device->repeat_key, 1);
start_key_repeat (device, device->repeat_key);
}
static const struct wl_callback_listener sync_after_repeat_callback_listener = {
@@ -1804,6 +2302,8 @@ keyboard_repeat (gpointer data)
&sync_after_repeat_callback_listener,
device);
device->repeat_timer = 0;
return G_SOURCE_REMOVE;
}
@@ -1823,7 +2323,8 @@ keyboard_handle_key (void *data,
device->repeat_count = 0;
_gdk_wayland_display_update_serial (display, serial);
deliver_key_event (data, time, key + 8, state_w);
process_key_event (data, time, key + 8, state_w);
}
static void
@@ -1839,14 +2340,48 @@ keyboard_handle_modifiers (void *data,
GdkKeymap *keymap;
struct xkb_state *xkb_state;
PangoDirection direction;
GdkModifierType modifiers;
device->mods_depressed = mods_depressed;
if (get_sticky_keys_enabled (device))
{
if (mods_depressed == 0)
return;
if (get_sticky_keys_modifier_beep (device))
gdk_display_beep (device->display);
if (device->mods_locked & mods_depressed)
{
device->mods_locked &= ~mods_depressed;
}
else if (device->mods_latched == mods_depressed)
{
device->mods_locked = mods_depressed;
device->mods_latched = 0;
}
else
{
device->mods_latched = mods_depressed;
}
mods_depressed = 0;
mods_latched = device->mods_latched;
mods_locked = device->mods_locked;
}
keymap = device->keymap;
direction = gdk_keymap_get_direction (keymap);
xkb_state = _gdk_wayland_keymap_get_xkb_state (keymap);
modifiers = device->key_modifiers;
device->key_modifiers = mods_depressed | mods_latched | mods_locked;
device->group = group;
xkb_state_update_mask (xkb_state, mods_depressed, mods_latched, mods_locked, group, 0, 0);
toggle_keys_apply (device, modifiers, device->key_modifiers);
g_signal_emit_by_name (keymap, "state-changed");
if (direction != gdk_keymap_get_direction (keymap))
g_signal_emit_by_name (keymap, "direction-changed");
@@ -2653,10 +3188,14 @@ gdk_wayland_seat_finalize (GObject *object)
wl_surface_destroy (seat->pointer_surface);
/* FIXME: destroy data_device */
g_clear_object (&seat->keyboard_settings);
g_clear_object (&seat->a11y_settings);
g_clear_object (&seat->drop_context);
g_hash_table_destroy (seat->touches);
gdk_window_destroy (seat->foreign_dnd_window);
stop_key_repeat (seat);
stop_slow_keys (seat);
stop_bounce_keys (seat);
stop_toggle_slow_keys (seat);
G_OBJECT_CLASS (gdk_wayland_seat_parent_class)->finalize (object);
}

View File

@@ -27,7 +27,9 @@
#include <sys/syscall.h>
#include <glib.h>
#include "gdkintl.h"
#include "gdkwayland.h"
#include "gdkprivate-wayland.h"
#include "gdkdisplay.h"
#include "gdkdisplay-wayland.h"
#include "gdkscreen.h"
@@ -39,6 +41,8 @@
#include "gdkglcontext-wayland.h"
#include "pointer-gestures-unstable-v1-client-protocol.h"
#include <canberra.h>
/**
* SECTION:wayland_interaction
* @Short_description: Wayland backend-specific functions
@@ -522,7 +526,25 @@ gdk_wayland_display_get_default_screen (GdkDisplay *display)
static void
gdk_wayland_display_beep (GdkDisplay *display)
{
ca_context *c;
ca_proplist *p;
g_return_if_fail (GDK_IS_DISPLAY (display));
c = gdk_wayland_screen_get_ca_context (gdk_display_get_default_screen (display));
if (!c)
return;
ca_proplist_create (&p);
ca_proplist_sets (p, CA_PROP_EVENT_ID, "bell-window-system");
ca_proplist_sets (p, CA_PROP_EVENT_DESCRIPTION, _("Bell event"));
ca_proplist_sets (p, CA_PROP_CANBERRA_CACHE_CONTROL, "permanent");
ca_proplist_setf (p, CA_PROP_APPLICATION_PROCESS_ID, "%d", getpid ());
ca_context_play_full (c, 1, p, NULL, NULL);
ca_proplist_destroy (p);
}
static void

View File

@@ -36,6 +36,8 @@
#include <xkbcommon/xkbcommon.h>
#include <canberra.h>
#include "gdkinternals.h"
#include "wayland/gtk-primary-selection-client-protocol.h"
@@ -276,4 +278,6 @@ EGLSurface gdk_wayland_window_get_dummy_egl_surface (GdkWindow *window,
void gdk_wayland_seat_set_global_cursor (GdkSeat *seat,
GdkCursor *cursor);
ca_context *gdk_wayland_screen_get_ca_context (GdkScreen *screen);
#endif /* __GDK_PRIVATE_WAYLAND_H__ */

View File

@@ -31,6 +31,8 @@
#include "wm-button-layout-translation.h"
#include "canberra.h"
typedef struct _GdkWaylandScreen GdkWaylandScreen;
typedef struct _GdkWaylandScreenClass GdkWaylandScreenClass;
@@ -70,6 +72,7 @@ struct _GdkWaylandScreen
GHashTable *settings;
GsdXftSettings xft_settings;
ca_context *ca_context;
guint32 shell_capabilities;
};
@@ -159,6 +162,9 @@ gdk_wayland_screen_finalize (GObject *object)
deinit_multihead (GDK_SCREEN (object));
if (screen_wayland->ca_context)
ca_context_destroy (screen_wayland->ca_context);
g_hash_table_destroy (screen_wayland->settings);
G_OBJECT_CLASS (_gdk_wayland_screen_parent_class)->finalize (object);
@@ -595,6 +601,83 @@ find_translation_entry_by_setting (const gchar *setting)
return NULL;
}
ca_context *
gdk_wayland_screen_get_ca_context (GdkScreen *screen)
{
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
ca_context *c;
ca_proplist *p;
const char *name;
GSettings *settings;
if (screen_wayland->ca_context)
goto out;
if (ca_context_create (&c) != CA_SUCCESS)
return NULL;
if (ca_proplist_create (&p) != CA_SUCCESS)
{
ca_context_destroy (c);
return NULL;
}
name = g_get_application_name ();
if (name)
ca_proplist_sets (p, CA_PROP_APPLICATION_NAME, name);
settings = g_hash_table_lookup (screen_wayland->settings, "org.gnome.desktop.sound");
if (settings)
{
char *theme_name;
gboolean event_sounds;
theme_name = g_settings_get_string (settings, "theme-name");
event_sounds = g_settings_get_boolean (settings, "event-sounds");
ca_proplist_sets (p, CA_PROP_CANBERRA_XDG_THEME_NAME, theme_name);
ca_proplist_sets (p, CA_PROP_CANBERRA_ENABLE, event_sounds ? "1" : "0");
g_free (theme_name);
}
ca_context_change_props_full (c, p);
ca_proplist_destroy (p);
screen_wayland->ca_context = c;
out:
return screen_wayland->ca_context;
}
static void
update_sound_settings (GSettings *settings,
const char *key,
GdkScreen *screen)
{
GdkWaylandScreen *screen_wayland = GDK_WAYLAND_SCREEN (screen);
if (screen_wayland->ca_context == NULL)
return;
if (strcmp (key, "theme-name") == 0)
{
gchar *theme_name;
theme_name = g_settings_get_string (settings, key);
ca_context_change_props (screen_wayland->ca_context, CA_PROP_CANBERRA_XDG_THEME_NAME, theme_name, NULL);
g_free (theme_name);
}
else if (strcmp (key, "event-sounds") == 0)
{
gboolean event_sounds;
event_sounds = g_settings_get_boolean (settings, key);
ca_context_change_props (screen_wayland->ca_context, CA_PROP_CANBERRA_ENABLE, event_sounds ? "1" : "0", NULL);
}
}
static void
settings_changed (GSettings *settings,
const gchar *key,
@@ -606,6 +689,9 @@ settings_changed (GSettings *settings,
if (entry != NULL)
{
if (strcmp (entry->schema, "org.gnome.desktop.sound") == 0)
update_sound_settings (settings, key, screen);
if (entry->type != G_TYPE_NONE)
notify_setting (screen, entry->setting);
else