Skip to content

Instantly share code, notes, and snippets.

@tene
Forked from phillipberndt/Fake xinerama
Last active August 29, 2015 13:57
Show Gist options
  • Save tene/9475025 to your computer and use it in GitHub Desktop.
Save tene/9475025 to your computer and use it in GitHub Desktop.
WHAT THIS IS
------------
The DELL LATITUDE E7440's docking station supports two external displays, and
the notebook's Haswell architecture supports having three displays active at
the same time. It works well, but the two external monitors are merged into one
big display:
$ xrandr
Screen 0: minimum 320 x 200, current 5280 x 1080, maximum 32767 x 32767
eDP1 connected primary 1920x1080+0+0 (normal left inverted right x axis y axis) 309mm x 174mm
1920x1080 60.0*+ 59.9
[...]
DP1 disconnected (normal left inverted right x axis y axis)
HDMI1 disconnected (normal left inverted right x axis y axis)
DP2 connected 3360x1050+1920+0 (normal left inverted right x axis y axis) 474mm x 296mm
1680x1050 59.9 +
3360x1050 60.0*
[..]
HDMI2 disconnected (normal left inverted right x axis y axis)
VIRTUAL1 disconnected (normal left inverted right x axis y axis)
(Note: For some reason, 1680x1050 is favored over the wide resolution. But as
long as it is active, one does not see anything on the screens! Set 3360x1060
manually to see output)
I hacked this fake xinerama library to split the large output into two fake
xinerama outputs, such that maximizing works as expected in my window manager.
ACKNOWLEDGEMENTS
----------------
The fakexinerama.c file was taken from
http://lists.suckless.org/dev/0910/1599.html and was written by Kris Maglione
<maglione.k_AT_gmail.com>. I merely replaced some lines in it such that the
library would only be active if the large external monitor was actually
connected.
HOW-TO
------
1) Adjust XineramaQueryScreens() to your needs. Starting with line 57, I manually
change the configuration. Replace that with your configuration! x_org and y_org are
x and y coordinates of the screen's origin (top left corner) in the wide desktop.
2) Compile with `cc -fPIC -O2 -shared -o libXinerama.so fakexinerama.c -lX11' and create
a link libXinerama.so.1 to that library.
3) Move both files to /usr/local/lib
4) Restart, enjoy your working desktop :-)
If you want to test your configuration, test.c must be compiled with `cc -otest test.c -lXinerama -lX11'.
#ifdef notdef
set -x
exec cc -O2 -std=c99 -pedantic -Wall $0 -fPIC -o libXinerama.so -shared
#endif
#define _XOPEN_SOURCE 600
#include <X11/Xlibint.h>
#include <X11/extensions/Xinerama.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <dlfcn.h>
typedef XineramaScreenInfo* (queryfn)(Display*, int*);
typedef Status (versionfn)(Display*, int*, int*);
typedef Bool (extensionfn)(Display*, int*, int*);
typedef Bool (activefn)(Display*);
static void* libxinerama;
static queryfn* queryscreens;
static extensionfn* queryextension;
static versionfn* queryversion;
static activefn* isactive;
static void init() {
libxinerama = dlopen("/usr/lib/x86_64-linux-gnu/libXinerama.so.1", RTLD_GLOBAL | RTLD_LAZY);
if(!libxinerama)
abort();
isactive = (activefn*) (uintptr_t)dlsym(libxinerama, "XineramaIsActive");
queryversion = (versionfn*) (uintptr_t)dlsym(libxinerama, "XineramaQueryVersion");
queryextension = (extensionfn*) (uintptr_t)dlsym(libxinerama, "XineramaQueryExtension");
queryscreens = (queryfn*) (uintptr_t)dlsym(libxinerama, "XineramaQueryScreens");
}
Bool XineramaQueryExtension(Display *dpy, int *event_base, int *error_base) {
init();
return queryextension(dpy, event_base, error_base);
}
Status XineramaQueryVersion(Display *dpy, int *major, int *minor) {
init();
return queryversion(dpy, major, minor);
}
Bool XineramaIsActive(Display *dpy) {
init();
return isactive(dpy);
}
XineramaScreenInfo* XineramaQueryScreens(Display *dpy, int *number)
{
XineramaScreenInfo *ret, *work;
int i=0, j=0, newsize;
init();
ret = queryscreens(dpy, number);
newsize=*number;
work = Xmalloc(newsize * sizeof(XineramaScreenInfo));
for (i=0; i<*number; i++, j++) {
memcpy(&work[j], &ret[i], sizeof(XineramaScreenInfo));
if (ret[i].width == 3840) {
newsize++;
Xrealloc(work, newsize * sizeof(XineramaScreenInfo));
memcpy(&work[j+1], &ret[i], sizeof(XineramaScreenInfo));
work[j].width = ret[i].width/2;
work[j+1].screen_number+=1;
work[j+1].x_org += ret[i].width/2;
work[j+1].width = ret[i].width/2;
j++;
}
}
*number = newsize;
XFree(ret);
ret = work;
return ret;
}
#define _XOPEN_SOURCE 600
#include <X11/Xlibint.h>
#include <X11/extensions/Xinerama.h>
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <dlfcn.h>
void main() {
Display *dpl = XOpenDisplay(":0");
if(XineramaIsActive(dpl)) {
printf("Xinerama is active\n");
int screens;
XineramaScreenInfo* s = XineramaQueryScreens(dpl, &screens);
printf("%d screens\n", screens);
int j;
for(j=0; j<screens; j++) {
printf("%d: %hd,%hd %hdx%hd\n", j, s[j].x_org, s[j].y_org, s[j].width, s[j].height);
}
XFree(s);
}
else {
printf("Xinerama is not active\n");
}
XCloseDisplay(dpl);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment