added mouse-based resizals b9da4b08
Anselm R. Garbe · 2006-07-11 21:24 7 file(s) · +181 −19
Makefile +1 −1
3 3
4 4
include config.mk
5 5
6 -
WMSRC = bar.c client.c cmd.c draw.c event.c key.c util.c wm.c
6 +
WMSRC = bar.c client.c cmd.c draw.c event.c kb.c mouse.c util.c wm.c
7 7
WMOBJ = ${WMSRC:.c=.o}
8 8
MENSRC = menu.c draw.c util.c
9 9
MENOBJ = ${MENSRC:.c=.o}
README +1 −9
5 5
arranges all windows in a grid.
6 6
7 7
8 -
Configuration
9 -
-------------
10 -
You have to edit the source code for configuration, this WM is intended to
11 -
provide sane defaults, if something doesn't fits your needs, edit config.h and
12 -
maybe key.c. To change the status output edit that status variable definition
13 -
in wm.c.
14 -
15 -
16 8
Requirements
17 9
------------
18 10
In order to build gridwm you need the Xlib header files.
46 38
Configuration
47 39
-------------
48 40
The configuration of gridwm is done by customizing the config.h source file. To
49 -
customize the key bindings edit key.c. To change the status output, edit the
41 +
customize the key bindings edit kb.c. To change the status output, edit the
50 42
status command definition in wm.c.
51 43
client.c +30 −2
10 10
#include "util.h"
11 11
#include "wm.h"
12 12
13 +
#define CLIENT_MASK		(StructureNotifyMask | PropertyChangeMask | EnterWindowMask)
14 +
13 15
void
14 16
update_name(Client *c)
15 17
{
70 72
	c->r[RFloat].height = wa->height;
71 73
	c->border = wa->border_width;
72 74
	XSetWindowBorderWidth(dpy, c->win, 0);
73 -
	XSelectInput(dpy, c->win, StructureNotifyMask | PropertyChangeMask | EnterWindowMask);
75 +
	XSelectInput(dpy, c->win, CLIENT_MASK);
74 76
	XGetTransientForHint(dpy, c->win, &c->trans);
75 77
	if(!XGetWMNormalHints(dpy, c->win, &c->size, &msize) || !c->size.flags)
76 78
		c->size.flags = PSize;
95 97
	c->snext = stack;
96 98
	stack = c;
97 99
	XMapWindow(dpy, c->win);
100 +
	XGrabButton(dpy, AnyButton, Mod1Mask, c->win, False, ButtonPressMask,
101 +
			GrabModeAsync, GrabModeSync, None, None);
98 102
	focus(c);
99 103
}
100 104
105 +
void
106 +
resize(Client *c)
107 +
{
108 +
	XConfigureEvent e;
109 +
110 +
	XMoveResizeWindow(dpy, c->win, c->r[RFloat].x, c->r[RFloat].y,
111 +
			c->r[RFloat].width, c->r[RFloat].height);
112 +
	e.type = ConfigureNotify;
113 +
	e.event = c->win;
114 +
	e.window = c->win;
115 +
	e.x = c->r[RFloat].x;
116 +
	e.y = c->r[RFloat].y;
117 +
	e.width = c->r[RFloat].width;
118 +
	e.height = c->r[RFloat].height;
119 +
	e.border_width = c->border;
120 +
	e.above = None;
121 +
	e.override_redirect = False;
122 +
	XSelectInput(dpy, c->win, CLIENT_MASK & ~StructureNotifyMask);
123 +
	XSendEvent(dpy, c->win, False, StructureNotifyMask, (XEvent *)&e);
124 +
	XSelectInput(dpy, c->win, CLIENT_MASK);
125 +
	XFlush(dpy);
126 +
}
127 +
101 128
static int
102 129
dummy_error_handler(Display *dpy, XErrorEvent *error)
103 130
{
112 139
	XGrabServer(dpy);
113 140
	XSetErrorHandler(dummy_error_handler);
114 141
142 +
	XUngrabButton(dpy, AnyButton, AnyModifier, c->win);
115 143
	XUnmapWindow(dpy, c->win);
116 144
	XDestroyWindow(dpy, c->title);
117 145
126 154
	XFlush(dpy);
127 155
	XSetErrorHandler(error_handler);
128 156
	XUngrabServer(dpy);
129 -
	flush_events(EnterWindowMask);
157 +
	discard_events(EnterWindowMask);
130 158
	if(stack)
131 159
		focus(stack);
132 160
}
event.c +27 −3
12 12
#include "wm.h"
13 13
14 14
/* local functions */
15 +
static void buttonpress(XEvent *e);
15 16
static void configurerequest(XEvent *e);
16 17
static void destroynotify(XEvent *e);
17 18
static void enternotify(XEvent *e);
23 24
static void unmapnotify(XEvent *e);
24 25
25 26
void (*handler[LASTEvent]) (XEvent *) = {
27 +
	[ButtonPress] = buttonpress,
26 28
	[ConfigureRequest] = configurerequest,
27 29
	[DestroyNotify] = destroynotify,
28 30
	[EnterNotify] = enternotify,
36 38
};
37 39
38 40
unsigned int
39 -
flush_events(long even_mask)
41 +
discard_events(long even_mask)
40 42
{
41 43
	XEvent ev;
42 44
	unsigned int n = 0;
45 47
}
46 48
47 49
static void
50 +
buttonpress(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 +
72 +
static void
48 73
configurerequest(XEvent *e)
49 74
{
50 75
	XConfigureRequestEvent *ev = &e->xconfigurerequest;
51 76
	XWindowChanges wc;
52 77
	Client *c;
53 78
54 -
	c = getclient(ev->window);
55 79
	ev->value_mask &= ~CWSibling;
56 -
	if(c) {
80 +
	if((c = getclient(ev->window))) {
57 81
		if(ev->value_mask & CWX)
58 82
			c->r[RFloat].x = ev->x;
59 83
		if(ev->value_mask & CWY)
key.c → kb.c +0 −0
mouse.c (added) +100 −0
1 +
/*
2 +
 * (C)opyright MMVI Anselm R. Garbe <garbeam at gmail dot com>
3 +
 * (C)opyright MMVI Kris Maglione <fbsdaemon@gmail.com>
4 +
 * See LICENSE file for license details.
5 +
 */
6 +
7 +
#include <stdlib.h>
8 +
#include <string.h>
9 +
#include <unistd.h>
10 +
11 +
#include "wm.h"
12 +
13 +
#define ButtonMask      (ButtonPressMask | ButtonReleaseMask)
14 +
#define MouseMask       (ButtonMask | PointerMotionMask)
15 +
16 +
static void
17 +
mmatch(Client *c, int x1, int y1, int x2, int y2)
18 +
{
19 +
	c->r[RFloat].width = abs(x1 - x2);
20 +
	c->r[RFloat].height = abs(y1 - y2);
21 +
	c->r[RFloat].width -=
22 +
		(c->r[RFloat].width - c->size.base_width) % c->size.width_inc;
23 +
	c->r[RFloat].height -=
24 +
		(c->r[RFloat].height - c->size.base_height) % c->size.height_inc;
25 +
	if(c->size.min_width && c->r[RFloat].width < c->size.min_width)
26 +
		c->r[RFloat].width = c->size.min_width;
27 +
	if(c->size.min_height && c->r[RFloat].height < c->size.min_height)
28 +
		c->r[RFloat].height = c->size.min_height;
29 +
	if(c->size.max_width && c->r[RFloat].width > c->size.max_width)
30 +
		c->r[RFloat].width = c->size.max_width;
31 +
	if(c->size.max_height && c->r[RFloat].height > c->size.max_height)
32 +
		c->r[RFloat].height = c->size.max_height;
33 +
	c->r[RFloat].x = (x1 <= x2) ? x1 : x1 - c->r[RFloat].width;
34 +
	c->r[RFloat].y = (y1 <= y2) ? y1 : y1 - c->r[RFloat].height;
35 +
}
36 +
37 +
void
38 +
mresize(Client *c)
39 +
{
40 +
	XEvent ev;
41 +
	int old_cx, old_cy;
42 +
43 +
	old_cx = c->r[RFloat].x;
44 +
	old_cy = c->r[RFloat].y;
45 +
	if(XGrabPointer(dpy, c->win, False, MouseMask, GrabModeAsync, GrabModeAsync,
46 +
				None, cursor[CurResize], CurrentTime) != GrabSuccess)
47 +
		return;
48 +
	XGrabServer(dpy);
49 +
	XWarpPointer(dpy, None, c->win, 0, 0, 0, 0,
50 +
			c->r[RFloat].width, c->r[RFloat].height);
51 +
	for(;;) {
52 +
		XMaskEvent(dpy, MouseMask, &ev);
53 +
		switch(ev.type) {
54 +
		default: break;
55 +
		case MotionNotify:
56 +
			XUngrabServer(dpy);
57 +
			mmatch(c, old_cx, old_cy, ev.xmotion.x, ev.xmotion.y);
58 +
			resize(c);
59 +
			XGrabServer(dpy);
60 +
			break;
61 +
		case ButtonRelease:
62 +
			XUngrabPointer(dpy, CurrentTime);
63 +
			return;
64 +
		}
65 +
	}
66 +
}
67 +
68 +
void
69 +
mmove(Client *c)
70 +
{
71 +
	XEvent ev;
72 +
	int x1, y1, old_cx, old_cy, di;
73 +
	unsigned int dui;
74 +
	Window dummy;
75 +
76 +
	old_cx = c->r[RFloat].x;
77 +
	old_cy = c->r[RFloat].y;
78 +
	if(XGrabPointer(dpy, c->win, False, MouseMask, GrabModeAsync, GrabModeAsync,
79 +
				None, cursor[CurMove], CurrentTime) != GrabSuccess)
80 +
		return;
81 +
	XQueryPointer(dpy, root, &dummy, &dummy, &x1, &y1, &di, &di, &dui);
82 +
	XGrabServer(dpy);
83 +
	for(;;) {
84 +
		XMaskEvent(dpy, MouseMask, &ev);
85 +
		switch (ev.type) {
86 +
		default: break;
87 +
		case MotionNotify:
88 +
			XUngrabServer(dpy);
89 +
			c->r[RFloat].x = old_cx + (ev.xmotion.x - x1);
90 +
			c->r[RFloat].y = old_cy + (ev.xmotion.y - y1);
91 +
			resize(c);
92 +
			XGrabServer(dpy);
93 +
			break;
94 +
		case ButtonRelease:
95 +
			XUngrabServer(dpy);
96 +
			XUngrabPointer(dpy, CurrentTime);
97 +
			return;
98 +
		}
99 +
	}
100 +
}
wm.h +22 −4
11 11
12 12
#define WM_PROTOCOL_DELWIN 1
13 13
14 +
typedef struct Client Client;
15 +
typedef struct Key Key;
16 +
typedef enum Align Align;
17 +
18 +
enum Align {
19 +
	NORTH = 0x01,
20 +
	EAST  = 0x02,
21 +
	SOUTH = 0x04,
22 +
	WEST  = 0x08,
23 +
	NEAST = NORTH | EAST,
24 +
	NWEST = NORTH | WEST,
25 +
	SEAST = SOUTH | EAST,
26 +
	SWEST = SOUTH | WEST,
27 +
	CENTER = NEAST | SWEST
28 +
};
29 +
14 30
/* atoms */
15 31
enum { WMProtocols, WMDelete, WMLast };
16 32
enum { NetSupported, NetWMName, NetLast };
20 36
21 37
/* rects */
22 38
enum { RFloat, RGrid, RLast };
23 -
24 -
typedef struct Client Client;
25 -
typedef struct Key Key;
26 39
27 40
struct Client {
28 41
	char name[256];
75 88
extern void focus(Client *c);
76 89
extern void update_name(Client *c);
77 90
extern void draw_client(Client *c);
91 +
extern void resize(Client *c);
78 92
79 93
/* event.c */
80 -
extern unsigned int flush_events(long even_mask);
94 +
extern unsigned int discard_events(long even_mask);
81 95
82 96
/* key.c */
83 97
extern void update_keys();
84 98
extern void keypress(XEvent *e);
99 +
100 +
/* mouse.c */
101 +
extern void mresize(Client *c);
102 +
extern void mmove(Client *c);
85 103
86 104
/* wm.c */
87 105
extern int error_handler(Display *dpy, XErrorEvent *error);