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

[virt-tools-list] [PATCH virt-viewer 9/9] spice: teach customizable key bindings with controller



Tested with RHEVM 3.0 instance with custom bindings for fullscreen &
ungrab.
---
 src/remote-viewer.c |  150 +++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 150 insertions(+), 0 deletions(-)

diff --git a/src/remote-viewer.c b/src/remote-viewer.c
index 1fddad4..3b8f168 100644
--- a/src/remote-viewer.c
+++ b/src/remote-viewer.c
@@ -337,6 +337,119 @@ remote_viewer_get_spice_session(RemoteViewer *self)
 #define G_VALUE_INIT  { 0, { { 0 } } }
 #endif
 
+static gchar *
+ctrl_key_to_gtk_key(const gchar *key)
+{
+    int i;
+
+    static const struct {
+        const char *ctrl;
+        const char *gtk;
+    } keys[] = {
+        /* FIXME: right alt, right ctrl, right shift, cmds */
+        { "alt", "<Alt>" },
+        { "ralt", "<Alt>" },
+        { "rightalt", "<Alt>" },
+        { "right-alt", "<Alt>" },
+        { "lalt", "<Alt>" },
+        { "leftalt", "<Alt>" },
+        { "left-alt", "<Alt>" },
+
+        { "ctrl", "<Ctrl>" },
+        { "rctrl", "<Ctrl>" },
+        { "rightctrl", "<Ctrl>" },
+        { "right-ctrl", "<Ctrl>" },
+        { "lctrl", "<Ctrl>" },
+        { "leftctrl", "<Ctrl>" },
+        { "left-ctrl", "<Ctrl>" },
+
+        { "shift", "<Shift>" },
+        { "rshift", "<Shift>" },
+        { "rightshift", "<Shift>" },
+        { "right-shift", "<Shift>" },
+        { "lshift", "<Shift>" },
+        { "leftshift", "<Shift>" },
+        { "left-shift", "<Shift>" },
+
+        { "cmd", "<Ctrl>" },
+        { "rcmd", "<Ctrl>" },
+        { "rightcmd", "<Ctrl>" },
+        { "right-cmd", "<Ctrl>" },
+        { "lcmd", "<Ctrl>" },
+        { "leftcmd", "<Ctrl>" },
+        { "left-cmd", "<Ctrl>" },
+
+        { "win", "<Super>" },
+        { "rwin", "<Super>" },
+        { "rightwin", "<Super>" },
+        { "right-win", "<Super>" },
+        { "lwin", "<Super>" },
+        { "leftwin", "<Super>" },
+        { "left-win", "<Super>" },
+
+        { "esc", "Escape" },
+        /* { "escape", "Escape" }, */
+
+        { "ins", "Insert" },
+        /* { "insert", "Insert" }, */
+
+        { "del", "Delete" },
+        /* { "delete", "Delete" }, */
+
+        { "pgup", "Page_Up" },
+        { "pageup", "Page_Up" },
+        { "pgdn", "Page_Down" },
+        { "pagedown", "Page_Down" },
+
+        /* { "home", "home" }, */
+        /* { "end", "end" }, */
+        /* { "space", "space" }, */
+
+        { "enter", "Return" },
+
+        /* { "tab", "tab" }, */
+        /* { "f1", "F1" }, */
+        /* { "f2", "F2" }, */
+        /* { "f3", "F3" }, */
+        /* { "f4", "F4" }, */
+        /* { "f5", "F5" }, */
+        /* { "f6", "F6" }, */
+        /* { "f7", "F7" }, */
+        /* { "f8", "F8" }, */
+        /* { "f9", "F9" }, */
+        /* { "f10", "F10" }, */
+        /* { "f11", "F11" }, */
+        /* { "f12", "F12" } */
+    };
+
+    for (i = 0; i < G_N_ELEMENTS(keys); ++i) {
+        if (g_ascii_strcasecmp(keys[i].ctrl, key) == 0)
+            return g_strdup(keys[i].gtk);
+    }
+
+    return g_ascii_strup(key, -1);
+}
+
+static gchar*
+ctrl_key_to_gtk_accelerator(const gchar *key)
+{
+    gchar *accel, **k, **keyv;
+
+    keyv = g_strsplit(key, "+", -1);
+    g_return_val_if_fail(keyv != NULL, NULL);
+
+    for (k = keyv; *k != NULL; k++) {
+        gchar *tmp = *k;
+        *k = ctrl_key_to_gtk_key(tmp);
+        g_free(tmp);
+    }
+
+    accel = g_strjoinv(NULL, keyv);
+    g_strfreev(keyv);
+
+    return accel;
+}
+
 static void
 spice_ctrl_notified(SpiceCtrlController *ctrl,
                     GParamSpec *pspec,
@@ -373,6 +486,42 @@ spice_ctrl_notified(SpiceCtrlController *ctrl,
         /* g_object_set(G_OBJECT(self), "resize-guest", auto_res, NULL); */
     } else if (g_str_equal(pspec->name, "menu")) {
         spice_ctrl_menu_updated(self, g_value_get_object(&value));
+    } else if (g_str_equal(pspec->name, "hotkeys")) {
+        gchar **hotkey, **hotkeys = g_strsplit(g_value_get_string(&value), ",", -1);
+        if (!hotkeys || g_strv_length(hotkeys) == 0) {
+            g_object_set(app, "enable-accel", FALSE, NULL);
+            goto end;
+        }
+
+        for (hotkey = hotkeys; *hotkey != NULL; hotkey++) {
+            gchar *key = strstr(*hotkey, "=");
+            if (key == NULL) {
+                g_warn_if_reached();
+                continue;
+            }
+            *key = '\0';
+
+            gchar *accel = ctrl_key_to_gtk_accelerator(key + 1);
+            guint accel_key;
+            GdkModifierType accel_mods;
+            gtk_accelerator_parse(accel, &accel_key, &accel_mods);
+            g_free(accel);
+
+            if (g_str_equal(*hotkey, "toggle-fullscreen")) {
+                gtk_accel_map_change_entry("<virt-viewer>/view/fullscreen", accel_key, accel_mods, TRUE);
+            } else if (g_str_equal(*hotkey, "release-cursor")) {
+                gtk_accel_map_change_entry("<virt-viewer>/view/release-cursor", accel_key, accel_mods, TRUE);
+            } else if (g_str_equal(*hotkey, "smartcard-insert")) {
+                gtk_accel_map_change_entry("<virt-viewer>/file/smartcard-insert", accel_key, accel_mods, TRUE);
+            } else if (g_str_equal(*hotkey, "smartcard-remove")) {
+                gtk_accel_map_change_entry("<virt-viewer>/file/smartcard-remove", accel_key, accel_mods, TRUE);
+            } else {
+                g_warning("Unknown hotkey command %s", *hotkey);
+            }
+        }
+        g_strfreev(hotkeys);
+
+        g_object_set(app, "enable-accel", TRUE, NULL);
     } else {
         gchar *content = g_strdup_value_contents(&value);
 
@@ -380,6 +529,7 @@ spice_ctrl_notified(SpiceCtrlController *ctrl,
         g_free(content);
     }
 
+end:
     g_object_unref(session);
     g_value_unset(&value);
 }
-- 
1.7.7.6


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