CTWM
Loading...
Searching...
No Matches
/usr/src/RPM/BUILD/ctwm-4.1.0/occupation.c
Go to the documentation of this file.
1/*
2 * Occupation handling bits
3 *
4 * This is in fact pretty tightly tied and extremely similar to the
5 * handling of the WorkSpaceManager in workmgr.c, and used to be there.
6 * It makes sense to consider them together (and indeed, many of the
7 * configs that affect how this works are really WorkSpaceManager* or
8 * WMgr* commands. But having them crammed together in one file is
9 * unwieldy.
10 */
11
12#include "ctwm.h"
13
14#include <stdio.h>
15#include <string.h>
16#include <stdlib.h>
17
18#include <X11/Xatom.h>
19
20#include "add_window.h"
21#include "ctwm_atoms.h"
22#include "drawing.h"
23#include "events.h"
24#include "iconmgr.h"
25#include "list.h"
26#include "screen.h"
27#include "occupation.h"
28#include "otp.h"
29#include "util.h"
30#include "vscreen.h"
31#include "win_iconify.h"
32#include "win_regions.h"
33#include "win_utils.h"
34#include "workspace_manager.h"
35#include "workspace_utils.h"
36
37
38static int GetMaskFromResource(TwmWindow *win, char *res);
39static char *mk_nullsep_string(const char *prop, int len);
40
42
44
45/*
46 * The window whose occupation is currently being manipulated.
47 *
48 * XXX Should probably be static, but currently needed in
49 * WMapRemoveWindow(). Revisit.
50 */
52
53
54/* XXX Share with captive.c? */
56 {"-xrm", NULL, XrmoptionResArg, (XPointer) NULL},
57};
58
59
60
61
62/*
63 ****************************************************************
64 *
65 * First, funcs related to setting and changing a window's occupation.
66 *
67 ****************************************************************
68 */
69
70
71/*
72 * Setup the occupation of a TwmWindow. Called as part of the
73 * AddWindow() process.
74 *
75 * XXX The logic flow in this is kinda weird, and it's not at all clear
76 * to what extent it's really doing the right on on what should override
77 * what, or which things should expand/contract on others...
78 */
79void
81{
82 char **cliargv = NULL;
83 int cliargc;
85
86 /* If there aren't any config'd workspaces, there's only 0 */
87 if(! Scr->workSpaceManagerActive) {
88 twm_win->occupation = 1 << 0; /* occupy workspace #0 */
89 /* more?... */
90
91 return;
92 }
93
94 /* Workspace manager window doesn't get futzed with */
95 if(twm_win->iswspmgr) {
96 return;
97 }
98
99 /*twm_win->occupation = twm_win->iswinbox ? fullOccupation : 0;*/
100 twm_win->occupation = 0;
101
102 /* Specified in any Occupy{} config params? */
103 for(ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
104 if(LookInList(ws->clientlist, twm_win->name, &twm_win->class)) {
105 twm_win->occupation |= 1 << ws->number;
106 }
107 }
108
109 /* OccupyAll{} */
110 if(LookInList(Scr->OccupyAll, twm_win->name, &twm_win->class)) {
111 twm_win->occupation = fullOccupation;
112 }
113
114 /* See if it specified in -xrm stuff */
115 if(XGetCommand(dpy, twm_win->w, &cliargv, &cliargc)) {
116 Bool status;
117 char *str_type;
118 XrmValue value;
120
121 XrmParseCommand(&db, table, 1, "ctwm", &cliargc, cliargv);
123 status = XrmGetResource(db, "ctwm.workspace", "Ctwm.Workspace",
124 &str_type, &value);
125 if((status == True) && (value.size != 0)) {
126 /* Copy the value.addr because it's in XRM memory not ours */
127 char wrkSpcList[512];
128 safe_strncpy(wrkSpcList, value.addr, MIN(value.size, 512));
129
130 twm_win->occupation = GetMaskFromResource(twm_win, wrkSpcList);
131 }
133 }
134
135 /* Does it have a property telling us */
138 int actual_format;
139 unsigned long nitems, bytesafter;
140 unsigned char *prop;
141
142 if(XGetWindowProperty(dpy, twm_win->w, XA_WM_OCCUPATION, 0L, 2500, False,
144 &bytesafter, &prop) == Success) {
145 if(nitems != 0) {
147 XFree(prop);
148 }
149 }
150 }
151
152#ifdef EWMH
153 /* Maybe EWMH has something to tell us? */
154 if(twm_win->occupation == 0) {
155 twm_win->occupation = EwmhGetOccupation(twm_win);
156 }
157#endif /* EWMH */
158
159 /* Icon Managers shouldn't get altered */
160 /* XXX Should this be up near the top? */
161 if(twm_win->isiconmgr) {
162 return; /* someone tried to modify occupation of icon managers */
163 }
164
165
166 /*
167 * Transient-ish things go with their parents unless
168 * TransientHasOccupation set in the config.
169 */
170 if(! Scr->TransientHasOccupation) {
171 TwmWindow *t;
172
173 if(twm_win->istransient) {
174 t = GetTwmWindow(twm_win->transientfor);
175 if(t != NULL) {
176 twm_win->occupation = t->occupation;
177 }
178 }
179 else if(twm_win->group != 0) {
180 t = GetTwmWindow(twm_win->group);
181 if(t != NULL) {
182 twm_win->occupation = t->occupation;
183 }
184 }
185 }
186
187
188 /* If we were told something specific, go with that */
189 if(occupation_hint != 0) {
190 twm_win->occupation = occupation_hint;
191 }
192
193 /* If it's apparently-nonsensical, put it in its vs's workspace */
194 if((twm_win->occupation & fullOccupation) == 0) {
195 twm_win->occupation = 1 << twm_win->vs->wsw->currentwspc->number;
196 }
197
198 /*
199 * If the occupation would not show it in the current vscreen,
200 * make it vanish.
201 *
202 * If it could be shown in one of the other vscreens, change the vscreen.
203 */
204 if(!OCCUPY(twm_win, twm_win->vs->wsw->currentwspc)) {
205
206 twm_win->vs = NULL;
207
208#ifdef VSCREEN
209 if(Scr->numVscreens > 1) {
210 VirtualScreen *vs;
211 for(vs = Scr->vScreenList; vs != NULL; vs = vs->next) {
212 if(OCCUPY(twm_win, vs->wsw->currentwspc)) {
213 twm_win->vs = vs;
214 twm_win->parent_vs = vs;
215 break;
216 }
217 }
218 }
219#endif
220 }
221
222
223 /* Set the property for the occupation */
224 {
225 long eventMask;
226 char *wsstr;
227 int len;
228
229 /* Ignore the PropertyChange we're about to do */
230 if((eventMask = mask_out_event(twm_win->w, PropertyChangeMask)) < 0) {
231 /* Window is horked, not much we can do */
232 return;
233 }
234
235 /* Set the property for the occupation */
238 PropModeReplace, (unsigned char *) wsstr, len);
239 free(wsstr);
240
241#ifdef EWMH
242 EwmhSet_NET_WM_DESKTOP(twm_win);
243#endif
244
245 /* Restore event mask */
246 restore_mask(twm_win->w, eventMask);
247 }
248
249 /* Set WM_STATE prop */
250 {
251 int state = NormalState;
252 Window icon;
253
255 && GetWMState(twm_win->w, &state, &icon)
256 && (state == NormalState || state == IconicState
257 || state == InactiveState))) {
258 if(twm_win->wmhints->flags & StateHint) {
259 state = twm_win->wmhints->initial_state;
260 }
261 }
262 if(visible(twm_win)) {
263 if(state == InactiveState) {
265 }
266 }
267 else {
268 if(state == NormalState) {
270 }
271 }
272 }
273}
274
275
276/*
277 * Make sure a window is marked in a given workspace. f.addtoworkspace.
278 * Also gets called as part of the process of mapping a window; if we're
279 * mapping it here, it should know that it's here. And Xinerama magic
280 * moves.
281 */
282void
284{
285 WorkSpace *ws;
286 int newoccupation;
287
288 if(!CanChangeOccupation(&twm_win)) {
289 return;
290 }
292 if(!ws) {
293 return;
294 }
295
296 if(twm_win->occupation & (1 << ws->number)) {
297 return;
298 }
299 newoccupation = twm_win->occupation | (1 << ws->number);
301}
302
303
304/*
305 * Converse of the above. f.removefromworkspace, also called from
306 * Xinerama-related magic.
307 */
308void
310{
311 WorkSpace *ws;
312 int newoccupation;
313
314 if(!CanChangeOccupation(&twm_win)) {
315 return;
316 }
318 if(!ws) {
319 return;
320 }
321
322 newoccupation = twm_win->occupation & ~(1 << ws->number);
323 if(!newoccupation) {
324 return;
325 }
327}
328
329
330/* f.toggleoccupation - flip setting for [current] workspace */
331void
333{
334 WorkSpace *ws;
335 int newoccupation;
336
337 if(!CanChangeOccupation(&twm_win)) {
338 return;
339 }
341 if(!ws) {
342 return;
343 }
344
345 newoccupation = twm_win->occupation ^ (1 << ws->number);
346 if(!newoccupation) {
347 /* Don't allow de-occupying _every_ ws */
348 return;
349 }
351}
352
353
354/* f.movetonextworkspace */
355void
357{
359 int newoccupation;
360
361 if(!CanChangeOccupation(&twm_win)) {
362 return;
363 }
364
365 wlist1 = vs->wsw->currentwspc;
366 wlist2 = wlist1->next;
367 wlist2 = wlist2 ? wlist2 : Scr->workSpaceMgr.workSpaceList;
368
369 /* Out of (here), into (here+1) */
370 newoccupation = (twm_win->occupation ^ (1 << wlist1->number))
371 | (1 << wlist2->number);
373}
374
375
376/* f.movetonextworkspaceandfollow */
377void
379{
380 if(!CanChangeOccupation(&twm_win)) {
381 return;
382 }
383
384 MoveToNextWorkSpace(vs, twm_win);
386#if 0
387 OtpRaise(twm_win, WinWin); /* XXX really do this? */
388#endif
389}
390
391
392/* f.movetoprevworkspaceand */
393void
395{
397 int newoccupation;
398
399 if(!CanChangeOccupation(&twm_win)) {
400 return;
401 }
402
403 wlist1 = Scr->workSpaceMgr.workSpaceList;
404 wlist2 = vs->wsw->currentwspc;
405 if(wlist1 == NULL) {
406 return;
407 }
408
409 while(wlist1->next != wlist2 && wlist1->next != NULL) {
410 wlist1 = wlist1->next;
411 }
412
413 /* Out of (here), into (here-1) */
414 newoccupation = (twm_win->occupation ^ (1 << wlist2->number))
415 | (1 << wlist1->number);
417}
418
419
420/* f.movetoprevworkspaceandfollow */
421void
423{
424 if(!CanChangeOccupation(&twm_win)) {
425 return;
426 }
427
428 MoveToPrevWorkSpace(vs, twm_win);
430#if 0
431 OtpRaise(twm_win, WinWin); /* XXX really do this? */
432#endif
433}
434
435
436/*
437 * Set the occupation based on the window name. This is called if
438 * AutoOccupy is set, when we get a notification about a window name
439 * change.
440 */
441void
443{
444 WorkSpace *ws;
445 int newoccupation;
446
447 if(LookInList(Scr->OccupyAll, win->name, &win->class)) {
449 }
450 else {
451 newoccupation = 0;
452 for(ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
453 if(LookInList(ws->clientlist, win->name, &win->class)) {
454 newoccupation |= 1 << ws->number;
455 }
456 }
457 }
458 if(newoccupation != 0) {
460 }
461}
462
463
464/* f.vanish */
465void
467{
468 WorkSpace *ws;
469 int newoccupation;
470
471 ws = vs->wsw->currentwspc;
472 if(!ws) {
473 /* Impossible? */
474 return;
475 }
476 if(! OCCUPY(win, ws)) {
477 return;
478 }
479
480 newoccupation = win->occupation & ~(1 << ws->number);
481 if(newoccupation == 0) {
482 return;
483 }
484
486}
487
488
489/* f.warphere */
490void
492{
493 TwmWindow *tw;
494 int newoccupation;
495
496 /* Find named window on this screen */
497 for(tw = Scr->FirstWindow; tw != NULL; tw = tw->next) {
498 if(match(winname, tw->name)) {
499 break;
500 }
501 }
502
503 /* Didn't find it by name? Try by class */
504 if(!tw) {
505 for(tw = Scr->FirstWindow; tw != NULL; tw = tw->next) {
506 if(match(winname, tw->class.res_name)) {
507 break;
508 }
509 }
510 }
511 if(!tw) {
512 for(tw = Scr->FirstWindow; tw != NULL; tw = tw->next) {
513 if(match(winname, tw->class.res_class)) {
514 break;
515 }
516 }
517 }
518
519 /* Still didn't find? Beep at the user and bail. */
520 if(!tw) {
521 XBell(dpy, 0);
522 return;
523 }
524
525 /* If WarpUnmapped isn't set and this isn't mapped, beep and bail */
526 if((! Scr->WarpUnmapped) && (! tw->mapped)) {
527 XBell(dpy, 0);
528 return;
529 }
530
531 /* Move it here if it's not */
532 if(! OCCUPY(tw, vs->wsw->currentwspc)) {
533 newoccupation = tw->occupation | (1 << vs->wsw->currentwspc->number);
535 }
536
537 /* If we get here, WarpUnmapped is set, so map it if we need to */
538 if(! tw->mapped) {
539 DeIconify(tw);
540 }
541
542 /* And go */
543 WarpToWindow(tw, Scr->RaiseOnWarp);
544}
545
546
547/* f.occupyall backend */
548void
550{
551 IconMgr *save;
552
553 if(!CanChangeOccupation(&twm_win)) {
554 return;
555 }
556
557 /*
558 * Temporarily alter Scr->iconmgr because stuff down in
559 * ChangeOccupation winds up adding/removing bits, and that doesn't
560 * work right when we're setting all? XXX Investigate further.
561 */
562 save = Scr->iconmgr;
563 Scr->iconmgr = Scr->workSpaceMgr.workSpaceList->iconmgr;
565 Scr->iconmgr = save;
566}
567
568
569
570/*
571 ****************************************************************
572 *
573 * Pieces related to the Occupy window
574 *
575 ****************************************************************
576 */
577
579
580static char *ok_string = "OK",
581 *cancel_string = "Cancel",
583
584/*
585 * Create the Occupy window. Part of startup process.
586 *
587 * Do not do the layout of the parts, only calculate the initial total
588 * size. For the layout, call ResizeOccupyWindow() at the end.
589 *
590 * There is only one Occupy window (per Screen), it is reparented to each
591 * virtual screen as needed.
592 */
593void
595{
596 int width; // Caculated and altered, unlike most others
597 int Dummy = 1;
599 /* Shorthands for the Occupy window */
600 OccupyWindow *occwin = Scr->workSpaceMgr.occupyWindow;
601 Window w; // occwin->w
602 /* Misc other shorthands */
603 const int lines = Scr->workSpaceMgr.lines;
604 const int columns = Scr->workSpaceMgr.columns;
605 const int bwidth = Scr->vScreenList->wsw->bwidth;
606 const int bheight = Scr->vScreenList->wsw->bheight;
607 const int vspace = occwin->vspace;
608 const int hspace = occwin->hspace;
609 const int height = ((bheight + vspace) * lines) + bheight + (2 * vspace);
610
611 /* Struct embedded in [struct embedded in] Scr, so memory's waiting */
612
613 /* There isn't anything we should do without workspaces... */
614 if(!Scr->workSpaceManagerActive) {
615 return;
616 }
617
618 /* Initialize font and colorpair bits */
619 occwin->font = Scr->IconManagerFont;
620 occwin->cp = Scr->IconManagerC;
621#ifdef COLOR_BLIND_USER
622 occwin->cp.shadc = Scr->White;
623 occwin->cp.shadd = Scr->Black;
624#else
625 if(!Scr->BeNiceToColormap) {
627 }
628#endif
629
630 /* We already know that these should be too */
631 occwin->lines = lines;
632 occwin->columns = columns;
633
634
635 /*
636 * Work out the necessary size of the OK/Cancel/All buttons at the
637 * bottom.
638 */
639 {
642 MyFont font = occwin->font;
643 int bbwidth; // Bottom button width
644 /* Window min width based on bottom vs. workspace btns */
645 int bb_width, ws_width;
646
647 /* Buttons gotta be as wide as the biggest of the three strings */
650 bbwidth = logical_rect.width;
651
655
657 strlen(everywhere_string),
660
661 /* Plus the padding width */
662 bbwidth += hspace;
663
664 /*
665 * So, the final width of those bottom buttons is that, plus the
666 * 3d button look extra on both sides, plus a little extra. I
667 * guess that extra + 2 is similar to TitlePadding or
668 * ButtonIndent on titlebars, but we don't have a config param
669 * for it on the workspace manager (which is the config used for
670 * the occupy window), so leave it as a magic constant for now.
671 */
672 occwin->owidth = bbwidth + 2 * Scr->WMgrButtonShadowDepth + 2;
673
674 /*
675 * The whole thing has to be at least triple the min width of
676 * those bottom buttons, since there are three of them. The
677 * layout is "hspace button hspace button [...] hspace", to pad
678 * between and on both sides.
679 */
680 bb_width = 3 * (bbwidth + hspace) + hspace;
681
682 /*
683 * It also has to be the width of our per-WS buttons. Per-ws
684 * buttons are sized the same as in the button-state WSM, and
685 * then we add the padding to them as above.
686 */
687 ws_width = columns * (bwidth + hspace) + hspace;
688
689 /* So the window has to be as wide as the wider of those */
690 width = MAX(bb_width, ws_width);
691 }
692
693
694 /* Now we know the size, so make the window */
695 w = occwin->w = XCreateSimpleWindow(dpy, Scr->Root, 0, 0, width, height,
696 1, Scr->Black, occwin->cp.back);
697
698 /* Take those base sizes as a minimum */
699 occwin->minwidth = width;
700 occwin->minheight = height;
701
702
703 /*
704 * Make subwindows as buttons for the workspaces. They're laid out
705 * in a grid mirroring the workspace manager's.
706 */
707 {
708 int i = 0, j = 0;
709 WorkSpace *ws;
710
711 occwin->obuttonw = calloc(Scr->workSpaceMgr.count, sizeof(Window));
712
713 for(ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
714 int idx = (j * columns) + i;
715
716 /*
717 * Make and map. Note that we're not setting the size or
718 * location at all here; ResizeOccupyWindow() does all that.
719 * We just make 'em.
720 */
721 occwin->obuttonw[idx] = XCreateSimpleWindow(dpy, w,
722 Dummy /* x */,
723 Dummy /* y */,
724 Dummy /* width */,
725 Dummy /* height */,
726 0, Scr->Black, ws->cp.back);
727 XMapWindow(dpy, occwin->obuttonw[idx]);
728
729 /* Inc around to the next location */
730 i++;
731 if(i == columns) {
732 i = 0;
733 j++;
734 }
735 }
736 }
737
738
739 /*
740 * Now start putting together the OK/Cancel/All buttons
741 */
742
743 /* Background for them is hardcoded */
744 GetColor(Scr->Monochrome, &(occupyButtoncp.back), "gray50");
745
746 /* Foreground (not used here) is too */
747 occupyButtoncp.fore = Scr->White;
748
749 /* Override (probably historical */
750 if(!Scr->BeNiceToColormap) {
752 }
753
754 /* Make 'em */
755 {
756 Window tw;
757
759 Scr->Black, occupyButtoncp.back);
760 XMapWindow(dpy, tw);
761 occwin->OK = tw;
762
764 Scr->Black, occupyButtoncp.back);
765 XMapWindow(dpy, tw);
766 occwin->cancel = tw;
767
769 Scr->Black, occupyButtoncp.back);
770 XMapWindow(dpy, tw);
771 occwin->allworkspc = tw;
772 }
773
774
775 /* Setup various window properties */
776 {
778 XWMHints wmhints;
779
781 sizehints.min_width = width;
782 sizehints.min_height = height;
783 sizehints.base_width = width;
784 sizehints.base_height = height;
785 sizehints.max_width = width;
786 sizehints.max_height = height;
787
788 wmhints.flags = InputHint | StateHint;
789 wmhints.input = True;
790 wmhints.initial_state = NormalState;
791
792 XmbSetWMProperties(dpy, w, occwin->name, occwin->icon_name,
793 NULL, 0, &sizehints, &wmhints, NULL);
794 }
795
796
797 /*
798 * Create the TwmWindow wrapping around it, with decorations etc. We
799 * do this so early in startup that we're not listening for window
800 * creation events yet.
801 */
802 tmp_win = AddWindow(w, AWT_OCCUPY, Scr->iconmgr, Scr->currentvs);
803 if(! tmp_win) {
804 fprintf(stderr, "cannot create occupy window, exiting...\n");
805 exit(1);
806 }
807 tmp_win->vs = NULL;
808 tmp_win->occupation = 0;
809
810 /* tmp_win is more convenient the rest of the func, but put in place */
811 occwin->twm_win = tmp_win;
812
813
814 /*
815 * Setup the window to have a button-pushing cursor and listen for
816 * clicks.
817 */
818 {
819 unsigned long attrmask;
822
823 attr.cursor = Scr->ButtonCursor;
826
828 attrmask = wattr.your_event_mask | KeyPressMask | KeyReleaseMask
829 | ExposureMask;
831 }
832
833
834 /*
835 * Now for each of the buttons (workspaces + OK/Cancel/All), we mark
836 * them as listening to click and exposure events. We also stash
837 * away the screen and wrapping TwmWindow in contexts so other code
838 * can dredge them up.
839 */
840#define EVT (ButtonPressMask | ButtonReleaseMask | ExposureMask)
841#define BTN_IPT_CTX(win) \
842 XSelectInput(dpy, (win), EVT); \
843 XSaveContext(dpy, (win), TwmContext, (XPointer) tmp_win); \
844 XSaveContext(dpy, (win), ScreenContext, (XPointer) Scr);
845
846 for(WorkSpace *ws = Scr->workSpaceMgr.workSpaceList
847 ; ws != NULL ; ws = ws->next) {
848 BTN_IPT_CTX(occwin->obuttonw[ws->number]);
849 }
850
851 BTN_IPT_CTX(occwin->OK);
852 BTN_IPT_CTX(occwin->cancel);
853 BTN_IPT_CTX(occwin->allworkspc);
854
855#undef BTN_IPT_CTX
856#undef EVT
857
858
859 /* Mark that we're not mapped */
861
862 /* Now call that func that sizes all the buttons */
864}
865
866
867/*
868 * Slightly misleading name: layout the internals of the Occupy window
869 * based on its current size. That does happen when it's resized, but
870 * also when it's initially created. I guess you could call "creation" a
871 * resize of a sort...
872 */
873void
875{
876 int bwidth, bheight, owidth, oheight;
877 int hspace, vspace;
878 int lines, columns;
879 int neww, newh;
880 WorkSpace *ws;
881 int i, j, x, y;
882 OccupyWindow *occwin = Scr->workSpaceMgr.occupyWindow;
883
884 /* Floor at the original size */
885 neww = MAX(win->attr.width, occwin->minwidth);
886 newh = MAX(win->attr.height, occwin->minheight);
887 if(occwin->width == neww && occwin->height == newh) {
888 return;
889 }
890
891 /* Space between WS buttons. From WMgr{Horiz,Vert}ButtonIndent. */
892 hspace = occwin->hspace;
893 vspace = occwin->vspace;
894
895 /* Lines/cols in the layout. Same as WorkspaceManager's */
896 lines = Scr->workSpaceMgr.lines;
897 columns = Scr->workSpaceMgr.columns;
898
899 /* Width/height of each button, based on the above and window size */
900 bwidth = (neww - columns * hspace) / columns;
901 bheight = (newh - (lines + 2) * vspace) / (lines + 1);
902
903 /* Width/height of the OK/Cancel/All buttons */
904 owidth = occwin->owidth;
905 oheight = bheight;
906
907
908 /*
909 * Lay out the workspace buttons
910 */
911 i = 0;
912 j = 0;
913 for(ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
914 XMoveResizeWindow(dpy, occwin->obuttonw [j * columns + i],
915 i * (bwidth + hspace) + (hspace / 2),
916 j * (bheight + vspace) + (vspace / 2),
917 bwidth, bheight);
918 i++;
919 if(i == columns) {
920 i = 0;
921 j++;
922 }
923 }
924
925
926 /*
927 * Now the action buttons
928 */
929 hspace = (neww - 3 * owidth) / 4; // Padding between
930 x = hspace;
931 y = ((bheight + vspace) * lines) + ((3 * vspace) / 2);
932 XMoveResizeWindow(dpy, occwin->OK, x, y, owidth, oheight);
933 x += owidth + hspace;
934 XMoveResizeWindow(dpy, occwin->cancel, x, y, owidth, oheight);
935 x += owidth + hspace;
936 XMoveResizeWindow(dpy, occwin->allworkspc, x, y, owidth, oheight);
937
938
939 /* Save all those dimensions we figured */
940 occwin->width = neww;
941 occwin->height = newh;
942 occwin->bwidth = bwidth;
943 occwin->bheight = bheight;
944 occwin->owidth = owidth;
945
946 /* Don't need to repaint it; it'll get expose events */
947}
948
949
950/*
951 * Draw the window when we need to (e.g., on expose)
952 */
953void
955{
956 WorkSpace *ws;
958 int width, height;
959
960 occwin = Scr->workSpaceMgr.occupyWindow;
961 width = occwin->width;
962 height = occwin->height;
963
964 Draw3DBorder(occwin->w, 0, 0, width, height, 2, occwin->cp, off, true, false);
965
966 for(ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
967 Window bw = occwin->obuttonw [ws->number];
968 ButtonState bs = (occwin->tmpOccupation & (1 << ws->number)) ? on : off;
969
970 PaintWsButton(OCCUPYWINDOW, NULL, bw, ws->label, ws->cp, bs);
971 }
978}
979
980
981/*
982 * Somebody clicked in the Occupy window
983 */
984void
986{
987 WorkSpace *ws;
990
991 /*
992 * Doesn't make sense that this can even happen if there are no
993 * workspaces...
994 */
995 if(! Scr->workSpaceManagerActive) {
996 return;
997 }
998
999 /* ... or if there's no Occupy window up for anything */
1000 if(occupyWin == NULL) {
1001 return;
1002 }
1003
1004 /* Which sub-window (button) was clicked */
1005 buttonW = event->xbutton.window;
1006 if(buttonW == 0) {
1007 return; /* icon */
1008 }
1009
1010 /* Grab onto the pointer for the duration of our action */
1011 XGrabPointer(dpy, Scr->Root, True,
1014 Scr->Root, None, CurrentTime);
1015
1016 /* Find the workspace button that was clicked */
1017 occupyW = Scr->workSpaceMgr.occupyWindow;
1018 for(ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
1019 if(occupyW->obuttonw [ws->number] == buttonW) {
1020 break;
1021 }
1022 }
1023
1024 if(ws != NULL) {
1025 /* If one was, toggle it */
1026 int mask = 1 << ws->number;
1027 ButtonState bs = (occupyW->tmpOccupation & mask) ? off : on;
1028
1029 PaintWsButton(OCCUPYWINDOW, NULL, occupyW->obuttonw [ws->number],
1030 ws->label, ws->cp, bs);
1031 occupyW->tmpOccupation ^= mask;
1032 }
1033 else if(buttonW == occupyW->OK) {
1034 /* Else if we clicked OK, set things and close the window */
1035 if(occupyW->tmpOccupation == 0) {
1036 return;
1037 }
1038 ChangeOccupation(occupyWin, occupyW->tmpOccupation);
1039 XUnmapWindow(dpy, occupyW->twm_win->frame);
1040 occupyW->twm_win->mapped = false;
1041 occupyW->twm_win->occupation = 0;
1042 occupyWin = NULL;
1043 XSync(dpy, 0);
1044 }
1045 else if(buttonW == occupyW->cancel) {
1046 /* Or cancel, do nothing and close the window */
1047 XUnmapWindow(dpy, occupyW->twm_win->frame);
1048 occupyW->twm_win->mapped = false;
1049 occupyW->twm_win->occupation = 0;
1050 occupyWin = NULL;
1051 XSync(dpy, 0);
1052 }
1053 else if(buttonW == occupyW->allworkspc) {
1054 /* Or All, set 'em all */
1055 for(ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
1056 PaintWsButton(OCCUPYWINDOW, NULL, occupyW->obuttonw [ws->number],
1057 ws->label, ws->cp, on);
1058 }
1059 occupyW->tmpOccupation = fullOccupation;
1060 }
1061
1062 /* Release the pointer, if ??? */
1063 if(ButtonPressed == -1) {
1065 }
1066}
1067
1068
1069/*
1070 * f.occupy backend - pop up Occupy control for some window
1071 */
1072void
1074{
1075 int x, y;
1076 unsigned int width, height;
1077 Window w;
1078 struct OccupyWindow *occupyWindow;
1080
1081 /* Don't pop up on stuff we can't change */
1083 return;
1084 }
1085
1086 /* Grab our one screen-wide f.occupy window */
1087 occupyWindow = Scr->workSpaceMgr.occupyWindow;
1088 occupyWindow->tmpOccupation = twm_win->occupation;
1089 w = occupyWindow->w;
1090
1091 /* Figure where to put it so it's centered on the cursor */
1093 &JunkBW, &JunkDepth);
1095 &x, &y, &JunkMask);
1096
1097 occupy_twm = occupyWindow->twm_win;
1099
1100 width += 2 * (occupy_twm->frame_bw3D + occupy_twm->frame_bw);
1101 height += 2 * (occupy_twm->frame_bw3D + occupy_twm->frame_bw);
1102 x -= (width / 2);
1103 y -= (height / 2);
1104
1105 /* Clip to screen */
1106 ConstrainByLayout(Scr->BorderedLayout, -1, &x, width, &y, height);
1107
1108 /* Move the occupy window to where it should be */
1109 if(occupy_twm->parent_vs != twm_win->parent_vs) {
1111 occupy_twm->frame_x = x;
1112 occupy_twm->frame_y = y;
1113 /*
1114 * XXX Should this be using DisplayWin() like everything else,
1115 * rather than manually grubbing beneath it?
1116 */
1118 }
1119 else {
1120 XMoveWindow(dpy, occupyWindow->twm_win->frame, x, y);
1121 }
1122
1123 /* And show it */
1125 XMapWindow(dpy, occupyWindow->w);
1126 XMapWindow(dpy, occupy_twm->frame);
1127
1128 /* XXX Must be a better way to express "all the way on top" */
1130
1131 /* Mark it shown, and stash what window we're showing it for */
1132 occupyWindow->twm_win->mapped = true;
1134}
1135
1136
1137
1138
1139/*
1140 ****************************************************************
1141 *
1142 * Backend and misc
1143 *
1144 ****************************************************************
1145 */
1146
1147
1148/*
1149 * The actual meat of occupation-changing; [re-]set the occupation for
1150 * the window. This is the func that actually sets and saves the new
1151 * occupation, moves the window where it should be, etc. Should maybe be
1152 * called something more like "SetOccupation()".
1153 */
1154void
1156{
1157 TwmWindow *t;
1158 WorkSpace *ws;
1159 int oldoccupation;
1161
1162 if((newoccupation == 0)
1163 || (newoccupation == tmp_win->occupation)) {
1164 /*
1165 * occupation=0 we interpret as "leave it alone". == current,
1166 * ditto. Go ahead and re-set the WM_OCCUPATION property though,
1167 * in case it's been broken by another client.
1168 */
1169 char *namelist;
1170 int len;
1171 long eventMask;
1172
1173 /* Mask out the PropertyChange events while we change the prop */
1175
1176 len = GetPropertyFromMask(tmp_win->occupation, &namelist);
1178 PropModeReplace, (unsigned char *) namelist, len);
1179 free(namelist);
1180#ifdef EWMH
1182#endif
1183
1184 /* Reset event mask */
1186 return;
1187 }
1188
1189 /*
1190 * OK, there's something to change. Stash the current state.
1191 */
1192 oldoccupation = tmp_win->occupation;
1193
1194 /*
1195 * Add it to IconManager in the new WS[en], remove from old. We have
1196 * to do the rather odd dance because AddIconManager() loops through
1197 * workspaces, and will add it to any workspaces it occupies (even if
1198 * it's already there). RemoveIconManager() goes over the window's
1199 * list of what icon managers it's on and removes it from any that
1200 * don't match the current occupation, so it can just be told "here's
1201 * where I should be".
1202 */
1203 tmp_win->occupation = newoccupation & ~oldoccupation;
1205 tmp_win->occupation = newoccupation;
1207
1208 /* If it shouldn't be "here", vanish it */
1209 if(tmp_win->vs && !OCCUPY(tmp_win, tmp_win->vs->wsw->currentwspc)) {
1210 Vanish(tmp_win->vs, tmp_win);
1211 }
1212
1213 /*
1214 * Try to find an(other) virtual screen which shows a workspace
1215 * where the window has occupation, so that the window can be shown
1216 * there now.
1217 */
1218 if(!tmp_win->vs) {
1219 VirtualScreen *vs;
1220 for(vs = Scr->vScreenList; vs != NULL; vs = vs->next) {
1221 if(OCCUPY(tmp_win, vs->wsw->currentwspc)) {
1222 DisplayWin(vs, tmp_win);
1223 break;
1224 }
1225 }
1226 }
1227
1228 /*
1229 * Loop over workspaces. Find the first one that it used to be in.
1230 * If it's not there anymore, take it out of the WindowRegion there
1231 * (RWFR() silently returns if we're not using WindowRegion's), and
1232 * add it the WindowRegion in the first WS it now occupies.
1233 *
1234 * XXX I'm not sure this is entirely sensible; it seems like just
1235 * unconditionally Remove/Place'ing would have the same effect?
1236 */
1237 for(ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
1238 int mask = 1 << ws->number;
1239 if(oldoccupation & mask) {
1240 if(!(newoccupation & mask)) {
1241 int final_x, final_y;
1245 }
1246 }
1247 break;
1248 }
1249 }
1250
1251 /* Now set the WM_OCCUPATION property */
1252 {
1253 char *namelist;
1254 int len;
1255 long eventMask;
1256
1258
1261 PropModeReplace, (unsigned char *) namelist, len);
1262 free(namelist);
1263#ifdef EWMH
1265#endif
1266
1268 }
1269
1270
1271 /*
1272 * Handle showing it up in the workspace map in the appropriate
1273 * places.
1274 *
1275 * Note that this whole block messes with the {new,old}occupation
1276 * vars. That's "safe" because they're no longer used for their
1277 * original purposes, only for the WSmap changes, but it's still
1278 * kinda fugly. Change to local vars at the drop of a hat with later
1279 * changes...
1280 */
1282 /* Not showing in the map, so pretend it's nowhere */
1283 newoccupation = 0;
1284 }
1285 if(Scr->workSpaceMgr.noshowoccupyall) {
1286 /*
1287 * Don't show OccupyAll. Note that this means both OccupyAll
1288 * window, AND windows manually set to occupy everything. We
1289 * don't have to adjust newoccupation, because the above
1290 * conditional would have caught it, so we only need to edit old.
1291 */
1293 oldoccupation = 0;
1294 }
1295 }
1296
1297 /* Flip the ones that need flipping */
1299 for(ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
1300 int mask = 1 << ws->number;
1301 if(changedoccupation & mask) {
1302 if(newoccupation & mask) {
1303 /* Add to WS */
1305 }
1306 else {
1307 /*
1308 * Remove from WS. We have to take it out of saved focus
1309 * if it were there. Maybe there are other places we
1310 * might need to remove it from (warpring?)?
1311 */
1313 if(Scr->SaveWorkspaceFocus && ws->save_focus == tmp_win) {
1314 ws->save_focus = NULL;
1315 }
1316 }
1317 }
1318 }
1319
1320
1321 /*
1322 * If transients don't have their own occupation, find any transients
1323 * of this window and move them with it.
1324 */
1325 if(! Scr->TransientHasOccupation) {
1326 for(t = Scr->FirstWindow; t != NULL; t = t->next) {
1327 if(t != tmp_win &&
1328 ((t->istransient && t->transientfor == tmp_win->w) ||
1329 t->group == tmp_win->w)) {
1330 ChangeOccupation(t, tmp_win->occupation);
1331 }
1332 }
1333 }
1334
1335 /* All done */
1336 return;
1337}
1338
1339
1340/*
1341 * There are various reasons you might not be able to change the
1342 * occupation of a window (either due to attributes of it, or the state
1343 * of your session/WM), so provide a function to check them all when we
1344 * try a change.
1345 *
1346 * Note that this is _not_ called from ChangeOccupation(); only from
1347 * other things that wrap it. Since CO() gets called from states where
1348 * this would [falsely] fail, it would be a bad idea to put it there.
1349 */
1350static bool
1352{
1354
1355 /* No workspaces config'd? Changing is nonsensical. */
1356 if(!Scr->workSpaceManagerActive) {
1357 return false;
1358 }
1359
1360 /*
1361 * f.occupy window up? Can't change in the middle of changing.
1362 * Though if it's not mapped, still pull it up, else iconifying the
1363 * occupy window breaks it forever.
1364 */
1365 if(occupyWin != NULL && Scr->workSpaceMgr.occupyWindow->twm_win->mapped) {
1366 return false;
1367 }
1368
1369 /* XXX Can we jut do this in the init? Check all callers. */
1370 twm_win = *twm_winp;
1371
1372 /* Don't change occupation of icon managers */
1373 if(twm_win->isiconmgr) {
1374 return false;
1375 }
1376
1377 /* XXX Should check iswspmgr here too? */
1378
1379 /*
1380 * If transients don't have their own occupation, check
1381 * transient/group bits.
1382 */
1383 if(!Scr->TransientHasOccupation) {
1384 if(twm_win->istransient) {
1385 return false;
1386 }
1387 if(twm_win->group != (Window) 0 && twm_win->group != twm_win->w) {
1388 /*
1389 * When trying to modify a group member window,
1390 * operate on the group leader instead
1391 * (and thereby on all group member windows as well).
1392 * If we can't find the group leader, pretend it isn't set.
1393 */
1395 if(!twm_win) {
1396 return true;
1397 }
1398 *twm_winp = twm_win;
1399 }
1400 }
1401
1402 /* Sure, go ahead, change it */
1403 return true;
1404}
1405
1406
1407/*
1408 * Add a client name to a list determining which workspaces it will
1409 * occupy. Used in handling the Occupy { } block in config file.
1410 */
1411bool
1413{
1414 WorkSpace *ws;
1415
1416 /* "all" is a magic workspace value which makes it occupy anywhere */
1417 if(strcmp(workspace, "all") == 0) {
1418 for(ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
1419 AddToList(&ws->clientlist, client, "");
1420 }
1421 return true;
1422 }
1423
1424 /* If prefixed with "ws:", strip the prefix and lookup by WS name */
1425 if(strncmp(workspace, "ws:", 3) == 0) {
1426 if((ws = GetWorkspace(workspace + 3)) != NULL) {
1427 AddToList(&ws->clientlist, client, "");
1428 return true;
1429 }
1430 }
1431
1432 /* Else find that named workspace and all this to it */
1433 if((ws = GetWorkspace(workspace)) != NULL) {
1434 AddToList(&ws->clientlist, client, "");
1435 return true;
1436 }
1437
1438 /* Couldn't figure where to put it */
1439 return false;
1440}
1441
1442
1443/*
1444 * Turn a ctwm.workspace resource string into an occupation mask. n.b.;
1445 * this changes the 'res' arg in-place.
1446 */
1447static int
1449{
1450 WorkSpace *ws;
1451 int mask;
1452 enum { O_SET, O_ADD, O_REM } mode;
1453 char *wrkSpcName, *tokst;
1454
1455 /*
1456 * This can set the occupation to a specific set of workspaces ("ws1
1457 * ws3"), add to the set it woudl have otherwise ("+ws1 ws3"), or
1458 * remove from the set it would otherwise ("-ws1 ws3"). The +/-
1459 * apply to the whole expression, not to the individual entries in
1460 * it. So first, figure out what we're doing.
1461 */
1462 mode = O_SET;
1463 if(*res == '+') {
1464 mode = O_ADD;
1465 res++;
1466 }
1467 else if(*res == '-') {
1468 mode = O_REM;
1469 res++;
1470 }
1471
1472 /*
1473 * Walk through the string adding the workspaces specified into the
1474 * mask of what we're doing.
1475 */
1476 mask = 0;
1477 for(wrkSpcName = strtok_r(res, " ", &tokst) ; wrkSpcName
1478 ; wrkSpcName = strtok_r(NULL, " ", &tokst)) {
1479 if(strcmp(wrkSpcName, "all") == 0) {
1480 mask = fullOccupation;
1481 break;
1482 }
1483 if(strcmp(wrkSpcName, "current") == 0) {
1484 VirtualScreen *vs = Scr->currentvs;
1485 if(vs) {
1486 mask |= (1 << vs->wsw->currentwspc->number);
1487 }
1488 continue;
1489 }
1490
1492 if(ws != NULL) {
1493 mask |= (1 << ws->number);
1494 }
1495 else {
1496 fprintf(stderr, "unknown workspace : %s\n", wrkSpcName);
1497 }
1498 }
1499
1500 /*
1501 * And return that mask, with necessary alterations depending on +/-
1502 * specified.
1503 */
1504 switch(mode) {
1505 case O_SET:
1506 return (mask);
1507 case O_ADD:
1508 return (mask | win->occupation);
1509 case O_REM:
1510 return (win->occupation & ~mask);
1511 }
1512
1513 /* Can't get here */
1514 fprintf(stderr, "%s(): Unreachable.\n", __func__);
1515 return 0;
1516}
1517
1518
1519/*
1520 * Turns a \0-separated buffer of workspace names into an occupation
1521 * bitmask.
1522 */
1523unsigned int
1524GetMaskFromProperty(unsigned char *_prop, unsigned long len)
1525{
1526 char wrkSpcName[256];
1527 WorkSpace *ws;
1528 unsigned int mask;
1529 int l;
1530 char *prop;
1531
1532 mask = 0;
1533 l = 0;
1534 prop = (char *) _prop;
1535 while(l < len) {
1536 /* If you have WS names longer than 256 chars, that's just Too Bad */
1538 l += strlen(prop) + 1;
1539 prop += strlen(prop) + 1;
1540 if(strcmp(wrkSpcName, "all") == 0) {
1541 mask = fullOccupation;
1542 break;
1543 }
1544
1546 if(ws != NULL) {
1547 mask |= (1 << ws->number);
1548 }
1549 else {
1550 fprintf(stderr, "unknown workspace : %s\n", wrkSpcName);
1551 }
1552 }
1553
1554#if 0
1555 {
1556 char *dbs = mk_nullsep_string((char *)_prop, len);
1557 fprintf(stderr, "%s('%s') -> 0x%x\n", __func__, dbs, mask);
1558 free(dbs);
1559 }
1560#endif
1561
1562 return (mask);
1563}
1564
1565
1566/*
1567 * Turns an occupation mask into a \0-separated buffer (not really a
1568 * string) of the workspace names.
1569 */
1570int
1571GetPropertyFromMask(unsigned int mask, char **prop)
1572{
1573 WorkSpace *ws;
1574 int len;
1575 char *wss[MAXWORKSPACE];
1576 int i;
1577
1578 /* If it's everything, just say 'all' */
1579 if(mask == fullOccupation) {
1580 *prop = strdup("all");
1581 return 3;
1582 }
1583
1584 /* Stash up pointers to all the labels for WSen it's in */
1585 memset(wss, 0, sizeof(wss));
1586 i = 0;
1587 len = 0;
1588 for(ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) {
1589 if(mask & (1 << ws->number)) {
1590 wss[i++] = ws->label;
1591 len += strlen(ws->label) + 1;
1592 }
1593 }
1594
1595 /* Assemble them into \0-separated string */
1596 *prop = malloc(len);
1597 len = 0;
1598 for(i = 0 ; wss[i] != NULL ; i++) {
1599 strcpy((*prop + len), wss[i]);
1600 len += strlen(wss[i]) + 1; // Skip past \0
1601 }
1602
1603#if 0
1604 {
1605 char *dbs = mk_nullsep_string(*prop, len);
1606 fprintf(stderr, "%s(0x%x) -> %d:'%s'\n", __func__, mask, len, dbs);
1607 free(dbs);
1608 }
1609#endif
1610
1611 return len;
1612}
1613
1614
1615/*
1616 * Generate a printable variant of the null-separated strings we use for
1617 * stashing in XA_WM_OCCUPATION. Used for debugging
1618 * Get{Property,Mask}From{Mask,Property}().
1619 */
1620#ifdef __GNUC__
1621# pragma GCC diagnostic push
1622# pragma GCC diagnostic ignored "-Wunused-function"
1623#endif
1624static char *
1625mk_nullsep_string(const char *prop, int len)
1626{
1627 char *dbs;
1628 int i, j;
1629
1630 /*
1631 * '\0' => "\\0" means we need longer than input; *2 is overkill,
1632 * but always sufficient, and it's cheap.
1633 */
1634 dbs = malloc(len * 2);
1635 i = j = 0;
1636 while(i < len) {
1637 size_t slen = strlen(prop + i);
1638
1639 strcpy(dbs + j, (prop + i));
1640 i += slen + 1;
1641 strcpy(dbs + j + slen, "\\0");
1642 j += slen + 2;
1643 }
1644
1645 return dbs;
1646}
1647#ifdef __GNUC__
1648# pragma GCC diagnostic pop
1649#endif
static int PlaceX
Definition add_window.c:82
TwmWindow * AddWindow(Window w, AWType wtype, IconMgr *iconp, VirtualScreen *vs)
Definition add_window.c:113
@ AWT_OCCUPY
Definition add_window.h:28
bool RestartPreviousState
Definition ctwm_main.c:151
int JunkY
Definition ctwm.h:358
#define OCCUPY(w, b)
Definition ctwm.h:369
unsigned int JunkBW
Definition ctwm.h:359
Window JunkRoot
Definition ctwm_main.c:142
int JunkX
Definition ctwm_main.c:143
Display * dpy
Definition ctwm_main.c:84
unsigned int JunkMask
Definition ctwm.h:359
unsigned int JunkDepth
Definition ctwm.h:359
#define Scr
void Draw3DBorder(Window w, int x, int y, int width, int height, int bw, ColorPair cp, ButtonState state, bool fill, bool forcebw)
Definition drawing.c:34
void PaintWsButton(PWBType which, VirtualScreen *vs, Window w, char *label, ColorPair cp, ButtonState state)
Definition drawing.c:153
ButtonState
Definition drawing.h:8
@ off
Definition drawing.h:8
@ on
Definition drawing.h:8
@ OCCUPYBUTTON
Definition drawing.h:18
@ OCCUPYWINDOW
Definition drawing.h:17
int ButtonPressed
Definition event_core.c:93
void EwmhSet_NET_WM_DESKTOP(TwmWindow *twm_win)
Definition ewmh.c:1469
int EwmhGetOccupation(TwmWindow *twm_win)
Definition ewmh.c:1602
Window frame
The X window for the overall frame.
void RemoveIconManager(TwmWindow *tmp_win)
Definition iconmgr.c:982
WList * AddIconManager(TwmWindow *tmp_win)
Definition iconmgr.c:697
int match(const char *p, const char *t)
Definition list.c:433
void AddToList(name_list **list_head, const char *name, void *ptr)
Definition list.c:63
void * LookInList(name_list *list_head, const char *name, XClassHint *class)
Definition list.c:101
int y
Definition menus.c:70
int x
Definition menus.c:69
void Occupy(TwmWindow *twm_win)
void OccupyHandleButtonEvent(XEvent *event)
Definition occupation.c:985
static XrmOptionDescRec table[]
Definition occupation.c:55
static ColorPair occupyButtoncp
Definition occupation.c:578
void RemoveFromWorkSpace(char *wname, TwmWindow *twm_win)
Definition occupation.c:309
unsigned int GetMaskFromProperty(unsigned char *_prop, unsigned long len)
static char * ok_string
Definition occupation.c:580
static int GetMaskFromResource(TwmWindow *win, char *res)
static char * mk_nullsep_string(const char *prop, int len)
void PaintOccupyWindow(void)
Definition occupation.c:954
static char * everywhere_string
Definition occupation.c:582
TwmWindow * occupyWin
Definition occupation.c:51
void OccupyAll(TwmWindow *twm_win)
Definition occupation.c:549
void AddToWorkSpace(char *wname, TwmWindow *twm_win)
Definition occupation.c:283
static bool CanChangeOccupation(TwmWindow **twm_winp)
int fullOccupation
Definition occupation.c:43
void MoveToPrevWorkSpace(VirtualScreen *vs, TwmWindow *twm_win)
Definition occupation.c:394
void CreateOccupyWindow(void)
Definition occupation.c:594
static char * cancel_string
Definition occupation.c:581
void ChangeOccupation(TwmWindow *tmp_win, int newoccupation)
int GetPropertyFromMask(unsigned int mask, char **prop)
void MoveToNextWorkSpace(VirtualScreen *vs, TwmWindow *twm_win)
Definition occupation.c:356
void WmgrRedoOccupation(TwmWindow *win)
Definition occupation.c:442
#define BTN_IPT_CTX(win)
bool AddToClientsList(char *workspace, char *client)
void WMgrRemoveFromCurrentWorkSpace(VirtualScreen *vs, TwmWindow *win)
Definition occupation.c:466
void ResizeOccupyWindow(TwmWindow *win)
Definition occupation.c:874
void MoveToNextWorkSpaceAndFollow(VirtualScreen *vs, TwmWindow *twm_win)
Definition occupation.c:378
void MoveToPrevWorkSpaceAndFollow(VirtualScreen *vs, TwmWindow *twm_win)
Definition occupation.c:422
void ToggleOccupation(char *wname, TwmWindow *twm_win)
Definition occupation.c:332
void SetupOccupation(TwmWindow *twm_win, int occupation_hint)
Definition occupation.c:80
void WMgrAddToCurrentWorkSpaceAndWarp(VirtualScreen *vs, char *winname)
Definition occupation.c:491
void OtpSetPriority(TwmWindow *twm_win, WinType wintype, int new_pri, int where)
Definition otp.c:894
void OtpRaise(TwmWindow *twm_win, WinType wintype)
Definition otp.c:763
@ WinWin
Definition otp.h:14
static int len
Definition parse.c:75
Pixel back
Definition ctwm.h:141
Pixel fore
Definition ctwm.h:141
Definition ctwm.h:127
XFontSet font_set
Definition ctwm.h:129
int tmpOccupation
Definition occupation.h:25
TwmWindow * twm_win
Definition occupation.h:11
Info and control for every X Window we take over.
bool iswspmgr
This is a workspace manager window.
bool isiconmgr
This is an icon manager window.
XWMHints * wmhints
Window manager hints.
Window w
The actual X Window handle.
bool istransient
This is a transient window.
char * name
Current window name. Points into TwmWindow::names.
int occupation
Workspaces the window is in (bitmap)
struct VirtualScreen * vs
Where the window is currently mapped (may be NULL)
bool mapped
Is the window mapped ?
XClassHint class
Window class info. From XGetClassHint().
struct VirtualScreen * parent_vs
Where the window is parented. Always set.
XWindowAttributes attr
Window attributes from XGetWindowAttributes()
Window transientfor
What window it's transient for.
Window group
Window group, from WM hints.
struct VirtualScreen * next
Definition vscreen.h:12
struct WorkSpaceWindow * wsw
Definition vscreen.h:11
WorkSpace * currentwspc
struct WorkSpace * next
void safe_strncpy(char *dest, const char *src, size_t size)
Definition util.c:586
void GetColor(int kind, Pixel *what, const char *name)
Get info from the server about a given color.
Definition util.c:154
void GetShadeColors(ColorPair *cp)
Try and create a 'shaded' version of a color for prettier UI.
Definition util.c:245
#define MIN(x, y)
Definition util.h:39
#define MAX(x, y)
Definition util.h:36
void ReparentFrameAndIcon(TwmWindow *tmp_win)
Definition vscreen.c:313
void Vanish(VirtualScreen *vs, TwmWindow *tmp_win)
Definition vscreen.c:344
void DisplayWin(VirtualScreen *vs, TwmWindow *tmp_win)
Definition vscreen.c:232
void DeIconify(TwmWindow *tmp_win)
void RemoveWindowFromRegion(TwmWindow *tmp_win)
bool PlaceWindowInRegion(TwmWindow *tmp_win, int *final_x, int *final_y)
bool visible(const TwmWindow *tmp_win)
Definition win_utils.c:341
bool GetWMState(Window w, int *statep, Window *iwp)
Definition win_utils.c:429
TwmWindow * GetTwmWindow(Window w)
Definition win_utils.c:190
int restore_mask(Window w, long restore)
Definition win_utils.c:399
bool ConstrainByLayout(RLayout *layout, int move_off_res, int *left, int width, int *top, int height)
Definition win_utils.c:760
long mask_out_event(Window w, long ignore_event)
Definition win_utils.c:366
void SetMapStateProp(TwmWindow *tmp_win, int state)
Definition win_utils.c:415
void WarpToWindow(TwmWindow *t, bool must_raise)
Definition win_utils.c:883
void WMapAddWindowToWorkspace(TwmWindow *win, WorkSpace *ws)
bool WMapWindowMayBeAdded(TwmWindow *win)
void WMapRemoveWindowFromWorkspace(TwmWindow *win, WorkSpace *ws)
#define MAXWORKSPACE
void GotoPrevWorkSpace(VirtualScreen *vs)
WorkSpace * GetWorkspace(const char *wname)
void GotoNextWorkSpace(VirtualScreen *vs)