overlay: Add support for multi-monitor positioning
authorChris Wilson <chris@chris-wilson.co.uk>
Tue, 27 Aug 2013 13:25:38 +0000 (14:25 +0100)
committerChris Wilson <chris@chris-wilson.co.uk>
Tue, 27 Aug 2013 13:26:22 +0000 (14:26 +0100)
Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
configure.ac
overlay/Makefile.am
overlay/kms/kms-overlay.c
overlay/overlay.h
overlay/x11/position.c
overlay/x11/position.h
overlay/x11/x11-overlay.c
overlay/x11/x11-window.c

index b7034ac..9eafe63 100644 (file)
@@ -84,6 +84,7 @@ fi
 if test x$enable_overlay_xlib = xyes; then
        AC_DEFINE(HAVE_OVERLAY_XLIB, 1, [Enable X backend])
 fi
+PKG_CHECK_MODULES(XRANDR, xrandr >= 1.3, AC_DEFINE(HAVE_XRANDR, 1, [Have libXrandr]), [have_xrandr=no])
 
 # for testdisplay
 PKG_CHECK_MODULES(CAIRO, [cairo >= 1.12.0])
index 8f829fe..395b8ed 100644 (file)
@@ -39,8 +39,8 @@ intel_gpu_overlay_SOURCES = \
 
 if BUILD_OVERLAY_XLIB
 both_x11_sources = x11/position.c x11/position.h
-AM_CFLAGS += $(OVERLAY_XLIB_CFLAGS)
-LDADD += $(OVERLAY_XLIB_LIBS)
+AM_CFLAGS += $(OVERLAY_XLIB_CFLAGS) $(XRANDR_CFLAGS)
+LDADD += $(OVERLAY_XLIB_LIBS) $(XRANDR_LIBS)
 intel_gpu_overlay_SOURCES += \
        x11/x11-window.c \
        $(NULL)
@@ -48,8 +48,8 @@ endif
 
 if BUILD_OVERLAY_XVLIB
 both_x11_sources = x11/x11-position.c
-AM_CFLAGS += $(OVERLAY_XVLIB_CFLAGS)
-LDADD += $(OVERLAY_XVLIB_LIBS)
+AM_CFLAGS += $(OVERLAY_XVLIB_CFLAGS) $(XRANDR_CFLAGS)
+LDADD += $(OVERLAY_XVLIB_LIBS) $(XRANDR_LIBS)
 intel_gpu_overlay_SOURCES += \
        x11/dri2.c \
        x11/dri2.h \
index e49a495..cfb3d5a 100644 (file)
@@ -124,11 +124,6 @@ static void kms_overlay_show(struct overlay *overlay)
        }
 }
 
