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