[gnome-settings-daemon] media-keys: Add support for Killswitch media keys



commit 3fa0f7260a6864dfe67bdbd82b22b168e1e66457
Author: Bastien Nocera <hadess hadess net>
Date:   Fri Jan 8 04:11:02 2016 +0100

    media-keys: Add support for Killswitch media keys
    
    Add support for the XF86Bluetooth, XF86WLAN and XF86UWB media keys.
    The first one will toggle Bluetooth on/off, as the Bluetooth panel does,
    the latter ones will toggle the global software killswitch.
    
    The reasoning behind those 2 keys toggling the global software
    killswitch is that:
    - we don't have a killswitch for only WiFi
    - there are very very few laptops with a UWB killswitch button, if
      anyone actually remembers what UWB actually is
    - there are no XF86 keys for the global killswitch, so they usually get
      mislabeled as the WLAN killswitch
    
    https://bugzilla.gnome.org/show_bug.cgi?id=661643

 plugins/media-keys/gsd-media-keys-manager.c |  158 +++++++++++++++++++++++++++
 plugins/media-keys/media-keys.h             |    2 +
 plugins/media-keys/shortcuts-list.h         |    3 +
 3 files changed, 163 insertions(+), 0 deletions(-)
---
diff --git a/plugins/media-keys/gsd-media-keys-manager.c b/plugins/media-keys/gsd-media-keys-manager.c
index 917b47c..b688fcc 100644
--- a/plugins/media-keys/gsd-media-keys-manager.c
+++ b/plugins/media-keys/gsd-media-keys-manager.c
@@ -185,6 +185,11 @@ struct GsdMediaKeysManagerPrivate
         guint            orientation_watch_id;
         gboolean         orientation_available;
 
+        /* RFKill stuff */
+        guint            rfkill_watch_id;
+        GDBusProxy      *rfkill_proxy;
+        GCancellable    *rfkill_cancellable;
+
         /* systemd stuff */
         GDBusProxy      *logind_proxy;
         gint             inhibit_keys_fd;
@@ -1979,6 +1984,107 @@ do_battery_action (GsdMediaKeysManager *manager)
         g_free (icon_name);
 }
 
