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