wmii

git clone git://oldgit.suckless.org/wmii/
Log | Files | Refs | README | LICENSE

xext.c (3417B)


      1 /* Copyright ©2008-2010 Kris Maglione <maglione.k at Gmail>
      2  * See LICENSE file for license details.
      3  */
      4 #define _X11_VISIBLE
      5 #include <stuff/x.h>
      6 #include <stuff/util.h>
      7 #include <X11/extensions/Xrandr.h>
      8 #include <X11/extensions/Xrender.h>
      9 #include <X11/extensions/Xinerama.h>
     10 
     11 #if RANDR_MAJOR < 1
     12 #  error XRandR versions less than 1.0 are not supported
     13 #endif
     14 
     15 static void	randr_screenchange(XRRScreenChangeNotifyEvent*);
     16 static bool	randr_event_p(XEvent *e);
     17 static void	randr_init(void);
     18 static void	render_init(void);
     19 static void	xinerama_init(void);
     20 
     21 typedef void		(*EvHandler)(XEvent*);
     22 static EvHandler	randr_handlers[RRNumberEvents];
     23 
     24 bool	have_RandR;
     25 bool	have_render;
     26 bool	have_xinerama;
     27 int	randr_eventbase;
     28 Visual*	render_visual;
     29 
     30 static void
     31 handle(XEvent *e, EvHandler h[], int base) {
     32 
     33 	if(h[e->type-base])
     34 		h[e->type-base](e);
     35 }
     36 
     37 void
     38 xext_init(void) {
     39 	randr_init();
     40 	render_init();
     41 	xinerama_init();
     42 }
     43 
     44 void
     45 xext_event(XEvent *e) {
     46 
     47 	if(randr_event_p(e))
     48 		handle(e, randr_handlers, randr_eventbase);
     49 }
     50 
     51 static void
     52 randr_init(void) {
     53 	int errorbase, major, minor;
     54 
     55 	have_RandR = XRRQueryExtension(display, &randr_eventbase, &errorbase);
     56 	if(have_RandR)
     57 		if(XRRQueryVersion(display, &major, &minor) && major < 1)
     58 			have_RandR = false;
     59 	if(have_RandR)
     60 		XRRSelectInput(display, scr.root.xid, RRScreenChangeNotifyMask);
     61 }
     62 
     63 static bool
     64 randr_event_p(XEvent *e) {
     65 	return have_RandR
     66 	    && (uint)e->type - randr_eventbase < RRNumberEvents;
     67 }
     68 
     69 static void
     70 randr_screenchange(XRRScreenChangeNotifyEvent *ev) {
     71 
     72 	XRRUpdateConfiguration((XEvent*)ev);
     73 	if(ev->rotation*90 % 180)
     74 		scr.rect = Rect(0, 0, ev->width, ev->height);
     75 	else
     76 		scr.rect = Rect(0, 0, ev->height, ev->width);
     77 	init_screens();
     78 }
     79 
     80 static EvHandler randr_handlers[] = {
     81 	[RRScreenChangeNotify] = (EvHandler)randr_screenchange,
     82 };
     83 
     84 /* Ripped most graciously from ecore_x. XRender documentation
     85  * is sparse.
     86  */
     87 static void
     88 render_init(void) {
     89 	XVisualInfo *vip;
     90 	XVisualInfo vi;
     91 	int base, i, n;
     92 
     93 	have_render = XRenderQueryExtension(display, &base, &base);
     94 	if(!have_render)
     95 		return;
     96 
     97 	vi.class = TrueColor;
     98 	vi.depth = 32;
     99 	vi.screen = scr.screen;
    100 	vip = XGetVisualInfo(display, VisualClassMask
    101 				    | VisualDepthMask
    102 				    | VisualScreenMask,
    103 				    &vi, &n);
    104 	for(i=0; i < n; i++)
    105 		if(render_argb_p(vip[i].visual)) {
    106 			render_visual = vip[i].visual;
    107 			scr.visual32 = render_visual;
    108 			break;
    109 		}
    110 	XFree(vip);
    111 	if(render_visual)
    112 		scr.colormap32 = XCreateColormap(display, scr.root.xid, render_visual, AllocNone);
    113 }
    114 
    115 bool
    116 render_argb_p(Visual *v) {
    117 	XRenderPictFormat *f;
    118 
    119 	if(!have_render)
    120 		return false;
    121 	f = XRenderFindVisualFormat(display, v);
    122 	return f
    123 	    && f->type == PictTypeDirect
    124 	    && f->direct.alphaMask;
    125 }
    126 
    127 static void
    128 xinerama_init(void) {
    129 	int base;
    130 
    131 	have_xinerama = XineramaQueryExtension(display, &base, &base);
    132 }
    133 
    134 static bool
    135 xinerama_active(void) {
    136 	return have_xinerama && XineramaIsActive(display);
    137 }
    138 
    139 Rectangle*
    140 xinerama_screens(int *np) {
    141 	static Rectangle *rects;
    142 	XineramaScreenInfo *res;
    143 	int i, n;
    144 
    145 	if(!xinerama_active()) {
    146 		*np = 1;
    147 		return &scr.rect;
    148 	}
    149 
    150 	free(rects);
    151 	res = XineramaQueryScreens(display, &n);
    152 	rects = emalloc(n * sizeof *rects);
    153 	for(i=0; i < n; i++) {
    154 		rects[i].min.x = res[i].x_org;
    155 		rects[i].min.y = res[i].y_org;
    156 		rects[i].max.x = res[i].x_org + res[i].width;
    157 		rects[i].max.y = res[i].y_org + res[i].height;
    158 	}
    159 	XFree(res);
    160 
    161 	*np = n;
    162 	return rects;
    163 }
    164