all repos — dwm @ 48b6e9a3968e54a87f022c8e68b5bec5423cb75f

fork of suckless dynamic window manager

event.c (view raw)

  1/*
  2 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
  3 * See LICENSE file for license details.
  4 */
  5
  6#include <fcntl.h>
  7#include <stdlib.h>
  8#include <string.h>
  9#include <X11/keysym.h>
 10#include <X11/Xatom.h>
 11
 12#include "wm.h"
 13
 14/* local functions */
 15static void buttonpress(XEvent *e);
 16static void configurerequest(XEvent *e);
 17static void destroynotify(XEvent *e);
 18static void enternotify(XEvent *e);
 19static void leavenotify(XEvent *e);
 20static void expose(XEvent *e);
 21static void keymapnotify(XEvent *e);
 22static void maprequest(XEvent *e);
 23static void propertynotify(XEvent *e);
 24static void unmapnotify(XEvent *e);
 25
 26void (*handler[LASTEvent]) (XEvent *) = {
 27	[ButtonPress] = buttonpress,
 28	[ConfigureRequest] = configurerequest,
 29	[DestroyNotify] = destroynotify,
 30	[EnterNotify] = enternotify,
 31	[LeaveNotify] = leavenotify,
 32	[Expose] = expose,
 33	[KeyPress] = keypress,
 34	[KeymapNotify] = keymapnotify,
 35	[MapRequest] = maprequest,
 36	[PropertyNotify] = propertynotify,
 37	[UnmapNotify] = unmapnotify
 38};
 39
 40unsigned int
 41discard_events(long even_mask)
 42{
 43	XEvent ev;
 44	unsigned int n = 0;
 45	while(XCheckMaskEvent(dpy, even_mask, &ev)) n++;
 46	return n;
 47}
 48
 49static void
 50buttonpress(XEvent *e)
 51{
 52	XButtonPressedEvent *ev = &e->xbutton;
 53	Client *c;
 54
 55	if((c = getclient(ev->window))) {
 56		switch(ev->button) {
 57		default:
 58			break;
 59		case Button1:
 60			mmove(c);
 61			break;
 62		case Button2:
 63			XLowerWindow(dpy, c->win);
 64			break;
 65		case Button3:
 66			mresize(c);
 67			break;
 68		}
 69	}
 70}
 71
 72static void
 73configurerequest(XEvent *e)
 74{
 75	XConfigureRequestEvent *ev = &e->xconfigurerequest;
 76	XWindowChanges wc;
 77	Client *c;
 78
 79	ev->value_mask &= ~CWSibling;
 80	if((c = getclient(ev->window))) {
 81		if(ev->value_mask & CWX)
 82			c->r[RFloat].x = ev->x;
 83		if(ev->value_mask & CWY)
 84			c->r[RFloat].y = ev->y;
 85		if(ev->value_mask & CWWidth)
 86			c->r[RFloat].width = ev->width;
 87		if(ev->value_mask & CWHeight)
 88			c->r[RFloat].height = ev->height;
 89	}
 90
 91	wc.x = ev->x;
 92	wc.y = ev->y;
 93	wc.width = ev->width;
 94	wc.height = ev->height;
 95	wc.border_width = 0;
 96	wc.sibling = None;
 97	wc.stack_mode = Above;
 98	ev->value_mask &= ~CWStackMode;
 99	ev->value_mask |= CWBorderWidth;
100	XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
101	XFlush(dpy);
102}
103
104static void
105destroynotify(XEvent *e)
106{
107	Client *c;
108	XDestroyWindowEvent *ev = &e->xdestroywindow;
109
110	if((c = getclient(ev->window)))
111		unmanage(c);
112}
113
114static void
115enternotify(XEvent *e)
116{
117	XCrossingEvent *ev = &e->xcrossing;
118	Client *c;
119
120	if(ev->mode != NotifyNormal || ev->detail == NotifyInferior)
121		return;
122
123	if((c = getclient(ev->window)))
124		focus(c);
125	else if(ev->window == root) {
126		sel_screen = True;
127		/*draw_frames();*/
128	}
129}
130
131static void
132leavenotify(XEvent *e)
133{
134	XCrossingEvent *ev = &e->xcrossing;
135
136	if((ev->window == root) && !ev->same_screen) {
137		sel_screen = True;
138		/*draw_frames();*/
139	}
140}
141
142static void
143expose(XEvent *e)
144{
145	XExposeEvent *ev = &e->xexpose;
146
147	if(ev->count == 0) {
148		if(ev->window == barwin)
149			draw_bar();
150	}
151}
152
153static void
154keymapnotify(XEvent *e)
155{
156	update_keys();
157}
158
159static void
160maprequest(XEvent *e)
161{
162	XMapRequestEvent *ev = &e->xmaprequest;
163	static XWindowAttributes wa;
164
165	if(!XGetWindowAttributes(dpy, ev->window, &wa))
166		return;
167
168	if(wa.override_redirect) {
169		XSelectInput(dpy, ev->window,
170				(StructureNotifyMask | PropertyChangeMask));
171		return;
172	}
173
174	if(!getclient(ev->window))
175		manage(ev->window, &wa);
176}
177
178static void
179propertynotify(XEvent *e)
180{
181	XPropertyEvent *ev = &e->xproperty;
182	long msize;
183	Client *c;
184
185	if(ev->state == PropertyDelete)
186		return; /* ignore */
187
188	if(ev->atom == wm_atom[WMProtocols]) {
189		c->proto = win_proto(c->win);
190		return;
191	}
192	if((c = getclient(ev->window))) {
193		switch (ev->atom) {
194			default: break;
195			case XA_WM_TRANSIENT_FOR:
196				XGetTransientForHint(dpy, c->win, &c->trans);
197				break;
198			case XA_WM_NORMAL_HINTS:
199				if(!XGetWMNormalHints(dpy, c->win, &c->size, &msize)
200						|| !c->size.flags)
201					c->size.flags = PSize;
202				if(c->size.flags & PMinSize && c->size.flags & PMaxSize
203						&& c->size.min_width == c->size.max_width
204						&& c->size.min_height == c->size.max_height)
205					c->fixedsize = True;
206				else
207					c->fixedsize = False;
208				break;
209		}
210		if(ev->atom == XA_WM_NAME || ev->atom == net_atom[NetWMName]) {
211			update_name(c);
212		}
213	}
214}
215
216static void
217unmapnotify(XEvent *e)
218{
219	Client *c;
220	XUnmapEvent *ev = &e->xunmap;
221
222	if((c = getclient(ev->window)))
223		unmanage(c);
224}