xserver: Branch 'master' - 3 commits

Keith Packard keithp at kemper.freedesktop.org
Thu Aug 21 18:16:20 PDT 2014


 configure.ac                |    2 
 hw/kdrive/ephyr/ephyr.c     |    8 +-
 hw/kdrive/ephyr/ephyr.h     |    3 
 hw/kdrive/ephyr/ephyrinit.c |   31 ++++++++
 hw/kdrive/ephyr/hostx.c     |  156 ++++++++++++++++++++++++++++++++++++++++++--
 hw/kdrive/ephyr/hostx.h     |   10 ++
 hw/kdrive/src/kdrive.c      |   23 +++++-
 hw/kdrive/src/kdrive.h      |    2 
 8 files changed, 220 insertions(+), 15 deletions(-)

New commits:
commit 3a51418b2db353519a1779cf3cebbcc9afba2520
Author: Laércio de Sousa <laerciosousa at sme-mogidascruzes.sp.gov.br>
Date:   Mon Aug 18 08:45:43 2014 -0300

    ephyr: set screen size & origin from host X server output's CRTC geometry
    
    If a given output is passed via new -output option, Xephyr will query
    host X server for its info. If the following conditions are met:
    
     a. RandR extension is enabled in host X server;
     b. supported RandR version in host X server is 1.2 or newer;
     c. the given output name is valid;
     d. the given output is connected;
    
    then Xephyr will get output's CRTC geometry and use it to set its own
    screen size and origin. It's just like starting Xephyr in fullscreen mode,
    but restricted to the given output's CRTC geometry (fake "Zaphod mode").
    
    This is the main feature needed for Xephyr-based single-card multiseat
    setups where we don't have separate screens to start Xephyr in fullscreen
    mode safely.
    
    Signed-off-by: Laércio de Sousa <laerciosousa at sme-mogidascruzes.sp.gov.br>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/configure.ac b/configure.ac
index f3d9654..cba7d24 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2364,7 +2364,7 @@ if test "$KDRIVE" = yes; then
        AC_DEFINE(KDRIVE_MOUSE, 1, [Enable KDrive mouse driver])
     fi
 
-    XEPHYR_REQUIRED_LIBS="xau xdmcp xcb xcb-shape xcb-aux xcb-image xcb-icccm xcb-shm xcb-keysyms"
+    XEPHYR_REQUIRED_LIBS="xau xdmcp xcb xcb-shape xcb-aux xcb-image xcb-icccm xcb-shm xcb-keysyms xcb-randr"
     if test "x$XV" = xyes; then
         XEPHYR_REQUIRED_LIBS="$XEPHYR_REQUIRED_LIBS xcb-xv"
     fi
diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index b039c68..85d4193 100644
--- a/hw/kdrive/ephyr/ephyr.c
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -111,13 +111,16 @@ Bool
 ephyrScreenInitialize(KdScreenInfo *screen)
 {
     EphyrScrPriv *scrpriv = screen->driver;
+    int x = 0, y = 0;
     int width = 640, height = 480;
     CARD32 redMask, greenMask, blueMask;
 
-    if (hostx_want_screen_size(screen, &width, &height)
+    if (hostx_want_screen_geometry(screen, &width, &height, &x, &y)
         || !screen->width || !screen->height) {
         screen->width = width;
         screen->height = height;
+        screen->x = x;
+        screen->y = y;
     }
 
     if (EphyrWantGrayScale)
diff --git a/hw/kdrive/ephyr/ephyr.h b/hw/kdrive/ephyr/ephyr.h
index 5c4936b..4e753f1 100644
--- a/hw/kdrive/ephyr/ephyr.h
+++ b/hw/kdrive/ephyr/ephyr.h
@@ -74,8 +74,10 @@ typedef struct _ephyrScrPriv {
     xcb_window_t peer_win;            /* Used for GL; should be at most one */
     xcb_image_t *ximg;
     Bool win_explicit_position;
+    int win_x, win_y;
     int win_width, win_height;
     int server_depth;
+    const char *output;         /* Set via -output option */
     unsigned char *fb_data;     /* only used when host bpp != server bpp */
     xcb_shm_segment_info_t shminfo;
 
diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c
index e04c8dc..38acc52 100644
--- a/hw/kdrive/ephyr/ephyrinit.c
+++ b/hw/kdrive/ephyr/ephyrinit.c
@@ -47,6 +47,8 @@ extern KdPointerDriver LinuxEvdevMouseDriver;
 extern KdKeyboardDriver LinuxEvdevKeyboardDriver;
 #endif
 
+void processScreenOrOutputArg(const char *screen_size, const char *output, char *parent_id);
+void processOutputArg(const char *output, char *parent_id);
 void processScreenArg(const char *screen_size, char *parent_id);
 
 void
@@ -134,6 +136,7 @@ ddxUseMsg(void)
     ErrorF("-parent <XID>        Use existing window as Xephyr root win\n");
     ErrorF("-sw-cursor           Render cursors in software in Xephyr\n");
     ErrorF("-fullscreen          Attempt to run Xephyr fullscreen\n");
+    ErrorF("-output <NAME>       Attempt to run Xephyr fullscreen (restricted to given output geometry)\n");
     ErrorF("-grayscale           Simulate 8bit grayscale\n");
     ErrorF("-resizeable          Make Xephyr windows resizeable\n");
 #ifdef GLAMOR
@@ -154,7 +157,7 @@ ddxUseMsg(void)
 }
 
 void
-processScreenArg(const char *screen_size, char *parent_id)
+processScreenOrOutputArg(const char *screen_size, const char *output, char *parent_id)
 {
     KdCardInfo *card;
 
@@ -178,13 +181,25 @@ processScreenArg(const char *screen_size, char *parent_id)
 
         use_geometry = (strchr(screen_size, '+') != NULL);
         EPHYR_DBG("screen number:%d\n", screen->mynum);
-        hostx_add_screen(screen, p_id, screen->mynum, use_geometry);
+        hostx_add_screen(screen, p_id, screen->mynum, use_geometry, output);
     }
     else {
         ErrorF("No matching card found!\n");
     }
 }
 
+void
+processScreenArg(const char *screen_size, char *parent_id)
+{
+    processScreenOrOutputArg(screen_size, NULL, parent_id);
+}
+
+void
+processOutputArg(const char *output, char *parent_id)
+{
+    processScreenOrOutputArg("100x100+0+0", output, parent_id);
+}
+
 int
 ddxProcessArgument(int argc, char **argv, int i)
 {
@@ -226,6 +241,15 @@ ddxProcessArgument(int argc, char **argv, int i)
         UseMsg();
         exit(1);
     }
+    else if (!strcmp(argv[i], "-output")) {
+        if (i + 1 < argc) {
+            processOutputArg(argv[i + 1], NULL);
+            return 2;
+        }
+
+        UseMsg();
+        exit(1);
+    }
     else if (!strcmp(argv[i], "-sw-cursor")) {
         hostx_use_sw_cursor();
         return 1;
diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index 92a8ada..2161ad5 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -51,6 +51,7 @@
 #include <xcb/xcb_image.h>
 #include <xcb/shape.h>
 #include <xcb/xcb_keysyms.h>
+#include <xcb/randr.h>
 #ifdef XF86DRI
 #include <xcb/xf86dri.h>
 #include <xcb/glx.h>
@@ -104,12 +105,15 @@ static void
 #define host_depth_matches_server(_vars) (HostX.depth == (_vars)->server_depth)
 
 int
-hostx_want_screen_size(KdScreenInfo *screen, int *width, int *height)
+hostx_want_screen_geometry(KdScreenInfo *screen, int *width, int *height, int *x, int *y)
 {
     EphyrScrPriv *scrpriv = screen->driver;
 
     if (scrpriv && (scrpriv->win_pre_existing != None ||
+                    scrpriv->output != NULL ||
                     HostX.use_fullscreen == TRUE)) {
+        *x = scrpriv->win_x;
+        *y = scrpriv->win_y;
         *width = scrpriv->win_width;
         *height = scrpriv->win_height;
         return 1;
@@ -119,7 +123,7 @@ hostx_want_screen_size(KdScreenInfo *screen, int *width, int *height)
 }
 
 void
-hostx_add_screen(KdScreenInfo *screen, unsigned long win_id, int screen_num, Bool use_geometry)
+hostx_add_screen(KdScreenInfo *screen, unsigned long win_id, int screen_num, Bool use_geometry, const char *output)
 {
     EphyrScrPriv *scrpriv = screen->driver;
     int index = HostX.n_screens;
@@ -132,6 +136,7 @@ hostx_add_screen(KdScreenInfo *screen, unsigned long win_id, int screen_num, Boo
     scrpriv->screen = screen;
     scrpriv->win_pre_existing = win_id;
     scrpriv->win_explicit_position = use_geometry;
+    scrpriv->output = output;
 }
 
 void
@@ -211,6 +216,119 @@ hostx_want_preexisting_window(KdScreenInfo *screen)
 }
 
 void
+hostx_get_output_geometry(const char *output,
+                          int *x, int *y,
+                          int *width, int *height)
+{
+    int i, name_len = 0, output_found = FALSE;
+    char *name = NULL;
+    xcb_generic_error_t *error;
+    xcb_randr_query_version_cookie_t version_c;
+    xcb_randr_query_version_reply_t *version_r;
+    xcb_randr_get_screen_resources_cookie_t screen_resources_c;
+    xcb_randr_get_screen_resources_reply_t *screen_resources_r;
+    xcb_randr_output_t *randr_outputs;
+    xcb_randr_get_output_info_cookie_t output_info_c;
+    xcb_randr_get_output_info_reply_t *output_info_r;
+    xcb_randr_get_crtc_info_cookie_t crtc_info_c;
+    xcb_randr_get_crtc_info_reply_t *crtc_info_r;
+
+    /* First of all, check for extension */
+    if (!xcb_get_extension_data(HostX.conn, &xcb_randr_id)->present)
+    {
+        fprintf(stderr, "\nHost X server does not support RANDR extension (or it's disabled).\n");
+        exit(1);
+    }
+
+    /* Check RandR version */
+    version_c = xcb_randr_query_version(HostX.conn, 1, 2);
+    version_r = xcb_randr_query_version_reply(HostX.conn,
+                                              version_c,
+                                              &error);
+
+    if (error != NULL || version_r == NULL)
+    {
+        fprintf(stderr, "\nFailed to get RandR version supported by host X server.\n");
+        exit(1);
+    }
+    else if (version_r->major_version < 1 || version_r->minor_version < 2)
+    {
+        free(version_r);
+        fprintf(stderr, "\nHost X server doesn't support RandR 1.2, needed for -output usage.\n");
+        exit(1);
+    }
+
+    free(version_r);
+
+    /* Get list of outputs from screen resources */
+    screen_resources_c = xcb_randr_get_screen_resources(HostX.conn,
+                                                        HostX.winroot);
+    screen_resources_r = xcb_randr_get_screen_resources_reply(HostX.conn,
+                                                              screen_resources_c,
+                                                              NULL);
+    randr_outputs = xcb_randr_get_screen_resources_outputs(screen_resources_r);
+
+    for (i = 0; !output_found && i < screen_resources_r->num_outputs; i++)
+    {
+        /* Get info on the output */
+        output_info_c = xcb_randr_get_output_info(HostX.conn,
+                                                  randr_outputs[i],
+                                                  XCB_CURRENT_TIME);
+        output_info_r = xcb_randr_get_output_info_reply(HostX.conn,
+                                                        output_info_c,
+                                                        NULL);
+
+        /* Get output name */
+        name_len = xcb_randr_get_output_info_name_length(output_info_r);
+        name = malloc(name_len + 1);
+        strncpy(name, (char*)xcb_randr_get_output_info_name(output_info_r), name_len);
+        name[name_len] = '\0';
+
+        if (!strcmp(name, output))
+        {
+            output_found = TRUE;
+
+            /* Check if output is connected */
+            if (output_info_r->crtc == XCB_NONE)
+            {
+                free(name);
+                free(output_info_r);
+                free(screen_resources_r);
+                fprintf(stderr, "\nOutput %s is currently disabled (or not connected).\n", output);
+                exit(1);
+            }
+
+            /* Get CRTC from output info */
+            crtc_info_c = xcb_randr_get_crtc_info(HostX.conn,
+                                                  output_info_r->crtc,
+                                                  XCB_CURRENT_TIME);
+            crtc_info_r = xcb_randr_get_crtc_info_reply(HostX.conn,
+                                                        crtc_info_c,
+                                                        NULL);
+
+            /* Get CRTC geometry */
+            *x = crtc_info_r->x;
+            *y = crtc_info_r->y;
+            *width = crtc_info_r->width;
+            *height = crtc_info_r->height;
+
+            free(crtc_info_r);
+        }
+
+        free(name);
+        free(output_info_r);
+    }
+
+    free(screen_resources_r);
+
+    if (!output_found)
+    {
+        fprintf(stderr, "\nOutput %s not available in host X server.\n", output);
+        exit(1);
+    }
+}
+
+void
 hostx_use_fullscreen(void)
 {
     HostX.use_fullscreen = TRUE;
@@ -359,6 +477,8 @@ hostx_init(void)
         scrpriv->win = xcb_generate_id(HostX.conn);
         scrpriv->server_depth = HostX.depth;
         scrpriv->ximg = NULL;
+        scrpriv->win_x = 0;
+        scrpriv->win_y = 0;
 
         if (scrpriv->win_pre_existing != XCB_WINDOW_NONE) {
             xcb_get_geometry_reply_t *prewin_geom;
@@ -416,6 +536,17 @@ hostx_init(void)
 
                 hostx_set_fullscreen_hint();
             }
+            else if (scrpriv->output) {
+                hostx_get_output_geometry(scrpriv->output,
+                                          &scrpriv->win_x,
+                                          &scrpriv->win_y,
+                                          &scrpriv->win_width,
+                                          &scrpriv->win_height);
+
+                HostX.use_fullscreen = TRUE;
+                hostx_set_fullscreen_hint();
+            }
+
 
             tmpstr = getenv("RESOURCE_NAME");
             if (tmpstr && (!ephyrResNameFromCmd))
@@ -759,6 +890,8 @@ hostx_screen_init(KdScreenInfo *screen,
 
     scrpriv->win_width = width;
     scrpriv->win_height = height;
+    scrpriv->win_x = x;
+    scrpriv->win_y = y;
 
 #ifdef GLAMOR
     if (ephyr_glamor) {
diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h
index c554ca3..80894c8 100644
--- a/hw/kdrive/ephyr/hostx.h
+++ b/hw/kdrive/ephyr/hostx.h
@@ -74,7 +74,7 @@ typedef struct {
 } EphyrRect;
 
 int
-hostx_want_screen_size(KdScreenInfo *screen, int *width, int *height);
+hostx_want_screen_geometry(KdScreenInfo *screen, int *width, int *height, int *x, int *y);
 
 int
  hostx_want_host_cursor(void);
@@ -83,6 +83,11 @@ void
  hostx_use_sw_cursor(void);
 
 void
+ hostx_get_output_geometry(const char *output,
+                           int *x, int *y,
+                           int *width, int *height);
+
+void
  hostx_use_fullscreen(void);
 
 int
@@ -107,7 +112,7 @@ int
  hostx_init(void);
 
 void
-hostx_add_screen(KdScreenInfo *screen, unsigned long win_id, int screen_num, Bool use_geometry);
+hostx_add_screen(KdScreenInfo *screen, unsigned long win_id, int screen_num, Bool use_geometry, const char *output);
 
 void
  hostx_set_display_name(char *name);
commit 84b02469ef97e6f85d074d220a517d752180045f
Author: Laércio de Sousa <laerciosousa at sme-mogidascruzes.sp.gov.br>
Date:   Mon Aug 18 08:45:42 2014 -0300

    ephyr: enable screen window placement following kdrive -screen option extended syntax
    
    With this patch, one can launch Xephyr with option "-screen WxH+X+Y"
    to place its window origin at (X,Y). This patch relies on a previous
    one that extends kdrive -screen option syntax to parse +X+Y substring
    as expected.
    
    If +X+Y is not passed in -screen argument string, let the WM place
    the window for us, as before.
    
    Signed-off-by: Laércio de Sousa <laerciosousa at sme-mogidascruzes.sp.gov.br>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/kdrive/ephyr/ephyr.c b/hw/kdrive/ephyr/ephyr.c
index d57e9f3..b039c68 100644
--- a/hw/kdrive/ephyr/ephyr.c
+++ b/hw/kdrive/ephyr/ephyr.c
@@ -242,7 +242,8 @@ ephyrMapFramebuffer(KdScreenInfo * screen)
     buffer_height = ephyrBufferHeight(screen);
 
     priv->base =
-        hostx_screen_init(screen, screen->width, screen->height, buffer_height,
+        hostx_screen_init(screen, screen->x, screen->y,
+                          screen->width, screen->height, buffer_height,
                           &priv->bytes_per_line, &screen->fb.bitsPerPixel);
 
     if ((scrpriv->randr & RR_Rotate_0) && !(scrpriv->randr & RR_Reflect_All)) {
diff --git a/hw/kdrive/ephyr/ephyr.h b/hw/kdrive/ephyr/ephyr.h
index dfd93c9..5c4936b 100644
--- a/hw/kdrive/ephyr/ephyr.h
+++ b/hw/kdrive/ephyr/ephyr.h
@@ -73,6 +73,7 @@ typedef struct _ephyrScrPriv {
     xcb_window_t win_pre_existing;    /* Set via -parent option like xnest */
     xcb_window_t peer_win;            /* Used for GL; should be at most one */
     xcb_image_t *ximg;
+    Bool win_explicit_position;
     int win_width, win_height;
     int server_depth;
     unsigned char *fb_data;     /* only used when host bpp != server bpp */
diff --git a/hw/kdrive/ephyr/ephyrinit.c b/hw/kdrive/ephyr/ephyrinit.c
index fc00010..e04c8dc 100644
--- a/hw/kdrive/ephyr/ephyrinit.c
+++ b/hw/kdrive/ephyr/ephyrinit.c
@@ -164,6 +164,7 @@ processScreenArg(const char *screen_size, char *parent_id)
     if (card) {
         KdScreenInfo *screen;
         unsigned long p_id = 0;
+        Bool use_geometry;
 
         screen = KdScreenInfoAdd(card);
         KdParseScreen(screen, screen_size);
@@ -174,8 +175,10 @@ processScreenArg(const char *screen_size, char *parent_id)
         if (parent_id) {
             p_id = strtol(parent_id, NULL, 0);
         }
+
+        use_geometry = (strchr(screen_size, '+') != NULL);
         EPHYR_DBG("screen number:%d\n", screen->mynum);
-        hostx_add_screen(screen, p_id, screen->mynum);
+        hostx_add_screen(screen, p_id, screen->mynum, use_geometry);
     }
     else {
         ErrorF("No matching card found!\n");
diff --git a/hw/kdrive/ephyr/hostx.c b/hw/kdrive/ephyr/hostx.c
index 1c75974..92a8ada 100644
--- a/hw/kdrive/ephyr/hostx.c
+++ b/hw/kdrive/ephyr/hostx.c
@@ -119,7 +119,7 @@ hostx_want_screen_size(KdScreenInfo *screen, int *width, int *height)
 }
 
 void
-hostx_add_screen(KdScreenInfo *screen, unsigned long win_id, int screen_num)
+hostx_add_screen(KdScreenInfo *screen, unsigned long win_id, int screen_num, Bool use_geometry)
 {
     EphyrScrPriv *scrpriv = screen->driver;
     int index = HostX.n_screens;
@@ -131,6 +131,7 @@ hostx_add_screen(KdScreenInfo *screen, unsigned long win_id, int screen_num)
 
     scrpriv->screen = screen;
     scrpriv->win_pre_existing = win_id;
+    scrpriv->win_explicit_position = use_geometry;
 }
 
 void
@@ -637,6 +638,7 @@ hostx_set_cmap_entry(unsigned char idx,
  */
 void *
 hostx_screen_init(KdScreenInfo *screen,
+                  int x, int y,
                   int width, int height, int buffer_height,
                   int *bytes_per_line, int *bits_per_pixel)
 {
@@ -648,8 +650,8 @@ hostx_screen_init(KdScreenInfo *screen,
         exit(1);
     }
 
-    EPHYR_DBG("host_screen=%p wxh=%dx%d, buffer_height=%d",
-              host_screen, width, height, buffer_height);
+    EPHYR_DBG("host_screen=%p x=%d, y=%d, wxh=%dx%d, buffer_height=%d",
+              host_screen, x, y, width, height, buffer_height);
 
     if (scrpriv->ximg != NULL) {
         /* Free up the image data if previously used
@@ -740,6 +742,19 @@ hostx_screen_init(KdScreenInfo *screen,
 
     xcb_map_window(HostX.conn, scrpriv->win);
 
+    /* Set explicit window position if it was informed in
+     * -screen option (WxH+X or WxH+X+Y). Otherwise, accept the
+     * position set by WM.
+     * The trick here is putting this code after xcb_map_window() call,
+     * so these values won't be overriden by WM. */
+    if (scrpriv->win_explicit_position)
+    {
+        uint32_t mask = XCB_CONFIG_WINDOW_X | XCB_CONFIG_WINDOW_Y;
+        uint32_t values[2] = {x, y};
+        xcb_configure_window(HostX.conn, scrpriv->win, mask, values);
+    }
+
+
     xcb_aux_sync(HostX.conn);
 
     scrpriv->win_width = width;
diff --git a/hw/kdrive/ephyr/hostx.h b/hw/kdrive/ephyr/hostx.h
index e83323a..c554ca3 100644
--- a/hw/kdrive/ephyr/hostx.h
+++ b/hw/kdrive/ephyr/hostx.h
@@ -107,7 +107,7 @@ int
  hostx_init(void);
 
 void
-hostx_add_screen(KdScreenInfo *screen, unsigned long win_id, int screen_num);
+hostx_add_screen(KdScreenInfo *screen, unsigned long win_id, int screen_num, Bool use_geometry);
 
 void
  hostx_set_display_name(char *name);
@@ -136,6 +136,7 @@ hostx_set_cmap_entry(unsigned char idx,
                      unsigned char r, unsigned char g, unsigned char b);
 
 void *hostx_screen_init(KdScreenInfo *screen,
+                        int x, int y,
                         int width, int height, int buffer_height,
                         int *bytes_per_line, int *bits_per_pixel);
 
commit 376f4de8ae927748417046390c24afbda24b0583
Author: Laércio de Sousa <laerciosousa at sme-mogidascruzes.sp.gov.br>
Date:   Mon Aug 18 08:45:41 2014 -0300

    kdrive: add support to +X+Y syntax in -screen option parsing
    
    This patch enhances current -screen option parsing for kdrive-based
    applications. It can parse strings like
    <WIDTH>x<HEIGHT>+<XOFFSET>+<YOFFSET>, storing X and Y offsets
    in KdScreenInfo instances.
    
    For negative values, this patch supports +-X+-Y (not -X-Y) syntax.
    
    It will allow e.g. proper Xephyr window placement for multiseat
    purposes.
    
    Signed-off-by: Laércio de Sousa <laerciosousa at sme-mogidascruzes.sp.gov.br>
    Reviewed-by: Keith Packard <keithp at keithp.com>
    Signed-off-by: Keith Packard <keithp at keithp.com>

diff --git a/hw/kdrive/src/kdrive.c b/hw/kdrive/src/kdrive.c
index b5b91c0..5dbff3f 100644
--- a/hw/kdrive/src/kdrive.c
+++ b/hw/kdrive/src/kdrive.c
@@ -300,6 +300,8 @@ KdParseScreen(KdScreenInfo * screen, const char *arg)
     screen->softCursor = kdSoftCursor;
     screen->origin = kdOrigin;
     screen->randr = RR_Rotate_0;
+    screen->x = 0;
+    screen->y = 0;
     screen->width = 0;
     screen->height = 0;
     screen->width_mm = 0;
@@ -313,7 +315,7 @@ KdParseScreen(KdScreenInfo * screen, const char *arg)
         return;
 
     for (i = 0; i < 2; i++) {
-        arg = KdParseFindNext(arg, "x/@XY", save, &delim);
+        arg = KdParseFindNext(arg, "x/+ at XY", save, &delim);
         if (!save[0])
             return;
 
@@ -321,7 +323,7 @@ KdParseScreen(KdScreenInfo * screen, const char *arg)
         mm = 0;
 
         if (delim == '/') {
-            arg = KdParseFindNext(arg, "x at XY", save, &delim);
+            arg = KdParseFindNext(arg, "x+ at XY", save, &delim);
             if (!save[0])
                 return;
             mm = atoi(save);
@@ -335,7 +337,8 @@ KdParseScreen(KdScreenInfo * screen, const char *arg)
             screen->height = pixels;
             screen->height_mm = mm;
         }
-        if (delim != 'x' && delim != '@' && delim != 'X' && delim != 'Y' &&
+        if (delim != 'x' && delim != '+' && delim != '@' &&
+            delim != 'X' && delim != 'Y' &&
             (delim != '\0' || i == 0))
             return;
     }
@@ -346,6 +349,18 @@ KdParseScreen(KdScreenInfo * screen, const char *arg)
     kdSoftCursor = FALSE;
     kdSubpixelOrder = SubPixelUnknown;
 
+    if (delim == '+') {
+        arg = KdParseFindNext(arg, "+ at xXY", save, &delim);
+        if (save[0])
+            screen->x = atoi(save);
+    }
+
+    if (delim == '+') {
+        arg = KdParseFindNext(arg, "@xXY", save, &delim);
+        if (save[0])
+            screen->y = atoi(save);
+    }
+
     if (delim == '@') {
         arg = KdParseFindNext(arg, "xXY", save, &delim);
         if (save[0]) {
@@ -425,7 +440,7 @@ KdUseMsg(void)
 {
     ErrorF("\nTinyX Device Dependent Usage:\n");
     ErrorF
-        ("-screen WIDTH[/WIDTHMM]xHEIGHT[/HEIGHTMM][@ROTATION][X][Y][xDEPTH/BPP[xFREQ]]  Specify screen characteristics\n");
+        ("-screen WIDTH[/WIDTHMM]xHEIGHT[/HEIGHTMM][+[-]XOFFSET][+[-]YOFFSET][@ROTATION][X][Y][xDEPTH/BPP[xFREQ]]  Specify screen characteristics\n");
     ErrorF
         ("-rgba rgb/bgr/vrgb/vbgr/none   Specify subpixel ordering for LCD panels\n");
     ErrorF
diff --git a/hw/kdrive/src/kdrive.h b/hw/kdrive/src/kdrive.h
index 08b1681..066a134 100644
--- a/hw/kdrive/src/kdrive.h
+++ b/hw/kdrive/src/kdrive.h
@@ -89,6 +89,8 @@ typedef struct _KdScreenInfo {
     ScreenPtr pScreen;
     void *driver;
     Rotation randr;             /* rotation and reflection */
+    int x;
+    int y;
     int width;
     int height;
     int rate;


More information about the xorg-commit mailing list