Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 397 lines (323 sloc) 8.337 kb
3d12c94 Initial revision
bernd authored
1 /*
2 * calmwm - the calm window manager
3 *
4 * Copyright (c) 2004 Andy Adamson <dros@monkey.org>
5 * Copyright (c) 2004,2005 Marius Aamodt Eriksen <marius@monkey.org>
e5cabb0 - Remove the "all rights reserved" tag at the top of most of the source
oga authored
6 *
7 * Permission to use, copy, modify, and distribute this software for any
8 * purpose with or without fee is hereby granted, provided that the above
9 * copyright notice and this permission notice appear in all copies.
10 *
11 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
3d12c94 Initial revision
bernd authored
18 *
19 * $Id$
20 */
21
22 #include "headers.h"
23 #include "calmwm.h"
24
25 #define CALMWM_NGROUPS 9
26
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
27 static void group_add(struct group_ctx *, struct client_ctx *);
28 static void group_remove(struct client_ctx *);
29 static void group_hide(struct group_ctx *);
30 static void group_show(struct group_ctx *);
31 static void group_fix_hidden_state(struct group_ctx *);
49e218c - add missing prototypes.
okan authored
32
75182c6 hit it with the knf stick.
oga authored
33 struct group_ctx *Group_active = NULL;
34 struct group_ctx Groups[CALMWM_NGROUPS];
35 int Grouphideall = 0;
36 struct group_ctx_q Groupq;
3d12c94 Initial revision
bernd authored
37
d1050af shortcut_to_name should not be defined as static in a header file. Put
oga authored
38 const char *shortcut_to_name[] = {
49e218c - add missing prototypes.
okan authored
39 "nogroup", "one", "two", "three", "four", "five", "six",
40 "seven", "eight", "nine"
d1050af shortcut_to_name should not be defined as static in a header file. Put
oga authored
41 };
42
3d12c94 Initial revision
bernd authored
43 static void
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
44 group_add(struct group_ctx *gc, struct client_ctx *cc)
3d12c94 Initial revision
bernd authored
45 {
46 if (cc == NULL || gc == NULL)
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
47 errx(1, "group_add: a ctx is NULL");
3d12c94 Initial revision
bernd authored
48
49 if (cc->group == gc)
50 return;
51
52 if (cc->group != NULL)
53 TAILQ_REMOVE(&cc->group->clients, cc, group_entry);
54
c750462 One of the most annoying things to do was restart cwm and lose all of
oga authored
55 XChangeProperty(X_Dpy, cc->win, _CWM_GRP, XA_STRING,
56 8, PropModeReplace, gc->name, strlen(gc->name));
57
3d12c94 Initial revision
bernd authored
58 TAILQ_INSERT_TAIL(&gc->clients, cc, group_entry);
59 cc->group = gc;
60 }
61
62 static void
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
63 group_remove(struct client_ctx *cc)
3d12c94 Initial revision
bernd authored
64 {
65 if (cc == NULL || cc->group == NULL)
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
66 errx(1, "group_remove: a ctx is NULL");
3d12c94 Initial revision
bernd authored
67
c750462 One of the most annoying things to do was restart cwm and lose all of
oga authored
68 XChangeProperty(X_Dpy, cc->win, _CWM_GRP, XA_STRING, 8,
69 PropModeReplace, shortcut_to_name[0],
70 strlen(shortcut_to_name[0]));
71
3d12c94 Initial revision
bernd authored
72 TAILQ_REMOVE(&cc->group->clients, cc, group_entry);
73 cc->group = NULL;
74 }
75
76 static void
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
77 group_hide(struct group_ctx *gc)
3d12c94 Initial revision
bernd authored
78 {
b23fad3 spacing, declaration lineup to be consistent throughout cwm,
okan authored
79 struct client_ctx *cc;
3d12c94 Initial revision
bernd authored
80
81 screen_updatestackingorder();
82
83 gc->nhidden = 0;
84 gc->highstack = 0;
85 TAILQ_FOREACH(cc, &gc->clients, group_entry) {
86 client_hide(cc);
87 gc->nhidden++;
88 if (cc->stackingorder > gc->highstack)
89 gc->highstack = cc->stackingorder;
90 }
91 gc->hidden = 1; /* XXX: equivalent to gc->nhidden > 0 */
92 }
93
94 static void
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
95 group_show(struct group_ctx *gc)
3d12c94 Initial revision
bernd authored
96 {
b23fad3 spacing, declaration lineup to be consistent throughout cwm,
okan authored
97 struct client_ctx *cc;
98 Window *winlist;
99 u_int i;
100 int lastempty = -1;
3d12c94 Initial revision
bernd authored
101
f473dc3 Replace a few leftover calls to strdup and calloc with xstrdup and xcall...
oga authored
102 winlist = (Window *) xcalloc(sizeof(*winlist), (gc->highstack + 1));
3d12c94 Initial revision
bernd authored
103
104 /*
105 * Invert the stacking order as XRestackWindows() expects them
106 * top-to-bottom.
107 */
108 TAILQ_FOREACH(cc, &gc->clients, group_entry) {
ec8e605 remove pwin, bringing us to one client, one window. we no longer have
okan authored
109 winlist[gc->highstack - cc->stackingorder] = cc->win;
3d12c94 Initial revision
bernd authored
110 client_unhide(cc);
111 }
112
113 /* Un-sparseify */
114 for (i = 0; i <= gc->highstack; i++) {
115 if (!winlist[i] && lastempty == -1)
116 lastempty = i;
117 else if (winlist[i] && lastempty != -1) {
118 winlist[lastempty] = winlist[i];
119 if (++lastempty == i)
120 lastempty = -1;
121 }
122 }
123
9006bbf convert globals from G_foo to Foo, as per TODO.
jasper authored
124 XRestackWindows(X_Dpy, winlist, gc->nhidden);
3d12c94 Initial revision
bernd authored
125 xfree(winlist);
126
127 gc->hidden = 0;
9006bbf convert globals from G_foo to Foo, as per TODO.
jasper authored
128 Group_active = gc;
3d12c94 Initial revision
bernd authored
129 }
130
131 void
132 group_init(void)
133 {
b23fad3 spacing, declaration lineup to be consistent throughout cwm,
okan authored
134 int i;
3d12c94 Initial revision
bernd authored
135
9006bbf convert globals from G_foo to Foo, as per TODO.
jasper authored
136 TAILQ_INIT(&Groupq);
3d12c94 Initial revision
bernd authored
137
138 for (i = 0; i < CALMWM_NGROUPS; i++) {
9006bbf convert globals from G_foo to Foo, as per TODO.
jasper authored
139 TAILQ_INIT(&Groups[i].clients);
140 Groups[i].hidden = 0;
141 Groups[i].shortcut = i + 1;
c750462 One of the most annoying things to do was restart cwm and lose all of
oga authored
142 Groups[i].name = shortcut_to_name[Groups[i].shortcut];
9006bbf convert globals from G_foo to Foo, as per TODO.
jasper authored
143 TAILQ_INSERT_TAIL(&Groupq, &Groups[i], entry);
3d12c94 Initial revision
bernd authored
144 }
145
4c10afe unbreak
okan authored
146 Group_active = &Groups[0];
eb78032 add a "movetogroup" function, which hides the current window from
sthen authored
147 }
148
149 void
150 group_movetogroup(struct client_ctx *cc, int idx)
151 {
152 if (idx < 0 || idx >= CALMWM_NGROUPS)
153 err(1, "group_movetogroup: index out of range (%d)", idx);
154
8bbc376 In movetogroup, check the window's current group and skip client_hide()
sthen authored
155 if(Group_active != &Groups[idx])
156 client_hide(cc);
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
157 group_add(&Groups[idx], cc);
3d12c94 Initial revision
bernd authored
158 }
159
36c1aac Rip out, burn, and dance around the grave of group-edit mode.
oga authored
160 /*
161 * Colouring for groups upon add/remove.
3d12c94 Initial revision
bernd authored
162 */
163 void
164 group_sticky_toggle_enter(struct client_ctx *cc)
165 {
b23fad3 spacing, declaration lineup to be consistent throughout cwm,
okan authored
166 struct group_ctx *gc;
167
168 gc = Group_active;
3d12c94 Initial revision
bernd authored
169
170 if (gc == cc->group) {
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
171 group_remove(cc);
4d5dc5d a long time coming - re-work the way we deal with colors: since we're
okan authored
172 cc->highlight = CLIENT_HIGHLIGHT_UNGROUP;
3d12c94 Initial revision
bernd authored
173 } else {
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
174 group_add(gc, cc);
4d5dc5d a long time coming - re-work the way we deal with colors: since we're
okan authored
175 cc->highlight = CLIENT_HIGHLIGHT_GROUP;
3d12c94 Initial revision
bernd authored
176 }
177
178 client_draw_border(cc);
179 }
180
181 void
182 group_sticky_toggle_exit(struct client_ctx *cc)
183 {
184 cc->highlight = 0;
185 client_draw_border(cc);
186 }
187
188 /*
49e218c - add missing prototypes.
okan authored
189 * if group_hidetoggle would produce no effect, toggle the group's hidden state
3d12c94 Initial revision
bernd authored
190 */
49e218c - add missing prototypes.
okan authored
191 static void
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
192 group_fix_hidden_state(struct group_ctx *gc)
3d12c94 Initial revision
bernd authored
193 {
b23fad3 spacing, declaration lineup to be consistent throughout cwm,
okan authored
194 struct client_ctx *cc;
195 int same = 0;
3d12c94 Initial revision
bernd authored
196
197 TAILQ_FOREACH(cc, &gc->clients, group_entry) {
198 if (gc->hidden == ((cc->flags & CLIENT_HIDDEN) ? 1 : 0))
199 same++;
200 }
201
202 if (same == 0)
203 gc->hidden = !gc->hidden;
204 }
205
206 void
207 group_hidetoggle(int idx)
208 {
b23fad3 spacing, declaration lineup to be consistent throughout cwm,
okan authored
209 struct group_ctx *gc;
3d12c94 Initial revision
bernd authored
210
211 if (idx < 0 || idx >= CALMWM_NGROUPS)
212 err(1, "group_hidetoggle: index out of range (%d)", idx);
213
9006bbf convert globals from G_foo to Foo, as per TODO.
jasper authored
214 gc = &Groups[idx];
3d12c94 Initial revision
bernd authored
215
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
216 group_fix_hidden_state(gc);
3d12c94 Initial revision
bernd authored
217
218 if (gc->hidden)
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
219 group_show(gc);
3d12c94 Initial revision
bernd authored
220 else {
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
221 group_hide(gc);
3d12c94 Initial revision
bernd authored
222 if (TAILQ_EMPTY(&gc->clients))
9006bbf convert globals from G_foo to Foo, as per TODO.
jasper authored
223 Group_active = gc;
3d12c94 Initial revision
bernd authored
224 }
225 }
226
3de90d4 Add a new command (currently no default keybindings for it), grouponly[1...
oga authored
227 void
228 group_only(int idx)
229 {
230 int i;
231
232 if (idx < 0 || idx >= CALMWM_NGROUPS)
233 err(1, "group_only: index out of range (%d)", idx);
234
235 for (i = 0; i < CALMWM_NGROUPS; i++) {
5d51c8e minor bit of knf, just to be consistent; oga@ doesn't mind that much
okan authored
236 if (i == idx)
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
237 group_show(&Groups[i]);
5d51c8e minor bit of knf, just to be consistent; oga@ doesn't mind that much
okan authored
238 else
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
239 group_hide(&Groups[i]);
3de90d4 Add a new command (currently no default keybindings for it), grouponly[1...
oga authored
240 }
241 }
242
3d12c94 Initial revision
bernd authored
243 /*
d347aa3 as done with cycle/rcycle, make prev/next group switching one kbfuncs
okan authored
244 * Cycle through active groups. If none exist, then just stay put.
3d12c94 Initial revision
bernd authored
245 */
246 void
d347aa3 as done with cycle/rcycle, make prev/next group switching one kbfuncs
okan authored
247 group_cycle(int reverse)
3d12c94 Initial revision
bernd authored
248 {
b23fad3 spacing, declaration lineup to be consistent throughout cwm,
okan authored
249 struct group_ctx *gc, *showgroup = NULL;
3d12c94 Initial revision
bernd authored
250
9006bbf convert globals from G_foo to Foo, as per TODO.
jasper authored
251 assert(Group_active != NULL);
3d12c94 Initial revision
bernd authored
252
556f7a0 Put back the initialisation of gc in group_cycle. No cookie for okan.
oga authored
253 gc = Group_active;
3d12c94 Initial revision
bernd authored
254 for (;;) {
d347aa3 as done with cycle/rcycle, make prev/next group switching one kbfuncs
okan authored
255 gc = reverse ? TAILQ_PREV(gc, group_ctx_q, entry) :
256 TAILQ_NEXT(gc, entry);
3d12c94 Initial revision
bernd authored
257 if (gc == NULL)
d347aa3 as done with cycle/rcycle, make prev/next group switching one kbfuncs
okan authored
258 gc = reverse ? TAILQ_LAST(&Groupq, group_ctx_q) :
259 TAILQ_FIRST(&Groupq);
9006bbf convert globals from G_foo to Foo, as per TODO.
jasper authored
260 if (gc == Group_active)
3d12c94 Initial revision
bernd authored
261 break;
262
263 if (!TAILQ_EMPTY(&gc->clients) && showgroup == NULL)
264 showgroup = gc;
265 else if (!gc->hidden)
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
266 group_hide(gc);
3d12c94 Initial revision
bernd authored
267 }
268
269 if (showgroup == NULL)
270 return;
271
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
272 group_hide(Group_active);
3d12c94 Initial revision
bernd authored
273
274 if (showgroup->hidden)
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
275 group_show(showgroup);
3d12c94 Initial revision
bernd authored
276 else
9006bbf convert globals from G_foo to Foo, as per TODO.
jasper authored
277 Group_active = showgroup;
3d12c94 Initial revision
bernd authored
278 }
279
280 /* called when a client is deleted */
281 void
282 group_client_delete(struct client_ctx *cc)
283 {
284 if (cc->group == NULL)
75182c6 hit it with the knf stick.
oga authored
285 return;
3d12c94 Initial revision
bernd authored
286
287 TAILQ_REMOVE(&cc->group->clients, cc, group_entry);
288 cc->group = NULL; /* he he */
289 }
290
291 void
292 group_menu(XButtonEvent *e)
293 {
b23fad3 spacing, declaration lineup to be consistent throughout cwm,
okan authored
294 struct group_ctx *gc;
75182c6 hit it with the knf stick.
oga authored
295 struct menu *mi;
b23fad3 spacing, declaration lineup to be consistent throughout cwm,
okan authored
296 struct menu_q menuq;
75182c6 hit it with the knf stick.
oga authored
297 int i;
3d12c94 Initial revision
bernd authored
298
299 TAILQ_INIT(&menuq);
300
301 for (i = 0; i < CALMWM_NGROUPS; i++) {
9006bbf convert globals from G_foo to Foo, as per TODO.
jasper authored
302 gc = &Groups[i];
3d12c94 Initial revision
bernd authored
303
304 if (TAILQ_EMPTY(&gc->clients))
305 continue;
306
58d1213 unroll XCALLOC/XMALLOC macros; since we use xcalloc/xmalloc all over the
okan authored
307 mi = xcalloc(1, sizeof(*mi));
3d12c94 Initial revision
bernd authored
308 if (gc->hidden)
309 snprintf(mi->text, sizeof(mi->text), "%d: [%s]",
5c40253 group_ctx->name is only used in this one function, and for now it
oga authored
310 gc->shortcut, shortcut_to_name[gc->shortcut]);
3d12c94 Initial revision
bernd authored
311 else
312 snprintf(mi->text, sizeof(mi->text), "%d: %s",
5c40253 group_ctx->name is only used in this one function, and for now it
oga authored
313 gc->shortcut, shortcut_to_name[gc->shortcut]);
3d12c94 Initial revision
bernd authored
314 mi->ctx = gc;
315 TAILQ_INSERT_TAIL(&menuq, mi, entry);
316 }
317
318 if (TAILQ_EMPTY(&menuq))
319 return;
320
779cf04 Make menu_filter handle mouse movement too. This enables the keyboard
oga authored
321 mi = menu_filter(&menuq, NULL, NULL, 0, NULL, NULL);
3d12c94 Initial revision
bernd authored
322
323 if (mi == NULL || mi->ctx == NULL)
324 goto cleanup;
325
326 gc = (struct group_ctx *)mi->ctx;
327
328 if (gc->hidden)
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
329 group_show(gc);
3d12c94 Initial revision
bernd authored
330 else
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
331 group_hide(gc);
3d12c94 Initial revision
bernd authored
332
5034a77 KNF, no binary change.
oga authored
333 cleanup:
3d12c94 Initial revision
bernd authored
334 while ((mi = TAILQ_FIRST(&menuq)) != NULL) {
335 TAILQ_REMOVE(&menuq, mi, entry);
336 xfree(mi);
337 }
338 }
339
340 void
341 group_alltoggle(void)
342 {
b23fad3 spacing, declaration lineup to be consistent throughout cwm,
okan authored
343 int i;
3d12c94 Initial revision
bernd authored
344
75182c6 hit it with the knf stick.
oga authored
345 for (i = 0; i < CALMWM_NGROUPS; i++) {
9006bbf convert globals from G_foo to Foo, as per TODO.
jasper authored
346 if (Grouphideall)
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
347 group_show(&Groups[i]);
3d12c94 Initial revision
bernd authored
348 else
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
349 group_hide(&Groups[i]);
3d12c94 Initial revision
bernd authored
350 }
351
9006bbf convert globals from G_foo to Foo, as per TODO.
jasper authored
352 if (Grouphideall)
353 Grouphideall = 0;
3d12c94 Initial revision
bernd authored
354 else
9006bbf convert globals from G_foo to Foo, as per TODO.
jasper authored
355 Grouphideall = 1;
3d12c94 Initial revision
bernd authored
356 }
357
358 void
359 group_autogroup(struct client_ctx *cc)
360 {
b23fad3 spacing, declaration lineup to be consistent throughout cwm,
okan authored
361 struct autogroupwin *aw;
362 struct group_ctx *gc;
c750462 One of the most annoying things to do was restart cwm and lose all of
oga authored
363 unsigned char *grpstr = NULL;
b23fad3 spacing, declaration lineup to be consistent throughout cwm,
okan authored
364 char group[CALMWM_MAXNAMELEN];
3d12c94 Initial revision
bernd authored
365
366 if (cc->app_class == NULL || cc->app_name == NULL)
367 return;
c750462 One of the most annoying things to do was restart cwm and lose all of
oga authored
368 if (xu_getprop(cc, _CWM_GRP, XA_STRING,
369 (CALMWM_MAXNAMELEN - 1)/sizeof(long), &grpstr) > 0) {
370 strlcpy(group, grpstr, sizeof(group));
371 XFree(grpstr);
372 } else {
373 TAILQ_FOREACH(aw, &Conf.autogroupq, entry) {
374 if (strcmp(aw->class, cc->app_class) == 0 &&
375 (aw->name == NULL ||
376 strcmp(aw->name, cc->app_name) == 0)) {
377 strlcpy(group, aw->group, sizeof(group));
378 break;
379 }
3d12c94 Initial revision
bernd authored
380 }
381 }
382
71f99ab allow an autogroup value of 0 to mean no group. This means you can set
oga authored
383 if (strncmp("nogroup", group, 7) == 0)
384 return;
385
9006bbf convert globals from G_foo to Foo, as per TODO.
jasper authored
386 TAILQ_FOREACH(gc, &Groupq, entry) {
38ff7a9 allow autogrouping and sticky mode to work together
okan authored
387 if (strcmp(shortcut_to_name[gc->shortcut], group) == 0) {
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
388 group_add(gc, cc);
38ff7a9 allow autogrouping and sticky mode to work together
okan authored
389 return;
390 }
3d12c94 Initial revision
bernd authored
391 }
392
38ff7a9 allow autogrouping and sticky mode to work together
okan authored
393 if (Conf.flags & CONF_STICKY_GROUPS)
2c29a1d nuke the leading underscore notation for local static functions - there
okan authored
394 group_add(Group_active, cc);
38ff7a9 allow autogrouping and sticky mode to work together
okan authored
395
3d12c94 Initial revision
bernd authored
396 }
Something went wrong with that request. Please try again.