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@sme-mogidascruzes.sp.gov.br> Reviewed-by: Keith Packard <keithp@keithp.com> Signed-off-by: Keith Packard <keithp@keithp.com>
This commit is contained in:
parent
84b02469ef
commit
3a51418b2d
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
@ -210,6 +215,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)
|
||||
{
|
||||
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
@ -82,6 +82,11 @@ int
|
|||
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);
|
||||
|
||||
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue
Block a user