+static gboolean
+get_rfkill_property (GsdMediaKeysManager *manager,
+                     const char          *property)
+{
+        GVariant *v;
+        gboolean ret;
+
+        v = g_dbus_proxy_get_cached_property (manager->priv->rfkill_proxy, property);
+        if (!v)
+                return FALSE;
+        ret = g_variant_get_boolean (v);
+        g_variant_unref (v);
+
+        return ret;
+}
+
+typedef struct {
+        GsdMediaKeysManager *manager;
+        char *property;
+        gboolean bluetooth;
+        gboolean target_state;
+} RfkillData;
+
+static void
+set_rfkill_complete (GObject      *object,
+                     GAsyncResult *result,
+                     gpointer      user_data)
+{
+        GError *error = NULL;
+        GVariant *variant;
+        RfkillData *data = user_data;
+
+        variant = g_dbus_proxy_call_finish (G_DBUS_PROXY (object), result, &error);
+
+        if (variant == NULL) {
+                if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
+                        g_warning ("Failed to set '%s' property: %s", data->property, error->message);
+                g_error_free (error);
+                goto out;
+        }
+        g_variant_unref (variant);
+
+        g_debug ("Finished changing rfkill, property %s is now %s",
+                 data->property, data->target_state ? "true" : "false");
+
+        if (data->bluetooth)
+                show_osd (data->manager, data->target_state ? "bluetooth-disabled-symbolic"
+                          : "bluetooth-active-symbolic", NULL, -1, OSD_ALL_OUTPUTS);
+        else
+                show_osd (data->manager, data->target_state ? "airplane-mode-symbolic"
+                          : "network-wireless-signal-excellent-symbolic", NULL, -1, OSD_ALL_OUTPUTS);
+
+out:
+        g_free (data->property);
+        g_free (data);
+}
+
+static void
+do_rfkill_action (GsdMediaKeysManager *manager,
+                  gboolean             bluetooth)
+{
+        const char *has_mode, *hw_mode, *mode;
+        gboolean new_state;
+        RfkillData *data;
+
+        has_mode = bluetooth ? "BluetoothHasAirplaneMode" : "HasAirplaneMode";
+        hw_mode = bluetooth ? "BluetoothHardwareAirplaneMode" : "HardwareAirplaneMode";
+        mode = bluetooth ? "BluetoothAirplaneMode" : "AirplaneMode";
+
+        if (manager->priv->rfkill_proxy == NULL)
+                return;
+
+        if (get_rfkill_property (manager, has_mode) == FALSE)
+                return;
+
+        if (get_rfkill_property (manager, hw_mode)) {
+                show_osd (manager, "airplane-mode-symbolic",
+                          _("Hardware Airplane Mode"), -1, OSD_ALL_OUTPUTS);
+                return;
+        }
+
+        new_state = !get_rfkill_property (manager, mode);
+        data = g_new0 (RfkillData, 1);
+        data->manager = manager;
+        data->property = g_strdup (mode);
+        data->bluetooth = bluetooth;
+        data->target_state = new_state;
+        g_dbus_proxy_call (manager->priv->rfkill_proxy,
+                           "org.freedesktop.DBus.Properties.Set",
+                           g_variant_new ("(ssv)",
+                                          "org.gnome.SettingsDaemon.Rfkill",
+                                          data->property,
+                                          g_variant_new_boolean (new_state)),
+                           G_DBUS_CALL_FLAGS_NONE, -1,
+                           manager->priv->rfkill_cancellable,
+                           set_rfkill_complete, data);
+
+        g_debug ("Setting rfkill property %s to %s",
+                 data->property, new_state ? "true" : "false");
+}
+
 static void
 screencast_stop (GsdMediaKeysManager *manager)
 {
@@ -2205,6 +2311,12 @@ do_action (GsdMediaKeysManager *manager,
         case BATTERY_KEY:
                 do_battery_action (manager);
                 break;
+        case RFKILL_KEY:
+                do_rfkill_action (manager, FALSE);
+                break;
+        case BLUETOOTH_RFKILL_KEY:
+                do_rfkill_action (manager, TRUE);
+                break;
         /* Note, no default so compiler catches missing keys */
         case CUSTOM_KEY:
                 g_assert_not_reached ();
@@ -2366,6 +2478,34 @@ shell_presence_changed (GsdMediaKeysManager *manager)
         }
 }
 
+static void
+on_rfkill_proxy_ready (GObject      *source,
+                       GAsyncResult *result,
+                       gpointer      data)
+{
+        GsdMediaKeysManager *manager = data;
+
+        manager->priv->rfkill_proxy =
+                g_dbus_proxy_new_for_bus_finish (result, NULL);
+}
+
+static void
+rfkill_appeared_cb (GDBusConnection *connection,
+                    const gchar     *name,
+                    const gchar     *name_owner,
+                    gpointer         user_data)
+{
+        GsdMediaKeysManager *manager = user_data;
+
+        g_dbus_proxy_new_for_bus (G_BUS_TYPE_SESSION,
+                                  0, NULL,
+                                  "org.gnome.SettingsDaemon.Rfkill",
+                                  "/org/gnome/SettingsDaemon/Rfkill",
+                                  "org.gnome.SettingsDaemon.Rfkill",
+                                  manager->priv->rfkill_cancellable,
+                                  on_rfkill_proxy_ready, manager);
+}
+
 static gboolean
 start_media_keys_idle_cb (GsdMediaKeysManager *manager)
 {
@@ -2405,12 +2545,20 @@ start_media_keys_idle_cb (GsdMediaKeysManager *manager)
 
         ensure_cancellable (&manager->priv->grab_cancellable);
         ensure_cancellable (&manager->priv->screencast_cancellable);
+        ensure_cancellable (&manager->priv->rfkill_cancellable);
 
         manager->priv->shell_proxy = gnome_settings_bus_get_shell_proxy ();
         g_signal_connect_swapped (manager->priv->shell_proxy, "notify::g-name-owner",
                                   G_CALLBACK (shell_presence_changed), manager);
         shell_presence_changed (manager);
 
+        manager->priv->rfkill_watch_id = g_bus_watch_name (G_BUS_TYPE_SESSION,
+                                                           "org.gnome.SettingsDaemon.Rfkill",
+                                                           G_BUS_NAME_WATCHER_FLAGS_NONE,
+                                                           rfkill_appeared_cb,
+                                                           NULL,
+                                                           manager, NULL);
+
         g_debug ("Starting mpris controller");
         manager->priv->mpris_controller = mpris_controller_new ();
 
@@ -2476,6 +2624,11 @@ gsd_media_keys_manager_stop (GsdMediaKeysManager *manager)
                 manager->priv->gtksettings = NULL;
         }
 
