summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHans de Goede <hans@localhost.localdomain>2013-04-10 17:41:14 +0200
committerHans de Goede <hdegoede@redhat.com>2013-04-10 17:48:54 +0200
commita322d13b7ee7ced191d50e44ad8a79bdd6839779 (patch)
tree00ee7ca5c06621d1222c81cd6a3fd9416a568bb3
parentcc6f3d5a72d01a87a3630acb3f79e860ddf79901 (diff)
vdagent-x11: Add support for setups with multiple screens
Some users have a need for old-fashioned setups with multiple X11 Screens rather then one large virtual Screen as modern X usually has. This can be accomplished by using multiple qxl devices + a xorg.conf file assigning one Screen per qxl device. Limitations: -Max one monitor per Screen / qxl device -All monitors / Screens must have the same resolution -No client -> guest resolution syncing Signed-off-by: Hans de Goede <hdegoede@redhat.com>
-rw-r--r--src/vdagent-x11-priv.h3
-rw-r--r--src/vdagent-x11-randr.c44
-rw-r--r--src/vdagent-x11.c35
3 files changed, 57 insertions, 25 deletions
diff --git a/src/vdagent-x11-priv.h b/src/vdagent-x11-priv.h
index 71c26b9..c607850 100644
--- a/src/vdagent-x11-priv.h
+++ b/src/vdagent-x11-priv.h
@@ -89,6 +89,7 @@ struct vdagent_x11 {
char *net_wm_name;
int debug;
int fd;
+ int screen_count;
int width[MAX_SCREENS];
int height[MAX_SCREENS];
int has_xfixes;
@@ -142,7 +143,7 @@ void vdagent_x11_randr_init(struct vdagent_x11 *x11);
void vdagent_x11_send_daemon_guest_xorg_res(struct vdagent_x11 *x11,
int update);
void vdagent_x11_randr_handle_root_size_change(struct vdagent_x11 *x11,
- int width, int height);
+ int screen, int width, int height);
void vdagent_x11_set_error_handler(struct vdagent_x11 *x11,
int (*handler)(Display *, XErrorEvent *));
diff --git a/src/vdagent-x11-randr.c b/src/vdagent-x11-randr.c
index 1d609bd..5223f88 100644
--- a/src/vdagent-x11-randr.c
+++ b/src/vdagent-x11-randr.c
@@ -123,6 +123,12 @@ void vdagent_x11_randr_init(struct vdagent_x11 *x11)
{
int i;
+ if (x11->screen_count > 1) {
+ syslog(LOG_WARNING, "X-server has more then 1 screen, "
+ "disabling client -> guest resolution syncing");
+ return;
+ }
+
if (XRRQueryExtension(x11->display, &i, &i)) {
XRRQueryVersion(x11->display, &x11->xrandr_major, &x11->xrandr_minor);
if (x11->xrandr_major == 1 && x11->xrandr_minor >= 3)
@@ -455,18 +461,18 @@ static int set_screen_to_best_size(struct vdagent_x11 *x11, int width, int heigh
}
void vdagent_x11_randr_handle_root_size_change(struct vdagent_x11 *x11,
- int width, int height)
+ int screen, int width, int height)
{
- if (width == x11->width[0] && height == x11->height[0]) {
+ if (width == x11->width[screen] && height == x11->height[screen]) {
return;
}
if (x11->debug)
- syslog(LOG_DEBUG, "Root size changed to %dx%d send %d",
- width, height, !x11->dont_send_guest_xorg_res);
+ syslog(LOG_DEBUG, "Root size of screen %d changed to %dx%d send %d",
+ screen, width, height, !x11->dont_send_guest_xorg_res);
- x11->width[0] = width;
- x11->height[0] = height;
+ x11->width[screen] = width;
+ x11->height[screen] = height;
if (!x11->dont_send_guest_xorg_res) {
vdagent_x11_send_daemon_guest_xorg_res(x11, 1);
}
@@ -809,7 +815,7 @@ exit:
void vdagent_x11_send_daemon_guest_xorg_res(struct vdagent_x11 *x11, int update)
{
struct vdagentd_guest_xorg_resolution *res = NULL;
- int i, screen_count = 0;
+ int i, width = 0, height = 0, screen_count = 0;
if (x11->has_xrandr) {
VDAgentMonitorsConfig *curr;
@@ -835,6 +841,8 @@ void vdagent_x11_send_daemon_guest_xorg_res(struct vdagent_x11 *x11, int update)
res[i].y = curr->monitors[i].y;
}
free(curr);
+ width = x11->width[0];
+ height = x11->height[0];
} else if (x11->has_xinerama) {
XineramaScreenInfo *screen_info = NULL;
@@ -860,16 +868,24 @@ void vdagent_x11_send_daemon_guest_xorg_res(struct vdagent_x11 *x11, int update)
res[screen_info[i].screen_number].y = screen_info[i].y_org;
}
XFree(screen_info);
+ width = x11->width[0];
+ height = x11->height[0];
} else {
no_info:
- screen_count = 1;
+ screen_count = x11->screen_count;
res = malloc(screen_count * sizeof(*res));
if (!res)
goto no_mem;
- res[0].width = x11->width[0];
- res[0].height = x11->height[0];
- res[0].x = 0;
- res[0].y = 0;
+ for (i = 0; i < screen_count; i++) {
+ res[i].width = x11->width[i];
+ res[i].height = x11->height[i];
+ /* No way to get screen coordinates, assume rtl order */
+ res[i].x = width;
+ res[i].y = 0;
+ width += x11->width[i];
+ if (x11->height[i] > height)
+ height = x11->height[i];
+ }
}
if (x11->debug) {
@@ -878,8 +894,8 @@ no_info:
res[i].height, res[i].x, res[i].y);
}
- udscs_write(x11->vdagentd, VDAGENTD_GUEST_XORG_RESOLUTION, x11->width[0],
- x11->height[0], (uint8_t *)res, screen_count * sizeof(*res));
+ udscs_write(x11->vdagentd, VDAGENTD_GUEST_XORG_RESOLUTION, width, height,
+ (uint8_t *)res, screen_count * sizeof(*res));
free(res);
return;
no_mem:
diff --git a/src/vdagent-x11.c b/src/vdagent-x11.c
index 51f9315..6a58532 100644
--- a/src/vdagent-x11.c
+++ b/src/vdagent-x11.c
@@ -196,12 +196,22 @@ struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
return NULL;
}
+ x11->screen_count = ScreenCount(x11->display);
+ if (x11->screen_count > MAX_SCREENS) {
+ syslog(LOG_ERR, "Error too much screens: %d > %d",
+ x11->screen_count, MAX_SCREENS);
+ XCloseDisplay(x11->display);
+ free(x11);
+ return NULL;
+ }
+
if (sync) {
XSetErrorHandler(vdagent_x11_debug_error_handler);
XSynchronize(x11->display, True);
}
- x11->root_window[0] = RootWindow(x11->display, 0);
+ for (i = 0; i < x11->screen_count; i++)
+ x11->root_window[i] = RootWindow(x11->display, i);
x11->fd = ConnectionNumber(x11->display);
x11->clipboard_atom = XInternAtom(x11->display, "CLIPBOARD", False);
x11->clipboard_primary_atom = XInternAtom(x11->display, "PRIMARY", False);
@@ -253,13 +263,15 @@ struct vdagent_x11 *vdagent_x11_create(struct udscs_connection *vdagentd,
if (x11->max_prop_size > 262144)
x11->max_prop_size = 262144;
- /* Catch resolution changes */
- XSelectInput(x11->display, x11->root_window[0], StructureNotifyMask);
+ for (i = 0; i < x11->screen_count; i++) {
+ /* Catch resolution changes */
+ XSelectInput(x11->display, x11->root_window[i], StructureNotifyMask);
- /* Get the current resolution */
- XGetWindowAttributes(x11->display, x11->root_window[0], &attrib);
- x11->width[0] = attrib.width;
- x11->height[0] = attrib.height;
+ /* Get the current resolution */
+ XGetWindowAttributes(x11->display, x11->root_window[i], &attrib);
+ x11->width[i] = attrib.width;
+ x11->height[i] = attrib.height;
+ }
vdagent_x11_send_daemon_guest_xorg_res(x11, 1);
/* Get net_wm_name, since we are started at the same time as the wm,
@@ -443,7 +455,7 @@ static int vdagent_x11_get_clipboard_selection(struct vdagent_x11 *x11,
static void vdagent_x11_handle_event(struct vdagent_x11 *x11, XEvent event)
{
- int handled = 0;
+ int i, handled = 0;
uint8_t selection;
if (event.type == x11->xfixes_event_base) {
@@ -493,11 +505,14 @@ static void vdagent_x11_handle_event(struct vdagent_x11 *x11, XEvent event)
switch (event.type) {
case ConfigureNotify:
// TODO: handle CrtcConfigureNotify, OutputConfigureNotify can be ignored.
- if (event.xconfigure.window != x11->root_window[0])
+ for (i = 0; i < x11->screen_count; i++)
+ if (event.xconfigure.window == x11->root_window[i])
+ break;
+ if (i == x11->screen_count)
break;
handled = 1;
- vdagent_x11_randr_handle_root_size_change(x11,
+ vdagent_x11_randr_handle_root_size_change(x11, i,
event.xconfigure.width, event.xconfigure.height);
break;
case MappingNotify: