Nov 2003

Mon, 10 Nov 2003

XFree_Xinerama_extension_hack

When installing my 3 monitor setup I quickly discovered that the native xfree xinerama extension is incompatible with nvidia twinview. You can only have either one. This leads to applications believing I have one 2560x1024 screen and one 1280x1024 screen. If I maximized windows they would always span two screens. Therefore I spent a long time searching for a solution on google, but unfortunately there are a) few people with 3 monitors and b) no one had solved this. So I decided to patch the X server. What I've done so far is to take programs/Xserver/Xext/panoramiX.c and fake the reply like this: When installing my 3 monitor setup I quickly discovered that the native xfree xinerama extension is incompatible with nvidia twinview. You can only have either one. This leads to applications believing I have one 2560x1024 screen and one 1280x1024 screen. If I maximized windows they would always span two screens. Therefore I spent a long time searching for a solution on google, but unfortunately there are a) few people with 3 monitors and b) no one had solved this. So I decided to patch the X server. What I've done so far is to take programs/Xserver/Xext/panoramiX.c and fake the reply like this:
--- x/xc/programs/Xserver/Xext/panoramiX.c      2003-11-10 19:21:43.000000000 +0100
+++ x2/xc/programs/Xserver/Xext/panoramiX.c 2004-02-15 11:39:15.000000000 +0100
@@ -1026,7 +1030,8 @@

rep.type = X_Reply;
rep.sequenceNumber = client->sequence;
- rep.number = (noPanoramiXExtension) ? 0 : PanoramiXNumScreens;
+ /* rep.number = (noPanoramiXExtension) ? 0 : PanoramiXNumScreens; */
+ rep.number = (noPanoramiXExtension) ? 0 : (PanoramiXNumScreens + 1);
rep.length = rep.number * sz_XineramaScreenInfo >> 2;
if (client->swapped) {
register int n;
@@ -1040,11 +1045,17 @@
xXineramaScreenInfo scratch;

int i;

- for(i = 0; i < PanoramiXNumScreens; i++) {
+ for(i = 0; i < (PanoramiXNumScreens + 1); i++) {
+ /*
scratch.x_org = panoramiXdataPtr[i].x;
scratch.y_org = panoramiXdataPtr[i].y;
scratch.width = panoramiXdataPtr[i].width;
scratch.height = panoramiXdataPtr[i].height;
+ */
+ scratch.x_org = 1280 * i;
+ scratch.y_org = 0;
+ scratch.width = 1280;
+ scratch.height = 1024;

This is pretty specific, so I'm currently working my way through the code to make this configurable in the XF86Config-4.

I also wrote a small test program:
#include <stdio.h>
#include <X11/extensions/Xinerama.h>

int main() {
XineramaScreenInfo *xsi;
Display *dpy;
int number;
int i;
dpy = XOpenDisplay(NULL);
xsi = XineramaQueryScreens(dpy, &number);
for(i = 0; i < number; i++) {
printf("%d %d %d %d %d
", xsi[i].screen_number, xsi[i].x_org,
xsi[i].y_org, xsi[i].width, xsi[i].height);
}
return 1;
}
Output before the patch: (Columns are screennum x y width height):
0 0 0 2560 1024
2 2560 0 1280 1024
Output after the patch:
0 0 0 1280 1024 
1 1280 0 1280 1024
2 2560 0 1280 1024
Pretty successful.

posted at 19:21 | path: /unix | permanent link to this entry

Creative Commons License
This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.