swm

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

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 }