+        if (manager->priv->rfkill_watch_id > 0) {
+                g_bus_unwatch_name (manager->priv->rfkill_watch_id);
+                manager->priv->rfkill_watch_id = 0;
+        }
+
         if (manager->priv->orientation_watch_id > 0) {
                 g_bus_unwatch_name (manager->priv->orientation_watch_id);
                 manager->priv->orientation_watch_id = 0;
@@ -2530,6 +2683,11 @@ gsd_media_keys_manager_stop (GsdMediaKeysManager *manager)
                 g_clear_object (&priv->screencast_cancellable);
         }
 
+        if (priv->rfkill_cancellable != NULL) {
+                g_cancellable_cancel (priv->rfkill_cancellable);
+                g_clear_object (&priv->rfkill_cancellable);
+        }
+
         g_clear_object (&priv->sink);
         g_clear_object (&priv->source);
         g_clear_object (&priv->volume);
diff --git a/plugins/media-keys/media-keys.h b/plugins/media-keys/media-keys.h
index 970415b..387ff05 100644
--- a/plugins/media-keys/media-keys.h
+++ b/plugins/media-keys/media-keys.h
@@ -78,6 +78,8 @@ typedef enum {
         KEYBOARD_BRIGHTNESS_DOWN_KEY,
         KEYBOARD_BRIGHTNESS_TOGGLE_KEY,
         BATTERY_KEY,
+        RFKILL_KEY,
+        BLUETOOTH_RFKILL_KEY,
         CUSTOM_KEY
 } MediaKeyType;
 
diff --git a/plugins/media-keys/shortcuts-list.h b/plugins/media-keys/shortcuts-list.h
index e8ab8ea..3ed24c4 100644
--- a/plugins/media-keys/shortcuts-list.h
+++ b/plugins/media-keys/shortcuts-list.h
@@ -107,6 +107,9 @@ static struct {
         { KEYBOARD_BRIGHTNESS_DOWN_KEY, NULL, N_("Keyboard Brightness Down"), "XF86KbdBrightnessDown", 
SHELL_ACTION_MODE_ALL },
         { KEYBOARD_BRIGHTNESS_TOGGLE_KEY, NULL, N_("Keyboard Brightness Toggle"), "XF86KbdLightOnOff", 
SHELL_ACTION_MODE_ALL },
         { BATTERY_KEY, NULL, N_("Battery Status"), "XF86Battery", GSD_ACTION_MODE_LAUNCHER },
+        { RFKILL_KEY, NULL, N_("Toggle Airplane Mode"), "XF86WLAN", GSD_ACTION_MODE_LAUNCHER },
+        { RFKILL_KEY, NULL, N_("Toggle Airplane Mode"), "XF86UWB", GSD_ACTION_MODE_LAUNCHER },
+        { BLUETOOTH_RFKILL_KEY, NULL, N_("Toggle Bluetooth"), "XF86Bluetooth", GSD_ACTION_MODE_LAUNCHER }
 };
 
 #undef SCREENSAVER_MODE


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]