From bb9664de38f9bfc1e093843eb868233b7199d620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= Date: Thu, 11 Feb 2021 14:14:54 +0000 Subject: [PATCH] src: switch main window to use GtkHeaderBar MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This removes the main menu bar in favour of using the GtkHeaderBar with integrated bars. This reduces the amount of vertical screen real estate consumed by the application, leaving more for the guest display. The new buttons are laid out to make the more common actions available with a single click. The buttons are grouped into two sets. On the left hand side of the header are buttons that are interacting with the server - Send key - USB device selection - Monitor selection and VM pause/shutdown whle on the right hand side are buttons interacting with the local user interface - Fullscreen - Preferences / About / Guest detail / zoom level Signed-off-by: Daniel P. Berrangé --- src/resources/ui/virt-viewer-menus.ui | 60 ++++ src/resources/ui/virt-viewer.ui | 402 ++++++------------------ src/resources/virt-viewer.gresource.xml | 1 + src/virt-viewer-app.c | 100 +++--- src/virt-viewer-app.h | 1 - src/virt-viewer-window.c | 266 +++++++--------- src/virt-viewer-window.h | 5 +- src/virt-viewer.c | 1 - 8 files changed, 315 insertions(+), 521 deletions(-) create mode 100644 src/resources/ui/virt-viewer-menus.ui 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); }