mirror of
https://gitlab.uni-freiburg.de/opensourcevdi/virt-viewer
synced 2026-01-05 11:18:38 +00:00
Shift top-left display to origin
When using a custom fullscreen display configuration, it's possible to specify that e.g. a single screen should be fullscreen on client monitor #4. Since we send down absolute positions and disable alignment when all windows are in fullscreen, we can send configurations with a very large offset to the top-left corner. This could result in the guest trying to create a screen that was much larger than necessary. For example when sending a configuration of 1280x1024+4240+0, the guest would need to allocate a screen of size 5520x1024, which might fail if video memory was too low. To avoid this issue, we shift all displays so that the minimum X coordinate for all screens is at x=0, and the minimum y coordinate is at y=0.
This commit is contained in:
parent
221d5f5cd4
commit
8fa5e004ec
@ -804,7 +804,7 @@ virt_viewer_session_spice_fullscreen_auto_conf(VirtViewerSessionSpice *self)
|
||||
GdkScreen *screen = gdk_screen_get_default();
|
||||
SpiceMainChannel* cmain = virt_viewer_session_spice_get_main_channel(self);
|
||||
VirtViewerApp *app = NULL;
|
||||
GdkRectangle dest;
|
||||
GdkRectangle *displays;
|
||||
gboolean agent_connected;
|
||||
gint i;
|
||||
gsize ndisplays = 0;
|
||||
@ -838,19 +838,29 @@ virt_viewer_session_spice_fullscreen_auto_conf(VirtViewerSessionSpice *self)
|
||||
|
||||
ndisplays = virt_viewer_app_get_n_initial_displays(app);
|
||||
g_debug("Performing full screen auto-conf, %" G_GSIZE_FORMAT " host monitors", ndisplays);
|
||||
displays = g_new0(GdkRectangle, ndisplays);
|
||||
|
||||
for (i = 0; i < ndisplays; i++) {
|
||||
GdkRectangle* rect = &displays[i];
|
||||
gint j = virt_viewer_app_get_initial_monitor_for_display(app, i);
|
||||
if (j == -1)
|
||||
continue;
|
||||
|
||||
gdk_screen_get_monitor_geometry(screen, j, &dest);
|
||||
g_debug("Set SPICE display %d to (%d,%d)-(%dx%d)",
|
||||
i, dest.x, dest.y, dest.width, dest.height);
|
||||
spice_main_set_display(cmain, i, dest.x, dest.y, dest.width, dest.height);
|
||||
spice_main_set_display_enabled(cmain, i, TRUE);
|
||||
gdk_screen_get_monitor_geometry(screen, j, rect);
|
||||
}
|
||||
|
||||
virt_viewer_shift_monitors_to_origin(displays, ndisplays);
|
||||
|
||||
for (i = 0; i < ndisplays; i++) {
|
||||
GdkRectangle *rect = &displays[i];
|
||||
|
||||
spice_main_set_display(cmain, i, rect->x, rect->y, rect->width, rect->height);
|
||||
spice_main_set_display_enabled(cmain, i, TRUE);
|
||||
g_debug("Set SPICE display %d to (%d,%d)-(%dx%d)",
|
||||
i, rect->x, rect->y, rect->width, rect->height);
|
||||
}
|
||||
g_free(displays);
|
||||
|
||||
spice_main_send_monitor_config(cmain);
|
||||
self->priv->did_auto_conf = TRUE;
|
||||
return TRUE;
|
||||
|
||||
@ -381,6 +381,8 @@ virt_viewer_session_on_monitor_geometry_changed(VirtViewerSession* self,
|
||||
if (!all_fullscreen)
|
||||
virt_viewer_align_monitors_linear(monitors, nmonitors);
|
||||
|
||||
virt_viewer_shift_monitors_to_origin(monitors, nmonitors);
|
||||
|
||||
klass->apply_monitor_geometry(self, monitors, nmonitors);
|
||||
g_free(monitors);
|
||||
}
|
||||
|
||||
@ -538,6 +538,48 @@ virt_viewer_align_monitors_linear(GdkRectangle *displays, guint ndisplays)
|
||||
g_free(sorted_displays);
|
||||
}
|
||||
|
||||
/* Shift all displays so that the monitor origin is at (0,0). This reduces the
|
||||
* size of the screen that will be required on the guest when all client
|
||||
* monitors are fullscreen but do not begin at the origin. For example, instead
|
||||
* of sending down the following configuration:
|
||||
* 1280x1024+4240+0
|
||||
* (which implies that the guest screen must be at least 5520x1024), we'd send
|
||||
* 1280x1024+0+0
|
||||
* (which implies the guest screen only needs to be 1280x1024). The first
|
||||
* version might fail if the guest video memory is not large enough to handle a
|
||||
* screen of that size.
|
||||
*/
|
||||
void
|
||||
virt_viewer_shift_monitors_to_origin(GdkRectangle *displays, guint ndisplays)
|
||||
{
|
||||
gint xmin = G_MAXINT;
|
||||
gint ymin = G_MAXINT;
|
||||
gint i;
|
||||
|
||||
g_return_if_fail(ndisplays > 0);
|
||||
|
||||
for (i = 0; i < ndisplays; i++) {
|
||||
GdkRectangle *display = &displays[i];
|
||||
if (display->width > 0 && display->height > 0) {
|
||||
xmin = MIN(xmin, display->x);
|
||||
ymin = MIN(ymin, display->y);
|
||||
}
|
||||
}
|
||||
g_return_if_fail(xmin < G_MAXINT && ymin < G_MAXINT);
|
||||
|
||||
if (xmin > 0 || ymin > 0) {
|
||||
g_debug("%s: Shifting all monitors by (%i, %i)", G_STRFUNC, xmin, ymin);
|
||||
for (i = 0; i < ndisplays; i++) {
|
||||
GdkRectangle *display = &displays[i];
|
||||
if (display->width > 0 && display->height > 0) {
|
||||
display->x -= xmin;
|
||||
display->y -= ymin;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Local variables:
|
||||
* c-indent-level: 4
|
||||
|
||||
@ -58,6 +58,7 @@ gint virt_viewer_compare_version(const gchar *s1, const gchar *s2);
|
||||
|
||||
/* monitor alignment */
|
||||
void virt_viewer_align_monitors_linear(GdkRectangle *displays, guint ndisplays);
|
||||
void virt_viewer_shift_monitors_to_origin(GdkRectangle *displays, guint ndisplays);
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user