-static void kms_overlay_position(struct overlay *overlay,
-                                enum position p)
-{
-}
-
 static void kms_overlay_hide(struct overlay *overlay)
 {
        struct kms_overlay *priv = to_kms_overlay(overlay);
@@ -309,7 +304,6 @@ kms_overlay_create(struct config *config, int *width, int *height)
                goto err_mem;
 
        priv->base.show = kms_overlay_show;
-       priv->base.position = kms_overlay_position;
        priv->base.hide = kms_overlay_hide;
 
        priv->visible = false;
index 3733fce..793816d 100644 (file)
@@ -58,7 +58,6 @@ enum position {
 struct overlay {
        cairo_surface_t *surface;
        void (*show)(struct overlay *);
-       void (*position)(struct overlay *, enum position);
        void (*hide)(struct overlay *);
 };
 
index ebfc3af..f430281 100644 (file)
  *
  */
 
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
 #include <X11/Xlib.h>
+#ifdef HAVE_XRANDR
+#include <X11/extensions/Xrandr.h>
+#endif
 #include <string.h>
 #include <stdio.h>
+#include <stdlib.h>
 
 #include "position.h"
 #include "../overlay.h"
@@ -65,8 +73,47 @@ static enum position get_position(struct config *config)
        return POS_UNSET;
 }
 
+static void screen_size(Display *dpy, struct config *config,
+                       int *scr_x, int *scr_y, int *scr_width, int *scr_height)
+{
+       const char *crtc;
+       Screen *scr;
+
+#ifdef HAVE_XRANDR
+       crtc = config_get_value(config, "x11", "crtc");
+       if (crtc) {
+               XRRScreenResources *res;
+               int i = atoi(crtc);
+               int ok = 0;
+
+               res = XRRGetScreenResourcesCurrent(dpy, DefaultRootWindow(dpy));
+               if (res) {
+                       if (i < res->ncrtc) {
+                               XRRCrtcInfo *info = XRRGetCrtcInfo (dpy, res, res->crtcs[i]);
+                               if (info) {
+                                       *scr_x = info->x;
+                                       *scr_y = info->y;
+                                       *scr_width = info->width;
+                                       *scr_height = info->height;
+                                       ok = 1;
+                                       XRRFreeCrtcInfo(info);
+                               }
+                       }
+                       XRRFreeScreenResources(res);
+               }
+               if (ok)
+                       return;
+       }
+#endif
+
+       scr = ScreenOfDisplay(dpy, DefaultScreen(dpy));
+       *scr_x = *scr_y = 0;
+       *scr_width = scr->width;
+       *scr_height = scr->height;
+}
+
 enum position
-x11_position(Screen *scr, int width, int height,
+x11_position(Display *dpy, int width, int height,
             struct config *config,
             int *x, int *y, int *w, int *h)
 {
@@ -85,11 +132,14 @@ x11_position(Screen *scr, int width, int height,
                if (*h < height/2)
                        *h = height/2;
        } else {
+               int scr_x, scr_y, scr_width, scr_height;
+
+               screen_size(dpy, config, &scr_x, &scr_y, &scr_width, &scr_height);
                position = get_position(config);
 
                if (position != POS_UNSET) {
                        if (width == -1) {
-                               *w = scr->width;
+                               *w = scr_width;
                                switch (position & 7) {
                                default:
                                case 0:
@@ -98,7 +148,7 @@ x11_position(Screen *scr, int width, int height,
                        }
 
                        if (height == -1) {
-                               *h = scr->height;
+                               *h = scr_height;
                                switch ((position >> 4) & 7) {
                                default:
                                case 0:
@@ -132,27 +182,30 @@ x11_position(Screen *scr, int width, int height,
                                *h = height/2;
                }
 
-               if ((unsigned)*w > scr->width)
-                       *w = scr->width;
+               if ((unsigned)*w > scr_width)
+                       *w = scr_width;
 
-               if ((unsigned)*h > scr->height)
-                       *h = scr->height;
+               if ((unsigned)*h > scr_height)
+                       *h = scr_height;
 
                if (position != POS_UNSET) {
                        switch (position & 7) {
                        default:
                        case 0: *x = 0; break;
-                       case 1: *x = (scr->width - *w)/2; break;
-                       case 2: *x = scr->width - *w; break;
+                       case 1: *x = (scr_width - *w)/2; break;
+                       case 2: *x = scr_width - *w; break;
                        }
 
                        switch ((position >> 4) & 7) {
                        default:
                        case 0: *y = 0; break;
-                       case 1: *y = (scr->height - *h)/2; break;
-                       case 2: *y = scr->height - *h; break;
+                       case 1: *y = (scr_height - *h)/2; break;
+                       case 2: *y = scr_height - *h; break;
                        }
                }
+
+               *x += scr_x;
+               *y += scr_y;
        }
 
        return position;
index 6221109..c0713df 100644 (file)
@@ -31,7 +31,7 @@ struct config;
 enum position;
 
 enum position
-x11_position(Screen *scr, int width, int height,
+x11_position(Display *dpy, int width, int height,
             struct config *config,
             int *x, int *y, int *w, int *h);
 
index f57bd55..38d58b0 100644 (file)
@@ -92,37 +92,6 @@ static void x11_overlay_show(struct overlay *overlay)
        }
 }
 
-static void x11_overlay_position(struct overlay *overlay,
-                                enum position p)
-{
-       struct x11_overlay *priv = to_x11_overlay(overlay);
-       Screen *scr = ScreenOfDisplay(priv->dpy, DefaultScreen(priv->dpy));
-
-       switch (p & 7) {
-       default:
-       case 0: priv->x = 0; break;
-       case 1: priv->x = (scr->width - priv->image->width)/2; break;
-       case 2: priv->x = scr->width - priv->image->width; break;
-       }
-
-       switch ((p >> 4) & 7) {
-       default:
-       case 0: priv->y = 0; break;
-       case 1: priv->y = (scr->height - priv->image->height)/2; break;
-       case 2: priv->y = scr->height - priv->image->height; break;
-       }
-
-       if (priv->visible) {
-               XvPutImage(priv->dpy, priv->port, DefaultRootWindow(priv->dpy),
-                          priv->gc, priv->image,
-                          0, 0,
-                          priv->image->width, priv->image->height,
-                          priv->x, priv->y,
-                          priv->image->width, priv->image->height);
-               XFlush(priv->dpy);
-       }
-}
-
 static void x11_overlay_hide(struct overlay *overlay)
 {
        struct x11_overlay *priv = to_x11_overlay(overlay);
@@ -197,7 +166,7 @@ x11_overlay_create(struct config *config, int *width, int *height)
 
        XSetErrorHandler(noop);
 
-       position = x11_position(scr, *width, *height, config, &x, &y, &w, &h);
+       position = x11_position(dpy, *width, *height, config, &x, &y, &w, &h);
 
        image = XvCreateImage(dpy, port, FOURCC_RGB565, NULL, w, h);
        if (image == NULL)
@@ -276,7 +245,6 @@ x11_overlay_create(struct config *config, int *width, int *height)
 
        priv->base.surface = surface;
        priv->base.show = x11_overlay_show;
-       priv->base.position = x11_overlay_position;
        priv->base.hide = x11_overlay_hide;
 
        priv->dpy = dpy;
index 89d5c73..6bdc48c 100644 (file)
@@ -74,33 +74,6 @@ static void x11_window_show(struct overlay *overlay)
        XFlush(priv->dpy);
 }
 
-static void x11_window_position(struct overlay *overlay,
-                               enum position p)
-{
-       struct x11_window *priv = to_x11_window(overlay);
-       Screen *scr = ScreenOfDisplay(priv->dpy, DefaultScreen(priv->dpy));
-       int x, y;
-
-       switch (p & 7) {
-       default:
-       case 0: x = 0; break;
-       case 1: x = (scr->width - priv->width)/2; break;
-       case 2: x = scr->width - priv->width; break;
-       }
-
-       switch ((p >> 4) & 7) {
-       default:
-       case 0: y = 0; break;
-       case 1: y = (scr->height - priv->height)/2; break;
-       case 2: y = scr->height - priv->height; break;
-       }
-
-       if (priv->visible) {
-               XMoveWindow(priv->dpy, priv->win, x, y);
-               XFlush(priv->dpy);
-       }
-}
-
 static void x11_window_hide(struct overlay *overlay)
 {
        struct x11_window *priv = to_x11_window(overlay);
@@ -136,7 +109,6 @@ cairo_surface_t *
 x11_window_create(struct config *config, int *width, int *height)
 {
        Display *dpy;
-       Screen *scr;
        Window win;
        int screen;
        cairo_surface_t *surface;
@@ -149,11 +121,10 @@ x11_window_create(struct config *config, int *width, int *height)
                return NULL;
 
        screen = DefaultScreen(dpy);
-       scr = XScreenOfDisplay(dpy, screen);
 
        XSetErrorHandler(noop);
 
-       x11_position(scr, *width, *height, config, &x, &y, &w, &h);
+       x11_position(dpy, *width, *height, config, &x, &y, &w, &h);
 
        attr.override_redirect = True;
        win = XCreateWindow(dpy, DefaultRootWindow(dpy),
@@ -179,7 +150,6 @@ x11_window_create(struct config *config, int *width, int *height)
                goto err_priv;
 
        priv->base.show = x11_window_show;
-       priv->base.position = x11_window_position;
        priv->base.hide = x11_window_hide;
 
        priv->dpy = dpy;