mirror of https://github.com/0intro/wmii
165 lines
3.3 KiB
C
165 lines
3.3 KiB
C
/* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail>
|
|
* See LICENSE file for license details.
|
|
*/
|
|
#define _X11_VISIBLE
|
|
#include <stuff/x.h>
|
|
#include <stuff/util.h>
|
|
#include <X11/extensions/Xrandr.h>
|
|
#include <X11/extensions/Xrender.h>
|
|
#include <X11/extensions/Xinerama.h>
|
|
|
|
#if RANDR_MAJOR < 1
|
|
# error XRandR versions less than 1.0 are not supported
|
|
#endif
|
|
|
|
static void randr_screenchange(XRRScreenChangeNotifyEvent*);
|
|
static bool randr_event_p(XEvent *e);
|
|
static void randr_init(void);
|
|
static void render_init(void);
|
|
static void xinerama_init(void);
|
|
|
|
typedef void (*EvHandler)(XEvent*);
|
|
static EvHandler randr_handlers[RRNumberEvents];
|
|
|
|
bool have_RandR;
|
|
bool have_render;
|
|
bool have_xinerama;
|
|
int randr_eventbase;
|
|
Visual* render_visual;
|
|
|
|
static void
|
|
handle(XEvent *e, EvHandler h[], int base) {
|
|
|
|
if(h[e->type-base])
|
|
h[e->type-base](e);
|
|
}
|
|
|
|
void
|
|
xext_init(void) {
|
|
randr_init();
|
|
render_init();
|
|
xinerama_init();
|
|
}
|
|
|
|
void
|
|
xext_event(XEvent *e) {
|
|
|
|
if(randr_event_p(e))
|
|
handle(e, randr_handlers, randr_eventbase);
|
|
}
|
|
|
|
static void
|
|
randr_init(void) {
|
|
int errorbase, major, minor;
|
|
|
|
have_RandR = XRRQueryExtension(display, &randr_eventbase, &errorbase);
|
|
if(have_RandR)
|
|
if(XRRQueryVersion(display, &major, &minor) && major < 1)
|
|
have_RandR = false;
|
|
if(have_RandR)
|
|
XRRSelectInput(display, scr.root.xid, RRScreenChangeNotifyMask);
|
|
}
|
|
|
|
static bool
|
|
randr_event_p(XEvent *e) {
|
|
return have_RandR
|
|
&& (uint)e->type - randr_eventbase < RRNumberEvents;
|
|
}
|
|
|
|
static void
|
|
randr_screenchange(XRRScreenChangeNotifyEvent *ev) {
|
|
|
|
XRRUpdateConfiguration((XEvent*)ev);
|
|
if(ev->rotation*90 % 180)
|
|
scr.rect = Rect(0, 0, ev->width, ev->height);
|
|
else
|
|
scr.rect = Rect(0, 0, ev->height, ev->width);
|
|
init_screens();
|
|
}
|
|
|
|
static EvHandler randr_handlers[] = {
|
|
[RRScreenChangeNotify] = (EvHandler)randr_screenchange,
|
|
};
|
|
|
|
/* Ripped most graciously from ecore_x. XRender documentation
|
|
* is sparse.
|
|
*/
|
|
static void
|
|
render_init(void) {
|
|
XVisualInfo *vip;
|
|
XVisualInfo vi;
|
|
int base, i, n;
|
|
|
|
have_render = XRenderQueryExtension(display, &base, &base);
|
|
if(!have_render)
|
|
return;
|
|
|
|
vi.class = TrueColor;
|
|
vi.depth = 32;
|
|
vi.screen = scr.screen;
|
|
vip = XGetVisualInfo(display, VisualClassMask
|
|
| VisualDepthMask
|
|
| VisualScreenMask,
|
|
&vi, &n);
|
|
for(i=0; i < n; i++)
|
|
if(render_argb_p(vip[i].visual)) {
|
|
render_visual = vip[i].visual;
|
|
scr.visual32 = render_visual;
|
|
break;
|
|
}
|
|
XFree(vip);
|
|
if(render_visual)
|
|
scr.colormap32 = XCreateColormap(display, scr.root.xid, render_visual, AllocNone);
|
|
}
|
|
|
|
bool
|
|
render_argb_p(Visual *v) {
|
|
XRenderPictFormat *f;
|
|
|
|
if(!have_render)
|
|
return false;
|
|
f = XRenderFindVisualFormat(display, v);
|
|
return f
|
|
&& f->type == PictTypeDirect
|
|
&& f->direct.alphaMask;
|
|
}
|
|
|
|
static void
|
|
xinerama_init(void) {
|
|
int base;
|
|
|
|
have_xinerama = XineramaQueryExtension(display, &base, &base);
|
|
}
|
|
|
|
static bool
|
|
xinerama_active(void) {
|
|
return have_xinerama && XineramaIsActive(display);
|
|
}
|
|
|
|
Rectangle*
|
|
xinerama_screens(int *np) {
|
|
static Rectangle *rects;
|
|
XineramaScreenInfo *res;
|
|
int i, n;
|
|
|
|
if(!xinerama_active()) {
|
|
*np = 1;
|
|
return &scr.rect;
|
|
}
|
|
|
|
free(rects);
|
|
res = XineramaQueryScreens(display, &n);
|
|
rects = emalloc(n * sizeof *rects);
|
|
for(i=0; i < n; i++) {
|
|
rects[i].min.x = res[i].x_org;
|
|
rects[i].min.y = res[i].y_org;
|
|
rects[i].max.x = res[i].x_org + res[i].width;
|
|
rects[i].max.y = res[i].y_org + res[i].height;
|
|
}
|
|
XFree(res);
|
|
|
|
*np = n;
|
|
return rects;
|
|
}
|
|
|