diff --git a/src/virt-viewer-app.c b/src/virt-viewer-app.c index 314da82..99ff424 100644 --- a/src/virt-viewer-app.c +++ b/src/virt-viewer-app.c @@ -162,12 +162,9 @@ struct _VirtViewerAppPrivate { GKeyFile *config; gchar *config_file; - guint insert_smartcard_accel_key; - GdkModifierType insert_smartcard_accel_mods; - guint remove_smartcard_accel_key; - GdkModifierType remove_smartcard_accel_mods; - guint usb_device_reset_accel_key; - GdkModifierType usb_device_reset_accel_mods; + gchar **insert_smartcard_accel; + gchar **remove_smartcard_accel; + gchar **usb_device_reset_accel; gboolean quit_on_disconnect; gboolean supports_share_clipboard; VirtViewerKeyMapping *keyMappings; @@ -2130,28 +2127,6 @@ virt_viewer_app_init(VirtViewerApp *self) g_signal_connect(self, "notify::guri", G_CALLBACK(title_maybe_changed), NULL); } -static void -virt_viewer_set_insert_smartcard_accel(VirtViewerApp *self, - guint accel_key, - GdkModifierType accel_mods) -{ - VirtViewerAppPrivate *priv = virt_viewer_app_get_instance_private(self); - - priv->insert_smartcard_accel_key = accel_key; - priv->insert_smartcard_accel_mods = accel_mods; -} - -static void -virt_viewer_set_remove_smartcard_accel(VirtViewerApp *self, - guint accel_key, - GdkModifierType accel_mods) -{ - VirtViewerAppPrivate *priv = virt_viewer_app_get_instance_private(self); - - priv->remove_smartcard_accel_key = accel_key; - priv->remove_smartcard_accel_mods = accel_mods; -} - static void virt_viewer_update_smartcard_accels(VirtViewerApp *self) { @@ -2166,38 +2141,30 @@ virt_viewer_update_smartcard_accels(VirtViewerApp *self) sw_smartcard = FALSE; } if (sw_smartcard) { - gboolean r; g_debug("enabling smartcard shortcuts"); - r = gtk_accel_map_change_entry("/file/smartcard-insert", - priv->insert_smartcard_accel_key, - priv->insert_smartcard_accel_mods, - TRUE); - if (!r) - g_warning("Unable to set hotkey for 'smartcard-insert' due to a conflict in GTK"); - r = gtk_accel_map_change_entry("/file/smartcard-remove", - priv->remove_smartcard_accel_key, - priv->remove_smartcard_accel_mods, - TRUE); - if (!r) - g_warning("Unable to set hotkey for 'smartcard-remove' due to a conflict in GTK"); + + gtk_application_set_accels_for_action(GTK_APPLICATION(self), "app.smartcard-insert", + (const gchar * const *)priv->insert_smartcard_accel); + gtk_application_set_accels_for_action(GTK_APPLICATION(self), "app.smartcard-remove", + (const gchar * const *)priv->remove_smartcard_accel); } else { g_debug("disabling smartcard shortcuts"); - gtk_accel_map_change_entry("/file/smartcard-insert", 0, 0, TRUE); - gtk_accel_map_change_entry("/file/smartcard-remove", 0, 0, TRUE); + const gchar *no_accels[] = { NULL }; + char **old_insert_accels = gtk_application_get_accels_for_action(GTK_APPLICATION(self), "win.smartcard-insert"); + char **old_remove_accels = gtk_application_get_accels_for_action(GTK_APPLICATION(self), "win.smartcard-remove"); + if (old_insert_accels) { + g_strfreev(priv->insert_smartcard_accel); + priv->insert_smartcard_accel = old_insert_accels; + } + if (old_remove_accels) { + g_strfreev(priv->remove_smartcard_accel); + priv->remove_smartcard_accel = old_remove_accels; + } + gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.smartcard-insert", no_accels); + gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.smartcard-remove", no_accels); } } -static void -virt_viewer_set_usb_device_reset_accel(VirtViewerApp *self, - guint accel_key, - GdkModifierType accel_mods) -{ - VirtViewerAppPrivate *priv = virt_viewer_app_get_instance_private(self); - - priv->usb_device_reset_accel_key = accel_key; - priv->usb_device_reset_accel_mods = accel_mods; -} - static void virt_viewer_update_usbredir_accels(VirtViewerApp *self) { @@ -2212,12 +2179,17 @@ virt_viewer_update_usbredir_accels(VirtViewerApp *self) } if (has_usbredir) { - gtk_accel_map_change_entry("/file/usb-device-reset", - priv->usb_device_reset_accel_key, - priv->usb_device_reset_accel_mods, - TRUE); + gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.usb-device-reset", + (const gchar * const *)priv->usb_device_reset_accel); } else { - gtk_accel_map_change_entry("/file/usb-device-reset", 0, 0, TRUE); + const gchar *no_accels[] = { NULL }; + char **old_accels = gtk_application_get_accels_for_action(GTK_APPLICATION(self), "win.usb-device-reset"); + + if (old_accels) { + g_strfreev(priv->usb_device_reset_accel); + priv->usb_device_reset_accel = old_accels; + } + gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.usb-device-reset", no_accels); } } @@ -2388,12 +2360,30 @@ static GActionEntry actions[] = { .activate = virt_viewer_app_action_smartcard_remove }, }; +struct VirtViewerActionAccels { + const char *action; + const char *accels[3]; +}; + +static const struct VirtViewerActionAccels action_accels[] = { + { "win.fullscreen", {"F11", NULL, NULL} }, + { "win.zoom-in", { "plus", "KP_Add", NULL } }, + { "win.zoom-out", { "minus", "KP_Subtract", NULL } }, + { "win.zoom-reset", { "0", "KP_0", NULL } }, + { "win.release-cursor", {"F12", NULL, NULL} }, + { "app.smartcard-insert", {"F8", NULL, NULL} }, + { "app.smartcard-remove", {"F9", NULL, NULL} }, + { "win.secure-attention", {"End", NULL, NULL} }, + { "win.usb-device-reset", {"r", NULL, NULL} }, +}; + static void virt_viewer_app_on_application_startup(GApplication *app) { VirtViewerApp *self = VIRT_VIEWER_APP(app); VirtViewerAppPrivate *priv = virt_viewer_app_get_instance_private(self); GError *error = NULL; + gint i; G_APPLICATION_CLASS(virt_viewer_app_parent_class)->startup(app); @@ -2404,6 +2394,12 @@ virt_viewer_app_on_application_startup(GApplication *app) priv->resource = virt_viewer_get_resource(); + for (i = 0 ; i < G_N_ELEMENTS(action_accels); i++) { + gtk_application_set_accels_for_action(GTK_APPLICATION(app), + action_accels[i].action, + action_accels[i].accels); + } + virt_viewer_app_set_debug(opt_debug); virt_viewer_app_set_fullscreen(self, opt_fullscreen); @@ -2427,17 +2423,6 @@ virt_viewer_app_on_application_startup(GApplication *app) virt_viewer_window_set_zoom_level(priv->main_window, opt_zoom); - virt_viewer_set_insert_smartcard_accel(self, GDK_KEY_F8, GDK_SHIFT_MASK); - virt_viewer_set_remove_smartcard_accel(self, GDK_KEY_F9, GDK_SHIFT_MASK); - virt_viewer_set_usb_device_reset_accel(self, GDK_KEY_r, GDK_SHIFT_MASK | GDK_CONTROL_MASK); - - gtk_accel_map_add_entry("/view/toggle-fullscreen", GDK_KEY_F11, 0); - gtk_accel_map_add_entry("/view/release-cursor", GDK_KEY_F12, GDK_SHIFT_MASK); - gtk_accel_map_add_entry("/view/zoom-reset", GDK_KEY_0, GDK_CONTROL_MASK); - gtk_accel_map_add_entry("/view/zoom-out", GDK_KEY_minus, GDK_CONTROL_MASK); - gtk_accel_map_add_entry("/view/zoom-in", GDK_KEY_plus, GDK_CONTROL_MASK); - gtk_accel_map_add_entry("/send/secure-attention", GDK_KEY_End, GDK_CONTROL_MASK | GDK_MOD1_MASK); - // Restore initial state of config-share-clipboard property from config and notify about it virt_viewer_app_set_config_share_clipboard(self, virt_viewer_app_get_config_share_clipboard(self)); @@ -2675,16 +2660,14 @@ gboolean virt_viewer_app_get_direct(VirtViewerApp *self) void virt_viewer_app_clear_hotkeys(VirtViewerApp *self) { - /* Disable default bindings and replace them with our own */ - gtk_accel_map_change_entry("/view/toggle-fullscreen", 0, 0, TRUE); - gtk_accel_map_change_entry("/view/release-cursor", 0, 0, TRUE); - gtk_accel_map_change_entry("/view/zoom-reset", 0, 0, TRUE); - gtk_accel_map_change_entry("/view/zoom-in", 0, 0, TRUE); - gtk_accel_map_change_entry("/view/zoom-out", 0, 0, TRUE); - gtk_accel_map_change_entry("/send/secure-attention", 0, 0, TRUE); - virt_viewer_set_insert_smartcard_accel(self, 0, 0); - virt_viewer_set_remove_smartcard_accel(self, 0, 0); - virt_viewer_set_usb_device_reset_accel(self, 0, 0); + gint i; + const gchar *no_accels[] = { NULL }; + + for (i = 0 ; i < G_N_ELEMENTS(action_accels); i++) { + gtk_application_set_accels_for_action(GTK_APPLICATION(self), + action_accels[i].action, + no_accels); + } } void @@ -2708,6 +2691,8 @@ virt_viewer_app_set_hotkeys(VirtViewerApp *self, const gchar *hotkeys_str) if (!hotkeys || g_strv_length(hotkeys) == 0) { g_strfreev(hotkeys); virt_viewer_app_set_enable_accel(self, FALSE); + virt_viewer_update_smartcard_accels(self); + virt_viewer_update_usbredir_accels(self); return; } @@ -2724,38 +2709,37 @@ virt_viewer_app_set_hotkeys(VirtViewerApp *self, const gchar *hotkeys_str) gchar *accel = spice_hotkey_to_gtk_accelerator(value); guint accel_key; GdkModifierType accel_mods; + const gchar *accels[] = { accel, NULL }; gtk_accelerator_parse(accel, &accel_key, &accel_mods); - g_free(accel); if (accel_key == 0 && accel_mods == 0) { g_warning("Invalid value '%s' for key '%s'", value, *hotkey); + g_free(accel); continue; } - gboolean status = TRUE; if (g_str_equal(*hotkey, "toggle-fullscreen")) { - status = gtk_accel_map_change_entry("/view/toggle-fullscreen", accel_key, accel_mods, TRUE); + gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.fullscreen", accels); } else if (g_str_equal(*hotkey, "release-cursor")) { - status = gtk_accel_map_change_entry("/view/release-cursor", accel_key, accel_mods, TRUE); + gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.release-cursor", accels); } else if (g_str_equal(*hotkey, "zoom-reset")) { - status = gtk_accel_map_change_entry("/view/zoom-reset", accel_key, accel_mods, TRUE); + gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.zoom-reset", accels); } else if (g_str_equal(*hotkey, "zoom-out")) { - status = gtk_accel_map_change_entry("/view/zoom-out", accel_key, accel_mods, TRUE); + gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.zoom-out", accels); } else if (g_str_equal(*hotkey, "zoom-in")) { - status = gtk_accel_map_change_entry("/view/zoom-in", accel_key, accel_mods, TRUE); + gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.zoom-in", accels); } else if (g_str_equal(*hotkey, "secure-attention")) { - status = gtk_accel_map_change_entry("/send/secure-attention", accel_key, accel_mods, TRUE); + gtk_application_set_accels_for_action(GTK_APPLICATION(self), "win.secure-attention", accels); } else if (g_str_equal(*hotkey, "smartcard-insert")) { - virt_viewer_set_insert_smartcard_accel(self, accel_key, accel_mods); + gtk_application_set_accels_for_action(GTK_APPLICATION(self), "app.smartcard-insert", accels); } else if (g_str_equal(*hotkey, "smartcard-remove")) { - virt_viewer_set_remove_smartcard_accel(self, accel_key, accel_mods); + gtk_application_set_accels_for_action(GTK_APPLICATION(self), "app.smartcard-remove", accels); } else if (g_str_equal(*hotkey, "usb-device-reset")) { - virt_viewer_set_usb_device_reset_accel(self, accel_key, accel_mods); + gtk_application_set_accels_for_action(GTK_APPLICATION(self), "app.usb-device-reset", accels); } else { g_warning("Unknown hotkey command %s", *hotkey); } - if (!status) - g_warning("Unable to set hotkey for '%s' due to a conflict in GTK", *hotkey); + g_free(accel); } g_strfreev(hotkeys); diff --git a/src/virt-viewer-display-spice.c b/src/virt-viewer-display-spice.c index 0eed789..058a710 100644 --- a/src/virt-viewer-display-spice.c +++ b/src/virt-viewer-display-spice.c @@ -237,15 +237,21 @@ enable_accel_changed(VirtViewerApp *app, GParamSpec *pspec G_GNUC_UNUSED, VirtViewerDisplaySpice *self) { - GtkAccelKey key = {0, 0, 0}; gboolean kiosk; + guint accel_key = 0; + GdkModifierType accel_mods = 0; + gchar **accels; - if (virt_viewer_app_get_enable_accel(app)) - gtk_accel_map_lookup_entry("/view/release-cursor", &key); + if (virt_viewer_app_get_enable_accel(app)){ + accels = gtk_application_get_accels_for_action(GTK_APPLICATION(app), "win.release-cursor"); + if (accels[0]) + gtk_accelerator_parse(accels[0], &accel_key, &accel_mods); + g_strfreev(accels); + } g_object_get(app, "kiosk", &kiosk, NULL); - if (key.accel_key || key.accel_mods || kiosk) { + if (accel_key || accel_mods || kiosk) { SpiceGrabSequence *seq = spice_grab_sequence_new(0, NULL); /* disable default grab sequence */ spice_display_set_grab_keys(self->display, seq); diff --git a/src/virt-viewer-display-vnc.c b/src/virt-viewer-display-vnc.c index 2fb5f54..0bfefa2 100644 --- a/src/virt-viewer-display-vnc.c +++ b/src/virt-viewer-display-vnc.c @@ -187,15 +187,21 @@ enable_accel_changed(VirtViewerApp *app, GParamSpec *pspec G_GNUC_UNUSED, VncDisplay *vnc) { - GtkAccelKey key = {0, 0, 0}; gboolean kiosk; + guint accel_key = 0; + GdkModifierType accel_mods = 0; + gchar **accels; - if (virt_viewer_app_get_enable_accel(app)) - gtk_accel_map_lookup_entry("/view/release-cursor", &key); + if (virt_viewer_app_get_enable_accel(app)){ + accels = gtk_application_get_accels_for_action(GTK_APPLICATION(app), "win.release-cursor"); + if (accels[0]) + gtk_accelerator_parse(accels[0], &accel_key, &accel_mods); + g_strfreev(accels); + } g_object_get(app, "kiosk", &kiosk, NULL); - if (key.accel_key || key.accel_mods || kiosk) { + if (accel_key || accel_mods || kiosk) { VncGrabSequence *seq = vnc_grab_sequence_new(0, NULL); /* disable default grab sequence */ vnc_display_set_grab_keys(vnc, seq); diff --git a/src/virt-viewer-file.c b/src/virt-viewer-file.c index 21c3050..c8c09c1 100644 --- a/src/virt-viewer-file.c +++ b/src/virt-viewer-file.c @@ -869,17 +869,14 @@ virt_viewer_file_set_ovirt_admin(VirtViewerFile* self, gint value) } static void -spice_hotkey_set_accel(const gchar *accel_path, const gchar *key) +spice_hotkey_set_accel(VirtViewerApp *app, const gchar *action_name, const gchar *key) { - gchar *accel; - guint accel_key; - GdkModifierType accel_mods; + gchar *accel = spice_hotkey_to_gtk_accelerator(key); + const gchar *accels[] = { accel, NULL }; + + gtk_application_set_accels_for_action(GTK_APPLICATION(app), action_name, accels); - accel = spice_hotkey_to_gtk_accelerator(key); - gtk_accelerator_parse(accel, &accel_key, &accel_mods); g_free(accel); - - gtk_accel_map_change_entry(accel_path, accel_key, accel_mods, TRUE); } static gboolean @@ -960,16 +957,16 @@ virt_viewer_file_fill_app(VirtViewerFile* self, VirtViewerApp *app, GError **err gchar *val; static const struct { const char *prop; - const char *accel; + const char *action_name; } accels[] = { - { "release-cursor", "/view/release-cursor" }, - { "toggle-fullscreen", "/view/toggle-fullscreen" }, - { "zoom-in", "/view/zoom-in" }, - { "zoom-out", "/view/zoom-out" }, - { "zoom-reset", "/view/zoom-reset" }, - { "smartcard-insert", "/file/smartcard-insert" }, - { "smartcard-remove", "/file/smartcard-remove" }, - { "secure-attention", "/send/secure-attention" } + { "release-cursor", "win.release-cursor" }, + { "toggle-fullscreen", "win.fullscreen" }, + { "zoom-in", "win.zoom-in" }, + { "zoom-out", "win.zoom-out" }, + { "zoom-reset", "win.zoom-reset" }, + { "smartcard-insert", "app.smartcard-insert" }, + { "smartcard-remove", "app.smartcard-remove" }, + { "secure-attention", "win.secure-attention" }, }; int i; @@ -977,7 +974,7 @@ virt_viewer_file_fill_app(VirtViewerFile* self, VirtViewerApp *app, GError **err if (!virt_viewer_file_is_set(self, accels[i].prop)) continue; g_object_get(self, accels[i].prop, &val, NULL); - spice_hotkey_set_accel(accels[i].accel, val); + spice_hotkey_set_accel(app, accels[i].action_name, val); g_free(val); } } diff --git a/src/virt-viewer-window.c b/src/virt-viewer-window.c index fa4d063..905c9c7 100644 --- a/src/virt-viewer-window.c +++ b/src/virt-viewer-window.c @@ -501,6 +501,20 @@ virt_viewer_window_action_change_cd(GSimpleAction *act G_GNUC_UNUSED, virt_viewer_window_change_cd(VIRT_VIEWER_WINDOW(opaque)); } +static void +virt_viewer_window_action_secure_attention(GSimpleAction *action G_GNUC_UNUSED, + GVariant *param G_GNUC_UNUSED, + gpointer opaque) +{ + g_return_if_fail(VIRT_VIEWER_IS_WINDOW(opaque)); + + VirtViewerWindow *self = VIRT_VIEWER_WINDOW(opaque); + guint keys[] = { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_Delete }; + + virt_viewer_display_send_keys(VIRT_VIEWER_DISPLAY(self->display), + keys, G_N_ELEMENTS(keys)); +} + static GActionEntry actions[] = { { .name = "zoom-out", .activate = virt_viewer_window_action_zoom_out }, @@ -534,6 +548,8 @@ static GActionEntry actions[] = { .activate = virt_viewer_window_action_preferences }, { .name = "change-cd", .activate = virt_viewer_window_action_change_cd }, + { .name = "secure-attention", + .activate = virt_viewer_window_action_secure_attention }, }; static void @@ -789,27 +805,26 @@ virt_viewer_window_enter_fullscreen(VirtViewerWindow *self, gint monitor) struct keyComboDef { guint32 keys[MAX_KEY_COMBO]; const char *accel_label; - const gchar* accel_path; }; static const struct keyComboDef keyCombos[] = { - { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_Delete, GDK_KEY_VoidSymbol }, "Delete", "/send/secure-attention"}, - { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_BackSpace, GDK_KEY_VoidSymbol }, "BackSpace", NULL}, - { { GDK_KEY_VoidSymbol }, "" , NULL}, - { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F1, GDK_KEY_VoidSymbol }, "F1", NULL}, - { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F2, GDK_KEY_VoidSymbol }, "F2", NULL}, - { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F3, GDK_KEY_VoidSymbol }, "F3", NULL}, - { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F4, GDK_KEY_VoidSymbol }, "F4", NULL}, - { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F5, GDK_KEY_VoidSymbol }, "F5", NULL}, - { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F6, GDK_KEY_VoidSymbol }, "F6", NULL}, - { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F7, GDK_KEY_VoidSymbol }, "F7", NULL}, - { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F8, GDK_KEY_VoidSymbol }, "F8", NULL}, - { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F9, GDK_KEY_VoidSymbol }, "F9", NULL}, - { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F10, GDK_KEY_VoidSymbol }, "F10", NULL}, - { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F11, GDK_KEY_VoidSymbol }, "F11", NULL}, - { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F12, GDK_KEY_VoidSymbol }, "F12", NULL}, - { { GDK_KEY_VoidSymbol }, "" , NULL}, - { { GDK_KEY_Print, GDK_KEY_VoidSymbol }, "Print", NULL}, + { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_Delete, GDK_KEY_VoidSymbol }, "Delete" }, + { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_BackSpace, GDK_KEY_VoidSymbol }, "BackSpace" }, + { { GDK_KEY_VoidSymbol }, "" }, + { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F1, GDK_KEY_VoidSymbol }, "F1" }, + { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F2, GDK_KEY_VoidSymbol }, "F2" }, + { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F3, GDK_KEY_VoidSymbol }, "F3" }, + { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F4, GDK_KEY_VoidSymbol }, "F4" }, + { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F5, GDK_KEY_VoidSymbol }, "F5" }, + { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F6, GDK_KEY_VoidSymbol }, "F6" }, + { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F7, GDK_KEY_VoidSymbol }, "F7" }, + { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F8, GDK_KEY_VoidSymbol }, "F8" }, + { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F9, GDK_KEY_VoidSymbol }, "F9" }, + { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F10, GDK_KEY_VoidSymbol }, "F10" }, + { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F11, GDK_KEY_VoidSymbol }, "F11" }, + { { GDK_KEY_Control_L, GDK_KEY_Alt_L, GDK_KEY_F12, GDK_KEY_VoidSymbol }, "F12" }, + { { GDK_KEY_VoidSymbol }, "" }, + { { GDK_KEY_Print, GDK_KEY_VoidSymbol }, "Print" }, }; static guint @@ -824,8 +839,8 @@ get_nkeys(const guint32 *keys) } static void -virt_viewer_menu_add_combo(VirtViewerWindow *self, GtkMenu *menu, - const guint *keys, const gchar *label, const gchar* accel_path) +virt_viewer_menu_add_combo(VirtViewerWindow *self G_GNUC_UNUSED, GtkMenu *menu, + const guint *keys, const gchar *label) { GtkWidget *item; @@ -833,11 +848,6 @@ virt_viewer_menu_add_combo(VirtViewerWindow *self, GtkMenu *menu, item = gtk_separator_menu_item_new(); } else { item = gtk_menu_item_new_with_label(label); - if (accel_path) { - gtk_menu_item_set_accel_path(GTK_MENU_ITEM(item), accel_path); - /* make accel work in fullscreen */ - g_signal_connect(item, "can-activate-accel", G_CALLBACK(can_activate_cb), self); - } gtk_actionable_set_action_name(GTK_ACTIONABLE(item), "win.send-key"); gtk_actionable_set_action_target_value(GTK_ACTIONABLE(item), g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, @@ -850,7 +860,8 @@ virt_viewer_menu_add_combo(VirtViewerWindow *self, GtkMenu *menu, } static guint* -accel_key_to_keys(const GtkAccelKey *key) +accel_key_to_keys(guint accel_key, + GdkModifierType accel_mods) { guint i; guint *val, *keys; @@ -863,59 +874,28 @@ accel_key_to_keys(const GtkAccelKey *key) {GDK_MOD1_MASK, GDK_KEY_Alt_L}, }; - g_warn_if_fail((key->accel_mods & + g_warn_if_fail((accel_mods & ~(GDK_SHIFT_MASK | GDK_CONTROL_MASK | GDK_MOD1_MASK)) == 0); keys = val = g_new(guint, G_N_ELEMENTS(modifiers) + 2); /* up to 3 modifiers, key and the stop symbol */ /* first, send the modifiers */ for (i = 0; i < G_N_ELEMENTS(modifiers); i++) { - if (key->accel_mods & modifiers[i].mask) + if (accel_mods & modifiers[i].mask) *val++ = modifiers[i].key; } /* only after, the non-modifier key (ctrl-t, not t-ctrl) */ - *val++ = key->accel_key; + *val++ = accel_key; /* stop symbol */ *val = GDK_KEY_VoidSymbol; return keys; } -struct accelCbData -{ - VirtViewerWindow *self; - GtkMenu *menu; -}; - -static void -accel_map_item_cb(gpointer data, - const gchar *accel_path, - guint accel_key, - GdkModifierType accel_mods, - gboolean changed G_GNUC_UNUSED) -{ - struct accelCbData *d = data; - GtkAccelKey key = { - .accel_key = accel_key, - .accel_mods = accel_mods - }; - - if (!g_str_has_prefix(accel_path, "")) - return; - if (accel_key == GDK_KEY_VoidSymbol || accel_key == 0) - return; - - guint *keys = accel_key_to_keys(&key); - gchar *label = gtk_accelerator_get_label(accel_key, accel_mods); - virt_viewer_menu_add_combo(d->self, d->menu, keys, label, NULL); - g_free(label); - g_free(keys); -} - static GtkMenu* virt_viewer_window_get_keycombo_menu(VirtViewerWindow *self) { - gint i; + gint i, j; GtkMenu *menu = GTK_MENU(gtk_menu_new()); gtk_menu_set_accel_group(menu, self->accel_group); @@ -927,43 +907,44 @@ virt_viewer_window_get_keycombo_menu(VirtViewerWindow *self) gtk_accelerator_parse(keyCombos[i].accel_label, &key, &mods); label = gtk_accelerator_get_label(key, mods); } - virt_viewer_menu_add_combo(self, menu, keyCombos[i].keys, label, keyCombos[i].accel_path); + virt_viewer_menu_add_combo(self, menu, keyCombos[i].keys, label); g_free(label); } if (virt_viewer_app_get_enable_accel(self->app)) { - struct accelCbData d = { - .self = self, - .menu = menu - }; + gchar **accelactions = gtk_application_list_action_descriptions(GTK_APPLICATION(self->app)); - gtk_accel_map_foreach(&d, accel_map_item_cb); + for (i = 0; accelactions[i] != NULL; i++) { + gchar **accels = gtk_application_get_accels_for_action(GTK_APPLICATION(self->app), + accelactions[i]); + + for (j = 0; accels[j] != NULL; j++) { + guint accel_key; + GdkModifierType accel_mods; + gtk_accelerator_parse(accels[j], &accel_key, &accel_mods); + + guint *keys = accel_key_to_keys(accel_key, accel_mods); + gchar *label = gtk_accelerator_get_label(accel_key, accel_mods); + virt_viewer_menu_add_combo(self, menu, keys, label); + g_free(label); + g_free(keys); + } + g_strfreev(accels); + } + + g_strfreev(accelactions); } gtk_widget_show_all(GTK_WIDGET(menu)); return menu; } - -struct VirtViewerActionAccels { - const char *accels[2]; - const char *action; -}; - -static const struct VirtViewerActionAccels action_accels[] = { - /* numpad keys are not handled automatically by gtk, see bgo#699823 */ - { {"KP_Add", NULL}, "win.zoom-in" }, - { {"KP_Subtract", NULL}, "win.zoom-out" }, - { {"KP_0", NULL}, "win.zoom-reset" }, -}; - void virt_viewer_window_disable_modifiers(VirtViewerWindow *self) { GtkSettings *settings = gtk_settings_get_default(); GValue empty; GSList *accels; - guint i; if (!self->accel_enabled) return; @@ -991,13 +972,6 @@ virt_viewer_window_disable_modifiers(VirtViewerWindow *self) "gtk-enable-mnemonics", FALSE, NULL); - for (i = 0; i < G_N_ELEMENTS(action_accels); i++) { - const char *noaccels[1] = { NULL }; - gtk_application_set_accels_for_action(GTK_APPLICATION(self->app), - action_accels[i].action, - noaccels); - } - self->accel_enabled = FALSE; } @@ -1006,8 +980,6 @@ virt_viewer_window_enable_modifiers(VirtViewerWindow *self) { GtkSettings *settings = gtk_settings_get_default(); GSList *accels; - guint i; - GtkAccelKey key; GSList *attached_accels; if (self->accel_enabled) @@ -1031,19 +1003,6 @@ virt_viewer_window_enable_modifiers(VirtViewerWindow *self) "gtk-enable-mnemonics", self->enable_mnemonics_save, NULL); - /* if the user did not set hotkeys and - * zoom actions using "normal" +/-/0 keys are enabled, - * allow the user to use the numpad +/-/0 keys as well */ - if (!virt_viewer_app_get_enable_accel(self->app) - && gtk_accel_map_lookup_entry("/view/zoom-out", &key) - && key.accel_key != 0) { - for (i = 0; i < G_N_ELEMENTS(action_accels); i++) { - gtk_application_set_accels_for_action(GTK_APPLICATION(self->app), - action_accels[i].action, - action_accels[i].accels); - } - } - self->accel_enabled = TRUE; } @@ -1453,14 +1412,20 @@ virt_viewer_window_update_title(VirtViewerWindow *self) if (self->grabbed) { gchar *label; - GtkAccelKey key = {0, 0, 0}; + guint accel_key = 0; + GdkModifierType accel_mods = 0; + gchar **accels; - if (virt_viewer_app_get_enable_accel(self->app)) - gtk_accel_map_lookup_entry("/view/release-cursor", &key); + if (virt_viewer_app_get_enable_accel(self->app)) { + accels = gtk_application_get_accels_for_action(GTK_APPLICATION(self->app), "win.release-cursor"); + if (accels[0]) + gtk_accelerator_parse(accels[0], &accel_key, &accel_mods); + g_strfreev(accels); + } - if (key.accel_key || key.accel_mods) { - g_debug("release-cursor accel key: key=%u, mods=%x, flags=%u", key.accel_key, key.accel_mods, key.accel_flags); - label = gtk_accelerator_get_label(key.accel_key, key.accel_mods); + if (accel_key || accel_mods) { + g_debug("release-cursor accel key: key=%u, mods=%x", accel_key, accel_mods); + label = gtk_accelerator_get_label(accel_key, accel_mods); } else { label = g_strdup(_("Ctrl_L+Alt_L")); }