diff --git a/src/resources/ui/virt-viewer-menus.ui b/src/resources/ui/virt-viewer-menus.ui new file mode 100644 index 0000000..fb82c2f --- /dev/null +++ b/src/resources/ui/virt-viewer-menus.ui @@ -0,0 +1,60 @@ + + + +
+ + _Screenshot + win.screenshot + + + _Preferences… + win.preferences + +
+
+ + Zoom _In + win.zoom-in + + + Zoom _Out + win.zoom-out + + + _Normal Size + win.zoom-reset + +
+
+ + _About + win.about + + + _Guest details + win.guest-details + +
+
+ + +
+
+
+ + _Pause + app.machine-pause + +
+
+ + _Reset + app.machine-reset + + + Power _down + app.machine-powerdown + +
+
+
diff --git a/src/resources/ui/virt-viewer.ui b/src/resources/ui/virt-viewer.ui index 35bbed0..552e202 100644 --- a/src/resources/ui/virt-viewer.ui +++ b/src/resources/ui/virt-viewer.ui @@ -18,312 +18,7 @@ False vertical - - True - False - - - False - True - False - _File - True - - - True - False - accelgroup - - - False - True - False - False - win.screenshot - _Screenshot - True - - - - - False - True - False - False - win.usb-device-select - _USB device selection - True - - - - - False - True - False - win.usb-device-reset - <virt-viewer>/file/usb-device-reset - USB device _reset - True - - - - - False - False - app.smartcard-insert - <virt-viewer>/file/smartcard-insert - Smartcard insertion - True - - - - - False - False - app.smartcard-remove - <virt-viewer>/file/smartcard-remove - Smartcard removal - True - - - - - False - win.change-cd - _Change CD - True - - - - - True - False - False - win.preferences - _Preferences - True - - - - - True - False - - - - - False - True - False - win.quit - _Quit - True - - - - - - - - - - False - _Machine - True - - - True - False - - - True - False - app.machine-pause - _Pause - True - - - - - True - False - - - - - True - False - app.machine-reset - _Reset - True - - - - - True - False - app.machine-powerdown - _Power down - True - - - - - - - - - False - True - False - _View - True - - - True - False - accelgroup - - - False - True - False - win.fullscreen - <virt-viewer>/view/toggle-fullscreen - _Full screen - True - - - - - False - True - False - False - _Zoom - True - - - True - False - accelgroup - - - False - True - False - win.zoom-in - <virt-viewer>/view/zoom-in - Zoom _In - True - - - - - False - True - False - win.zoom-out - <virt-viewer>/view/zoom-out - Zoom _Out - True - - - - - True - False - - - - - False - True - False - win.zoom-reset - <virt-viewer>/view/zoom-reset - _Normal Size - True - - - - - - - - - False - True - False - _Displays - True - - - - - False - False - win.release-cursor - <virt-viewer>/view/release-cursor - Release cursor - True - - - - - - - - - False - True - False - False - _Send key - True - - - - - False - True - False - _Help - True - - - True - False - - - False - True - False - win.guest-details - _Guest Details - True - - - - - False - True - False - win.about - _About - True - - - - - - - - - False - True - 0 - + @@ -332,5 +27,100 @@ + + + True + False + True + + + True + True + True + + + True + False + open-menu-symbolic + + + + + end + + + + + True + True + True + + + True + False + preferences-desktop-keyboard-shortcuts-symbolic + + + + + 1 + + + + + True + True + True + win.usb-device-select + + + True + False + audio-card-symbolic + + + + + 2 + + + + + True + True + True + + + True + False + computer-symbolic + + + + + 3 + + + + + True + True + True + win.fullscreen + + + True + False + view-fullscreen-symbolic + + + + + end + 4 + + + + diff --git a/src/resources/virt-viewer.gresource.xml b/src/resources/virt-viewer.gresource.xml index 334fa47..77e4315 100644 --- a/src/resources/virt-viewer.gresource.xml +++ b/src/resources/virt-viewer.gresource.xml @@ -10,6 +10,7 @@ ui/virt-viewer-vm-connection.ui ui/virt-viewer.ui ui/virt-viewer-file-transfer-dialog.ui + ui/virt-viewer-menus.ui ../../icons/16x16/virt-viewer.png ../../icons/22x22/virt-viewer.png ../../icons/24x24/virt-viewer.png diff --git a/src/virt-viewer-app.c b/src/virt-viewer-app.c index 99ff424..b53734a 100644 --- a/src/virt-viewer-app.c +++ b/src/virt-viewer-app.c @@ -105,6 +105,7 @@ static void virt_viewer_update_usbredir_accels(VirtViewerApp *self); static void virt_viewer_app_add_option_entries(VirtViewerApp *self, GOptionContext *context, GOptionGroup *group); static VirtViewerWindow *virt_viewer_app_get_nth_window(VirtViewerApp *self, gint nth); static VirtViewerWindow *virt_viewer_app_get_vte_window(VirtViewerApp *self, const gchar *name); +static void virt_viewer_app_set_actions_sensitive(VirtViewerApp *self); /* Application actions */ static void virt_viewer_app_action_monitor(GSimpleAction *act, @@ -1033,17 +1034,38 @@ virt_viewer_app_set_usb_reset_sensitive(VirtViewerApp *self, gboolean sensitive) } static void -set_menus_sensitive(gpointer value, gpointer user_data) +set_actions_sensitive(gpointer value, gpointer user_data) { - virt_viewer_window_set_menus_sensitive(VIRT_VIEWER_WINDOW(value), - GPOINTER_TO_INT(user_data)); + VirtViewerApp *self = VIRT_VIEWER_APP(user_data); + VirtViewerAppPrivate *priv = virt_viewer_app_get_instance_private(self); + virt_viewer_window_set_actions_sensitive(VIRT_VIEWER_WINDOW(value), + priv->connected); } -void -virt_viewer_app_set_menus_sensitive(VirtViewerApp *self, gboolean sensitive) +static void +virt_viewer_app_set_actions_sensitive(VirtViewerApp *self) { VirtViewerAppPrivate *priv = virt_viewer_app_get_instance_private(self); - g_list_foreach(priv->windows, set_menus_sensitive, GINT_TO_POINTER(sensitive)); + GActionMap *map = G_ACTION_MAP(self); + GAction *action; + + g_list_foreach(priv->windows, set_actions_sensitive, self); + + action = g_action_map_lookup_action(map, "machine-pause"); + g_simple_action_set_enabled(G_SIMPLE_ACTION(action), + priv->connected && + priv->vm_ui); + + action = g_action_map_lookup_action(map, "machine-reset"); + g_simple_action_set_enabled(G_SIMPLE_ACTION(action), + priv->connected && + priv->vm_ui); + + action = g_action_map_lookup_action(map, "machine-powerdown"); + g_simple_action_set_enabled(G_SIMPLE_ACTION(action), + priv->connected && + priv->vm_ui); + } static VirtViewerWindow * @@ -1709,6 +1731,7 @@ virt_viewer_app_deactivate(VirtViewerApp *self, gboolean connect_error) #endif priv->grabbed = FALSE; virt_viewer_app_update_title(self); + virt_viewer_app_set_actions_sensitive(self); if (priv->authretry) { priv->authretry = FALSE; @@ -1732,6 +1755,8 @@ virt_viewer_app_connected(VirtViewerSession *session G_GNUC_UNUSED, virt_viewer_app_show_status(self, "%s", ""); else virt_viewer_app_show_status(self, _("Connected to graphic server")); + + virt_viewer_app_set_actions_sensitive(self); } static void @@ -1924,6 +1949,7 @@ virt_viewer_app_set_property (GObject *object, guint property_id, g_return_if_fail(VIRT_VIEWER_IS_APP(object)); VirtViewerApp *self = VIRT_VIEWER_APP(object); VirtViewerAppPrivate *priv = virt_viewer_app_get_instance_private(self); + GAction *action; switch (property_id) { case PROP_VERBOSE: @@ -1968,10 +1994,16 @@ virt_viewer_app_set_property (GObject *object, guint property_id, case PROP_VM_UI: priv->vm_ui = g_value_get_boolean(value); + + virt_viewer_app_set_actions_sensitive(self); break; case PROP_VM_RUNNING: priv->vm_running = g_value_get_boolean(value); + + action = g_action_map_lookup_action(G_ACTION_MAP(self), "machine-pause"); + g_simple_action_set_state(G_SIMPLE_ACTION(action), + g_variant_new_boolean(priv->vm_running)); break; case PROP_CONFIG_SHARE_CLIPBOARD: @@ -2421,6 +2453,7 @@ virt_viewer_app_on_application_startup(GApplication *app) opt_zoom = NORMAL_ZOOM_LEVEL; } + virt_viewer_app_set_actions_sensitive(self); virt_viewer_window_set_zoom_level(priv->main_window, opt_zoom); // Restore initial state of config-share-clipboard property from config and notify about it @@ -2881,35 +2914,6 @@ update_menu_displays_sort(gconstpointer a, gconstpointer b) return 0; } -static GtkMenuShell * -window_empty_display_submenu(VirtViewerWindow *window) -{ - /* Because of what apparently is a gtk+2 bug (rhbz#922712), we - * cannot recreate the submenu every time we need to refresh it, - * otherwise the application may get frozen with the keyboard and - * mouse grabbed if gtk_menu_item_set_submenu is called while - * the menu is displayed. Reusing the same menu every time - * works around this issue. - */ - GtkMenuItem *menu = virt_viewer_window_get_menu_displays(window); - GtkMenuShell *submenu; - - submenu = GTK_MENU_SHELL(gtk_menu_item_get_submenu(menu)); - if (submenu) { - GList *subitems; - GList *it; - subitems = gtk_container_get_children(GTK_CONTAINER(submenu)); - for (it = subitems; it != NULL; it = it->next) { - gtk_container_remove(GTK_CONTAINER(submenu), GTK_WIDGET(it->data)); - } - g_list_free(subitems); - } else { - submenu = GTK_MENU_SHELL(gtk_menu_new()); - gtk_menu_item_set_submenu(menu, GTK_WIDGET(submenu)); - } - - return submenu; -} static void window_update_menu_displays_cb(gpointer value, @@ -2917,32 +2921,29 @@ window_update_menu_displays_cb(gpointer value, { VirtViewerApp *self = VIRT_VIEWER_APP(user_data); VirtViewerAppPrivate *priv = virt_viewer_app_get_instance_private(self); - GtkMenuShell *submenu; + VirtViewerWindow *window = VIRT_VIEWER_WINDOW(value); + GMenuModel *menu; GList *keys = g_hash_table_get_keys(priv->displays); GList *tmp; - gboolean sensitive; int nth; keys = g_list_sort(keys, update_menu_displays_sort); - submenu = window_empty_display_submenu(VIRT_VIEWER_WINDOW(value)); - sensitive = (keys != NULL); - virt_viewer_window_set_menu_displays_sensitive(VIRT_VIEWER_WINDOW(value), sensitive); + menu = virt_viewer_window_get_menu_displays(window); + g_menu_remove_all(G_MENU(menu)); tmp = keys; while (tmp) { - GtkWidget *item; + GMenuItem *item; gchar *label; gchar *actionname; nth = GPOINTER_TO_INT(tmp->data); actionname = g_strdup_printf("app.monitor-%d", nth); label = g_strdup_printf(_("Display _%d"), nth + 1); - item = gtk_check_menu_item_new_with_mnemonic(label); + item = g_menu_item_new(label, actionname); - gtk_actionable_set_action_name(GTK_ACTIONABLE(item), actionname); - - gtk_menu_shell_append(submenu, item); + g_menu_append_item(G_MENU(menu), item); g_free(label); g_free(actionname); @@ -2956,24 +2957,21 @@ window_update_menu_displays_cb(gpointer value, if (VIRT_VIEWER_IS_DISPLAY_VTE(display)) { gchar *name = NULL; - GtkWidget *item; + GMenuItem *item; gchar *actionname; g_object_get(display, "name", &name, NULL); actionname = g_strdup_printf("app.vte-%d", nth); - item = gtk_check_menu_item_new_with_label(name); + item = g_menu_item_new(name, actionname); - gtk_actionable_set_action_name(GTK_ACTIONABLE(item), actionname); - - gtk_menu_shell_append(submenu, item); + g_menu_append_item(G_MENU(menu), item); g_free(actionname); g_free(name); } } - gtk_widget_show_all(GTK_WIDGET(submenu)); g_list_free(keys); } diff --git a/src/virt-viewer-app.h b/src/virt-viewer-app.h index 720eda0..ad40550 100644 --- a/src/virt-viewer-app.h +++ b/src/virt-viewer-app.h @@ -95,7 +95,6 @@ GList* virt_viewer_app_get_initial_displays(VirtViewerApp* self); gint virt_viewer_app_get_initial_monitor_for_display(VirtViewerApp* self, gint display); void virt_viewer_app_set_enable_accel(VirtViewerApp *app, gboolean enable); void virt_viewer_app_show_preferences(VirtViewerApp *app, GtkWidget *parent); -void virt_viewer_app_set_menus_sensitive(VirtViewerApp *self, gboolean sensitive); gboolean virt_viewer_app_get_session_cancelled(VirtViewerApp *self); gboolean virt_viewer_app_get_config_share_clipboard(VirtViewerApp *self); diff --git a/src/virt-viewer-window.c b/src/virt-viewer-window.c index 905c9c7..1615465 100644 --- a/src/virt-viewer-window.c +++ b/src/virt-viewer-window.c @@ -57,7 +57,7 @@ static void virt_viewer_window_enable_modifiers(VirtViewerWindow *self); static void virt_viewer_window_disable_modifiers(VirtViewerWindow *self); static void virt_viewer_window_queue_resize(VirtViewerWindow *self); static void virt_viewer_window_toolbar_setup(VirtViewerWindow *self); -static GtkMenu* virt_viewer_window_get_keycombo_menu(VirtViewerWindow *self); +static GMenu* virt_viewer_window_get_keycombo_menu(VirtViewerWindow *self); static void virt_viewer_window_get_minimal_dimensions(VirtViewerWindow *self, guint *width, guint *height); static gint virt_viewer_window_get_minimal_zoom_level(VirtViewerWindow *self); static void virt_viewer_window_set_fullscreen(VirtViewerWindow *self, @@ -81,6 +81,7 @@ struct _VirtViewerWindow { GtkWidget *toolbar; GtkWidget *toolbar_usb_device_selection; GtkWidget *toolbar_send_key; + GtkWidget *toolbar_send_menu; GtkAccelGroup *accel_group; VirtViewerNotebook *notebook; VirtViewerDisplay *display; @@ -205,37 +206,19 @@ rebuild_combo_menu(GObject *gobject G_GNUC_UNUSED, gpointer user_data) { VirtViewerWindow *self = user_data; - GtkWidget *menu; + GObject *button; + GMenu *menu; - menu = GTK_WIDGET(gtk_builder_get_object(self->builder, "menu-send")); - gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu), - GTK_WIDGET(virt_viewer_window_get_keycombo_menu(self))); -} + button = gtk_builder_get_object(self->builder, "header-send-key"); + menu = virt_viewer_window_get_keycombo_menu(self); -static void -vm_ui_changed(GObject *gobject G_GNUC_UNUSED, - GParamSpec *pspec G_GNUC_UNUSED, - gpointer user_data) -{ - VirtViewerWindow *self = user_data; - gboolean vm_ui; + gtk_menu_button_set_menu_model( + GTK_MENU_BUTTON(button), + G_MENU_MODEL(menu)); - g_object_get(G_OBJECT(self->app), "vm-ui", &vm_ui, NULL); - gtk_widget_set_visible(GTK_WIDGET(gtk_builder_get_object(self->builder, "menu-machine")), vm_ui); -} - -static void -vm_running_changed(GObject *gobject G_GNUC_UNUSED, - GParamSpec *pspec G_GNUC_UNUSED, - gpointer user_data) -{ - VirtViewerWindow *self = user_data; - GtkCheckMenuItem *check = GTK_CHECK_MENU_ITEM(gtk_builder_get_object(self->builder, "menu-vm-pause")); - gboolean running; - - g_object_get(G_OBJECT(self->app), "vm-running", &running, NULL); - - gtk_check_menu_item_set_active(check, !running); + if (self->toolbar_send_menu) + gtk_widget_destroy(self->toolbar_send_menu); + self->toolbar_send_menu = gtk_menu_new_from_model(G_MENU_MODEL(menu)); } static void @@ -248,10 +231,6 @@ virt_viewer_window_constructed(GObject *object) g_signal_connect(self->app, "notify::enable-accel", G_CALLBACK(rebuild_combo_menu), object); - g_signal_connect(self->app, "notify::vm-ui", - G_CALLBACK(vm_ui_changed), object); - g_signal_connect(self->app, "notify::vm-running", - G_CALLBACK(vm_running_changed), object); rebuild_combo_menu(NULL, NULL, object); } @@ -313,14 +292,6 @@ virt_viewer_window_class_init (VirtViewerWindowClass *klass) } -static gboolean -can_activate_cb (GtkWidget *widget G_GNUC_UNUSED, - guint signal_id G_GNUC_UNUSED, - VirtViewerWindow *self G_GNUC_UNUSED) -{ - return TRUE; -} - static void virt_viewer_window_action_zoom_out(GSimpleAction *act G_GNUC_UNUSED, GVariant *param G_GNUC_UNUSED, @@ -557,6 +528,8 @@ virt_viewer_window_init (VirtViewerWindow *self) { GtkWidget *vbox; GSList *accels; + GObject *menu; + GtkBuilder *menuBuilder; self->fullscreen_monitor = -1; g_value_init(&self->accel_setting, G_TYPE_STRING); @@ -570,24 +543,6 @@ virt_viewer_window_init (VirtViewerWindow *self) self->accel_group = GTK_ACCEL_GROUP(gtk_builder_get_object(self->builder, "accelgroup")); - /* make sure they can be activated even if the menu item is not visible */ - g_signal_connect(gtk_builder_get_object(self->builder, "menu-view-fullscreen"), - "can-activate-accel", G_CALLBACK(can_activate_cb), self); - g_signal_connect(gtk_builder_get_object(self->builder, "menu-file-smartcard-insert"), - "can-activate-accel", G_CALLBACK(can_activate_cb), self); - g_signal_connect(gtk_builder_get_object(self->builder, "menu-file-smartcard-remove"), - "can-activate-accel", G_CALLBACK(can_activate_cb), self); - g_signal_connect(gtk_builder_get_object(self->builder, "menu-view-release-cursor"), - "can-activate-accel", G_CALLBACK(can_activate_cb), self); - g_signal_connect(gtk_builder_get_object(self->builder, "menu-view-zoom-reset"), - "can-activate-accel", G_CALLBACK(can_activate_cb), self); - g_signal_connect(gtk_builder_get_object(self->builder, "menu-view-zoom-in"), - "can-activate-accel", G_CALLBACK(can_activate_cb), self); - g_signal_connect(gtk_builder_get_object(self->builder, "menu-view-zoom-out"), - "can-activate-accel", G_CALLBACK(can_activate_cb), self); - g_signal_connect(gtk_builder_get_object(self->builder, "menu-file-usb-device-reset"), - "can-activate-accel", G_CALLBACK(can_activate_cb), self); - vbox = GTK_WIDGET(gtk_builder_get_object(self->builder, "viewer-box")); virt_viewer_window_toolbar_setup(self); @@ -600,6 +555,19 @@ virt_viewer_window_init (VirtViewerWindow *self) gtk_window_add_accel_group(GTK_WINDOW(self->window), self->accel_group); + menuBuilder = + gtk_builder_new_from_resource(VIRT_VIEWER_RESOURCE_PREFIX "/ui/virt-viewer-menus.ui"); + + menu = gtk_builder_get_object(self->builder, "header-action"); + gtk_menu_button_set_menu_model( + GTK_MENU_BUTTON(menu), + G_MENU_MODEL(gtk_builder_get_object(menuBuilder, "action-menu"))); + + menu = gtk_builder_get_object(self->builder, "header-machine"); + gtk_menu_button_set_menu_model( + GTK_MENU_BUTTON(menu), + G_MENU_MODEL(gtk_builder_get_object(menuBuilder, "machine-menu"))); + virt_viewer_window_update_title(self); gtk_window_set_resizable(GTK_WINDOW(self->window), TRUE); self->accel_enabled = TRUE; @@ -718,19 +686,9 @@ mapped(GtkWidget *widget, GdkEvent *event G_GNUC_UNUSED, return FALSE; } -static void -virt_viewer_window_menu_fullscreen_set_active(VirtViewerWindow *self, gboolean active) -{ - GtkCheckMenuItem *check = GTK_CHECK_MENU_ITEM(gtk_builder_get_object(self->builder, "menu-view-fullscreen")); - - gtk_check_menu_item_set_active(check, active); -} - void virt_viewer_window_leave_fullscreen(VirtViewerWindow *self) { - GtkWidget *menu = GTK_WIDGET(gtk_builder_get_object(self->builder, "top-menu")); - /* if we enter and leave fullscreen mode before being shown, make sure to * disconnect the mapped signal handler */ g_signal_handlers_disconnect_by_func(self->window, mapped, self); @@ -738,7 +696,6 @@ virt_viewer_window_leave_fullscreen(VirtViewerWindow *self) if (!self->fullscreen) return; - virt_viewer_window_menu_fullscreen_set_active(self, FALSE); self->fullscreen = FALSE; self->fullscreen_monitor = -1; if (self->display) { @@ -746,7 +703,6 @@ virt_viewer_window_leave_fullscreen(VirtViewerWindow *self) virt_viewer_display_set_fullscreen(self->display, FALSE); } virt_viewer_timed_revealer_force_reveal(self->revealer, FALSE); - gtk_widget_show(menu); gtk_widget_hide(self->toolbar); gtk_widget_set_size_request(self->window, -1, -1); gtk_window_unfullscreen(GTK_WINDOW(self->window)); @@ -756,8 +712,6 @@ virt_viewer_window_leave_fullscreen(VirtViewerWindow *self) void virt_viewer_window_enter_fullscreen(VirtViewerWindow *self, gint monitor) { - GtkWidget *menu = GTK_WIDGET(gtk_builder_get_object(self->builder, "top-menu")); - if (self->fullscreen && self->fullscreen_monitor != monitor) virt_viewer_window_leave_fullscreen(self); @@ -778,9 +732,6 @@ virt_viewer_window_enter_fullscreen(VirtViewerWindow *self, gint monitor) return; } - virt_viewer_window_menu_fullscreen_set_active(self, TRUE); - gtk_widget_hide(menu); - if (!self->kiosk) { gtk_widget_show(self->toolbar); virt_viewer_timed_revealer_force_reveal(self->revealer, TRUE); @@ -839,24 +790,19 @@ get_nkeys(const guint32 *keys) } static void -virt_viewer_menu_add_combo(VirtViewerWindow *self G_GNUC_UNUSED, GtkMenu *menu, +virt_viewer_menu_add_combo(VirtViewerWindow *self G_GNUC_UNUSED, GMenu *menu, const guint *keys, const gchar *label) { - GtkWidget *item; + GMenuItem *item = g_menu_item_new(label, NULL); - if (keys == NULL || keys[0] == GDK_KEY_VoidSymbol) { - item = gtk_separator_menu_item_new(); - } else { - item = gtk_menu_item_new_with_label(label); - 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, - keys, - get_nkeys(keys), - sizeof(guint32))); - } + g_menu_item_set_action_and_target_value(item, + "win.send-key", + g_variant_new_fixed_array(G_VARIANT_TYPE_UINT32, + keys, + get_nkeys(keys), + sizeof(guint32))); - gtk_container_add(GTK_CONTAINER(menu), item); + g_menu_append_item(menu, item); } static guint* @@ -892,28 +838,40 @@ accel_key_to_keys(guint accel_key, return keys; } -static GtkMenu* +static GMenu * virt_viewer_window_get_keycombo_menu(VirtViewerWindow *self) { gint i, j; - GtkMenu *menu = GTK_MENU(gtk_menu_new()); - gtk_menu_set_accel_group(menu, self->accel_group); + GMenu *menu = g_menu_new(); + GMenu *sectionitems = g_menu_new(); + GMenuItem *section = g_menu_item_new_section(NULL, G_MENU_MODEL(sectionitems)); + + g_menu_append_item(menu, section); for (i = 0 ; i < G_N_ELEMENTS(keyCombos); i++) { - gchar *label = NULL; - if (keyCombos[i].keys[0] != GDK_KEY_VoidSymbol) { + if (keyCombos[i].keys[0] == GDK_KEY_VoidSymbol) { + sectionitems = g_menu_new(); + section = g_menu_item_new_section(NULL, G_MENU_MODEL(sectionitems)); + g_menu_append_item(menu, section); + } else { + gchar *label = NULL; guint key; GdkModifierType mods; gtk_accelerator_parse(keyCombos[i].accel_label, &key, &mods); label = gtk_accelerator_get_label(key, mods); + + virt_viewer_menu_add_combo(self, sectionitems, keyCombos[i].keys, label); + g_free(label); } - virt_viewer_menu_add_combo(self, menu, keyCombos[i].keys, label); - g_free(label); } if (virt_viewer_app_get_enable_accel(self->app)) { gchar **accelactions = gtk_application_list_action_descriptions(GTK_APPLICATION(self->app)); + sectionitems = g_menu_new(); + section = g_menu_item_new_section(NULL, G_MENU_MODEL(sectionitems)); + g_menu_append_item(menu, section); + for (i = 0; accelactions[i] != NULL; i++) { gchar **accels = gtk_application_get_accels_for_action(GTK_APPLICATION(self->app), accelactions[i]); @@ -925,7 +883,7 @@ virt_viewer_window_get_keycombo_menu(VirtViewerWindow *self) 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); + virt_viewer_menu_add_combo(self, sectionitems, keys, label); g_free(label); g_free(keys); } @@ -935,7 +893,6 @@ virt_viewer_window_get_keycombo_menu(VirtViewerWindow *self) g_strfreev(accelactions); } - gtk_widget_show_all(GTK_WIDGET(menu)); return menu; } @@ -1034,7 +991,6 @@ virt_viewer_window_set_fullscreen(VirtViewerWindow *self, } } - static void keycombo_menu_location(GtkMenu *menu G_GNUC_UNUSED, gint *x, gint *y, gboolean *push_in, gpointer user_data) { @@ -1054,15 +1010,13 @@ static void virt_viewer_window_toolbar_send_key(GtkWidget *button G_GNUC_UNUSED, VirtViewerWindow *self) { - GtkMenu *menu = virt_viewer_window_get_keycombo_menu(self); - gtk_menu_attach_to_widget(menu, self->window, NULL); - g_object_ref_sink(menu); - gtk_menu_popup(menu, NULL, NULL, keycombo_menu_location, self, + gtk_menu_attach_to_widget(GTK_MENU(self->toolbar_send_menu), + self->window, NULL); + gtk_menu_popup(GTK_MENU(self->toolbar_send_menu), + NULL, NULL, keycombo_menu_location, self, 0, gtk_get_current_event_time()); - g_object_unref(menu); } - static void add_if_writable (GdkPixbufFormat *data, GHashTable *formats) { if (gdk_pixbuf_format_is_writable(data)) { @@ -1345,7 +1299,6 @@ virt_viewer_window_toolbar_setup(VirtViewerWindow *self) gtk_widget_show(button); gtk_toolbar_insert(GTK_TOOLBAR(self->toolbar), GTK_TOOL_ITEM(button), 0); g_signal_connect(button, "clicked", G_CALLBACK(virt_viewer_window_toolbar_send_key), self); - gtk_widget_set_sensitive(button, FALSE); self->toolbar_send_key = button; /* Leave fullscreen */ @@ -1467,69 +1420,62 @@ virt_viewer_window_update_title(VirtViewerWindow *self) g_free(title); } -void -virt_viewer_window_set_menu_displays_sensitive(VirtViewerWindow *self, gboolean sensitive) -{ - GtkWidget *menu; - - g_return_if_fail(VIRT_VIEWER_IS_WINDOW(self)); - - menu = GTK_WIDGET(gtk_builder_get_object(self->builder, "menu-displays")); - gtk_widget_set_sensitive(menu, sensitive); -} - void virt_viewer_window_set_usb_options_sensitive(VirtViewerWindow *self, gboolean sensitive) { - GtkWidget *menu; + GAction *action; + GActionMap *map; g_return_if_fail(VIRT_VIEWER_IS_WINDOW(self)); - menu = GTK_WIDGET(gtk_builder_get_object(self->builder, "menu-file-usb-device-selection")); - gtk_widget_set_sensitive(menu, sensitive); - gtk_widget_set_visible(self->toolbar_usb_device_selection, sensitive); + map = G_ACTION_MAP(self->window); + action = g_action_map_lookup_action(map, "usb-device-select"); + g_simple_action_set_enabled(G_SIMPLE_ACTION(action), sensitive); } void virt_viewer_window_set_usb_reset_sensitive(VirtViewerWindow *self, gboolean sensitive) { - GtkWidget *menu; + GAction *action; + GActionMap *map; g_return_if_fail(VIRT_VIEWER_IS_WINDOW(self)); - menu = GTK_WIDGET(gtk_builder_get_object(self->builder, "menu-file-usb-device-reset")); - gtk_widget_set_sensitive(menu, sensitive); + map = G_ACTION_MAP(self->window); + action = g_action_map_lookup_action(map, "usb-device-reset"); + g_simple_action_set_enabled(G_SIMPLE_ACTION(action), sensitive); } void -virt_viewer_window_set_menus_sensitive(VirtViewerWindow *self, gboolean sensitive) +virt_viewer_window_set_actions_sensitive(VirtViewerWindow *self, gboolean sensitive) { - GtkWidget *menu; + GAction *action; + GActionMap *map; g_return_if_fail(VIRT_VIEWER_IS_WINDOW(self)); - menu = GTK_WIDGET(gtk_builder_get_object(self->builder, "menu-preferences")); - gtk_widget_set_sensitive(menu, sensitive); + map = G_ACTION_MAP(self->window); + action = g_action_map_lookup_action(map, "preferences"); + g_simple_action_set_enabled(G_SIMPLE_ACTION(action), sensitive); - menu = GTK_WIDGET(gtk_builder_get_object(self->builder, "menu-file-screenshot")); - gtk_widget_set_sensitive(menu, sensitive && - VIRT_VIEWER_DISPLAY_CAN_SCREENSHOT(self->display)); + action = g_action_map_lookup_action(map, "screenshot"); + g_simple_action_set_enabled(G_SIMPLE_ACTION(action), + sensitive && + VIRT_VIEWER_DISPLAY_CAN_SCREENSHOT(self->display)); - menu = GTK_WIDGET(gtk_builder_get_object(self->builder, "menu-view-zoom")); - gtk_widget_set_sensitive(menu, sensitive); + action = g_action_map_lookup_action(map, "zoom-in"); + g_simple_action_set_enabled(G_SIMPLE_ACTION(action), sensitive); - menu = GTK_WIDGET(gtk_builder_get_object(self->builder, "menu-machine")); - gtk_widget_set_sensitive(menu, sensitive); + action = g_action_map_lookup_action(map, "zoom-out"); + g_simple_action_set_enabled(G_SIMPLE_ACTION(action), sensitive); - { - gboolean can_send = sensitive && - VIRT_VIEWER_DISPLAY_CAN_SEND_KEYS(self->display); + action = g_action_map_lookup_action(map, "zoom-reset"); + g_simple_action_set_enabled(G_SIMPLE_ACTION(action), sensitive); - menu = GTK_WIDGET(gtk_builder_get_object(self->builder, "menu-send")); - gtk_widget_set_sensitive(menu, can_send); - - gtk_widget_set_sensitive(self->toolbar_send_key, can_send); - } + action = g_action_map_lookup_action(map, "send-key"); + g_simple_action_set_enabled(G_SIMPLE_ACTION(action), + sensitive && + VIRT_VIEWER_DISPLAY_CAN_SEND_KEYS(self->display)); } static void @@ -1537,6 +1483,8 @@ display_show_hint(VirtViewerDisplay *display, GParamSpec *pspec G_GNUC_UNUSED, VirtViewerWindow *self) { + GAction *action; + GActionMap *map; guint hint; g_object_get(display, "show-hint", &hint, NULL); @@ -1548,8 +1496,13 @@ display_show_hint(VirtViewerDisplay *display, virt_viewer_window_set_zoom_level(self, self->zoomlevel); } - gtk_widget_set_sensitive(GTK_WIDGET(gtk_builder_get_object(self->builder, "menu-file-screenshot")), hint); + map = G_ACTION_MAP(self->window); + action = g_action_map_lookup_action(map, "screenshot"); + g_simple_action_set_enabled(G_SIMPLE_ACTION(action), + hint); } + + static gboolean window_key_pressed (GtkWidget *widget G_GNUC_UNUSED, GdkEvent *ev, @@ -1642,8 +1595,6 @@ virt_viewer_window_set_display(VirtViewerWindow *self, VirtViewerDisplay *displa if (virt_viewer_display_get_enabled(display)) virt_viewer_window_desktop_resize(display, self); - - virt_viewer_window_set_menus_sensitive(self, TRUE); } } @@ -1733,12 +1684,17 @@ gint virt_viewer_window_get_zoom_level(VirtViewerWindow *self) return self->zoomlevel; } -GtkMenuItem* +GMenuModel * virt_viewer_window_get_menu_displays(VirtViewerWindow *self) { + GObject *menu; + GMenuModel *model; g_return_val_if_fail(VIRT_VIEWER_IS_WINDOW(self), NULL); - return GTK_MENU_ITEM(gtk_builder_get_object(self->builder, "menu-displays")); + menu = gtk_builder_get_object(self->builder, "header-machine"); + model = gtk_menu_button_get_menu_model(GTK_MENU_BUTTON(menu)); + + return g_menu_model_get_item_link(model, 0, G_MENU_LINK_SECTION); } GtkBuilder* @@ -1775,20 +1731,12 @@ virt_viewer_window_set_kiosk(VirtViewerWindow *self, gboolean enabled) } static void -virt_viewer_window_get_minimal_dimensions(VirtViewerWindow *self, +virt_viewer_window_get_minimal_dimensions(VirtViewerWindow *self G_GNUC_UNUSED, guint *width, guint *height) { - GtkRequisition req; - GtkWidget *top_menu; - - top_menu = GTK_WIDGET(gtk_builder_get_object(virt_viewer_window_get_builder(self), "top-menu")); - gtk_widget_get_preferred_size(top_menu, &req, NULL); - /* minimal dimensions of the window are the maximum of dimensions of the top-menu - * and minimal dimension of the display - */ *height = MIN_DISPLAY_HEIGHT; - *width = MAX(MIN_DISPLAY_WIDTH, req.width); + *width = MIN_DISPLAY_WIDTH; } /** diff --git a/src/virt-viewer-window.h b/src/virt-viewer-window.h index cdb51db..1f5a120 100644 --- a/src/virt-viewer-window.h +++ b/src/virt-viewer-window.h @@ -46,10 +46,9 @@ GtkWindow* virt_viewer_window_get_window (VirtViewerWindow* window); VirtViewerNotebook* virt_viewer_window_get_notebook (VirtViewerWindow* window); void virt_viewer_window_set_display(VirtViewerWindow *self, VirtViewerDisplay *display); VirtViewerDisplay* virt_viewer_window_get_display(VirtViewerWindow *self); -void virt_viewer_window_set_menu_displays_sensitive(VirtViewerWindow *self, gboolean sensitive); void virt_viewer_window_set_usb_options_sensitive(VirtViewerWindow *self, gboolean sensitive); void virt_viewer_window_set_usb_reset_sensitive(VirtViewerWindow *self, gboolean sensitive); -void virt_viewer_window_set_menus_sensitive(VirtViewerWindow *self, gboolean sensitive); +void virt_viewer_window_set_actions_sensitive(VirtViewerWindow *self, gboolean sensitive); void virt_viewer_window_update_title(VirtViewerWindow *self); void virt_viewer_window_show(VirtViewerWindow *self); void virt_viewer_window_hide(VirtViewerWindow *self); @@ -60,7 +59,7 @@ void virt_viewer_window_zoom_reset(VirtViewerWindow *self); gint virt_viewer_window_get_zoom_level(VirtViewerWindow *self); void virt_viewer_window_leave_fullscreen(VirtViewerWindow *self); void virt_viewer_window_enter_fullscreen(VirtViewerWindow *self, gint monitor); -GtkMenuItem *virt_viewer_window_get_menu_displays(VirtViewerWindow *self); +GMenuModel *virt_viewer_window_get_menu_displays(VirtViewerWindow *self); GtkBuilder* virt_viewer_window_get_builder(VirtViewerWindow *window); void virt_viewer_window_set_kiosk(VirtViewerWindow *self, gboolean enabled); void virt_viewer_window_show_about(VirtViewerWindow *self); diff --git a/src/virt-viewer.c b/src/virt-viewer.c index 23b6ad8..538c05c 100644 --- a/src/virt-viewer.c +++ b/src/virt-viewer.c @@ -294,7 +294,6 @@ virt_viewer_deactivated(VirtViewerApp *app, gboolean connect_error) virt_viewer_app_show_status(app, _("Waiting for guest domain to re-start")); virt_viewer_app_trace(app, "Guest %s display has disconnected, waiting to reconnect", self->domkey); - virt_viewer_app_set_menus_sensitive(app, FALSE); } else { VIRT_VIEWER_APP_CLASS(virt_viewer_parent_class)->deactivated(app, connect_error); }