1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
3
* Copyright (C) 2001-2003 Bastien Nocera <hadess@hadess.net>
4
* Copyright (C) 2006-2007 William Jon McCann <mccann@jhu.edu>
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; either version 2 of the License, or
9
* (at your option) any later version.
11
* This program is distributed in the hope that it will be useful,
12
* but WITHOUT ANY WARRANTY; without even the implied warranty of
13
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
* GNU General Public License for more details.
16
* You should have received a copy of the GNU General Public License
17
* along with this program; if not, write to the Free Software
18
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24
#include <sys/types.h>
36
#include <glib/gi18n.h>
41
#include <gio/gdesktopappinfo.h>
42
#include <gio/gunixfdlist.h>
45
#include <gudev/gudev.h>
48
#include "gnome-settings-plugin.h"
49
#include "gnome-settings-session.h"
50
#include "gnome-settings-profile.h"
51
#include "gsd-marshal.h"
52
#include "gsd-media-keys-manager.h"
54
#include "shortcuts-list.h"
55
#include "shell-key-grabber.h"
56
#include "gsd-screenshot-utils.h"
57
#include "gsd-input-helper.h"
58
#include "gsd-enums.h"
61
#include <pulse/pulseaudio.h>
62
#include "gvc-mixer-control.h"
63
#include "gvc-mixer-sink.h"
65
#include <libnotify/notify.h>
67
#define GSD_MEDIA_KEYS_DBUS_PATH GSD_DBUS_PATH "/MediaKeys"
68
#define GSD_MEDIA_KEYS_DBUS_NAME GSD_DBUS_NAME ".MediaKeys"
70
#define GNOME_KEYRING_DBUS_NAME "org.gnome.keyring"
71
#define GNOME_KEYRING_DBUS_PATH "/org/gnome/keyring/daemon"
72
#define GNOME_KEYRING_DBUS_INTERFACE "org.gnome.keyring.Daemon"
74
#define GS_DBUS_NAME "org.gnome.ScreenSaver"
75
#define GS_DBUS_PATH "/org/gnome/ScreenSaver"
76
#define GS_DBUS_INTERFACE "org.gnome.ScreenSaver"
78
#define SHELL_DBUS_NAME "org.gnome.Shell"
79
#define SHELL_DBUS_PATH "/org/gnome/Shell"
81
#define PANEL_DBUS_NAME "org.gnome.Panel"
83
#define UNITY_DBUS_NAME "com.canonical.Unity"
85
#define CUSTOM_BINDING_SCHEMA SETTINGS_BINDING_DIR ".custom-keybinding"
87
#define SHELL_GRABBER_RETRY_INTERVAL 1
89
static const gchar introspection_xml[] =
90
"<node name='/org/gnome/SettingsDaemon/MediaKeys'>"
91
" <interface name='org.gnome.SettingsDaemon.MediaKeys'>"
92
" <annotation name='org.freedesktop.DBus.GLib.CSymbol' value='gsd_media_keys_manager'/>"
93
" <method name='GrabMediaPlayerKeys'>"
94
" <arg name='application' direction='in' type='s'/>"
95
" <arg name='time' direction='in' type='u'/>"
97
" <method name='ReleaseMediaPlayerKeys'>"
98
" <arg name='application' direction='in' type='s'/>"
100
" <signal name='MediaPlayerKeyPressed'>"
101
" <arg name='application' type='s'/>"
102
" <arg name='key' type='s'/>"
107
#define SETTINGS_INTERFACE_DIR "org.gnome.desktop.interface"
108
#define SETTINGS_POWER_DIR "org.gnome.settings-daemon.plugins.power"
109
#define SETTINGS_XSETTINGS_DIR "org.gnome.settings-daemon.plugins.xsettings"
110
#define SETTINGS_TOUCHPAD_DIR "org.gnome.settings-daemon.peripherals.touchpad"
111
#define TOUCHPAD_ENABLED_KEY "touchpad-enabled"
112
#define HIGH_CONTRAST "HighContrast"
114
#define VOLUME_STEP 6 /* percents for one volume button press */
115
#define MAX_VOLUME 65536.0
117
#define GNOME_DESKTOP_INPUT_SOURCES_DIR "org.gnome.desktop.input-sources"
118
#define KEY_CURRENT_INPUT_SOURCE "current"
119
#define KEY_INPUT_SOURCES "sources"
121
#define SYSTEMD_DBUS_NAME "org.freedesktop.login1"
122
#define SYSTEMD_DBUS_PATH "/org/freedesktop/login1"
123
#define SYSTEMD_DBUS_INTERFACE "org.freedesktop.login1.Manager"
125
#define GSD_MEDIA_KEYS_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GSD_TYPE_MEDIA_KEYS_MANAGER, GsdMediaKeysManagerPrivate))
135
MediaKeyType key_type;
136
ShellKeyBindingMode modes;
137
const char *settings_key;
138
const char *hard_coded;
140
char *custom_command;
146
GsdMediaKeysManager *manager;
150
struct GsdMediaKeysManagerPrivate
153
GvcMixerControl *volume;
154
GvcMixerStream *sink;
155
GvcMixerStream *source;
157
GtkSettings *gtksettings;
159
GHashTable *streams; /* key = X device ID, value = stream id */
160
GUdevClient *udev_client;
161
#endif /* HAVE_GUDEV */
164
GSettings *input_settings;
165
GHashTable *custom_settings;
169
/* HighContrast theme settings */
170
GSettings *interface_settings;
175
GSettings *power_settings;
176
GDBusProxy *power_proxy;
177
GDBusProxy *power_screen_proxy;
178
GDBusProxy *power_keyboard_proxy;
182
GDBusProxy *shell_proxy;
183
ShellKeyGrabber *key_grabber;
184
GCancellable *shell_cancellable;
185
GCancellable *grab_cancellable;
188
GDBusProxy *logind_proxy;
189
gint inhibit_keys_fd;
191
/* Multihead stuff */
192
GdkScreen *current_screen;
198
GList *media_players;
200
GDBusNodeInfo *introspection_data;
201
GDBusConnection *connection;
202
GCancellable *bus_cancellable;
203
GDBusProxy *xrandr_proxy;
204
GCancellable *cancellable;
208
/* Ubuntu notifications */
209
NotifyNotification *volume_notification;
210
NotifyNotification *brightness_notification;
211
NotifyNotification *kb_backlight_notification;
213
/* Legacy keygrabber stuff */
214
guint unity_name_owner_id;
215
guint panel_name_owner_id;
216
guint have_legacy_keygrabber;
220
static void gsd_media_keys_manager_class_init (GsdMediaKeysManagerClass *klass);
221
static void gsd_media_keys_manager_init (GsdMediaKeysManager *media_keys_manager);
222
static void gsd_media_keys_manager_finalize (GObject *object);
223
static void register_manager (GsdMediaKeysManager *manager);
224
static void custom_binding_changed (GSettings *settings,
225
const char *settings_key,
226
GsdMediaKeysManager *manager);
227
static void grab_media_keys (GsdMediaKeysManager *manager);
228
static void grab_media_key (MediaKey *key,
229
GsdMediaKeysManager *manager);
230
static void ungrab_media_key (MediaKey *key,
231
GsdMediaKeysManager *manager);
232
G_DEFINE_TYPE (GsdMediaKeysManager, gsd_media_keys_manager, G_TYPE_OBJECT)
234
static gpointer manager_object = NULL;
236
#define NOTIFY_CAP_PRIVATE_SYNCHRONOUS "x-canonical-private-synchronous"
237
#define NOTIFY_CAP_PRIVATE_ICON_ONLY "x-canonical-private-icon-only"
238
#define NOTIFY_HINT_TRUE "true"
241
GsdMediaKeysManager *manager;
243
guint old_percentage;
245
} GsdBrightnessActionData;
247
static const char *volume_icons[] = {
248
"notification-audio-volume-muted",
249
"notification-audio-volume-low",
250
"notification-audio-volume-medium",
251
"notification-audio-volume-high",
255
static const char *brightness_icons[] = {
256
"notification-display-brightness-off",
257
"notification-display-brightness-low",
258
"notification-display-brightness-medium",
259
"notification-display-brightness-high",
260
"notification-display-brightness-full",
264
static const char *kb_backlight_icons[] = {
265
"notification-keyboard-brightness-off",
266
"notification-keyboard-brightness-low",
267
"notification-keyboard-brightness-medium",
268
"notification-keyboard-brightness-high",
269
"notification-keyboard-brightness-full",
274
calculate_icon_name (gint value, const char **icon_names)
276
value = CLAMP (value, 0, 100);
277
gint length = g_strv_length (icon_names);
278
gint s = (length - 1) * value / 100 + 1;
279
s = CLAMP (s, 1, length - 1);
281
return icon_names[s];
285
ubuntu_osd_notification_is_supported (void)
290
caps = notify_get_server_caps ();
291
has_cap = (g_list_find_custom (caps, NOTIFY_CAP_PRIVATE_SYNCHRONOUS, (GCompareFunc) g_strcmp0) != NULL);
292
g_list_foreach (caps, (GFunc) g_free, NULL);
299
ubuntu_osd_notification_show_icon (const char *icon,
302
if (!ubuntu_osd_notification_is_supported ())
305
NotifyNotification *notification = notify_notification_new (" ", "", icon);
306
notify_notification_set_hint_string (notification, NOTIFY_CAP_PRIVATE_SYNCHRONOUS, hint);
307
notify_notification_set_hint_string (notification, NOTIFY_CAP_PRIVATE_ICON_ONLY, NOTIFY_HINT_TRUE);
309
gboolean res = notify_notification_show (notification, NULL);
310
g_object_unref (notification);
316
ubuntu_osd_do_notification (NotifyNotification **notification,
320
const char **icon_names)
322
if (!ubuntu_osd_notification_is_supported ())
325
if (!*notification) {
326
*notification = notify_notification_new (" ", "", NULL);
327
notify_notification_set_hint_string (*notification, NOTIFY_CAP_PRIVATE_SYNCHRONOUS, hint);
330
value = CLAMP (value, -1, 101);
331
const char *icon = muted ? icon_names[0] : calculate_icon_name (value, icon_names);
332
notify_notification_set_hint_int32 (*notification, "value", value);
333
notify_notification_update (*notification, " ", "", icon);
335
return notify_notification_show (*notification, NULL);
339
ubuntu_osd_notification_show_volume (GsdMediaKeysManager *manager,
343
return ubuntu_osd_do_notification (&manager->priv->volume_notification,
344
"volume", value, muted, volume_icons);
348
ubuntu_osd_notification_show_brightness (GsdMediaKeysManager *manager,
351
return ubuntu_osd_do_notification (&manager->priv->brightness_notification,
352
"brightness", value, value <= 0, brightness_icons);
356
ubuntu_osd_notification_show_kb_backlight (GsdMediaKeysManager *manager,
359
return ubuntu_osd_do_notification (&manager->priv->kb_backlight_notification,
360
"keyboard", value, value <= 0, kb_backlight_icons);
364
init_screens (GsdMediaKeysManager *manager)
369
display = gdk_display_get_default ();
370
for (i = 0; i < gdk_display_get_n_screens (display); i++) {
373
screen = gdk_display_get_screen (display, i);
374
if (screen == NULL) {
377
manager->priv->screens = g_slist_append (manager->priv->screens, screen);
380
manager->priv->current_screen = manager->priv->screens->data;
384
media_key_free (MediaKey *key)
388
g_free (key->custom_path);
389
g_free (key->custom_command);
396
get_term_command (GsdMediaKeysManager *manager)
398
char *cmd_term, *cmd_args;;
402
settings = g_settings_new ("org.gnome.desktop.default-applications.terminal");
403
cmd_term = g_settings_get_string (settings, "exec");
404
if (cmd_term[0] == '\0')
405
cmd_term = g_strdup ("gnome-terminal");
407
cmd_args = g_settings_get_string (settings, "exec-arg");
408
if (strcmp (cmd_term, "") != 0) {
409
cmd = g_strdup_printf ("%s %s -e", cmd_term, cmd_args);
411
cmd = g_strdup_printf ("%s -e", cmd_term);
416
g_object_unref (settings);
422
get_keyring_env (GsdMediaKeysManager *manager)
424
GError *error = NULL;
425
GVariant *variant, *item;
429
variant = g_dbus_connection_call_sync (manager->priv->connection,
430
GNOME_KEYRING_DBUS_NAME,
431
GNOME_KEYRING_DBUS_PATH,
432
GNOME_KEYRING_DBUS_INTERFACE,
436
G_DBUS_CALL_FLAGS_NONE,
440
if (variant == NULL) {
441
g_warning ("Failed to call GetEnvironment on keyring daemon: %s", error->message);
442
g_error_free (error);
446
envp = g_get_environ ();
447
envp = g_environ_unsetenv (envp, "DESKTOP_AUTOSTART_ID");
449
g_variant_get (variant, "(a{ss})", &iter);
451
while ((item = g_variant_iter_next_value (iter))) {
460
envp = g_environ_setenv (envp, key, value, TRUE);
462
g_variant_unref (item);
467
g_variant_iter_free (iter);
468
g_variant_unref (variant);
474
execute (GsdMediaKeysManager *manager,
483
GError *error = NULL;
488
term = get_term_command (manager);
491
exec = g_strdup_printf ("%s %s", term, cmd);
494
exec = g_strdup (cmd);
497
if (g_shell_parse_argv (exec, &argc, &argv, NULL)) {
500
envp = get_keyring_env (manager);
502
retval = g_spawn_async (g_get_home_dir (),
515
if (retval == FALSE) {
516
g_warning ("Couldn't execute command: %s: %s", exec, error->message);
517
g_error_free (error);
523
print_key_parse_error (MediaKey *key,
526
if (str == NULL || *str == '\0')
528
if (key->settings_key != NULL)
529
g_debug ("Unable to parse key '%s' for GSettings entry '%s'", str, key->settings_key);
531
g_debug ("Unable to parse hard-coded key '%s'", key->hard_coded);
535
get_key_string (GsdMediaKeysManager *manager,
538
if (key->settings_key == "switch-input-source" || key->settings_key == "switch-input-source-backward")
539
return g_settings_get_strv (manager->priv->input_settings, key->settings_key)[0];
540
else if (key->settings_key != NULL)
541
return g_settings_get_string (manager->priv->settings, key->settings_key);
542
else if (key->hard_coded != NULL)
543
return g_strdup (key->hard_coded);
544
else if (key->custom_path != NULL) {
547
settings = g_hash_table_lookup (manager->priv->custom_settings,
549
return g_settings_get_string (settings, "binding");
551
g_assert_not_reached ();
555
ensure_cancellable (GCancellable **cancellable)
557
if (*cancellable == NULL) {
558
*cancellable = g_cancellable_new ();
559
g_object_add_weak_pointer (G_OBJECT (*cancellable),
560
(gpointer *)cancellable);
562
g_object_ref (*cancellable);
567
show_osd (GsdMediaKeysManager *manager,
572
GVariantBuilder builder;
574
if (manager->priv->shell_proxy == NULL)
577
g_variant_builder_init (&builder, G_VARIANT_TYPE_TUPLE);
578
g_variant_builder_open (&builder, G_VARIANT_TYPE_VARDICT);
580
g_variant_builder_add (&builder, "{sv}",
581
"icon", g_variant_new_string (icon));
583
g_variant_builder_add (&builder, "{sv}",
584
"label", g_variant_new_string (label));
586
g_variant_builder_add (&builder, "{sv}",
587
"level", g_variant_new_int32 (level));
588
g_variant_builder_close (&builder);
590
g_dbus_proxy_call (manager->priv->shell_proxy,
592
g_variant_builder_end (&builder),
593
G_DBUS_CALL_FLAGS_NO_AUTO_START,
595
manager->priv->shell_cancellable,
600
get_icon_name_for_volume (gboolean is_mic,
604
static const char *icon_names[] = {
605
"audio-volume-muted-symbolic",
606
"audio-volume-low-symbolic",
607
"audio-volume-medium-symbolic",
608
"audio-volume-high-symbolic",
611
static const char *mic_icon_names[] = {
612
"microphone-sensitivity-muted-symbolic",
613
"microphone-sensitivity-low-symbolic",
614
"microphone-sensitivity-medium-symbolic",
615
"microphone-sensitivity-high-symbolic",
624
n = 3 * volume / 100 + 1;
633
return mic_icon_names[n];
635
return icon_names[n];
639
retry_grabs (gpointer data)
641
GsdMediaKeysManager *manager = data;
643
grab_media_keys (manager);
648
grab_accelerators_complete (GObject *object,
649
GAsyncResult *result,
653
gboolean retry = FALSE;
654
GError *error = NULL;
655
GsdMediaKeysManager *manager = user_data;
657
shell_key_grabber_call_grab_accelerators_finish (SHELL_KEY_GRABBER (object),
658
&actions, result, &error);
661
retry = (error->code == G_DBUS_ERROR_UNKNOWN_METHOD);
663
g_warning ("%d: %s", error->code, error->message);
664
g_error_free (error);
667
for (i = 0; i < manager->priv->keys->len; i++) {
670
key = g_ptr_array_index (manager->priv->keys, i);
671
g_variant_get_child (actions, i, "u", &key->accel_id);
676
g_timeout_add_seconds (SHELL_GRABBER_RETRY_INTERVAL,
677
retry_grabs, manager);
681
grab_media_keys (GsdMediaKeysManager *manager)
683
GVariantBuilder builder;
686
g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(su)"));
688
for (i = 0; i < manager->priv->keys->len; i++) {
692
key = g_ptr_array_index (manager->priv->keys, i);
693
tmp = get_key_string (manager, key);
694
g_variant_builder_add (&builder, "(su)", tmp, key->modes);
698
shell_key_grabber_call_grab_accelerators (manager->priv->key_grabber,
699
g_variant_builder_end (&builder),
700
manager->priv->grab_cancellable,
701
grab_accelerators_complete,
706
grab_accelerator_complete (GObject *object,
707
GAsyncResult *result,
710
GrabData *data = user_data;
711
MediaKey *key = data->key;
713
shell_key_grabber_call_grab_accelerator_finish (SHELL_KEY_GRABBER (object),
714
&key->accel_id, result, NULL);
716
g_slice_free (GrabData, data);
720
grab_media_key (MediaKey *key,
721
GsdMediaKeysManager *manager)
726
ungrab_media_key (key, manager);
728
tmp = get_key_string (manager, key);
730
data = g_slice_new0 (GrabData);
731
data->manager = manager;
734
shell_key_grabber_call_grab_accelerator (manager->priv->key_grabber,
736
manager->priv->grab_cancellable,
737
grab_accelerator_complete,
744
grab_media_key_unity (MediaKey *key,
745
GsdMediaKeysManager *manager)
752
if (key->key != NULL) {
754
ungrab_key_unsafe (key->key, manager->priv->screens);
760
tmp = get_key_string (manager, key);
762
key->key = parse_key (tmp);
763
if (key->key == NULL) {
764
print_key_parse_error (key, tmp);
769
grab_key_unsafe (key->key, GSD_KEYGRAB_NORMAL, manager->priv->screens);
777
ungrab_accelerator_complete (GObject *object,
778
GAsyncResult *result,
781
GsdMediaKeysManager *manager = user_data;
782
shell_key_grabber_call_ungrab_accelerator_finish (SHELL_KEY_GRABBER (object),
787
ungrab_media_key (MediaKey *key,
788
GsdMediaKeysManager *manager)
790
if (key->accel_id == 0)
793
shell_key_grabber_call_ungrab_accelerator (manager->priv->key_grabber,
795
manager->priv->grab_cancellable,
796
ungrab_accelerator_complete,
802
gsettings_changed_cb (GSettings *settings,
803
const gchar *settings_key,
804
GsdMediaKeysManager *manager)
807
gboolean need_flush = FALSE;
809
if (manager->priv->have_legacy_keygrabber)
811
/* Give up if we don't have proxy to the shell */
812
else if (!manager->priv->key_grabber)
815
/* handled in gsettings_custom_changed_cb() */
816
if (g_str_equal (settings_key, "custom-keybindings"))
819
if (manager->priv->have_legacy_keygrabber)
820
gdk_error_trap_push ();
822
/* Find the key that was modified */
823
for (i = 0; i < manager->priv->keys->len; i++) {
826
key = g_ptr_array_index (manager->priv->keys, i);
828
/* Skip over hard-coded and GConf keys */
829
if (key->settings_key == NULL)
831
if (strcmp (settings_key, key->settings_key) == 0) {
832
if (!manager->priv->have_legacy_keygrabber)
833
grab_media_key (key, manager);
835
if (grab_media_key_unity (key, manager))
841
if (manager->priv->have_legacy_keygrabber) {
844
if (gdk_error_trap_pop ())
845
g_warning ("Grab failed for some keys, another application may already have access the them.");
850
media_key_new_for_path (GsdMediaKeysManager *manager,
854
char *command, *binding;
857
g_debug ("media_key_new_for_path: %s", path);
859
settings = g_hash_table_lookup (manager->priv->custom_settings, path);
860
if (settings == NULL) {
861
settings = g_settings_new_with_path (CUSTOM_BINDING_SCHEMA, path);
863
g_signal_connect (settings, "changed",
864
G_CALLBACK (custom_binding_changed), manager);
865
g_hash_table_insert (manager->priv->custom_settings,
866
g_strdup (path), settings);
869
command = g_settings_get_string (settings, "command");
870
binding = g_settings_get_string (settings, "binding");
872
if (*command == '\0' && *binding == '\0') {
873
g_debug ("Key binding (%s) is incomplete", path);
880
key = g_new0 (MediaKey, 1);
881
key->key_type = CUSTOM_KEY;
882
key->modes = GSD_KEYBINDING_MODE_LAUNCHER;
883
key->custom_path = g_strdup (path);
884
key->custom_command = command;
890
update_custom_binding (GsdMediaKeysManager *manager,
896
/* Remove the existing key */
897
for (i = 0; i < manager->priv->keys->len; i++) {
898
key = g_ptr_array_index (manager->priv->keys, i);
900
if (key->custom_path == NULL)
902
if (strcmp (key->custom_path, path) == 0) {
903
g_debug ("Removing custom key binding %s", path);
904
ungrab_media_key (key, manager);
905
g_ptr_array_remove_index_fast (manager->priv->keys, i);
910
/* And create a new one! */
911
key = media_key_new_for_path (manager, path);
913
g_debug ("Adding new custom key binding %s", path);
914
g_ptr_array_add (manager->priv->keys, key);
916
grab_media_key (key, manager);
921
custom_binding_changed (GSettings *settings,
922
const char *settings_key,
923
GsdMediaKeysManager *manager)
927
if (strcmp (settings_key, "name") == 0)
928
return; /* we don't care */
930
g_object_get (settings, "path", &path, NULL);
931
update_custom_binding (manager, path);
936
gsettings_custom_changed_cb (GSettings *settings,
937
const char *settings_key,
938
GsdMediaKeysManager *manager)
941
int i, j, n_bindings;
943
bindings = g_settings_get_strv (settings, settings_key);
944
n_bindings = g_strv_length (bindings);
946
/* Handle additions */
947
for (i = 0; i < n_bindings; i++) {
948
if (g_hash_table_lookup (manager->priv->custom_settings,
951
update_custom_binding (manager, bindings[i]);
954
/* Handle removals */
955
for (i = 0; i < manager->priv->keys->len; i++) {
956
gboolean found = FALSE;
957
MediaKey *key = g_ptr_array_index (manager->priv->keys, i);
958
if (key->key_type != CUSTOM_KEY)
961
for (j = 0; j < n_bindings && !found; j++)
962
found = strcmp (bindings[j], key->custom_path) == 0;
967
if (manager->priv->have_legacy_keygrabber && key->key) {
968
gdk_error_trap_push ();
970
ungrab_key_unsafe (key->key,
971
manager->priv->screens);
974
if (gdk_error_trap_pop ())
975
g_warning ("Ungrab failed for custom key '%s'", key->custom_path);
977
ungrab_media_key (key, manager);
978
g_hash_table_remove (manager->priv->custom_settings,
980
g_ptr_array_remove_index_fast (manager->priv->keys, i);
981
--i; /* make up for the removed key */
983
g_strfreev (bindings);
987
add_key (GsdMediaKeysManager *manager, guint i)
991
key = g_new0 (MediaKey, 1);
992
key->key_type = media_keys[i].key_type;
993
key->settings_key = media_keys[i].settings_key;
994
key->hard_coded = media_keys[i].hard_coded;
995
key->modes = media_keys[i].modes;
997
g_ptr_array_add (manager->priv->keys, key);
999
if (manager->priv->have_legacy_keygrabber)
1000
grab_media_key_unity (key, manager);
1004
init_kbd (GsdMediaKeysManager *manager)
1006
char **custom_paths;
1009
gnome_settings_profile_start (NULL);
1011
if (manager->priv->have_legacy_keygrabber)
1012
gdk_error_trap_push ();
1015
* Add hard-coded shortcuts first so that they can't be preempted */
1016
for (i = 0; i < G_N_ELEMENTS (media_keys); i++) {
1017
if (media_keys[i].hard_coded)
1018
add_key (manager, i);
1020
for (i = 0; i < G_N_ELEMENTS (media_keys); i++) {
1021
if (media_keys[i].hard_coded == NULL)
1022
add_key (manager, i);
1025
/* Custom shortcuts */
1026
custom_paths = g_settings_get_strv (manager->priv->settings,
1027
"custom-keybindings");
1029
for (i = 0; i < g_strv_length (custom_paths); i++) {
1032
g_debug ("Setting up custom keybinding %s", custom_paths[i]);
1034
key = media_key_new_for_path (manager, custom_paths[i]);
1038
g_ptr_array_add (manager->priv->keys, key);
1040
if (manager->priv->have_legacy_keygrabber)
1041
grab_media_key_unity (key, manager);
1043
g_strfreev (custom_paths);
1045
if (!manager->priv->have_legacy_keygrabber)
1046
grab_media_keys (manager);
1049
if (gdk_error_trap_pop ())
1050
g_warning ("Grab failed for some keys, another application may already have access the them.");
1053
gnome_settings_profile_end (NULL);
1057
launch_app (GAppInfo *app_info,
1060
GError *error = NULL;
1061
GdkAppLaunchContext *launch_context;
1063
/* setup the launch context so the startup notification is correct */
1064
launch_context = gdk_display_get_app_launch_context (gdk_display_get_default ());
1065
gdk_app_launch_context_set_timestamp (launch_context, timestamp);
1067
if (!g_app_info_launch (app_info, NULL, G_APP_LAUNCH_CONTEXT (launch_context), &error)) {
1068
g_warning ("Could not launch '%s': %s",
1069
g_app_info_get_commandline (app_info),
1071
g_error_free (error);
1073
g_object_unref (launch_context);
1077
do_url_action (GsdMediaKeysManager *manager,
1083
app_info = g_app_info_get_default_for_uri_scheme (scheme);
1084
if (app_info != NULL) {
1085
launch_app (app_info, timestamp);
1086
g_object_unref (app_info);
1088
g_warning ("Could not find default application for '%s' scheme", scheme);
1093
do_media_action (GsdMediaKeysManager *manager,
1098
app_info = g_app_info_get_default_for_type ("audio/x-vorbis+ogg", FALSE);
1099
if (app_info != NULL) {
1100
launch_app (app_info, timestamp);
1101
g_object_unref (app_info);
1103
g_warning ("Could not find default application for '%s' mime-type", "audio/x-vorbis+ogg");
1108
do_terminal_action (GsdMediaKeysManager *manager)
1110
GSettings *settings;
1113
settings = g_settings_new ("org.gnome.desktop.default-applications.terminal");
1114
term = g_settings_get_string (settings, "exec");
1117
execute (manager, term, FALSE);
1120
g_object_unref (settings);
1124
gnome_session_shutdown (GsdMediaKeysManager *manager)
1126
GError *error = NULL;
1130
proxy = gnome_settings_session_get_session_proxy ();
1131
variant = g_dbus_proxy_call_sync (proxy,
1134
G_DBUS_CALL_FLAGS_NONE,
1138
if (variant == NULL) {
1139
g_warning ("Failed to call Shutdown on session manager: %s", error->message);
1140
g_error_free (error);
1143
g_variant_unref (variant);
1144
g_object_unref (proxy);
1148
do_logout_action (GsdMediaKeysManager *manager)
1150
execute (manager, "gnome-session-quit --logout", FALSE);
1154
do_eject_action_cb (GDrive *drive,
1156
GsdMediaKeysManager *manager)
1158
g_drive_eject_with_operation_finish (drive, res, NULL);
1162
#define SCORE_CAN_EJECT 50
1163
#define SCORE_HAS_MEDIA 100
1165
do_eject_action (GsdMediaKeysManager *manager)
1170
GVolumeMonitor *volume_monitor;
1172
volume_monitor = g_volume_monitor_get ();
1175
/* Find the best drive to eject */
1178
drives = g_volume_monitor_get_connected_drives (volume_monitor);
1179
for (l = drives; l != NULL; l = l->next) {
1180
GDrive *drive = l->data;
1182
if (g_drive_can_eject (drive) == FALSE)
1184
if (g_drive_is_media_removable (drive) == FALSE)
1186
if (score < SCORE_CAN_EJECT) {
1188
score = SCORE_CAN_EJECT;
1190
if (g_drive_has_media (drive) == FALSE)
1192
if (score < SCORE_HAS_MEDIA) {
1194
score = SCORE_HAS_MEDIA;
1200
if (!ubuntu_osd_notification_show_icon ("notification-device-eject", "Eject")) {
1201
show_osd (manager, "media-eject-symbolic", NULL, -1);
1204
/* Clean up the drive selection and exit if no suitable
1205
* drives are found */
1206
if (fav_drive != NULL)
1207
fav_drive = g_object_ref (fav_drive);
1209
g_list_foreach (drives, (GFunc) g_object_unref, NULL);
1210
if (fav_drive == NULL)
1214
g_drive_eject_with_operation (fav_drive, G_MOUNT_UNMOUNT_FORCE,
1216
(GAsyncReadyCallback) do_eject_action_cb,
1218
g_object_unref (fav_drive);
1219
g_object_unref (volume_monitor);
1223
do_home_key_action (GsdMediaKeysManager *manager,
1227
GError *error = NULL;
1230
file = g_file_new_for_path (g_get_home_dir ());
1231
uri = g_file_get_uri (file);
1232
g_object_unref (file);
1234
if (gtk_show_uri (NULL, uri, timestamp, &error) == FALSE) {
1235
g_warning ("Failed to launch '%s': %s", uri, error->message);
1236
g_error_free (error);
1242
do_search_action (GsdMediaKeysManager *manager,
1245
g_dbus_proxy_call (manager->priv->shell_proxy,
1248
G_DBUS_CALL_FLAGS_NO_AUTO_START,
1250
manager->priv->shell_cancellable,
1255
do_execute_desktop_or_desktop (GsdMediaKeysManager *manager,
1256
const char *desktop,
1257
const char *alt_desktop,
1260
GDesktopAppInfo *app_info;
1262
app_info = g_desktop_app_info_new (desktop);
1263
if (app_info == NULL)
1264
app_info = g_desktop_app_info_new (alt_desktop);
1266
if (app_info != NULL) {
1267
launch_app (G_APP_INFO (app_info), timestamp);
1268
g_object_unref (app_info);
1272
g_warning ("Could not find application '%s' or '%s'", desktop, alt_desktop);
1276
do_touchpad_osd_action (GsdMediaKeysManager *manager, gboolean state)
1278
if (!ubuntu_osd_notification_show_icon ((!state) ? "touchpad-disabled-symbolic" : "input-touchpad-symbolic", "Touchpad")) {
1279
show_osd (manager, state ? "input-touchpad-symbolic"
1280
: "touchpad-disabled-symbolic", NULL, -1);
1285
do_touchpad_action (GsdMediaKeysManager *manager)
1287
GSettings *settings;
1290
if (touchpad_is_present () == FALSE) {
1291
do_touchpad_osd_action (manager, FALSE);
1295
settings = g_settings_new (SETTINGS_TOUCHPAD_DIR);
1296
state = g_settings_get_boolean (settings, TOUCHPAD_ENABLED_KEY);
1298
do_touchpad_osd_action (manager, !state);
1300
g_settings_set_boolean (settings, TOUCHPAD_ENABLED_KEY, !state);
1301
g_object_unref (settings);
1305
do_lock_screensaver (GsdMediaKeysManager *manager)
1307
GsdMediaKeysManagerPrivate *priv = manager->priv;
1309
if (priv->connection == NULL) {
1310
g_warning ("No existing D-Bus connection trying to handle screensaver lock key");
1313
g_dbus_connection_call (manager->priv->connection,
1319
G_DBUS_CALL_FLAGS_NONE, -1,
1324
update_dialog (GsdMediaKeysManager *manager,
1325
GvcMixerStream *stream,
1328
gboolean sound_changed,
1331
GvcMixerUIDevice *device;
1332
const GvcMixerStreamPort *port;
1335
if (ubuntu_osd_notification_show_volume (manager, vol, muted))
1338
vol = CLAMP (vol, 0, 100);
1340
icon = get_icon_name_for_volume (!GVC_IS_MIXER_SINK (stream), muted, vol);
1341
port = gvc_mixer_stream_get_port (stream);
1342
if (g_strcmp0 (gvc_mixer_stream_get_form_factor (stream), "internal") != 0 ||
1344
g_strcmp0 (port->port, "analog-output-speaker") != 0 &&
1345
g_strcmp0 (port->port, "analog-output") != 0)) {
1346
device = gvc_mixer_control_lookup_device_from_stream (manager->priv->volume, stream);
1347
show_osd (manager, icon,
1348
gvc_mixer_ui_device_get_description (device), vol);
1350
show_osd (manager, icon, NULL, vol);
1354
if (quiet == FALSE && sound_changed != FALSE && muted == FALSE) {
1355
ca_context_change_device (manager->priv->ca,
1356
gvc_mixer_stream_get_name (stream));
1357
ca_context_play (manager->priv->ca, 1,
1358
CA_PROP_EVENT_ID, "audio-volume-change",
1359
CA_PROP_EVENT_DESCRIPTION, "volume changed through key press",
1360
CA_PROP_CANBERRA_CACHE_CONTROL, "permanent",
1366
/* PulseAudio gives us /devices/... paths, when udev
1367
* expects /sys/devices/... paths. */
1368
static GUdevDevice *
1369
get_udev_device_for_sysfs_path (GsdMediaKeysManager *manager,
1370
const char *sysfs_path)
1375
path = g_strdup_printf ("/sys%s", sysfs_path);
1376
dev = g_udev_client_query_by_sysfs_path (manager->priv->udev_client, path);
1382
static GvcMixerStream *
1383
get_stream_for_device_id (GsdMediaKeysManager *manager,
1389
GvcMixerStream *res;
1390
GUdevDevice *dev, *parent;
1391
GSList *streams, *l;
1393
id_ptr = g_hash_table_lookup (manager->priv->streams, GUINT_TO_POINTER (deviceid));
1394
if (id_ptr != NULL) {
1395
if (GPOINTER_TO_UINT (id_ptr) == (guint) -1)
1398
return gvc_mixer_control_lookup_stream_id (manager->priv->volume, GPOINTER_TO_UINT (id_ptr));
1401
devnode = xdevice_get_device_node (deviceid);
1402
if (devnode == NULL) {
1403
g_debug ("Could not find device node for XInput device %d", deviceid);
1407
dev = g_udev_client_query_by_device_file (manager->priv->udev_client, devnode);
1409
g_debug ("Could not find udev device for device path '%s'", devnode);
1415
if (g_strcmp0 (g_udev_device_get_property (dev, "ID_BUS"), "usb") != 0) {
1416
g_debug ("Not handling XInput device %d, not USB", deviceid);
1417
g_hash_table_insert (manager->priv->streams,
1418
GUINT_TO_POINTER (deviceid),
1419
GUINT_TO_POINTER ((guint) -1));
1420
g_object_unref (dev);
1424
parent = g_udev_device_get_parent_with_subsystem (dev, "usb", "usb_device");
1425
if (parent == NULL) {
1426
g_warning ("No USB device parent for XInput device %d even though it's USB", deviceid);
1427
g_object_unref (dev);
1433
streams = gvc_mixer_control_get_sinks (manager->priv->volume);
1435
streams = gvc_mixer_control_get_sources (manager->priv->volume);
1436
for (l = streams; l; l = l->next) {
1437
GvcMixerStream *stream = l->data;
1438
const char *sysfs_path;
1439
GUdevDevice *stream_dev, *stream_parent;
1441
sysfs_path = gvc_mixer_stream_get_sysfs_path (stream);
1442
stream_dev = get_udev_device_for_sysfs_path (manager, sysfs_path);
1443
if (stream_dev == NULL)
1445
stream_parent = g_udev_device_get_parent_with_subsystem (stream_dev, "usb", "usb_device");
1446
g_object_unref (stream_dev);
1447
if (stream_parent == NULL)
1450
if (g_strcmp0 (g_udev_device_get_sysfs_path (stream_parent),
1451
g_udev_device_get_sysfs_path (parent)) == 0) {
1454
g_object_unref (stream_parent);
1459
g_slist_free (streams);
1462
g_hash_table_insert (manager->priv->streams,
1463
GUINT_TO_POINTER (deviceid),
1464
GUINT_TO_POINTER (gvc_mixer_stream_get_id (res)));
1466
g_hash_table_insert (manager->priv->streams,
1467
GUINT_TO_POINTER (deviceid),
1468
GUINT_TO_POINTER ((guint) -1));
1472
#endif /* HAVE_GUDEV */
1475
do_sound_action (GsdMediaKeysManager *manager,
1481
GvcMixerStream *stream;
1482
gboolean old_muted, new_muted;
1483
guint old_vol, new_vol, norm_vol_step, osd_vol;
1484
gboolean sound_changed;
1486
/* Find the stream that corresponds to the device, if any */
1489
stream = get_stream_for_device_id (manager, is_output, deviceid);
1490
#endif /* HAVE_GUDEV */
1492
if (stream == NULL) {
1494
stream = manager->priv->sink;
1496
stream = manager->priv->source;
1502
norm_vol_step = PA_VOLUME_NORM * VOLUME_STEP / 100;
1504
/* FIXME: this is racy */
1505
new_vol = old_vol = gvc_mixer_stream_get_volume (stream);
1506
new_muted = old_muted = gvc_mixer_stream_get_is_muted (stream);
1507
sound_changed = FALSE;
1511
new_muted = !old_muted;
1513
case VOLUME_DOWN_KEY:
1514
if (old_vol <= norm_vol_step) {
1518
new_vol = old_vol - norm_vol_step;
1523
/* When coming out of mute only increase the volume if it was 0 */
1524
if (!old_muted || old_vol == 0)
1525
new_vol = MIN (old_vol + norm_vol_step, MAX_VOLUME);
1529
if (old_muted != new_muted) {
1530
gvc_mixer_stream_change_is_muted (stream, new_muted);
1531
sound_changed = TRUE;
1534
if (old_vol != new_vol) {
1535
if (gvc_mixer_stream_set_volume (stream, new_vol) != FALSE) {
1536
gvc_mixer_stream_push_volume (stream);
1537
sound_changed = TRUE;
1541
if (type == VOLUME_DOWN_KEY && old_vol == 0 && old_muted)
1543
else if (type == VOLUME_UP_KEY && old_vol == PA_VOLUME_NORM && !old_muted)
1545
else if (!new_muted)
1546
osd_vol = (int) (100 * (double) new_vol / PA_VOLUME_NORM);
1550
update_dialog (manager, stream, osd_vol, new_muted, sound_changed, quiet);
1554
sound_theme_changed (GtkSettings *settings,
1556
GsdMediaKeysManager *manager)
1560
g_object_get (G_OBJECT (manager->priv->gtksettings), "gtk-sound-theme-name", &theme_name, NULL);
1562
ca_context_change_props (manager->priv->ca, CA_PROP_CANBERRA_XDG_THEME_NAME, theme_name, NULL);
1563
g_free (theme_name);
1567
update_default_sink (GsdMediaKeysManager *manager)
1569
GvcMixerStream *stream;
1571
stream = gvc_mixer_control_get_default_sink (manager->priv->volume);
1572
if (stream == manager->priv->sink)
1575
g_clear_object (&manager->priv->sink);
1577
if (stream != NULL) {
1578
manager->priv->sink = g_object_ref (stream);
1580
g_warning ("Unable to get default sink");
1585
update_default_source (GsdMediaKeysManager *manager)
1587
GvcMixerStream *stream;
1589
stream = gvc_mixer_control_get_default_source (manager->priv->volume);
1590
if (stream == manager->priv->source)
1593
g_clear_object (&manager->priv->source);
1595
if (stream != NULL) {
1596
manager->priv->source = g_object_ref (stream);
1598
g_warning ("Unable to get default source");
1603
on_control_state_changed (GvcMixerControl *control,
1604
GvcMixerControlState new_state,
1605
GsdMediaKeysManager *manager)
1607
update_default_sink (manager);
1608
update_default_source (manager);
1612
on_control_default_sink_changed (GvcMixerControl *control,
1614
GsdMediaKeysManager *manager)
1616
update_default_sink (manager);
1620
on_control_default_source_changed (GvcMixerControl *control,
1622
GsdMediaKeysManager *manager)
1624
update_default_source (manager);
1629
remove_stream (gpointer key,
1633
if (GPOINTER_TO_UINT (value) == GPOINTER_TO_UINT (id))
1637
#endif /* HAVE_GUDEV */
1640
on_control_stream_removed (GvcMixerControl *control,
1642
GsdMediaKeysManager *manager)
1644
if (manager->priv->sink != NULL) {
1645
if (gvc_mixer_stream_get_id (manager->priv->sink) == id)
1646
g_clear_object (&manager->priv->sink);
1648
if (manager->priv->source != NULL) {
1649
if (gvc_mixer_stream_get_id (manager->priv->source) == id)
1650
g_clear_object (&manager->priv->source);
1654
g_hash_table_foreach_remove (manager->priv->streams, (GHRFunc) remove_stream, GUINT_TO_POINTER (id));
1659
free_media_player (MediaPlayer *player)
1661
if (player->watch_id > 0) {
1662
g_bus_unwatch_name (player->watch_id);
1663
player->watch_id = 0;
1665
g_free (player->application);
1666
g_free (player->dbus_name);
1671
find_by_application (gconstpointer a,
1674
return strcmp (((MediaPlayer *)a)->application, b);
1678
find_by_name (gconstpointer a,
1681
return strcmp (((MediaPlayer *)a)->dbus_name, b);
1685
find_by_time (gconstpointer a,
1688
return ((MediaPlayer *)a)->time < ((MediaPlayer *)b)->time;
1692
name_vanished_handler (GDBusConnection *connection,
1694
GsdMediaKeysManager *manager)
1698
iter = g_list_find_custom (manager->priv->media_players,
1703
MediaPlayer *player;
1705
player = iter->data;
1706
g_debug ("Deregistering vanished %s (dbus_name: %s)", player->application, player->dbus_name);
1707
free_media_player (player);
1708
manager->priv->media_players = g_list_delete_link (manager->priv->media_players, iter);
1713
* Register a new media player. Most applications will want to call
1714
* this with time = GDK_CURRENT_TIME. This way, the last registered
1715
* player will receive media events. In some cases, applications
1716
* may want to register with a lower priority (usually 1), to grab
1717
* events only nobody is interested.
1720
gsd_media_keys_manager_grab_media_player_keys (GsdMediaKeysManager *manager,
1721
const char *application,
1722
const char *dbus_name,
1726
MediaPlayer *media_player;
1729
if (time == GDK_CURRENT_TIME) {
1732
g_get_current_time (&tv);
1733
time = tv.tv_sec * 1000 + tv.tv_usec / 1000;
1736
iter = g_list_find_custom (manager->priv->media_players,
1738
find_by_application);
1741
if (((MediaPlayer *)iter->data)->time < time) {
1742
MediaPlayer *player = iter->data;
1743
free_media_player (player);
1744
manager->priv->media_players = g_list_delete_link (manager->priv->media_players, iter);
1750
watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
1752
G_BUS_NAME_WATCHER_FLAGS_NONE,
1754
(GBusNameVanishedCallback) name_vanished_handler,
1758
g_debug ("Registering %s at %u", application, time);
1759
media_player = g_new0 (MediaPlayer, 1);
1760
media_player->application = g_strdup (application);
1761
media_player->dbus_name = g_strdup (dbus_name);
1762
media_player->time = time;
1763
media_player->watch_id = watch_id;
1765
manager->priv->media_players = g_list_insert_sorted (manager->priv->media_players,
1771
gsd_media_keys_manager_release_media_player_keys (GsdMediaKeysManager *manager,
1772
const char *application,
1777
g_return_if_fail (application != NULL || name != NULL);
1779
if (application != NULL) {
1780
iter = g_list_find_custom (manager->priv->media_players,
1782
find_by_application);
1785
if (iter == NULL && name != NULL) {
1786
iter = g_list_find_custom (manager->priv->media_players,
1792
MediaPlayer *player;
1794
player = iter->data;
1795
g_debug ("Deregistering %s (dbus_name: %s)", application, player->dbus_name);
1796
free_media_player (player);
1797
manager->priv->media_players = g_list_delete_link (manager->priv->media_players, iter);
1802
gsd_media_player_key_pressed (GsdMediaKeysManager *manager,
1805
const char *application;
1806
gboolean have_listeners;
1807
GError *error = NULL;
1808
MediaPlayer *player;
1810
g_return_val_if_fail (key != NULL, FALSE);
1812
g_debug ("Media key '%s' pressed", key);
1814
have_listeners = (manager->priv->media_players != NULL);
1816
if (!have_listeners) {
1817
/* Popup a dialog with an (/) icon */
1818
show_osd (manager, "action-unavailable-symbolic", NULL, -1);
1822
player = manager->priv->media_players->data;
1823
application = player->application;
1825
if (g_dbus_connection_emit_signal (manager->priv->connection,
1827
GSD_MEDIA_KEYS_DBUS_PATH,
1828
GSD_MEDIA_KEYS_DBUS_NAME,
1829
"MediaPlayerKeyPressed",
1830
g_variant_new ("(ss)", application ? application : "", key),
1832
g_debug ("Error emitting signal: %s", error->message);
1833
g_error_free (error);
1836
return !have_listeners;
1840
handle_method_call (GDBusConnection *connection,
1841
const gchar *sender,
1842
const gchar *object_path,
1843
const gchar *interface_name,
1844
const gchar *method_name,
1845
GVariant *parameters,
1846
GDBusMethodInvocation *invocation,
1849
GsdMediaKeysManager *manager = (GsdMediaKeysManager *) user_data;
1851
g_debug ("Calling method '%s' for media-keys", method_name);
1853
if (g_strcmp0 (method_name, "ReleaseMediaPlayerKeys") == 0) {
1854
const char *app_name;
1856
g_variant_get (parameters, "(&s)", &app_name);
1857
gsd_media_keys_manager_release_media_player_keys (manager, app_name, sender);
1858
g_dbus_method_invocation_return_value (invocation, NULL);
1859
} else if (g_strcmp0 (method_name, "GrabMediaPlayerKeys") == 0) {
1860
const char *app_name;
1863
g_variant_get (parameters, "(&su)", &app_name, &time);
1864
gsd_media_keys_manager_grab_media_player_keys (manager, app_name, sender, time);
1865
g_dbus_method_invocation_return_value (invocation, NULL);
1869
static const GDBusInterfaceVTable interface_vtable =
1872
NULL, /* Get Property */
1873
NULL, /* Set Property */
1877
do_multimedia_player_action (GsdMediaKeysManager *manager,
1882
ubuntu_osd_notification_show_icon (icon, key);
1883
return gsd_media_player_key_pressed (manager, key);
1887
on_xrandr_action_call_finished (GObject *source_object,
1889
GsdMediaKeysManager *manager)
1891
GError *error = NULL;
1895
action = g_object_get_data (G_OBJECT (source_object),
1896
"gsd-media-keys-manager-xrandr-action");
1898
variant = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object), res, &error);
1900
g_object_unref (manager->priv->cancellable);
1901
manager->priv->cancellable = NULL;
1903
if (error != NULL) {
1904
g_warning ("Unable to call '%s': %s", action, error->message);
1905
g_error_free (error);
1907
g_variant_unref (variant);
1914
do_xrandr_action (GsdMediaKeysManager *manager,
1918
GsdMediaKeysManagerPrivate *priv = manager->priv;
1920
if (priv->connection == NULL || priv->xrandr_proxy == NULL) {
1921
g_warning ("No existing D-Bus connection trying to handle XRANDR keys");
1925
if (priv->cancellable != NULL) {
1926
g_debug ("xrandr action already in flight");
1930
priv->cancellable = g_cancellable_new ();
1932
g_object_set_data (G_OBJECT (priv->xrandr_proxy),
1933
"gsd-media-keys-manager-xrandr-action",
1936
g_dbus_proxy_call (priv->xrandr_proxy,
1938
g_variant_new ("(x)", timestamp),
1939
G_DBUS_CALL_FLAGS_NONE,
1942
(GAsyncReadyCallback) on_xrandr_action_call_finished,
1947
do_video_out_action (GsdMediaKeysManager *manager,
1950
do_xrandr_action (manager, "VideoModeSwitch", timestamp);
1955
do_video_rotate_action (GsdMediaKeysManager *manager,
1958
do_xrandr_action (manager, "Rotate", timestamp);
1963
do_toggle_accessibility_key (const char *key)
1965
GSettings *settings;
1968
settings = g_settings_new ("org.gnome.desktop.a11y.applications");
1969
state = g_settings_get_boolean (settings, key);
1970
g_settings_set_boolean (settings, key, !state);
1971
g_object_unref (settings);
1975
do_magnifier_action (GsdMediaKeysManager *manager)
1977
do_toggle_accessibility_key ("screen-magnifier-enabled");
1981
do_screenreader_action (GsdMediaKeysManager *manager)
1983
do_toggle_accessibility_key ("screen-reader-enabled");
1987
do_on_screen_keyboard_action (GsdMediaKeysManager *manager)
1989
do_toggle_accessibility_key ("screen-keyboard-enabled");
1993
do_text_size_action (GsdMediaKeysManager *manager,
1996
gdouble factor, best, distance;
1999
/* Same values used in the Seeing tab of the Universal Access panel */
2000
static gdouble factors[] = {
2007
/* Figure out the current DPI scaling factor */
2008
factor = g_settings_get_double (manager->priv->interface_settings, "text-scaling-factor");
2009
factor += (type == INCREASE_TEXT_KEY ? 0.25 : -0.25);
2011
/* Try to find a matching value */
2014
for (i = 0; i < G_N_ELEMENTS(factors); i++) {
2016
d = fabs (factor - factors[i]);
2024
g_settings_reset (manager->priv->interface_settings, "text-scaling-factor");
2026
g_settings_set_double (manager->priv->interface_settings, "text-scaling-factor", best);
2030
do_magnifier_zoom_action (GsdMediaKeysManager *manager,
2033
GSettings *settings;
2034
gdouble offset, value;
2036
if (type == MAGNIFIER_ZOOM_IN_KEY)
2041
settings = g_settings_new ("org.gnome.desktop.a11y.magnifier");
2042
value = g_settings_get_double (settings, "mag-factor");
2044
value = roundl (value);
2045
g_settings_set_double (settings, "mag-factor", value);
2046
g_object_unref (settings);
2050
do_toggle_contrast_action (GsdMediaKeysManager *manager)
2052
gboolean high_contrast;
2055
/* Are we using HighContrast now? */
2056
theme = g_settings_get_string (manager->priv->interface_settings, "gtk-theme");
2057
high_contrast = g_str_equal (theme, HIGH_CONTRAST);
2060
if (high_contrast != FALSE) {
2061
if (manager->priv->gtk_theme == NULL)
2062
g_settings_reset (manager->priv->interface_settings, "gtk-theme");
2064
g_settings_set (manager->priv->interface_settings, "gtk-theme", manager->priv->gtk_theme);
2065
g_settings_set (manager->priv->interface_settings, "icon-theme", manager->priv->icon_theme);
2067
g_settings_set (manager->priv->interface_settings, "gtk-theme", HIGH_CONTRAST);
2068
g_settings_set (manager->priv->interface_settings, "icon-theme", HIGH_CONTRAST);
2073
power_action (GsdMediaKeysManager *manager,
2075
gboolean allow_interaction)
2077
g_dbus_proxy_call (manager->priv->logind_proxy,
2079
g_variant_new ("(b)", allow_interaction),
2080
G_DBUS_CALL_FLAGS_NONE,
2082
manager->priv->bus_cancellable,
2087
do_config_power_action (GsdMediaKeysManager *manager,
2088
const gchar *config_key,
2089
gboolean in_lock_screen)
2091
GsdPowerActionType action_type;
2093
action_type = g_settings_get_enum (manager->priv->power_settings,
2095
switch (action_type) {
2096
case GSD_POWER_ACTION_SUSPEND:
2097
power_action (manager, "Suspend", !in_lock_screen);
2099
case GSD_POWER_ACTION_INTERACTIVE:
2100
if (!in_lock_screen)
2101
gnome_session_shutdown (manager);
2103
case GSD_POWER_ACTION_SHUTDOWN:
2104
power_action (manager, "PowerOff", !in_lock_screen);
2106
case GSD_POWER_ACTION_HIBERNATE:
2107
power_action (manager, "Hibernate", !in_lock_screen);
2109
case GSD_POWER_ACTION_BLANK:
2110
case GSD_POWER_ACTION_NOTHING:
2111
/* these actions cannot be handled by media-keys and
2112
* are not used in this context */
2119
do_switch_input_source_action (GsdMediaKeysManager *manager,
2122
GSettings *settings;
2126
if (!manager->priv->have_legacy_keygrabber)
2129
settings = g_settings_new (GNOME_DESKTOP_INPUT_SOURCES_DIR);
2130
sources = g_settings_get_value (settings, KEY_INPUT_SOURCES);
2132
n = g_variant_n_children (sources);
2136
i = g_settings_get_uint (settings, KEY_CURRENT_INPUT_SOURCE);
2138
if (type == SWITCH_INPUT_SOURCE_KEY)
2148
g_settings_set_uint (settings, KEY_CURRENT_INPUT_SOURCE, i);
2151
g_variant_unref (sources);
2152
g_object_unref (settings);
2156
update_screen_cb (GObject *source_object,
2160
GError *error = NULL;
2162
GVariant *new_percentage;
2163
GsdBrightnessActionData *data = (GsdBrightnessActionData *) user_data;
2164
GsdMediaKeysManager *manager = data->manager;
2166
new_percentage = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
2168
if (new_percentage == NULL) {
2169
g_warning ("Failed to set new screen percentage: %s",
2171
g_error_free (error);
2176
/* update the dialog with the new value */
2177
g_variant_get (new_percentage, "(u)", &percentage);
2178
guint osd_percentage;
2180
if (data->old_percentage == 100 && data->type == SCREEN_BRIGHTNESS_UP_KEY)
2181
osd_percentage = 101;
2182
else if (data->old_percentage == 0 && data->type == SCREEN_BRIGHTNESS_DOWN_KEY)
2183
osd_percentage = -1;
2185
osd_percentage = CLAMP (percentage, 0, 100);
2187
if (!ubuntu_osd_notification_show_brightness (manager, osd_percentage)) {
2188
show_osd (manager, "display-brightness-symbolic", NULL, percentage);
2191
g_variant_unref (new_percentage);
2195
do_screen_brightness_action_real (GObject *source_object,
2199
GsdBrightnessActionData *data = (GsdBrightnessActionData *) user_data;
2200
GsdMediaKeysManager *manager = data->manager;
2201
GError *error = NULL;
2203
GVariant *old_percentage = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
2205
if (old_percentage == NULL) {
2206
g_warning ("Failed to get old screen percentage: %s", error->message);
2207
g_error_free (error);
2212
g_variant_get (old_percentage, "(u)", &data->old_percentage);
2214
/* call into the power plugin */
2215
g_dbus_proxy_call (manager->priv->power_screen_proxy,
2216
data->type == SCREEN_BRIGHTNESS_UP_KEY ? "StepUp" : "StepDown",
2218
G_DBUS_CALL_FLAGS_NONE,
2224
g_variant_unref (old_percentage);
2228
do_screen_brightness_action (GsdMediaKeysManager *manager,
2231
if (manager->priv->connection == NULL ||
2232
manager->priv->power_screen_proxy == NULL) {
2233
g_warning ("No existing D-Bus connection trying to handle power keys");
2237
GsdBrightnessActionData *data = g_new0 (GsdBrightnessActionData, 1);
2238
data->manager = manager;
2241
g_dbus_proxy_call (manager->priv->power_screen_proxy,
2244
G_DBUS_CALL_FLAGS_NONE,
2247
do_screen_brightness_action_real,
2252
update_keyboard_cb (GObject *source_object,
2256
GError *error = NULL;
2258
GVariant *new_percentage;
2259
GsdMediaKeysManager *manager = GSD_MEDIA_KEYS_MANAGER (user_data);
2261
new_percentage = g_dbus_proxy_call_finish (G_DBUS_PROXY (source_object),
2263
if (new_percentage == NULL) {
2264
g_warning ("Failed to set new keyboard percentage: %s",
2266
g_error_free (error);
2270
/* update the dialog with the new value */
2271
g_variant_get (new_percentage, "(u)", &percentage);
2273
/* FIXME: No overshoot effect for keyboard, as the power plugin has no interface
2274
* to get the old brightness */
2275
if (!ubuntu_osd_notification_show_kb_backlight (manager, CLAMP (percentage, 0, 100))) {
2276
show_osd (manager, "keyboard-brightness-symbolic", NULL, percentage);
2278
g_variant_unref (new_percentage);
2282
do_keyboard_brightness_action (GsdMediaKeysManager *manager,
2287
if (manager->priv->connection == NULL ||
2288
manager->priv->power_keyboard_proxy == NULL) {
2289
g_warning ("No existing D-Bus connection trying to handle power keys");
2294
case KEYBOARD_BRIGHTNESS_UP_KEY:
2297
case KEYBOARD_BRIGHTNESS_DOWN_KEY:
2300
case KEYBOARD_BRIGHTNESS_TOGGLE_KEY:
2304
g_assert_not_reached ();
2307
/* call into the power plugin */
2308
g_dbus_proxy_call (manager->priv->power_keyboard_proxy,
2311
G_DBUS_CALL_FLAGS_NONE,
2319
do_battery_action (GsdMediaKeysManager *manager)
2321
GVariant *icon_var, *percentage;
2324
if (manager->priv->power_proxy == NULL)
2327
icon_var = g_dbus_proxy_get_cached_property (manager->priv->power_proxy, "Icon");
2328
percentage = g_dbus_proxy_get_cached_property (manager->priv->power_proxy, "Percentage");
2330
if (g_variant_get_double (percentage) >= 0.0)
2331
label = g_strdup_printf ("%d %%", (int) g_variant_get_double (percentage));
2333
show_osd (manager, g_variant_get_string (icon_var, NULL),
2334
label, g_variant_get_double (percentage));
2338
do_screenshot_action (GsdMediaKeysManager *manager,
2341
if (!manager->priv->have_legacy_keygrabber)
2342
gsd_screenshot_take (type);
2345
case SCREENSHOT_KEY:
2346
execute (manager, "gnome-screenshot", FALSE);
2348
case WINDOW_SCREENSHOT_KEY:
2349
execute (manager, "gnome-screenshot --window", FALSE);
2351
case AREA_SCREENSHOT_KEY:
2352
execute (manager, "gnome-screenshot --area", FALSE);
2354
case SCREENSHOT_CLIP_KEY:
2355
execute (manager, "gnome-screenshot --clipboard", FALSE);
2357
case WINDOW_SCREENSHOT_CLIP_KEY:
2358
execute (manager, "gnome-screenshot --window --clipboard", FALSE);
2360
case AREA_SCREENSHOT_CLIP_KEY:
2361
execute (manager, "gnome-screenshot --area --clipboard", FALSE);
2367
do_custom_action (GsdMediaKeysManager *manager,
2372
g_debug ("Launching custom action for key (on device id %d)", deviceid);
2374
execute (manager, key->custom_command, FALSE);
2378
do_action (GsdMediaKeysManager *manager,
2383
g_debug ("Launching action for key type '%d' (on device id %d)", type, deviceid);
2387
do_touchpad_action (manager);
2389
case TOUCHPAD_ON_KEY:
2390
do_touchpad_osd_action (manager, TRUE);
2392
case TOUCHPAD_OFF_KEY:
2393
do_touchpad_osd_action (manager, FALSE);
2396
case VOLUME_DOWN_KEY:
2398
do_sound_action (manager, deviceid, type, TRUE, FALSE);
2401
do_sound_action (manager, deviceid, MUTE_KEY, FALSE, TRUE);
2403
case MUTE_QUIET_KEY:
2404
do_sound_action (manager, deviceid, MUTE_KEY, TRUE, TRUE);
2406
case VOLUME_DOWN_QUIET_KEY:
2407
do_sound_action (manager, deviceid, VOLUME_DOWN_KEY, TRUE, TRUE);
2409
case VOLUME_UP_QUIET_KEY:
2410
do_sound_action (manager, deviceid, VOLUME_UP_KEY, TRUE, TRUE);
2413
do_logout_action (manager);
2416
do_eject_action (manager);
2419
do_home_key_action (manager, timestamp);
2422
do_search_action (manager, timestamp);
2425
do_url_action (manager, "mailto", timestamp);
2427
case SCREENSAVER_KEY:
2428
do_lock_screensaver (manager);
2431
do_url_action (manager, "ghelp", timestamp);
2433
case SCREENSHOT_KEY:
2434
case SCREENSHOT_CLIP_KEY:
2435
case WINDOW_SCREENSHOT_KEY:
2436
case WINDOW_SCREENSHOT_CLIP_KEY:
2437
case AREA_SCREENSHOT_KEY:
2438
case AREA_SCREENSHOT_CLIP_KEY:
2439
do_screenshot_action (manager, type);
2442
do_terminal_action (manager);
2445
do_url_action (manager, "http", timestamp);
2448
do_media_action (manager, timestamp);
2450
case CALCULATOR_KEY:
2451
do_execute_desktop_or_desktop (manager, "gcalctool.desktop", "gnome-calculator.desktop", timestamp);
2454
return do_multimedia_player_action (manager, NULL, "Play");
2456
return do_multimedia_player_action (manager, NULL, "Pause");
2458
return do_multimedia_player_action (manager, NULL, "Stop");
2460
return do_multimedia_player_action (manager, NULL, "Previous");
2462
return do_multimedia_player_action (manager, NULL, "Next");
2464
return do_multimedia_player_action (manager, NULL, "Rewind");
2466
return do_multimedia_player_action (manager, NULL, "FastForward");
2468
return do_multimedia_player_action (manager, NULL, "Repeat");
2470
return do_multimedia_player_action (manager, NULL, "Shuffle");
2472
do_video_out_action (manager, timestamp);
2474
case ROTATE_VIDEO_KEY:
2475
do_video_rotate_action (manager, timestamp);
2478
do_magnifier_action (manager);
2480
case SCREENREADER_KEY:
2481
do_screenreader_action (manager);
2483
case ON_SCREEN_KEYBOARD_KEY:
2484
do_on_screen_keyboard_action (manager);
2486
case INCREASE_TEXT_KEY:
2487
case DECREASE_TEXT_KEY:
2488
do_text_size_action (manager, type);
2490
case MAGNIFIER_ZOOM_IN_KEY:
2491
case MAGNIFIER_ZOOM_OUT_KEY:
2492
do_magnifier_zoom_action (manager, type);
2494
case TOGGLE_CONTRAST_KEY:
2495
do_toggle_contrast_action (manager);
2498
do_config_power_action (manager, "button-power", FALSE);
2501
do_config_power_action (manager, "button-sleep", FALSE);
2504
do_config_power_action (manager, "button-suspend", FALSE);
2507
do_config_power_action (manager, "button-hibernate", FALSE);
2509
case POWER_KEY_NO_DIALOG:
2510
do_config_power_action (manager, "button-power", TRUE);
2512
case SLEEP_KEY_NO_DIALOG:
2513
do_config_power_action (manager, "button-sleep", TRUE);
2515
case SUSPEND_KEY_NO_DIALOG:
2516
do_config_power_action (manager, "button-suspend", TRUE);
2518
case HIBERNATE_KEY_NO_DIALOG:
2519
do_config_power_action (manager, "button-hibernate", TRUE);
2521
case SCREEN_BRIGHTNESS_UP_KEY:
2522
case SCREEN_BRIGHTNESS_DOWN_KEY:
2523
do_screen_brightness_action (manager, type);
2525
case KEYBOARD_BRIGHTNESS_UP_KEY:
2526
case KEYBOARD_BRIGHTNESS_DOWN_KEY:
2527
case KEYBOARD_BRIGHTNESS_TOGGLE_KEY:
2528
do_keyboard_brightness_action (manager, type);
2531
do_battery_action (manager);
2533
case SWITCH_INPUT_SOURCE_KEY:
2534
case SWITCH_INPUT_SOURCE_BACKWARD_KEY:
2535
do_switch_input_source_action (manager, type);
2537
/* Note, no default so compiler catches missing keys */
2539
g_assert_not_reached ();
2546
get_screen_from_root (GsdMediaKeysManager *manager,
2551
/* Look for which screen we're receiving events */
2552
for (l = manager->priv->screens; l != NULL; l = l->next) {
2553
GdkScreen *screen = (GdkScreen *) l->data;
2554
GdkWindow *window = gdk_screen_get_root_window (screen);
2556
if (GDK_WINDOW_XID (window) == root)
2563
static GdkFilterReturn
2564
filter_key_events (XEvent *xevent,
2566
GsdMediaKeysManager *manager)
2568
static gboolean ok_to_switch = TRUE;
2572
XGenericEventCookie *cookie;
2576
/* verify we have a key event */
2577
if (xevent->type != GenericEvent)
2578
return GDK_FILTER_CONTINUE;
2579
cookie = &xevent->xcookie;
2580
if (cookie->extension != manager->priv->opcode)
2581
return GDK_FILTER_CONTINUE;
2583
xiev = (XIEvent *) xevent->xcookie.data;
2585
if (xiev->evtype != XI_KeyPress &&
2586
xiev->evtype != XI_KeyRelease)
2587
return GDK_FILTER_CONTINUE;
2589
xev = (XIDeviceEvent *) xiev;
2591
deviceid = xev->sourceid;
2593
if (xiev->evtype == XI_KeyPress)
2594
ok_to_switch = TRUE;
2596
for (i = 0; i < manager->priv->keys->len; i++) {
2599
key = g_ptr_array_index (manager->priv->keys, i);
2601
if (match_xi2_key (key->key, xev)) {
2602
switch (key->key_type) {
2603
case VOLUME_DOWN_KEY:
2605
case VOLUME_DOWN_QUIET_KEY:
2606
case VOLUME_UP_QUIET_KEY:
2607
case SCREEN_BRIGHTNESS_UP_KEY:
2608
case SCREEN_BRIGHTNESS_DOWN_KEY:
2609
case KEYBOARD_BRIGHTNESS_UP_KEY:
2610
case KEYBOARD_BRIGHTNESS_DOWN_KEY:
2611
/* auto-repeatable keys */
2612
if (xiev->evtype != XI_KeyPress)
2613
return GDK_FILTER_CONTINUE;
2616
if (xiev->evtype != XI_KeyRelease) {
2617
return GDK_FILTER_CONTINUE;
2621
manager->priv->current_screen = get_screen_from_root (manager, xev->root);
2623
if (key->key_type == CUSTOM_KEY) {
2624
do_custom_action (manager, deviceid, key, xev->time);
2625
return GDK_FILTER_REMOVE;
2628
if (key->key_type == SWITCH_INPUT_SOURCE_KEY || key->key_type == SWITCH_INPUT_SOURCE_BACKWARD_KEY) {
2630
do_action (manager, deviceid, key->key_type, xev->time);
2631
ok_to_switch = FALSE;
2634
return GDK_FILTER_CONTINUE;
2637
if (do_action (manager, deviceid, key->key_type, xev->time) == FALSE) {
2638
return GDK_FILTER_REMOVE;
2640
return GDK_FILTER_CONTINUE;
2645
return GDK_FILTER_CONTINUE;
2649
on_accelerator_activated (ShellKeyGrabber *grabber,
2652
GsdMediaKeysManager *manager)
2656
for (i = 0; i < manager->priv->keys->len; i++) {
2659
key = g_ptr_array_index (manager->priv->keys, i);
2661
if (key->accel_id != accel_id)
2664
if (key->key_type == CUSTOM_KEY)
2665
do_custom_action (manager, deviceid, key, GDK_CURRENT_TIME);
2667
do_action (manager, deviceid, key->key_type, GDK_CURRENT_TIME);
2673
update_theme_settings (GSettings *settings,
2675
GsdMediaKeysManager *manager)
2679
theme = g_settings_get_string (manager->priv->interface_settings, key);
2680
if (g_str_equal (theme, HIGH_CONTRAST)) {
2683
if (g_str_equal (key, "gtk-theme")) {
2684
g_free (manager->priv->gtk_theme);
2685
manager->priv->gtk_theme = theme;
2687
g_free (manager->priv->icon_theme);
2688
manager->priv->icon_theme = theme;
2694
initialize_volume_handler (GsdMediaKeysManager *manager)
2696
/* initialise Volume handler
2698
* We do this one here to force checking gstreamer cache, etc.
2699
* The rest (grabbing and setting the keys) can happen in an
2702
gnome_settings_profile_start ("gvc_mixer_control_new");
2704
manager->priv->volume = gvc_mixer_control_new ("GNOME Volume Control Media Keys");
2706
g_signal_connect (manager->priv->volume,
2708
G_CALLBACK (on_control_state_changed),
2710
g_signal_connect (manager->priv->volume,
2711
"default-sink-changed",
2712
G_CALLBACK (on_control_default_sink_changed),
2714
g_signal_connect (manager->priv->volume,
2715
"default-source-changed",
2716
G_CALLBACK (on_control_default_source_changed),
2718
g_signal_connect (manager->priv->volume,
2720
G_CALLBACK (on_control_stream_removed),
2723
gvc_mixer_control_open (manager->priv->volume);
2725
gnome_settings_profile_end ("gvc_mixer_control_new");
2729
on_shell_proxy_ready (GObject *source,
2730
GAsyncResult *result,
2733
GsdMediaKeysManager *manager = data;
2735
manager->priv->shell_proxy =
2736
g_dbus_proxy_new_for_bus_finish (result, NULL);
2740
on_key_grabber_ready (GObject *source,
2741
GAsyncResult *result,
2744
GsdMediaKeysManager *manager = data;
2746
manager->priv->key_grabber =
2747
shell_key_grabber_proxy_new_for_bus_finish (result, NULL);
2749
if (!manager->priv->key_grabber)
2752
g_signal_connect (manager->priv->key_grabber, "accelerator-activated",
2753
G_CALLBACK (on_accelerator_activated), manager);
2759
on_shell_appeared (GDBusConnection *connection,
2761
const char *name_owner,
2764
if (g_strcmp0 (g_getenv ("DESKTOP_SESSION"), "gnome") != 0)
2767
GsdMediaKeysManager *manager = user_data;
2769
shell_key_grabber_proxy_new_for_bus (G_BUS_TYPE_SESSION,
2773
manager->priv->grab_cancellable,
2774
on_key_grabber_ready, manager);
2776
g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
2781
manager->priv->shell_cancellable,
2782
on_shell_proxy_ready, manager);
2786
on_shell_vanished (GDBusConnection *connection,
2790
if (g_strcmp0 (g_getenv ("DESKTOP_SESSION"), "gnome") != 0)
2793
GsdMediaKeysManager *manager = user_data;
2795
g_ptr_array_set_size (manager->priv->keys, 0);
2797
g_clear_object (&manager->priv->key_grabber);
2798
g_clear_object (&manager->priv->shell_proxy);
2802
start_legacy_grabber (GDBusConnection *connection,
2804
const char *name_owner,
2807
GsdMediaKeysManager *manager = user_data;
2810
if (g_strcmp0 (g_getenv ("DESKTOP_SESSION"), "gnome") == 0)
2813
manager->priv->have_legacy_keygrabber = TRUE;
2815
g_debug ("start_legacy_grabber");
2817
if (manager->priv->keys == NULL)
2823
init_screens (manager);
2826
/* Start filtering the events */
2827
for (l = manager->priv->screens; l != NULL; l = l->next) {
2828
gnome_settings_profile_start ("gdk_window_add_filter");
2830
g_debug ("adding key filter for screen: %d",
2831
gdk_screen_get_number (l->data));
2833
gdk_window_add_filter (gdk_screen_get_root_window (l->data),
2834
(GdkFilterFunc) filter_key_events,
2836
gnome_settings_profile_end ("gdk_window_add_filter");
2841
stop_legacy_grabber (GDBusConnection *connection,
2845
GsdMediaKeysManager *manager = user_data;
2847
if (g_strcmp0 (g_getenv ("DESKTOP_SESSION"), "gnome") == 0)
2850
manager->priv->have_legacy_keygrabber = FALSE;
2852
g_ptr_array_set_size (manager->priv->keys, 0);
2856
start_media_keys_idle_cb (GsdMediaKeysManager *manager)
2860
g_debug ("Starting media_keys manager");
2861
gnome_settings_profile_start (NULL);
2863
manager->priv->keys = g_ptr_array_new_with_free_func ((GDestroyNotify) media_key_free);
2865
initialize_volume_handler (manager);
2867
manager->priv->settings = g_settings_new (SETTINGS_BINDING_DIR);
2868
g_signal_connect (G_OBJECT (manager->priv->settings), "changed",
2869
G_CALLBACK (gsettings_changed_cb), manager);
2870
g_signal_connect (G_OBJECT (manager->priv->settings), "changed::custom-keybindings",
2871
G_CALLBACK (gsettings_custom_changed_cb), manager);
2873
manager->priv->input_settings = g_settings_new (INPUT_SETTINGS_BINDING_DIR);
2874
g_signal_connect (G_OBJECT (manager->priv->input_settings), "changed",
2875
G_CALLBACK (gsettings_changed_cb), manager);
2876
g_signal_connect (G_OBJECT (manager->priv->input_settings), "changed::custom-keybindings",
2877
G_CALLBACK (gsettings_custom_changed_cb), manager);
2879
manager->priv->custom_settings =
2880
g_hash_table_new_full (g_str_hash, g_str_equal,
2881
g_free, g_object_unref);
2884
ca_context_create (&manager->priv->ca);
2885
ca_context_set_driver (manager->priv->ca, "pulse");
2886
ca_context_change_props (manager->priv->ca, 0,
2887
CA_PROP_APPLICATION_ID, "org.gnome.VolumeControl",
2889
manager->priv->gtksettings = gtk_settings_get_for_screen (gdk_screen_get_default ());
2890
g_object_get (G_OBJECT (manager->priv->gtksettings), "gtk-sound-theme-name", &theme_name, NULL);
2892
ca_context_change_props (manager->priv->ca, CA_PROP_CANBERRA_XDG_THEME_NAME, theme_name, NULL);
2893
g_free (theme_name);
2894
g_signal_connect (manager->priv->gtksettings, "notify::gtk-sound-theme-name",
2895
G_CALLBACK (sound_theme_changed), manager);
2897
/* for the power plugin interface code */
2898
manager->priv->power_settings = g_settings_new (SETTINGS_POWER_DIR);
2900
/* Logic from http://git.gnome.org/browse/gnome-shell/tree/js/ui/status/accessibility.js#n163 */
2901
manager->priv->interface_settings = g_settings_new (SETTINGS_INTERFACE_DIR);
2902
g_signal_connect (G_OBJECT (manager->priv->interface_settings), "changed::gtk-theme",
2903
G_CALLBACK (update_theme_settings), manager);
2904
g_signal_connect (G_OBJECT (manager->priv->interface_settings), "changed::icon-theme",
2905
G_CALLBACK (update_theme_settings), manager);
2906
manager->priv->gtk_theme = g_settings_get_string (manager->priv->interface_settings, "gtk-theme");
2907
if (g_str_equal (manager->priv->gtk_theme, HIGH_CONTRAST)) {
2908
g_free (manager->priv->gtk_theme);
2909
manager->priv->gtk_theme = NULL;
2911
manager->priv->icon_theme = g_settings_get_string (manager->priv->interface_settings, "icon-theme");
2914
ensure_cancellable (&manager->priv->grab_cancellable);
2915
ensure_cancellable (&manager->priv->shell_cancellable);
2917
manager->priv->name_owner_id =
2918
g_bus_watch_name (G_BUS_TYPE_SESSION,
2924
manager->priv->unity_name_owner_id =
2925
g_bus_watch_name (G_BUS_TYPE_SESSION,
2927
start_legacy_grabber,
2928
stop_legacy_grabber,
2931
manager->priv->panel_name_owner_id =
2932
g_bus_watch_name (G_BUS_TYPE_SESSION,
2934
start_legacy_grabber,
2935
stop_legacy_grabber,
2938
gnome_settings_profile_end (NULL);
2940
manager->priv->start_idle_id = 0;
2946
gsd_media_keys_manager_start (GsdMediaKeysManager *manager,
2949
const char * const subsystems[] = { "input", "usb", "sound", NULL };
2951
gnome_settings_profile_start (NULL);
2953
if (supports_xinput2_devices (&manager->priv->opcode) == FALSE) {
2954
g_debug ("No Xinput2 support, disabling plugin");
2959
manager->priv->streams = g_hash_table_new (g_direct_hash, g_direct_equal);
2960
manager->priv->udev_client = g_udev_client_new (subsystems);
2963
manager->priv->start_idle_id = g_idle_add ((GSourceFunc) start_media_keys_idle_cb, manager);
2965
register_manager (manager_object);
2967
gnome_settings_profile_end (NULL);
2973
gsd_media_keys_manager_stop (GsdMediaKeysManager *manager)
2975
GsdMediaKeysManagerPrivate *priv = manager->priv;
2979
g_debug ("Stopping media_keys manager");
2981
if (priv->bus_cancellable != NULL) {
2982
g_cancellable_cancel (priv->bus_cancellable);
2983
g_object_unref (priv->bus_cancellable);
2984
priv->bus_cancellable = NULL;
2987
if (manager->priv->have_legacy_keygrabber){
2988
for (ls = priv->screens; ls != NULL; ls = ls->next) {
2989
gdk_window_remove_filter (gdk_screen_get_root_window (ls->data),
2990
(GdkFilterFunc) filter_key_events,
2995
if (manager->priv->gtksettings != NULL) {
2996
g_signal_handlers_disconnect_by_func (manager->priv->gtksettings, sound_theme_changed, manager);
2997
manager->priv->gtksettings = NULL;
3000
g_clear_pointer (&manager->priv->ca, ca_context_destroy);
3003
g_clear_pointer (&priv->streams, g_hash_table_destroy);
3004
g_clear_object (&priv->udev_client);
3005
#endif /* HAVE_GUDEV */
3007
g_clear_object (&priv->logind_proxy);
3008
g_clear_object (&priv->settings);
3009
g_clear_object (&priv->input_settings);
3010
g_clear_object (&priv->power_settings);
3011
g_clear_object (&priv->power_proxy);
3012
g_clear_object (&priv->power_screen_proxy);
3013
g_clear_object (&priv->power_keyboard_proxy);
3015
if (manager->priv->name_owner_id) {
3016
g_bus_unwatch_name (manager->priv->name_owner_id);
3017
manager->priv->name_owner_id = 0;
3020
if (manager->priv->unity_name_owner_id) {
3021
g_bus_unwatch_name (manager->priv->unity_name_owner_id);
3022
manager->priv->unity_name_owner_id = 0;
3025
if (manager->priv->panel_name_owner_id) {
3026
g_bus_unwatch_name (manager->priv->panel_name_owner_id);
3027
manager->priv->panel_name_owner_id = 0;
3030
if (priv->cancellable != NULL) {
3031
g_cancellable_cancel (priv->cancellable);
3032
g_clear_object (&priv->cancellable);
3035
g_clear_pointer (&priv->introspection_data, g_dbus_node_info_unref);
3036
g_clear_object (&priv->connection);
3038
if (priv->volume_notification != NULL) {
3039
notify_notification_close (priv->volume_notification, NULL);
3040
g_object_unref (priv->volume_notification);
3041
priv->volume_notification = NULL;
3044
if (priv->brightness_notification != NULL) {
3045
notify_notification_close (priv->brightness_notification, NULL);
3046
g_object_unref (priv->brightness_notification);
3047
priv->brightness_notification = NULL;
3050
if (priv->kb_backlight_notification != NULL) {
3051
notify_notification_close (priv->kb_backlight_notification, NULL);
3052
g_object_unref (priv->kb_backlight_notification);
3053
priv->kb_backlight_notification = NULL;
3056
if (priv->keys != NULL) {
3057
if (manager->priv->have_legacy_keygrabber)
3058
gdk_error_trap_push ();
3059
for (i = 0; i < priv->keys->len; ++i) {
3062
key = g_ptr_array_index (manager->priv->keys, i);
3063
if (manager->priv->have_legacy_keygrabber && key->key)
3064
ungrab_key_unsafe (key->key, priv->screens);
3066
ungrab_media_key (key, manager);
3068
g_ptr_array_free (priv->keys, TRUE);
3072
if (manager->priv->have_legacy_keygrabber){
3074
gdk_error_trap_pop_ignored ();
3077
if (priv->grab_cancellable != NULL) {
3078
g_cancellable_cancel (priv->grab_cancellable);
3079
g_clear_object (&priv->grab_cancellable);
3082
if (priv->shell_cancellable != NULL) {
3083
g_cancellable_cancel (priv->shell_cancellable);
3084
g_clear_object (&priv->shell_cancellable);
3087
g_clear_pointer (&priv->screens, g_slist_free);
3088
g_clear_object (&priv->sink);
3089
g_clear_object (&priv->source);
3090
g_clear_object (&priv->volume);
3092
if (priv->media_players != NULL) {
3093
g_list_free_full (priv->media_players, (GDestroyNotify) free_media_player);
3094
priv->media_players = NULL;
3099
gsd_media_keys_manager_constructor (GType type,
3100
guint n_construct_properties,
3101
GObjectConstructParam *construct_properties)
3103
GsdMediaKeysManager *media_keys_manager;
3105
media_keys_manager = GSD_MEDIA_KEYS_MANAGER (G_OBJECT_CLASS (gsd_media_keys_manager_parent_class)->constructor (type,
3106
n_construct_properties,
3107
construct_properties));
3109
return G_OBJECT (media_keys_manager);
3113
gsd_media_keys_manager_class_init (GsdMediaKeysManagerClass *klass)
3115
GObjectClass *object_class = G_OBJECT_CLASS (klass);
3117
object_class->constructor = gsd_media_keys_manager_constructor;
3118
object_class->finalize = gsd_media_keys_manager_finalize;
3120
g_type_class_add_private (klass, sizeof (GsdMediaKeysManagerPrivate));
3124
inhibit_done (GObject *source,
3125
GAsyncResult *result,
3128
GDBusProxy *proxy = G_DBUS_PROXY (source);
3129
GsdMediaKeysManager *manager = GSD_MEDIA_KEYS_MANAGER (user_data);
3130
GError *error = NULL;
3132
GUnixFDList *fd_list = NULL;
3135
res = g_dbus_proxy_call_with_unix_fd_list_finish (proxy, &fd_list, result, &error);
3137
g_warning ("Unable to inhibit keypresses: %s", error->message);
3138
g_error_free (error);
3140
g_variant_get (res, "(h)", &idx);
3141
manager->priv->inhibit_keys_fd = g_unix_fd_list_get (fd_list, idx, &error);
3142
if (manager->priv->inhibit_keys_fd == -1) {
3143
g_warning ("Failed to receive system inhibitor fd: %s", error->message);
3144
g_error_free (error);
3146
g_debug ("System inhibitor fd is %d", manager->priv->inhibit_keys_fd);
3147
g_object_unref (fd_list);
3148
g_variant_unref (res);
3153
gsd_media_keys_manager_init (GsdMediaKeysManager *manager)
3156
GDBusConnection *bus;
3159
manager->priv = GSD_MEDIA_KEYS_MANAGER_GET_PRIVATE (manager);
3161
bus = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &error);
3163
g_warning ("Failed to connect to system bus: %s",
3165
g_error_free (error);
3169
manager->priv->logind_proxy =
3170
g_dbus_proxy_new_sync (bus,
3175
SYSTEMD_DBUS_INTERFACE,
3179
if (manager->priv->logind_proxy == NULL) {
3180
g_warning ("Failed to connect to systemd: %s",
3182
g_error_free (error);
3185
g_object_unref (bus);
3187
g_debug ("Adding system inhibitors for power keys");
3188
manager->priv->inhibit_keys_fd = -1;
3189
g_dbus_proxy_call_with_unix_fd_list (manager->priv->logind_proxy,
3191
g_variant_new ("(ssss)",
3192
"handle-power-key:handle-suspend-key:handle-hibernate-key",
3194
"GNOME handling keypresses",
3206
gsd_media_keys_manager_finalize (GObject *object)
3208
GsdMediaKeysManager *media_keys_manager;
3210
g_return_if_fail (object != NULL);
3211
g_return_if_fail (GSD_IS_MEDIA_KEYS_MANAGER (object));
3213
media_keys_manager = GSD_MEDIA_KEYS_MANAGER (object);
3215
g_return_if_fail (media_keys_manager->priv != NULL);
3217
if (media_keys_manager->priv->start_idle_id != 0)
3218
g_source_remove (media_keys_manager->priv->start_idle_id);
3219
if (media_keys_manager->priv->inhibit_keys_fd != -1)
3220
close (media_keys_manager->priv->inhibit_keys_fd);
3222
G_OBJECT_CLASS (gsd_media_keys_manager_parent_class)->finalize (object);
3226
xrandr_ready_cb (GObject *source_object,
3228
GsdMediaKeysManager *manager)
3230
GError *error = NULL;
3232
manager->priv->xrandr_proxy = g_dbus_proxy_new_finish (res, &error);
3233
if (manager->priv->xrandr_proxy == NULL) {
3234
g_warning ("Failed to get proxy for XRandR operations: %s", error->message);
3235
g_error_free (error);
3240
power_ready_cb (GObject *source_object,
3242
GsdMediaKeysManager *manager)
3244
GError *error = NULL;
3246
manager->priv->power_proxy = g_dbus_proxy_new_finish (res, &error);
3247
if (manager->priv->power_proxy == NULL) {
3248
g_warning ("Failed to get proxy for power: %s",
3250
g_error_free (error);
3255
power_screen_ready_cb (GObject *source_object,
3257
GsdMediaKeysManager *manager)
3259
GError *error = NULL;
3261
manager->priv->power_screen_proxy = g_dbus_proxy_new_finish (res, &error);
3262
if (manager->priv->power_screen_proxy == NULL) {
3263
g_warning ("Failed to get proxy for power (screen): %s",
3265
g_error_free (error);
3270
power_keyboard_ready_cb (GObject *source_object,
3272
GsdMediaKeysManager *manager)
3274
GError *error = NULL;
3276
manager->priv->power_keyboard_proxy = g_dbus_proxy_new_finish (res, &error);
3277
if (manager->priv->power_keyboard_proxy == NULL) {
3278
g_warning ("Failed to get proxy for power (keyboard): %s",
3280
g_error_free (error);
3285
on_bus_gotten (GObject *source_object,
3287
GsdMediaKeysManager *manager)
3289
GDBusConnection *connection;
3290
GError *error = NULL;
3292
if (manager->priv->bus_cancellable == NULL ||
3293
g_cancellable_is_cancelled (manager->priv->bus_cancellable)) {
3294
g_warning ("Operation has been cancelled, so not retrieving session bus");
3298
connection = g_bus_get_finish (res, &error);
3299
if (connection == NULL) {
3300
g_warning ("Could not get session bus: %s", error->message);
3301
g_error_free (error);
3304
manager->priv->connection = connection;
3306
g_dbus_connection_register_object (connection,
3307
GSD_MEDIA_KEYS_DBUS_PATH,
3308
manager->priv->introspection_data->interfaces[0],
3314
g_dbus_proxy_new (manager->priv->connection,
3315
G_DBUS_PROXY_FLAGS_NONE,
3317
GSD_DBUS_NAME ".XRANDR",
3318
GSD_DBUS_PATH "/XRANDR",
3319
GSD_DBUS_BASE_INTERFACE ".XRANDR_2",
3321
(GAsyncReadyCallback) xrandr_ready_cb,
3324
g_dbus_proxy_new (manager->priv->connection,
3325
G_DBUS_PROXY_FLAGS_NONE,
3327
GSD_DBUS_NAME ".Power",
3328
GSD_DBUS_PATH "/Power",
3329
GSD_DBUS_BASE_INTERFACE ".Power",
3331
(GAsyncReadyCallback) power_ready_cb,
3334
g_dbus_proxy_new (manager->priv->connection,
3335
G_DBUS_PROXY_FLAGS_NONE,
3337
GSD_DBUS_NAME ".Power",
3338
GSD_DBUS_PATH "/Power",
3339
GSD_DBUS_BASE_INTERFACE ".Power.Screen",
3341
(GAsyncReadyCallback) power_screen_ready_cb,
3344
g_dbus_proxy_new (manager->priv->connection,
3345
G_DBUS_PROXY_FLAGS_NONE,
3347
GSD_DBUS_NAME ".Power",
3348
GSD_DBUS_PATH "/Power",
3349
GSD_DBUS_BASE_INTERFACE ".Power.Keyboard",
3351
(GAsyncReadyCallback) power_keyboard_ready_cb,
3356
register_manager (GsdMediaKeysManager *manager)
3358
manager->priv->introspection_data = g_dbus_node_info_new_for_xml (introspection_xml, NULL);
3359
manager->priv->bus_cancellable = g_cancellable_new ();
3360
g_assert (manager->priv->introspection_data != NULL);
3362
g_bus_get (G_BUS_TYPE_SESSION,
3363
manager->priv->bus_cancellable,
3364
(GAsyncReadyCallback) on_bus_gotten,
3368
GsdMediaKeysManager *
3369
gsd_media_keys_manager_new (void)
3371
if (manager_object != NULL) {
3372
g_object_ref (manager_object);
3374
manager_object = g_object_new (GSD_TYPE_MEDIA_KEYS_MANAGER, NULL);
3375
g_object_add_weak_pointer (manager_object,
3376
(gpointer *) &manager_object);
3379
return GSD_MEDIA_KEYS_MANAGER (manager_object);