all repos — dwm @ c0705eeb65733e8c5091e47d5bdc701a0779a949

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 <stdio.h>
  8#include <stdlib.h>
  9#include <string.h>
 10#include <unistd.h>
 11#include <X11/keysym.h>
 12#include <X11/Xatom.h>
 13
 14#include "dwm.h"
 15
 16#define ButtonMask      (ButtonPressMask | ButtonReleaseMask)
 17#define MouseMask       (ButtonMask | PointerMotionMask)
 18
 19/* local functions */
 20static void buttonpress(XEvent *e);
 21static void configurerequest(XEvent *e);
 22static void destroynotify(XEvent *e);
 23static void enternotify(XEvent *e);
 24static void leavenotify(XEvent *e);
 25static void expose(XEvent *e);
 26static void maprequest(XEvent *e);
 27static void propertynotify(XEvent *e);
 28static void unmapnotify(XEvent *e);
 29
 30void (*handler[LASTEvent]) (XEvent *) = {
 31	[ButtonPress] = buttonpress,
 32	[ConfigureRequest] = configurerequest,
 33	[DestroyNotify] = destroynotify,
 34	[EnterNotify] = enternotify,
 35	[LeaveNotify] = leavenotify,
 36	[Expose] = expose,
 37	[KeyPress] = keypress,
 38	[MapRequest] = maprequest,
 39	[PropertyNotify] = propertynotify,
 40	[UnmapNotify] = unmapnotify
 41};
 42
 43static void
 44mresize(Client *c)
 45{
 46	XEvent ev;
 47	int ocx, ocy;
 48
 49	ocx = c->x;
 50	ocy = c->y;
 51	if(XGrabPointer(dpy, root, False, MouseMask, GrabModeAsync, GrabModeAsync,
 52				None, cursor[CurResize], CurrentTime) != GrabSuccess)
 53		return;
 54	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0, c->w, c->h);
 55	for(;;) {
 56		XMaskEvent(dpy, MouseMask | ExposureMask, &ev);
 57		switch(ev.type) {
 58		default: break;
 59		case Expose:
 60			handler[Expose](&ev);
 61			break;
 62		case MotionNotify:
 63			XFlush(dpy);
 64			c->w = abs(ocx - ev.xmotion.x);
 65			c->h = abs(ocy - ev.xmotion.y);
 66			c->x = (ocx <= ev.xmotion.x) ? ocx : ocx - c->w;
 67			c->y = (ocy <= ev.xmotion.y) ? ocy : ocy - c->h;
 68			resize(c, True);
 69			break;
 70		case ButtonRelease:
 71			XUngrabPointer(dpy, CurrentTime);
 72			return;
 73		}
 74	}
 75}
 76
 77static void
 78mmove(Client *c)
 79{
 80	XEvent ev;
 81	int x1, y1, ocx, ocy, di;
 82	unsigned int dui;
 83	Window dummy;
 84
 85	ocx = c->x;
 86	ocy = c->y;
 87	if(XGrabPointer(dpy, root, False, MouseMask, GrabModeAsync, GrabModeAsync,
 88				None, cursor[CurMove], CurrentTime) != GrabSuccess)
 89		return;
 90	XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
 91	for(;;) {
 92		XMaskEvent(dpy, MouseMask | ExposureMask, &ev);
 93		switch (ev.type) {
 94		default: break;
 95		case Expose:
 96			handler[Expose](&ev);
 97			break;
 98		case MotionNotify:
 99			XFlush(dpy);
100			c->x = ocx + (ev.xmotion.x - x1);
101			c->y = ocy + (ev.xmotion.y - y1);
102			resize(c, False);
103			break;
104		case ButtonRelease:
105			XUngrabPointer(dpy, CurrentTime);
106			return;
107		}
108	}
109}
110
111static void
112buttonpress(XEvent *e)
113{
114	int x;
115	Arg a;
116	XButtonPressedEvent *ev = &e->xbutton;
117	Client *c;
118
119	if(barwin == ev->window) {
120		x = (arrange == floating) ? textw("~") : 0;
121		for(a.i = 0; a.i < TLast; a.i++) {
122			x += textw(tags[a.i]);
123			if(ev->x < x) {
124				view(&a);
125				break;
126			}
127		}
128	}
129	else if((c = getclient(ev->window))) {
130		if(arrange == tiling && !c->floating)
131			return;
132		higher(c);
133		switch(ev->button) {
134		default:
135			break;
136		case Button1:
137			mmove(c);
138			break;
139		case Button2:
140			lower(c);
141			break;
142		case Button3:
143			mresize(c);
144			break;
145		}
146	}
147}
148
149static void
150configurerequest(XEvent *e)
151{
152	XConfigureRequestEvent *ev = &e->xconfigurerequest;
153	XWindowChanges wc;
154	Client *c;
155
156	ev->value_mask &= ~CWSibling;
157	if((c = getclient(ev->window))) {
158		gravitate(c, True);
159		if(ev->value_mask & CWX)
160			c->x = ev->x;
161		if(ev->value_mask & CWY)
162			c->y = ev->y;
163		if(ev->value_mask & CWWidth)
164			c->w = ev->width;
165		if(ev->value_mask & CWHeight)
166			c->h = ev->height;
167		if(ev->value_mask & CWBorderWidth)
168			c->border = 1;
169		gravitate(c, False);
170		resize(c, True);
171	}
172
173	wc.x = ev->x;
174	wc.y = ev->y;
175	wc.width = ev->width;
176	wc.height = ev->height;
177	wc.border_width = 1;
178	wc.sibling = None;
179	wc.stack_mode = Above;
180	ev->value_mask &= ~CWStackMode;
181	ev->value_mask |= CWBorderWidth;
182	XConfigureWindow(dpy, ev->window, ev->value_mask, &wc);
183	XFlush(dpy);
184}
185
186static void
187destroynotify(XEvent *e)
188{
189	Client *c;
190	XDestroyWindowEvent *ev = &e->xdestroywindow;
191
192	if((c = getclient(ev->window)))
193		unmanage(c);
194}
195
196static void
197enternotify(XEvent *e)
198{
199	XCrossingEvent *ev = &e->xcrossing;
200	Client *c;
201
202	if(ev->mode != NotifyNormal || ev->detail == NotifyInferior)
203		return;
204
205	if((c = getclient(ev->window)))
206		focus(c);
207	else if(ev->window == root)
208		issel = True;
209}
210
211static void
212leavenotify(XEvent *e)
213{
214	XCrossingEvent *ev = &e->xcrossing;
215
216	if((ev->window == root) && !ev->same_screen)
217		issel = True;
218}
219
220static void
221expose(XEvent *e)
222{
223	XExposeEvent *ev = &e->xexpose;
224	Client *c;
225
226	if(ev->count == 0) {
227		if(barwin == ev->window)
228			drawstatus();
229		else if((c = gettitle(ev->window)))
230			drawtitle(c);
231	}
232}
233
234static void
235maprequest(XEvent *e)
236{
237	XMapRequestEvent *ev = &e->xmaprequest;
238	static XWindowAttributes wa;
239
240	if(!XGetWindowAttributes(dpy, ev->window, &wa))
241		return;
242
243	if(wa.override_redirect) {
244		XSelectInput(dpy, ev->window,
245				(StructureNotifyMask | PropertyChangeMask));
246		return;
247	}
248
249	if(!getclient(ev->window))
250		manage(ev->window, &wa);
251}
252
253static void
254propertynotify(XEvent *e)
255{
256	XPropertyEvent *ev = &e->xproperty;
257	Window trans;
258	Client *c;
259
260	if(ev->state == PropertyDelete)
261		return; /* ignore */
262
263	if((c = getclient(ev->window))) {
264		if(ev->atom == wm_atom[WMProtocols]) {
265			c->proto = proto(c->win);
266			return;
267		}
268		switch (ev->atom) {
269			default: break;
270			case XA_WM_TRANSIENT_FOR:
271				XGetTransientForHint(dpy, c->win, &trans);
272				if(!c->floating && (c->floating = (trans != 0)))
273					arrange(NULL);
274				break;
275			case XA_WM_NORMAL_HINTS:
276				setsize(c);
277				break;
278		}
279		if(ev->atom == XA_WM_NAME || ev->atom == net_atom[NetWMName]) {
280			settitle(c);
281			drawtitle(c);
282		}
283	}
284}
285
286static void
287unmapnotify(XEvent *e)
288{
289	Client *c;
290	XUnmapEvent *ev = &e->xunmap;
291
292	if((c = getclient(ev->window)))
293		unmanage(c);
294}