swm

sigma window manager
git clone git://wolog.xyz/swm
Log | Files | Refs | README | LICENSE

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 }