evt.c (5905B)
1 /* 2 * Copyright (C) Raymond Cole <rc@wolog.xyz> 3 * 4 * Licensed under the GNU General Public License; either version 3 of 5 * the License, or (at your option) any later version. See the LICENSE 6 * file for details. 7 * 8 * Portions of the code originally belong to dwm as developed by Anselm 9 * R. Garbe et al. See LICENSE-dwm for the copyright and license details 10 * of those portions. 11 */ 12 #include <X11/Xatom.h> 13 #include <X11/Xlib.h> 14 #include <X11/Xutil.h> 15 16 #include "swm.h" 17 #include "util.h" 18 19 static void clientmessage(XEvent *e); 20 static void configurenotify(XEvent *e); 21 static void configurerequest(XEvent *e); 22 static void destroynotify(XEvent *e); 23 static void enternotify(XEvent *e); 24 static void expose(XEvent *e); 25 static void focusin(XEvent *e); 26 static void mappingnotify(XEvent *e); 27 static void maprequest(XEvent *e); 28 static void motionnotify(XEvent *e); 29 static void propertynotify(XEvent *e); 30 static void unmapnotify(XEvent *e); 31 32 void (*handler[LASTEvent]) (XEvent *) = { 33 [ButtonPress] = buttonpress, 34 [ClientMessage] = clientmessage, 35 [ConfigureNotify] = configurenotify, 36 [ConfigureRequest] = configurerequest, 37 [DestroyNotify] = destroynotify, 38 [EnterNotify] = enternotify, 39 [Expose] = expose, 40 [FocusIn] = focusin, 41 [KeyPress] = keypress, 42 [MappingNotify] = mappingnotify, 43 [MapRequest] = maprequest, 44 [MotionNotify] = motionnotify, 45 [PropertyNotify] = propertynotify, 46 [UnmapNotify] = unmapnotify, 47 }; 48 49 void 50 clientmessage(XEvent *e) 51 { 52 XClientMessageEvent *ev = &e->xclient; 53 Client *c = wintoclient(ev->window); 54 55 if (!c) 56 return; 57 if (ev->message_type == netatom[NetWMState]) { 58 if (ev->data.l[1] == netatom[NetWMStateFullscreen] 59 || ev->data.l[2] == netatom[NetWMStateFullscreen]) 60 setfullscreen(c, ev->data.l[0] < 2 ? ev->data.l[0] 61 : !c->isfullscreen); 62 } else if (ev->message_type == netatom[NetActiveWindow]) { 63 if (c != selmon->sel) 64 seturgent(c, 1); 65 } 66 } 67 68 void 69 configurenotify(XEvent *e) 70 { 71 XConfigureEvent *ev = &e->xconfigure; 72 Monitor *m; 73 Client *c; 74 int t, dirty; 75 76 if (ev->window == root) { 77 dirty = (sw != ev->width || sh != ev->height); 78 sw = ev->width; 79 sh = ev->height; 80 if ((t = updategeom()) < 0) { 81 warn("cannot update geometry information"); 82 return; 83 } 84 if (!dirty && !t) 85 return; 86 updatedrawable(); 87 for (m = mons; m; m = m->next) { 88 if (!m->barwin) 89 initbar(m); 90 XMoveResizeWindow(dpy, m->barwin, m->x, BY(m), m->w, barh); 91 for (c = m->clients; c; c = c->next) 92 configure(c, 1); 93 parrange(m); 94 } 95 focus(selmon->stack); 96 } 97 } 98 99 void 100 configurerequest(XEvent *e) 101 { 102 XConfigureRequestEvent *ev = &e->xconfigurerequest; 103 Client *c; 104 Monitor *m; 105 XWindowChanges wc; 106 107 if ((c = wintoclient(ev->window))) { 108 if (!c->isfullscreen && (c->isfloating || !selmon->lyt)) { 109 m = c->mon; 110 if (ev->value_mask & CWX) 111 c->x = m->x + ev->x; 112 if (ev->value_mask & CWY) 113 c->y = m->y + ev->y; 114 if (ev->value_mask & CWWidth) 115 c->w = ev->width; 116 if (ev->value_mask & CWHeight) 117 c->h = ev->height; 118 if (ev->value_mask & (CWX|CWY|CWWidth|CWHeight)) 119 configure(c, ev->value_mask & (CWWidth|CWHeight)); 120 } else { 121 notifyconfigure(c); 122 } 123 } else { 124 wc.x = ev->x; 125 wc.y = ev->y; 126 wc.width = ev->width; 127 wc.height = ev->height; 128 wc.border_width = ev->border_width; 129 wc.sibling = ev->above; 130 wc.stack_mode = ev->detail; 131 XConfigureWindow(dpy, ev->window, ev->value_mask, &wc); 132 } 133 XSync(dpy, False); 134 } 135 136 void 137 destroynotify(XEvent *e) 138 { 139 XDestroyWindowEvent *ev = &e->xdestroywindow; 140 Client *c; 141 142 if ((c = wintoclient(ev->window))) 143 unmanage(c, 1); 144 } 145 146 void 147 enternotify(XEvent *e) 148 { 149 XCrossingEvent *ev = &e->xcrossing; 150 Monitor *m; 151 Client *c; 152 int x, y; 153 154 if (ev->window != root 155 && (ev->mode != NotifyNormal || ev->detail == NotifyInferior)) 156 return; 157 if (ev->window == root) { 158 getrootptr(&x, &y); 159 m = pttomon(x, y); 160 } else { 161 for (m = mons; m && m->barwin != ev->window; m = m->next) 162 ; 163 } 164 if (m) { 165 if (selmon != m) 166 focusmon(m); 167 } else if ((c = wintoclient(ev->window))) { 168 if (selmon->sel != c) 169 focus(c); 170 } 171 } 172 173 void 174 expose(XEvent *e) 175 { 176 XExposeEvent *ev = &e->xexpose; 177 Monitor *m; 178 179 if (ev->count != 0) 180 return; 181 for (m = mons; m; m = m->next) 182 if (m->barwin == ev->window) 183 pdrawbar(m); 184 } 185 186 /* there are some broken focus acquiring clients */ 187 void 188 focusin(XEvent *e) 189 { 190 XFocusChangeEvent *ev = &e->xfocus; 191 192 if (selmon->sel && ev->window != selmon->sel->win) 193 focus(selmon->sel); 194 } 195 196 void 197 mappingnotify(XEvent *e) 198 { 199 XMappingEvent *ev = &e->xmapping; 200 201 XRefreshKeyboardMapping(ev); 202 if (ev->request == MappingKeyboard) 203 grabkeys(); 204 } 205 206 void 207 maprequest(XEvent *e) 208 { 209 XMapRequestEvent *ev = &e->xmaprequest; 210 XWindowAttributes wa; 211 212 if (!XGetWindowAttributes(dpy, ev->window, &wa) 213 || wa.override_redirect || wintoclient(ev->window)) 214 return; 215 if (!manage(ev->window, &wa)) 216 warn("cannot manage window 0x%x", ev->window); 217 } 218 219 void 220 motionnotify(XEvent *e) 221 { 222 XMotionEvent *ev = &e->xmotion; 223 Monitor *m; 224 225 if (ev->window == root) { 226 m = pttomon(ev->x_root, ev->y_root); 227 if (m && selmon != m) 228 focusmon(m); 229 } 230 } 231 232 void 233 propertynotify(XEvent *e) 234 { 235 XPropertyEvent *ev = &e->xproperty; 236 Client *c; 237 Window dw; 238 239 if (ev->state == PropertyDelete) 240 return; 241 if ((c = wintoclient(ev->window))) { 242 switch(ev->atom) { 243 case XA_WM_TRANSIENT_FOR: 244 if (XGetTransientForHint(dpy, c->win, &dw)) 245 setfloating(c, 1); 246 break; 247 case XA_WM_NORMAL_HINTS: 248 c->hintsvalid = 0; 249 parrange(c->mon); 250 break; 251 case XA_WM_HINTS: 252 updatewmhints(c); 253 pdrawbar(c->mon); 254 break; 255 default: 256 if (ev->atom == netatom[NetWMName] 257 || ev->atom == XA_WM_NAME) { 258 updatetitle(c); 259 if (c == c->mon->sel) 260 pdrawbar(c->mon); 261 } else if (ev->atom == netatom[NetWMWindowType]) { 262 updatewindowtype(c); 263 } 264 break; 265 } 266 } 267 } 268 269 void 270 unmapnotify(XEvent *e) 271 { 272 XUnmapEvent *ev = &e->xunmap; 273 Client *c; 274 275 if ((c = wintoclient(ev->window))) 276 unmanage(c, 0); 277 }