1 /* evilwm - Minimalist Window Manager for X
2 * Copyright (C) 1999-2002 Ciaran Anscomb <evilwm@6809.org.uk>
3 * see README for license and other details. */
4
5 #include "yeahwm.h"
6 #include <stdlib.h>
7 #include <stdio.h>
8 #ifdef SHAPE
9 #include <X11/extensions/shape.h>
10 #endif
11
12 static int send_xmessage(Window w, Atom a, long x);
13
14 /* used all over the place. return the client that has specified window as
15 * either window or parent */
16
find_client(Window w)17 Client *find_client(Window w)
18 {
19 Client *c;
20
21 for (c = head_client; c; c = c->next)
22 if (w == c->parent || w == c->window || w == c->tab)
23 return c;
24 return NULL;
25 }
26
__set_wm_state(const Window win,const Atom a,int state,long vis)27 static void __set_wm_state(const Window win, const Atom a, int state, long vis)
28 {
29 long data[2];
30
31 data[0] = (long) state;
32 data[1] = vis;
33
34 XChangeProperty(dpy, win, a, a, 32, PropModeReplace, (unsigned char *) data, 2);
35 }
36
set_wm_state(Client * c,int state)37 void set_wm_state(Client * c, int state)
38 {
39 /* iconify window and set state */
40 __set_wm_state(c->window, xa_wm_state, state, None);
41 }
42
_g_wm_state(const Window win,const Atom where)43 static long *_g_wm_state(const Window win, const Atom where)
44 {
45 Atom real_type;
46 int real_format;
47 unsigned long n, extra;
48 unsigned char *data;
49
50 if ((XGetWindowProperty(dpy, win, where, 0L, 2L, False,
51 AnyPropertyType, &real_type, &real_format, &n, &extra, &data) == Success) && n) {
52 return (long *) data;
53 }
54 return NULL;
55 }
__wm_state(const Window win,const Atom where)56 static int __wm_state(const Window win, const Atom where)
57 {
58 long *data, state = WithdrawnState;
59
60 data = _g_wm_state(win, where);
61 if (data) {
62 state = *data;
63 XFree(data);
64 }
65 return state;
66 }
67
wm_state(Client * c)68 int wm_state(Client * c)
69 {
70 return __wm_state(c->window, xa_wm_state);
71 }
72
send_config(Client * c)73 void send_config(Client * c)
74 {
75 XConfigureEvent ce;
76 ce.type = ConfigureNotify;
77 ce.event = c->window;
78 ce.window = c->window;
79 ce.x = c->x;
80 ce.y = c->y;
81 ce.width = c->width;
82 ce.height = c->height;
83 ce.border_width = 0;
84 ce.above = None;
85 ce.override_redirect = 0;
86 XSendEvent(dpy, c->window, False, StructureNotifyMask, (XEvent *) & ce);
87 }
88
remove_client(Client * c)89 void remove_client(Client * c)
90 {
91 Client *p;
92 #ifdef DEBUG
93 fprintf(stderr, "remove_client() : Removing...\n");
94 #endif
95 XGrabServer(dpy);
96 XSetErrorHandler(ignore_xerror);
97 if (!quitting) {
98 #ifdef DEBUG
99 fprintf(stderr, "\tremove_client() : setting WithdrawnState\n");
100 #endif
101 set_wm_state(c, WithdrawnState);
102 XRemoveFromSaveSet(dpy, c->window);
103 }
104 ungravitate(c);
105 XSetWindowBorderWidth(dpy, c->window, 1);
106 XReparentWindow(dpy, c->window, root, c->x, c->y);
107 if (c->parent)
108 XDestroyWindow(dpy, c->parent);;
109 if (c->tab)
110 XDestroyWindow(dpy, c->tab);
111 if (head_client == c)
112 head_client = c->next;
113 else
114 for (p = head_client; p && p->next; p = p->next)
115 if (p->next == c)
116 p->next = c->next;
117 if (c->size)
118 XFree(c->size);
119 if (c->name)
120 XFree(c->name);
121 if (current == c)
122 current = NULL; /* an enter event should set this up again */
123 free(c);
124 #ifdef DEBUG
125 {
126 Client *p;
127 int i = 0;
128 for (p = head_client; p; p = p->next)
129 i++;
130 fprintf(stderr, "\tremove_client() : free(), window count now %d\n", i);
131 }
132 #endif
133 XSync(dpy, False);
134 XSetErrorHandler(handle_xerror);
135 XUngrabServer(dpy);
136 }
137
change_gravity(Client * c,int multiplier)138 void change_gravity(Client * c, int multiplier)
139 {
140 int dx = 0, dy = 0;
141 int gravity = (c->size->flags & PWinGravity) ? c->size->win_gravity : NorthWestGravity;
142 switch (gravity) {
143 case NorthWestGravity:
144 case SouthWestGravity:
145 case NorthEastGravity:
146 case StaticGravity:
147 dx = c->border;
148 case NorthGravity:
149 dy = c->border;
150 break;
151 }
152 c->x += multiplier * dx;
153 c->y += multiplier * dy;
154 #ifdef DEBUG
155 if (dx || dy) {
156 fprintf(stderr, "change_gravity() : window adjustment of %d,%d for ", multiplier * dx, multiplier * dy);
157 switch (gravity) {
158 case NorthWestGravity:
159 fprintf(stderr, "NorthWestGravity\n");
160 break;
161 case SouthWestGravity:
162 fprintf(stderr, "SouthWestGravity\n");
163 break;
164 case NorthEastGravity:
165 fprintf(stderr, "NorthEastGravity\n");
166 break;
167 case NorthGravity:
168 fprintf(stderr, "NorthGravity\n");
169 break;
170 case StaticGravity:
171 fprintf(stderr, "StaticGravity\n");
172 break;
173 default:
174 fprintf(stderr, "unhandled gravity %d\n", gravity);
175 break;
176 }
177 }
178 #endif
179 }
180
send_wm_delete(Client * c)181 void send_wm_delete(Client * c)
182 {
183 int i, n, found = 0;
184 Atom *protocols;
185 if (c) {
186 if (XGetWMProtocols(dpy, c->window, &protocols, &n)) {
187 for (i = 0; i < n; i++)
188 if (protocols[i] == xa_wm_delete)
189 found++;
190 XFree(protocols);
191 }
192 if (found)
193 send_xmessage(c->window, xa_wm_protos, xa_wm_delete);
194 else
195 XKillClient(dpy, c->window);
196 }
197 }
198
send_xmessage(Window w,Atom a,long x)199 static int send_xmessage(Window w, Atom a, long x)
200 {
201 XEvent ev;
202 ev.type = ClientMessage;
203 ev.xclient.window = w;
204 ev.xclient.message_type = a;
205 ev.xclient.format = 32;
206 ev.xclient.data.l[0] = x;
207 ev.xclient.data.l[1] = CurrentTime;
208 return XSendEvent(dpy, w, False, NoEventMask, &ev);
209 }
210
211 #ifdef SHAPE
set_shape(Client * c)212 void set_shape(Client * c)
213 {
214 int n, order;
215 XRectangle *rect;
216 rect = XShapeGetRectangles(dpy, c->window, ShapeBounding, &n, &order);
217 if (n > 1)
218 XShapeCombineShape(dpy, c->parent, ShapeBounding, c->border, c->border, c->window, ShapeBounding, ShapeSet);
219 XFree((void *) rect);
220 }
221 #endif
client_update_current(Client * c)222 void client_update_current(Client * c)
223 {
224
225 if (c) {
226 if (c->vdesk == STICKY) {
227 XSetWindowBackground(dpy, c->parent, fc.pixel);
228 XSetWindowBackground(dpy, c->tab, fc.pixel);
229 } else {
230
231 XSetWindowBackground(dpy, c->parent, abg.pixel);
232 XSetWindowBackground(dpy, c->tab, abg.pixel);
233 }
234 XClearWindow(dpy, c->parent);
235 XClearWindow(dpy, c->tab);
236 if (c->title)
237 show_info(c);
238 if (c == current)
239 return;
240 }
241 if (current) {
242 XSetWindowBackground(dpy, current->parent, bg.pixel);
243 XSetWindowBackground(dpy, current->tab, bg.pixel);
244 XClearWindow(dpy, current->parent);
245 XClearWindow(dpy, current->tab);
246 if (current->title)
247 show_info(current);
248 }
249 current = c;
250 }
251