[virt-tools-list] [PATCH virt-viewer 1/2] Shift top-left display down to origin

Christophe Fergeau cfergeau at redhat.com
Thu Oct 9 12:55:51 UTC 2014


Hey,

Patch looks good to me, just a couple of minor comments.
Fwiw, this was marginally easier to review by splitting the code
movement in one patch (virt_viewer_align_monitors_linear), then the
addition of virt_viewer_shift_monitors_to_origin and finally the actual
changes.


On Tue, Oct 07, 2014 at 01:30:03PM -0500, Jonathon Jongsma wrote:
> 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
> down so that the minimum X coordinate for all screens is at x=0, and the

Nit: For me the displays are shifted up as +0+0 is the top left corner.
"We shift all displays so that..." should be good for everyone :)

> minimum y coordinate is at y=0.
> ---
>  src/virt-viewer-session-spice.c | 22 +++++++---
>  src/virt-viewer-session.c       | 53 ++----------------------
>  src/virt-viewer-util.c          | 91 +++++++++++++++++++++++++++++++++++++++++
>  src/virt-viewer-util.h          |  6 +++
>  4 files changed, 117 insertions(+), 55 deletions(-)
> 
> diff --git a/src/virt-viewer-session-spice.c b/src/virt-viewer-session-spice.c
> index 885399c..37c083e 100644
> --- a/src/virt-viewer-session-spice.c
> +++ b/src/virt-viewer-session-spice.c
> @@ -770,7 +770,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;
> @@ -804,18 +804,30 @@ 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);
> +        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];
> +        if (rect->width == 0 || rect->height == 0)
> +            continue;

The initial code did not skip disabled displays, any idea if this was
causing issues? Or was this handled by checking
virt_viewer_app_get_initial_monitor_for_display() for -1 ?

> +
> +        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;
> diff --git a/src/virt-viewer-session.c b/src/virt-viewer-session.c
> index d9c84a6..4262eda 100644
> --- a/src/virt-viewer-session.c
> +++ b/src/virt-viewer-session.c
> @@ -339,55 +339,6 @@ virt_viewer_session_init(VirtViewerSession *session)
>      session->priv = VIRT_VIEWER_SESSION_GET_PRIVATE(session);
>  }
>  
> -/* simple sorting of monitors. Primary sort left-to-right, secondary sort from
> - * top-to-bottom, finally by monitor id */
> -static int
> -displays_cmp(const void *p1, const void *p2, gpointer user_data)
> -{
> -    guint diff;
> -    GdkRectangle *displays = user_data;
> -    guint i = *(guint*)p1;
> -    guint j = *(guint*)p2;
> -    GdkRectangle *m1 = &displays[i];
> -    GdkRectangle *m2 = &displays[j];
> -    diff = m1->x - m2->x;
> -    if (diff == 0)
> -        diff = m1->y - m2->y;
> -    if (diff == 0)
> -        diff = i - j;
> -
> -    return diff;
> -}
> -
> -static void
> -virt_viewer_session_align_monitors_linear(GdkRectangle *displays, guint ndisplays)
> -{
> -    gint i, x = 0;
> -    guint *sorted_displays;
> -
> -    g_return_if_fail(displays != NULL);
> -
> -    if (ndisplays == 0)
> -        return;
> -
> -    sorted_displays = g_new0(guint, ndisplays);
> -    for (i = 0; i < ndisplays; i++)
> -        sorted_displays[i] = i;
> -    g_qsort_with_data(sorted_displays, ndisplays, sizeof(guint), displays_cmp, displays);
> -
> -    /* adjust monitor positions so that there's no gaps or overlap between
> -     * monitors */
> -    for (i = 0; i < ndisplays; i++) {
> -        guint nth = sorted_displays[i];
> -        g_assert(nth < ndisplays);
> -        GdkRectangle *rect = &displays[nth];
> -        rect->x = x;
> -        rect->y = 0;
> -        x += rect->width;
> -    }
> -    g_free(sorted_displays);
> -}
> -
>  static void
>  virt_viewer_session_on_monitor_geometry_changed(VirtViewerSession* self,
>                                                  VirtViewerDisplay* display G_GNUC_UNUSED)
> @@ -428,7 +379,9 @@ virt_viewer_session_on_monitor_geometry_changed(VirtViewerSession* self,
>      }
>  
>      if (!all_fullscreen)
> -        virt_viewer_session_align_monitors_linear(monitors, nmonitors);
> +        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);
> diff --git a/src/virt-viewer-util.c b/src/virt-viewer-util.c
> index 655f489..401b220 100644
> --- a/src/virt-viewer-util.c
> +++ b/src/virt-viewer-util.c
> @@ -488,6 +488,97 @@ end:
>      g_strfreev(v2);
>      return retval;
>  }
> +
> +/* simple sorting of monitors. Primary sort left-to-right, secondary sort from
> + * top-to-bottom, finally by monitor id */
> +static int
> +displays_cmp(const void *p1, const void *p2, gpointer user_data)
> +{
> +    guint diff;
> +    GdkRectangle *displays = user_data;
> +    guint i = *(guint*)p1;
> +    guint j = *(guint*)p2;
> +    GdkRectangle *m1 = &displays[i];
> +    GdkRectangle *m2 = &displays[j];
> +    diff = m1->x - m2->x;
> +    if (diff == 0)
> +        diff = m1->y - m2->y;
> +    if (diff == 0)
> +        diff = i - j;
> +
> +    return diff;
> +}
> +
> +void
> +virt_viewer_align_monitors_linear(GdkRectangle *displays, guint ndisplays)
> +{
> +    gint i, x = 0;
> +    guint *sorted_displays;
> +
> +    g_return_if_fail(displays != NULL);
> +
> +    if (ndisplays == 0)
> +        return;
> +
> +    sorted_displays = g_new0(guint, ndisplays);
> +    for (i = 0; i < ndisplays; i++)
> +        sorted_displays[i] = i;
> +    g_qsort_with_data(sorted_displays, ndisplays, sizeof(guint), displays_cmp, displays);
> +
> +    /* adjust monitor positions so that there's no gaps or overlap between
> +     * monitors */
> +    for (i = 0; i < ndisplays; i++) {
> +        guint nth = sorted_displays[i];
> +        g_assert(nth < ndisplays);
> +        GdkRectangle *rect = &displays[nth];
> +        rect->x = x;
> +        rect->y = 0;
> +        x += rect->width;
> +    }
> +    g_free(sorted_displays);
> +}
> +
> +/* Shift all displays down so that the monitor origin is at (0,0). This reduces

Same comment about 'down' which could be removed.

> + * the size of the screen that will be required on the guest in the case where
> + * there is a fullscreen window on a non-primary client monitor. For example,

Is primary client monitor always +0+0 ? If not, let's remove the
'non-primary'

> + * 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 is only 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);
> +        }
> +    }
> +
> +    if (xmin > 0 || ymin > 0) {
> +        g_debug("%s: Shifting all monitors down by (%i, %i)", G_STRFUNC, xmin, ymin);

s/down//

ACK.

Christophe
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/virt-tools-list/attachments/20141009/98f877e3/attachment.sig>


More information about the virt-tools-list mailing list