aewl
diff wm.c @ 0:491f34c11291
initial import
author | Anselm R. Garbe <garbeam@wmii.de> |
---|---|
date | Mon, 10 Jul 2006 16:38:18 +0200 |
parents | |
children | a79188fe4a40 |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/wm.c Mon Jul 10 16:38:18 2006 +0200 1.3 @@ -0,0 +1,264 @@ 1.4 +/* 1.5 + * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com> 1.6 + * See LICENSE file for license details. 1.7 + */ 1.8 + 1.9 +#include <stdarg.h> 1.10 +#include <stdio.h> 1.11 +#include <stdlib.h> 1.12 + 1.13 +#include <X11/cursorfont.h> 1.14 +#include <X11/Xatom.h> 1.15 +#include <X11/Xproto.h> 1.16 + 1.17 +#include "wm.h" 1.18 + 1.19 +Display *dpy; 1.20 +Window root; 1.21 +XRectangle rect; 1.22 +int screen, sel_screen; 1.23 +Atom wm_atom[WMLast]; 1.24 +Atom net_atom[NetLast]; 1.25 +Cursor cursor[CurLast]; 1.26 +unsigned int kmask, numlock_mask; 1.27 +Pixmap pmap; 1.28 + 1.29 +enum { WM_PROTOCOL_DELWIN = 1 }; 1.30 + 1.31 +static Bool other_wm_running; 1.32 +static int (*x_error_handler) (Display *, XErrorEvent *); 1.33 +static char version[] = "gridwm - " VERSION ", (C)opyright MMVI Anselm R. Garbe\n"; 1.34 + 1.35 +static void 1.36 +usage() 1.37 +{ 1.38 + fputs("usage: gridwm [-v]\n", stderr); 1.39 + exit(1); 1.40 +} 1.41 + 1.42 +void 1.43 +error(char *errstr, ...) { 1.44 + va_list ap; 1.45 + va_start(ap, errstr); 1.46 + vfprintf(stderr, errstr, ap); 1.47 + va_end(ap); 1.48 + exit(1); 1.49 +} 1.50 + 1.51 +static void 1.52 +scan_wins() 1.53 +{ 1.54 + unsigned int i, num; 1.55 + Window *wins; 1.56 + XWindowAttributes wa; 1.57 + Window d1, d2; 1.58 + 1.59 + if(XQueryTree(dpy, root, &d1, &d2, &wins, &num)) { 1.60 + for(i = 0; i < num; i++) { 1.61 + if(!XGetWindowAttributes(dpy, wins[i], &wa)) 1.62 + continue; 1.63 + if(wa.override_redirect || XGetTransientForHint(dpy, wins[i], &d1)) 1.64 + continue; 1.65 + if(wa.map_state == IsViewable) 1.66 + /*manage*/; 1.67 + } 1.68 + } 1.69 + if(wins) 1.70 + XFree(wins); 1.71 +} 1.72 + 1.73 +static int 1.74 +win_property(Window w, Atom a, Atom t, long l, unsigned char **prop) 1.75 +{ 1.76 + Atom real; 1.77 + int format; 1.78 + unsigned long res, extra; 1.79 + int status; 1.80 + 1.81 + status = XGetWindowProperty(dpy, w, a, 0L, l, False, t, &real, &format, 1.82 + &res, &extra, prop); 1.83 + 1.84 + if(status != Success || *prop == 0) { 1.85 + return 0; 1.86 + } 1.87 + if(res == 0) { 1.88 + free((void *) *prop); 1.89 + } 1.90 + return res; 1.91 +} 1.92 + 1.93 +int 1.94 +win_proto(Window w) 1.95 +{ 1.96 + Atom *protocols; 1.97 + long res; 1.98 + int protos = 0; 1.99 + int i; 1.100 + 1.101 + res = win_property(w, wm_atom[WMProtocols], XA_ATOM, 20L, 1.102 + ((unsigned char **) &protocols)); 1.103 + if(res <= 0) { 1.104 + return protos; 1.105 + } 1.106 + for(i = 0; i < res; i++) { 1.107 + if(protocols[i] == wm_atom[WMDelete]) 1.108 + protos |= WM_PROTOCOL_DELWIN; 1.109 + } 1.110 + free((char *) protocols); 1.111 + return protos; 1.112 +} 1.113 + 1.114 +/* 1.115 + * There's no way to check accesses to destroyed windows, thus 1.116 + * those cases are ignored (especially on UnmapNotify's). 1.117 + * Other types of errors call Xlib's default error handler, which 1.118 + * calls exit(). 1.119 + */ 1.120 +static int 1.121 +error_handler(Display *dpy, XErrorEvent *error) 1.122 +{ 1.123 + if(error->error_code == BadWindow 1.124 + || (error->request_code == X_SetInputFocus 1.125 + && error->error_code == BadMatch) 1.126 + || (error->request_code == X_PolyText8 1.127 + && error->error_code == BadDrawable) 1.128 + || (error->request_code == X_PolyFillRectangle 1.129 + && error->error_code == BadDrawable) 1.130 + || (error->request_code == X_PolySegment 1.131 + && error->error_code == BadDrawable) 1.132 + || (error->request_code == X_ConfigureWindow 1.133 + && error->error_code == BadMatch) 1.134 + || (error->request_code == X_GrabKey 1.135 + && error->error_code == BadAccess)) 1.136 + return 0; 1.137 + fprintf(stderr, "gridwm: fatal error: request code=%d, error code=%d\n", 1.138 + error->request_code, error->error_code); 1.139 + return x_error_handler(dpy, error); /* may call exit() */ 1.140 +} 1.141 + 1.142 +/* 1.143 + * Startup Error handler to check if another window manager 1.144 + * is already running. 1.145 + */ 1.146 +static int 1.147 +startup_error_handler(Display *dpy, XErrorEvent *error) 1.148 +{ 1.149 + other_wm_running = True; 1.150 + return -1; 1.151 +} 1.152 + 1.153 +static void 1.154 +init_lock_keys() 1.155 +{ 1.156 + XModifierKeymap *modmap; 1.157 + KeyCode numlock; 1.158 + int i; 1.159 + static int masks[] = { 1.160 + ShiftMask, LockMask, ControlMask, Mod1Mask, 1.161 + Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask 1.162 + }; 1.163 + 1.164 + numlock_mask = 0; 1.165 + modmap = XGetModifierMapping(dpy); 1.166 + numlock = XKeysymToKeycode(dpy, XStringToKeysym("Num_Lock")); 1.167 + 1.168 + if(modmap && modmap->max_keypermod > 0) { 1.169 + int max = (sizeof(masks) / sizeof(int)) * modmap->max_keypermod; 1.170 + for(i = 0; i < max; i++) 1.171 + if(numlock && (modmap->modifiermap[i] == numlock)) 1.172 + numlock_mask = masks[i / modmap->max_keypermod]; 1.173 + } 1.174 + XFreeModifiermap(modmap); 1.175 + 1.176 + kmask = 255 & ~(numlock_mask | LockMask); 1.177 +} 1.178 + 1.179 +static void 1.180 +cleanup() 1.181 +{ 1.182 + /* 1.183 + Client *c; 1.184 + for(c=client; c; c=c->next) 1.185 + reparent_client(c, root, c->sel->rect.x, c->sel->rect.y); 1.186 + XSetInputFocus(dpy, PointerRoot, RevertToPointerRoot, CurrentTime); 1.187 + */ 1.188 +} 1.189 + 1.190 +int 1.191 +main(int argc, char *argv[]) 1.192 +{ 1.193 + int i; 1.194 + XSetWindowAttributes wa; 1.195 + unsigned int mask; 1.196 + Window w; 1.197 + 1.198 + /* command line args */ 1.199 + for(i = 1; (i < argc) && (argv[i][0] == '-'); i++) { 1.200 + switch (argv[i][1]) { 1.201 + case 'v': 1.202 + fprintf(stdout, "%s", version); 1.203 + exit(0); 1.204 + break; 1.205 + default: 1.206 + usage(); 1.207 + break; 1.208 + } 1.209 + } 1.210 + 1.211 + dpy = XOpenDisplay(0); 1.212 + if(!dpy) 1.213 + error("gridwm: cannot connect X server\n"); 1.214 + 1.215 + screen = DefaultScreen(dpy); 1.216 + root = RootWindow(dpy, screen); 1.217 + 1.218 + /* check if another WM is already running */ 1.219 + other_wm_running = False; 1.220 + XSetErrorHandler(startup_error_handler); 1.221 + /* this causes an error if some other WM is running */ 1.222 + XSelectInput(dpy, root, SubstructureRedirectMask); 1.223 + XSync(dpy, False); 1.224 + 1.225 + if(other_wm_running) 1.226 + error("gridwm: another window manager is already running\n"); 1.227 + 1.228 + rect.x = rect.y = 0; 1.229 + rect.width = DisplayWidth(dpy, screen); 1.230 + rect.height = DisplayHeight(dpy, screen); 1.231 + sel_screen = XQueryPointer(dpy, root, &w, &w, &i, &i, &i, &i, &mask); 1.232 + 1.233 + XSetErrorHandler(0); 1.234 + x_error_handler = XSetErrorHandler(error_handler); 1.235 + 1.236 + /* init atoms */ 1.237 + wm_atom[WMState] = XInternAtom(dpy, "WM_STATE", False); 1.238 + wm_atom[WMProtocols] = XInternAtom(dpy, "WM_PROTOCOLS", False); 1.239 + wm_atom[WMDelete] = XInternAtom(dpy, "WM_DELETE_WINDOW", False); 1.240 + net_atom[NetSupported] = XInternAtom(dpy, "_NET_SUPPORTED", False); 1.241 + net_atom[NetWMName] = XInternAtom(dpy, "_NET_WM_NAME", False); 1.242 + 1.243 + XChangeProperty(dpy, root, net_atom[NetSupported], XA_ATOM, 32, 1.244 + PropModeReplace, (unsigned char *) net_atom, NetLast); 1.245 + 1.246 + 1.247 + /* init cursors */ 1.248 + cursor[CurNormal] = XCreateFontCursor(dpy, XC_left_ptr); 1.249 + cursor[CurResize] = XCreateFontCursor(dpy, XC_sizing); 1.250 + cursor[CurMove] = XCreateFontCursor(dpy, XC_fleur); 1.251 + 1.252 + init_lock_keys(); 1.253 + 1.254 + pmap = XCreatePixmap(dpy, root, rect.width, rect.height, 1.255 + DefaultDepth(dpy, screen)); 1.256 + 1.257 + wa.event_mask = SubstructureRedirectMask | EnterWindowMask | LeaveWindowMask; 1.258 + wa.cursor = cursor[CurNormal]; 1.259 + XChangeWindowAttributes(dpy, root, CWEventMask | CWCursor, &wa); 1.260 + 1.261 + scan_wins(); 1.262 + 1.263 + cleanup(); 1.264 + XCloseDisplay(dpy); 1.265 + 1.266 + return 0; 1.267 +}