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