mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/virt-viewer
synced 2025-12-27 23:00:54 +00:00
src: convert full screen toolbar to GtkHeaderBar
The user interface for the fullscreen toolbar is now identical to that seen when non-fullscreen. All that differs is that the toolbar autohides in fullscreen mode and doesn't expand to fill the window width. There is a complication with the timed revealer and menus. With traditional GtkMenus, it appears a grab is held as long as the menu is open, so the revealer won't hide the toolbar. With modern GtkPopover based menus, however, the revealer hides the toolbar despite the menu being open, and thus in turn hides the menu. This hacks around the problem by setting the header buttons to force use of a traditional GtkMenu instead of a GtkPopover. It is not quite as visually pretty, but at least it works. Signed-off-by: Daniel P. Berrangé <berrange@redhat.com>
This commit is contained in:
parent
bb9664de38
commit
c43eb057bd
@ -13,12 +13,102 @@
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<child>
|
||||
<object class="GtkBox" id="viewer-box">
|
||||
<object class="GtkHeaderBar" id="toolbar">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="orientation">vertical</property>
|
||||
<property name="halign">center</property>
|
||||
<property name="valign">start</property>
|
||||
<property name="show-close-button">True</property>
|
||||
<child>
|
||||
<placeholder/>
|
||||
<object class="GtkMenuButton" id="toolbar-action">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="use-popover">False</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">open-menu-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack-type">end</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="toolbar-send-key">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="use-popover">False</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">preferences-desktop-keyboard-shortcuts-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">1</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="toolbar-usb">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="action-name">win.usb-device-select</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">audio-card-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">2</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkMenuButton" id="toolbar-machine">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="use-popover">False</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">computer-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="position">3</property>
|
||||
</packing>
|
||||
</child>
|
||||
<child>
|
||||
<object class="GtkButton" id="toolbar-fullscreen">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">True</property>
|
||||
<property name="receives-default">True</property>
|
||||
<property name="action-name">win.fullscreen</property>
|
||||
<child>
|
||||
<object class="GtkImage">
|
||||
<property name="visible">True</property>
|
||||
<property name="can-focus">False</property>
|
||||
<property name="icon-name">view-restore-symbolic</property>
|
||||
</object>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
<property name="pack-type">end</property>
|
||||
<property name="position">4</property>
|
||||
</packing>
|
||||
</child>
|
||||
</object>
|
||||
<packing>
|
||||
|
||||
@ -56,7 +56,6 @@ void virt_viewer_window_guest_details_response(GtkDialog *dialog, gint response_
|
||||
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 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);
|
||||
@ -78,10 +77,6 @@ struct _VirtViewerWindow {
|
||||
|
||||
GtkBuilder *builder;
|
||||
GtkWidget *window;
|
||||
GtkWidget *toolbar;
|
||||
GtkWidget *toolbar_usb_device_selection;
|
||||
GtkWidget *toolbar_send_key;
|
||||
GtkWidget *toolbar_send_menu;
|
||||
GtkAccelGroup *accel_group;
|
||||
VirtViewerNotebook *notebook;
|
||||
VirtViewerDisplay *display;
|
||||
@ -195,7 +190,6 @@ virt_viewer_window_dispose (GObject *object)
|
||||
self->subtitle = NULL;
|
||||
|
||||
g_value_unset(&self->accel_setting);
|
||||
self->toolbar = NULL;
|
||||
|
||||
G_OBJECT_CLASS (virt_viewer_window_parent_class)->dispose (object);
|
||||
}
|
||||
@ -209,16 +203,17 @@ rebuild_combo_menu(GObject *gobject G_GNUC_UNUSED,
|
||||
GObject *button;
|
||||
GMenu *menu;
|
||||
|
||||
button = gtk_builder_get_object(self->builder, "header-send-key");
|
||||
menu = virt_viewer_window_get_keycombo_menu(self);
|
||||
|
||||
button = gtk_builder_get_object(self->builder, "header-send-key");
|
||||
gtk_menu_button_set_menu_model(
|
||||
GTK_MENU_BUTTON(button),
|
||||
G_MENU_MODEL(menu));
|
||||
|
||||
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));
|
||||
button = gtk_builder_get_object(self->builder, "toolbar-send-key");
|
||||
gtk_menu_button_set_menu_model(
|
||||
GTK_MENU_BUTTON(button),
|
||||
G_MENU_MODEL(menu));
|
||||
}
|
||||
|
||||
static void
|
||||
@ -526,7 +521,8 @@ static GActionEntry actions[] = {
|
||||
static void
|
||||
virt_viewer_window_init (VirtViewerWindow *self)
|
||||
{
|
||||
GtkWidget *vbox;
|
||||
GtkWidget *overlay;
|
||||
GtkWidget *toolbar;
|
||||
GSList *accels;
|
||||
GObject *menu;
|
||||
GtkBuilder *menuBuilder;
|
||||
@ -543,10 +539,13 @@ virt_viewer_window_init (VirtViewerWindow *self)
|
||||
|
||||
self->accel_group = GTK_ACCEL_GROUP(gtk_builder_get_object(self->builder, "accelgroup"));
|
||||
|
||||
vbox = GTK_WIDGET(gtk_builder_get_object(self->builder, "viewer-box"));
|
||||
virt_viewer_window_toolbar_setup(self);
|
||||
overlay = GTK_WIDGET(gtk_builder_get_object(self->builder, "viewer-overlay"));
|
||||
toolbar = GTK_WIDGET(gtk_builder_get_object(self->builder, "toolbar"));
|
||||
|
||||
gtk_box_pack_end(GTK_BOX(vbox), GTK_WIDGET(self->notebook), TRUE, TRUE, 0);
|
||||
gtk_container_remove(GTK_CONTAINER(overlay), toolbar);
|
||||
gtk_container_add(GTK_CONTAINER(overlay), GTK_WIDGET(self->notebook));
|
||||
self->revealer = virt_viewer_timed_revealer_new(toolbar);
|
||||
gtk_overlay_add_overlay(GTK_OVERLAY(overlay), GTK_WIDGET(self->revealer));
|
||||
|
||||
self->window = GTK_WIDGET(gtk_builder_get_object(self->builder, "viewer"));
|
||||
|
||||
@ -568,6 +567,16 @@ virt_viewer_window_init (VirtViewerWindow *self)
|
||||
GTK_MENU_BUTTON(menu),
|
||||
G_MENU_MODEL(gtk_builder_get_object(menuBuilder, "machine-menu")));
|
||||
|
||||
menu = gtk_builder_get_object(self->builder, "toolbar-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, "toolbar-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;
|
||||
@ -703,7 +712,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_hide(self->toolbar);
|
||||
gtk_widget_set_size_request(self->window, -1, -1);
|
||||
gtk_window_unfullscreen(GTK_WINDOW(self->window));
|
||||
|
||||
@ -733,7 +741,6 @@ virt_viewer_window_enter_fullscreen(VirtViewerWindow *self, gint monitor)
|
||||
}
|
||||
|
||||
if (!self->kiosk) {
|
||||
gtk_widget_show(self->toolbar);
|
||||
virt_viewer_timed_revealer_force_reveal(self->revealer, TRUE);
|
||||
}
|
||||
|
||||
@ -991,31 +998,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)
|
||||
{
|
||||
VirtViewerWindow *self = user_data;
|
||||
GtkAllocation allocation;
|
||||
GtkWidget *toplevel = gtk_widget_get_toplevel(self->toolbar_send_key);
|
||||
|
||||
*push_in = TRUE;
|
||||
gdk_window_get_origin(gtk_widget_get_window(toplevel), x, y);
|
||||
gtk_widget_translate_coordinates(self->toolbar_send_key, toplevel,
|
||||
*x, *y, x, y);
|
||||
gtk_widget_get_allocation(self->toolbar_send_key, &allocation);
|
||||
*y += allocation.height;
|
||||
}
|
||||
|
||||
static void
|
||||
virt_viewer_window_toolbar_send_key(GtkWidget *button G_GNUC_UNUSED,
|
||||
VirtViewerWindow *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());
|
||||
}
|
||||
|
||||
static void add_if_writable (GdkPixbufFormat *data, GHashTable *formats)
|
||||
{
|
||||
@ -1255,67 +1237,6 @@ virt_viewer_window_change_cd(VirtViewerWindow *self G_GNUC_UNUSED)
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
virt_viewer_window_toolbar_setup(VirtViewerWindow *self)
|
||||
{
|
||||
GtkWidget *button;
|
||||
GtkWidget *overlay;
|
||||
|
||||
self->toolbar = gtk_toolbar_new();
|
||||
gtk_toolbar_set_show_arrow(GTK_TOOLBAR(self->toolbar), FALSE);
|
||||
gtk_widget_set_no_show_all(self->toolbar, TRUE);
|
||||
gtk_toolbar_set_style(GTK_TOOLBAR(self->toolbar), GTK_TOOLBAR_BOTH_HORIZ);
|
||||
|
||||
/* Close connection */
|
||||
button = GTK_WIDGET(gtk_tool_button_new(NULL, NULL));
|
||||
gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(button), "window-close");
|
||||
gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(button), _("Disconnect"));
|
||||
gtk_widget_show(button);
|
||||
gtk_toolbar_insert(GTK_TOOLBAR(self->toolbar), GTK_TOOL_ITEM (button), 0);
|
||||
gtk_actionable_set_action_name(GTK_ACTIONABLE(button), "win.quit");
|
||||
|
||||
/* Minimize */
|
||||
button = GTK_WIDGET(gtk_tool_button_new(NULL, NULL));
|
||||
gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(button), "window-minimize-symbolic");
|
||||
gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(button), _("Minimize"));
|
||||
gtk_widget_show(button);
|
||||
gtk_toolbar_insert(GTK_TOOLBAR(self->toolbar), GTK_TOOL_ITEM(button), 0);
|
||||
gtk_actionable_set_action_name(GTK_ACTIONABLE(button), "win.minimize");
|
||||
|
||||
/* USB Device selection */
|
||||
button = gtk_image_new_from_resource(VIRT_VIEWER_RESOURCE_PREFIX"/icons/24x24/virt-viewer-usb.png");
|
||||
button = GTK_WIDGET(gtk_tool_button_new(button, NULL));
|
||||
gtk_tool_button_set_label(GTK_TOOL_BUTTON(button), _("USB device selection"));
|
||||
gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(button), _("USB device selection"));
|
||||
gtk_toolbar_insert(GTK_TOOLBAR(self->toolbar), GTK_TOOL_ITEM(button), 0);
|
||||
gtk_actionable_set_action_name(GTK_ACTIONABLE(button), "win.usb-device-select");
|
||||
self->toolbar_usb_device_selection = button;
|
||||
gtk_widget_show_all(button);
|
||||
|
||||
/* Send key */
|
||||
button = GTK_WIDGET(gtk_tool_button_new(NULL, NULL));
|
||||
gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(button), "preferences-desktop-keyboard-shortcuts");
|
||||
gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(button), _("Send key combination"));
|
||||
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);
|
||||
self->toolbar_send_key = button;
|
||||
|
||||
/* Leave fullscreen */
|
||||
button = GTK_WIDGET(gtk_tool_button_new(NULL, NULL));
|
||||
gtk_tool_button_set_icon_name(GTK_TOOL_BUTTON(button), "view-restore");
|
||||
gtk_tool_button_set_label(GTK_TOOL_BUTTON(button), _("Leave fullscreen"));
|
||||
gtk_tool_item_set_tooltip_text(GTK_TOOL_ITEM(button), _("Leave fullscreen"));
|
||||
gtk_tool_item_set_is_important(GTK_TOOL_ITEM(button), TRUE);
|
||||
gtk_widget_show(button);
|
||||
gtk_toolbar_insert(GTK_TOOLBAR(self->toolbar), GTK_TOOL_ITEM(button), 0);
|
||||
gtk_actionable_set_action_name(GTK_ACTIONABLE(button), "win.fullscreen");
|
||||
|
||||
self->revealer = virt_viewer_timed_revealer_new(self->toolbar);
|
||||
overlay = GTK_WIDGET(gtk_builder_get_object(self->builder, "viewer-overlay"));
|
||||
gtk_overlay_add_overlay(GTK_OVERLAY(overlay), GTK_WIDGET(self->revealer));
|
||||
}
|
||||
|
||||
VirtViewerNotebook*
|
||||
virt_viewer_window_get_notebook (VirtViewerWindow *self)
|
||||
{
|
||||
|
||||
Loading…
Reference in New Issue
Block a user