From c0ec28ce8a08b4ec497d41fe520b287a2fec634e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Date: Tue, 14 Feb 2012 20:19:08 +0100 Subject: [PATCH] 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 file changed, 150 insertions(+) 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", "" }, + { "ralt", "" }, + { "rightalt", "" }, + { "right-alt", "" }, + { "lalt", "" }, + { "leftalt", "" }, + { "left-alt", "" }, + + { "ctrl", "" }, + { "rctrl", "" }, + { "rightctrl", "" }, + { "right-ctrl", "" }, + { "lctrl", "" }, + { "leftctrl", "" }, + { "left-ctrl", "" }, + + { "shift", "" }, + { "rshift", "" }, + { "rightshift", "" }, + { "right-shift", "" }, + { "lshift", "" }, + { "leftshift", "" }, + { "left-shift", "" }, + + { "cmd", "" }, + { "rcmd", "" }, + { "rightcmd", "" }, + { "right-cmd", "" }, + { "lcmd", "" }, + { "leftcmd", "" }, + { "left-cmd", "" }, + + { "win", "" }, + { "rwin", "" }, + { "rightwin", "" }, + { "right-win", "" }, + { "lwin", "" }, + { "leftwin", "" }, + { "left-win", "" }, + + { "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("/view/fullscreen", accel_key, accel_mods, TRUE); + } else if (g_str_equal(*hotkey, "release-cursor")) { + gtk_accel_map_change_entry("/view/release-cursor", accel_key, accel_mods, TRUE); + } else if (g_str_equal(*hotkey, "smartcard-insert")) { + gtk_accel_map_change_entry("/file/smartcard-insert", accel_key, accel_mods, TRUE); + } else if (g_str_equal(*hotkey, "smartcard-remove")) { + gtk_accel_map_change_entry("/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); }