503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
1 |
/*
|
2 |
* Occupation handling bits
|
|
503.1.97
by Matthew Fuller
Expand header comment to lampshade how tightly tied this is with |
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
|
|
503.1.112
by Matthew Fuller
Tpyo. |
8 |
* WMgr* commands. But having them crammed together in one file is
|
503.1.97
by Matthew Fuller
Expand header comment to lampshade how tightly tied this is with |
9 |
* unwieldy.
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
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" |
|
518.1.24
by Matthew Fuller
iconmgr.h isn't needed for add_window.h. Pull it out and add it to |
24 |
#include "iconmgr.h" |
524.1.5
by Matthew Fuller
Pull list.h out of screen.h and #include it in the places that need |
25 |
#include "list.h" |
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
26 |
#include "screen.h" |
524.1.1
by Matthew Fuller
Pull occupation.h out of screen.h, and include it directly in the |
27 |
#include "occupation.h" |
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
28 |
#include "otp.h" |
29 |
#include "util.h" |
|
524.1.3
by Matthew Fuller
Pull vscreen.h out of screen.h and #include it directly in the files |
30 |
#include "vscreen.h" |
520.1.2
by Matthew Fuller
Bust functions related to iconifying/deiconifying windows out of |
31 |
#include "win_iconify.h" |
518.1.22
by Matthew Fuller
Break the funcs for handling WindowRegion stuff out of add_window.c |
32 |
#include "win_regions.h" |
523.1.5
by Matthew Fuller
GetTwmWindow() is pretty obvious _utils fodder. |
33 |
#include "win_utils.h" |
510.1.9
by Matthew Fuller
Only stuff left in workmgr is the actual workspace manager stuff. |
34 |
#include "workspace_manager.h" |
510.1.5
by Matthew Fuller
Break the general/utility workspace functions out into their own file. |
35 |
#include "workspace_utils.h" |
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
36 |
|
37 |
||
38 |
static int GetMaskFromResource(TwmWindow *win, char *res); |
|
39 |
static char *mk_nullsep_string(const char *prop, int len); |
|
40 |
||
41 |
static bool CanChangeOccupation(TwmWindow **twm_winp); |
|
42 |
||
43 |
int fullOccupation = 0; |
|
44 |
||
45 |
/*
|
|
46 |
* The window whose occupation is currently being manipulated.
|
|
47 |
*
|
|
48 |
* XXX Should probably be static, but currently needed in
|
|
510.1.90
by Matthew Fuller
Rename several of these funcs for adding/removing windows to the WSM |
49 |
* WMapRemoveWindow(). Revisit.
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
50 |
*/
|
51 |
TwmWindow *occupyWin = NULL; |
|
52 |
||
53 |
||
503.1.98
by Matthew Fuller
Leave a comment on sharing this var. |
54 |
/* XXX Share with captive.c? */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
55 |
static XrmOptionDescRec table [] = { |
56 |
{"-xrm", NULL, XrmoptionResArg, (XPointer) NULL}, |
|
57 |
};
|
|
58 |
||
59 |
||
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
60 |
|
503.1.102
by Matthew Fuller
Rearrange the functions in occupation.c so they're ordered and grouped |
61 |
|
62 |
/*
|
|
63 |
****************************************************************
|
|
64 |
*
|
|
65 |
* First, funcs related to setting and changing a window's occupation.
|
|
66 |
*
|
|
67 |
****************************************************************
|
|
68 |
*/
|
|
69 |
||
70 |
||
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
71 |
/*
|
72 |
* Setup the occupation of a TwmWindow. Called as part of the
|
|
73 |
* AddWindow() process.
|
|
556.1.50
by Matthew Fuller
Drop an XXX on this func about the confusing and maybe incorrect |
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...
|
|
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
78 |
*/
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
79 |
void
|
80 |
SetupOccupation(TwmWindow *twm_win, int occupation_hint) |
|
81 |
{
|
|
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
82 |
char **cliargv = NULL; |
83 |
int cliargc; |
|
84 |
WorkSpace *ws; |
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
85 |
|
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
86 |
/* If there aren't any config'd workspaces, there's only 0 */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
87 |
if(! Scr->workSpaceManagerActive) { |
88 |
twm_win->occupation = 1 << 0; /* occupy workspace #0 */ |
|
89 |
/* more?... */
|
|
90 |
||
91 |
return; |
|
92 |
}
|
|
93 |
||
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
94 |
/* Workspace manager window doesn't get futzed with */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
95 |
if(twm_win->iswspmgr) { |
96 |
return; |
|
97 |
}
|
|
98 |
||
99 |
/*twm_win->occupation = twm_win->iswinbox ? fullOccupation : 0;*/
|
|
100 |
twm_win->occupation = 0; |
|
101 |
||
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
102 |
/* Specified in any Occupy{} config params? */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
103 |
for(ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) { |
563.1.4
by Matthew Fuller
Mechanically translate all these full_name references to name. |
104 |
if(LookInList(ws->clientlist, twm_win->name, &twm_win->class)) { |
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
105 |
twm_win->occupation |= 1 << ws->number; |
106 |
}
|
|
107 |
}
|
|
108 |
||
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
109 |
/* OccupyAll{} */
|
563.1.4
by Matthew Fuller
Mechanically translate all these full_name references to name. |
110 |
if(LookInList(Scr->OccupyAll, twm_win->name, &twm_win->class)) { |
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
111 |
twm_win->occupation = fullOccupation; |
112 |
}
|
|
113 |
||
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
114 |
/* See if it specified in -xrm stuff */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
115 |
if(XGetCommand(dpy, twm_win->w, &cliargv, &cliargc)) { |
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
116 |
Bool status; |
117 |
char *str_type; |
|
118 |
XrmValue value; |
|
503.1.67
by Matthew Fuller
Need to initialize this to NULL, or things go bad. |
119 |
XrmDatabase db = NULL; |
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
120 |
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
121 |
XrmParseCommand(&db, table, 1, "ctwm", &cliargc, cliargv); |
503.1.70
by Matthew Fuller
Free this list as soon as we're done with it. Not that it makes much |
122 |
XFreeStringList(cliargv); |
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
123 |
status = XrmGetResource(db, "ctwm.workspace", "Ctwm.Workspace", |
124 |
&str_type, &value); |
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
125 |
if((status == True) && (value.size != 0)) { |
126 |
/* Copy the value.addr because it's in XRM memory not ours */
|
|
127 |
char wrkSpcList[512]; |
|
503.1.68
by Matthew Fuller
Use safe_strncpy() here instead of manually implementing it. |
128 |
safe_strncpy(wrkSpcList, value.addr, MIN(value.size, 512)); |
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
129 |
|
503.1.69
by Matthew Fuller
Use our copy, not the one in memory we don't really control. |
130 |
twm_win->occupation = GetMaskFromResource(twm_win, wrkSpcList); |
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
131 |
}
|
132 |
XrmDestroyDatabase(db); |
|
133 |
}
|
|
134 |
||
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
135 |
/* Does it have a property telling us */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
136 |
if(RestartPreviousState) { |
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
137 |
Atom actual_type; |
138 |
int actual_format; |
|
139 |
unsigned long nitems, bytesafter; |
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
140 |
unsigned char *prop; |
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
141 |
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
142 |
if(XGetWindowProperty(dpy, twm_win->w, XA_WM_OCCUPATION, 0L, 2500, False, |
143 |
XA_STRING, &actual_type, &actual_format, &nitems, |
|
144 |
&bytesafter, &prop) == Success) { |
|
145 |
if(nitems != 0) { |
|
146 |
twm_win->occupation = GetMaskFromProperty(prop, nitems); |
|
147 |
XFree(prop); |
|
148 |
}
|
|
149 |
}
|
|
150 |
}
|
|
151 |
||
152 |
#ifdef EWMH
|
|
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
153 |
/* Maybe EWMH has something to tell us? */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
154 |
if(twm_win->occupation == 0) { |
155 |
twm_win->occupation = EwmhGetOccupation(twm_win); |
|
156 |
}
|
|
157 |
#endif /* EWMH */ |
|
158 |
||
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
159 |
/* Icon Managers shouldn't get altered */
|
160 |
/* XXX Should this be up near the top? */
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
161 |
if(twm_win->isiconmgr) { |
162 |
return; /* someone tried to modify occupation of icon managers */ |
|
163 |
}
|
|
164 |
||
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
165 |
|
166 |
/*
|
|
167 |
* Transient-ish things go with their parents unless
|
|
168 |
* TransientHasOccupation set in the config.
|
|
169 |
*/
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
170 |
if(! Scr->TransientHasOccupation) { |
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
171 |
TwmWindow *t; |
172 |
||
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
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 |
||
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
188 |
/* If we were told something specific, go with that */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
189 |
if(occupation_hint != 0) { |
190 |
twm_win->occupation = occupation_hint; |
|
191 |
}
|
|
192 |
||
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
193 |
/* If it's apparently-nonsensical, put it in its vs's workspace */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
194 |
if((twm_win->occupation & fullOccupation) == 0) { |
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
195 |
twm_win->occupation = 1 << twm_win->vs->wsw->currentwspc->number; |
196 |
}
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
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 |
||
696.1.14
by Matthew Fuller
Another "maybe show on different vscreen" case, that doesn't need to |
208 |
#ifdef VSCREEN
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
209 |
if(Scr->numVscreens > 1) { |
696.1.14
by Matthew Fuller
Another "maybe show on different vscreen" case, that doesn't need to |
210 |
VirtualScreen *vs; |
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
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 |
}
|
|
696.1.14
by Matthew Fuller
Another "maybe show on different vscreen" case, that doesn't need to |
219 |
#endif
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
220 |
}
|
221 |
||
222 |
||
511.1.9
by Matthew Fuller
Use mask_out_event{_mask}() and restore_mask() in place of manually |
223 |
/* Set the property for the occupation */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
224 |
{
|
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
225 |
long eventMask; |
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
226 |
char *wsstr; |
227 |
int len; |
|
228 |
||
511.1.9
by Matthew Fuller
Use mask_out_event{_mask}() and restore_mask() in place of manually |
229 |
/* Ignore the PropertyChange we're about to do */
|
230 |
if((eventMask = mask_out_event(twm_win->w, PropertyChangeMask)) < 0) { |
|
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
231 |
/* Window is horked, not much we can do */
|
232 |
return; |
|
233 |
}
|
|
234 |
||
235 |
/* Set the property for the occupation */
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
236 |
len = GetPropertyFromMask(twm_win->occupation, &wsstr); |
237 |
XChangeProperty(dpy, twm_win->w, XA_WM_OCCUPATION, XA_STRING, 8, |
|
238 |
PropModeReplace, (unsigned char *) wsstr, len); |
|
239 |
free(wsstr); |
|
240 |
||
241 |
#ifdef EWMH
|
|
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
242 |
EwmhSet_NET_WM_DESKTOP(twm_win); |
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
243 |
#endif
|
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
244 |
|
245 |
/* Restore event mask */
|
|
511.1.9
by Matthew Fuller
Use mask_out_event{_mask}() and restore_mask() in place of manually |
246 |
restore_mask(twm_win->w, eventMask); |
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
247 |
}
|
248 |
||
249 |
/* Set WM_STATE prop */
|
|
250 |
{
|
|
251 |
int state = NormalState; |
|
252 |
Window icon; |
|
253 |
||
254 |
if(!(RestartPreviousState |
|
255 |
&& GetWMState(twm_win->w, &state, &icon) |
|
256 |
&& (state == NormalState || state == IconicState |
|
257 |
|| state == InactiveState))) { |
|
557.1.3
by Matthew Fuller
GC now-unnecessary NULL checks of wmhints. |
258 |
if(twm_win->wmhints->flags & StateHint) { |
503.1.66
by Matthew Fuller
Comment through SetupOccupation(), localize some vars in it, leave |
259 |
state = twm_win->wmhints->initial_state; |
260 |
}
|
|
261 |
}
|
|
262 |
if(visible(twm_win)) { |
|
263 |
if(state == InactiveState) { |
|
264 |
SetMapStateProp(twm_win, NormalState); |
|
265 |
}
|
|
266 |
}
|
|
267 |
else { |
|
268 |
if(state == NormalState) { |
|
269 |
SetMapStateProp(twm_win, InactiveState); |
|
270 |
}
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
271 |
}
|
272 |
}
|
|
273 |
}
|
|
274 |
||
275 |
||
503.1.71
by Matthew Fuller
Comment up CanChangeOccupation(). |
276 |
/*
|
503.1.101
by Matthew Fuller
Expand comments a little. |
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.
|
|
503.1.72
by Matthew Fuller
Do a bit of commenting. |
281 |
*/
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
282 |
void
|
283 |
AddToWorkSpace(char *wname, TwmWindow *twm_win) |
|
284 |
{
|
|
285 |
WorkSpace *ws; |
|
286 |
int newoccupation; |
|
287 |
||
288 |
if(!CanChangeOccupation(&twm_win)) { |
|
289 |
return; |
|
290 |
}
|
|
291 |
ws = GetWorkspace(wname); |
|
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); |
|
300 |
ChangeOccupation(twm_win, newoccupation); |
|
301 |
}
|
|
302 |
||
303 |
||
503.1.101
by Matthew Fuller
Expand comments a little. |
304 |
/*
|
305 |
* Converse of the above. f.removefromworkspace, also called from
|
|
306 |
* Xinerama-related magic.
|
|
307 |
*/
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
308 |
void
|
309 |
RemoveFromWorkSpace(char *wname, TwmWindow *twm_win) |
|
310 |
{
|
|
311 |
WorkSpace *ws; |
|
312 |
int newoccupation; |
|
313 |
||
314 |
if(!CanChangeOccupation(&twm_win)) { |
|
315 |
return; |
|
316 |
}
|
|
317 |
ws = GetWorkspace(wname); |
|
318 |
if(!ws) { |
|
319 |
return; |
|
320 |
}
|
|
321 |
||
322 |
newoccupation = twm_win->occupation & ~(1 << ws->number); |
|
323 |
if(!newoccupation) { |
|
324 |
return; |
|
325 |
}
|
|
326 |
ChangeOccupation(twm_win, newoccupation); |
|
327 |
}
|
|
328 |
||
329 |
||
503.1.74
by Matthew Fuller
Comment another block of functions. Do some minor code rearrangement |
330 |
/* f.toggleoccupation - flip setting for [current] workspace */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
331 |
void
|
332 |
ToggleOccupation(char *wname, TwmWindow *twm_win) |
|
333 |
{
|
|
334 |
WorkSpace *ws; |
|
335 |
int newoccupation; |
|
336 |
||
337 |
if(!CanChangeOccupation(&twm_win)) { |
|
338 |
return; |
|
339 |
}
|
|
340 |
ws = GetWorkspace(wname); |
|
341 |
if(!ws) { |
|
342 |
return; |
|
343 |
}
|
|
344 |
||
345 |
newoccupation = twm_win->occupation ^ (1 << ws->number); |
|
346 |
if(!newoccupation) { |
|
503.1.74
by Matthew Fuller
Comment another block of functions. Do some minor code rearrangement |
347 |
/* Don't allow de-occupying _every_ ws */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
348 |
return; |
349 |
}
|
|
350 |
ChangeOccupation(twm_win, newoccupation); |
|
351 |
}
|
|
352 |
||
353 |
||
503.1.74
by Matthew Fuller
Comment another block of functions. Do some minor code rearrangement |
354 |
/* f.movetonextworkspace */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
355 |
void
|
356 |
MoveToNextWorkSpace(VirtualScreen *vs, TwmWindow *twm_win) |
|
357 |
{
|
|
358 |
WorkSpace *wlist1, *wlist2; |
|
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 |
||
503.1.74
by Matthew Fuller
Comment another block of functions. Do some minor code rearrangement |
369 |
/* Out of (here), into (here+1) */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
370 |
newoccupation = (twm_win->occupation ^ (1 << wlist1->number)) |
371 |
| (1 << wlist2->number); |
|
372 |
ChangeOccupation(twm_win, newoccupation); |
|
373 |
}
|
|
374 |
||
375 |
||
503.1.74
by Matthew Fuller
Comment another block of functions. Do some minor code rearrangement |
376 |
/* f.movetonextworkspaceandfollow */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
377 |
void
|
378 |
MoveToNextWorkSpaceAndFollow(VirtualScreen *vs, TwmWindow *twm_win) |
|
379 |
{
|
|
380 |
if(!CanChangeOccupation(&twm_win)) { |
|
381 |
return; |
|
382 |
}
|
|
383 |
||
384 |
MoveToNextWorkSpace(vs, twm_win); |
|
385 |
GotoNextWorkSpace(vs); |
|
386 |
#if 0
|
|
387 |
OtpRaise(twm_win, WinWin); /* XXX really do this? */
|
|
388 |
#endif
|
|
389 |
}
|
|
390 |
||
391 |
||
503.1.74
by Matthew Fuller
Comment another block of functions. Do some minor code rearrangement |
392 |
/* f.movetoprevworkspaceand */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
393 |
void
|
394 |
MoveToPrevWorkSpace(VirtualScreen *vs, TwmWindow *twm_win) |
|
395 |
{
|
|
396 |
WorkSpace *wlist1, *wlist2; |
|
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 |
||
503.1.74
by Matthew Fuller
Comment another block of functions. Do some minor code rearrangement |
413 |
/* Out of (here), into (here-1) */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
414 |
newoccupation = (twm_win->occupation ^ (1 << wlist2->number)) |
415 |
| (1 << wlist1->number); |
|
416 |
ChangeOccupation(twm_win, newoccupation); |
|
417 |
}
|
|
418 |
||
419 |
||
503.1.74
by Matthew Fuller
Comment another block of functions. Do some minor code rearrangement |
420 |
/* f.movetoprevworkspaceandfollow */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
421 |
void
|
422 |
MoveToPrevWorkSpaceAndFollow(VirtualScreen *vs, TwmWindow *twm_win) |
|
423 |
{
|
|
424 |
if(!CanChangeOccupation(&twm_win)) { |
|
425 |
return; |
|
426 |
}
|
|
427 |
||
428 |
MoveToPrevWorkSpace(vs, twm_win); |
|
429 |
GotoPrevWorkSpace(vs); |
|
430 |
#if 0
|
|
431 |
OtpRaise(twm_win, WinWin); /* XXX really do this? */
|
|
432 |
#endif
|
|
433 |
}
|
|
434 |
||
435 |
||
503.1.74
by Matthew Fuller
Comment another block of functions. Do some minor code rearrangement |
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 |
*/
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
441 |
void
|
442 |
WmgrRedoOccupation(TwmWindow *win) |
|
443 |
{
|
|
444 |
WorkSpace *ws; |
|
445 |
int newoccupation; |
|
446 |
||
563.1.4
by Matthew Fuller
Mechanically translate all these full_name references to name. |
447 |
if(LookInList(Scr->OccupyAll, win->name, &win->class)) { |
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
448 |
newoccupation = fullOccupation; |
449 |
}
|
|
450 |
else { |
|
451 |
newoccupation = 0; |
|
452 |
for(ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) { |
|
563.1.4
by Matthew Fuller
Mechanically translate all these full_name references to name. |
453 |
if(LookInList(ws->clientlist, win->name, &win->class)) { |
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
454 |
newoccupation |= 1 << ws->number; |
455 |
}
|
|
456 |
}
|
|
457 |
}
|
|
458 |
if(newoccupation != 0) { |
|
459 |
ChangeOccupation(win, newoccupation); |
|
460 |
}
|
|
461 |
}
|
|
462 |
||
463 |
||
503.1.74
by Matthew Fuller
Comment another block of functions. Do some minor code rearrangement |
464 |
/* f.vanish */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
465 |
void
|
466 |
WMgrRemoveFromCurrentWorkSpace(VirtualScreen *vs, TwmWindow *win) |
|
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 |
||
485 |
ChangeOccupation(win, newoccupation); |
|
486 |
}
|
|
487 |
||
488 |
||
503.1.74
by Matthew Fuller
Comment another block of functions. Do some minor code rearrangement |
489 |
/* f.warphere */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
490 |
void
|
491 |
WMgrAddToCurrentWorkSpaceAndWarp(VirtualScreen *vs, char *winname) |
|
492 |
{
|
|
493 |
TwmWindow *tw; |
|
494 |
int newoccupation; |
|
495 |
||
503.1.74
by Matthew Fuller
Comment another block of functions. Do some minor code rearrangement |
496 |
/* Find named window on this screen */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
497 |
for(tw = Scr->FirstWindow; tw != NULL; tw = tw->next) { |
563.1.4
by Matthew Fuller
Mechanically translate all these full_name references to name. |
498 |
if(match(winname, tw->name)) { |
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
499 |
break; |
500 |
}
|
|
501 |
}
|
|
503.1.74
by Matthew Fuller
Comment another block of functions. Do some minor code rearrangement |
502 |
|
503 |
/* Didn't find it by name? Try by class */
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
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 |
}
|
|
503.1.74
by Matthew Fuller
Comment another block of functions. Do some minor code rearrangement |
510 |
}
|
511 |
if(!tw) { |
|
512 |
for(tw = Scr->FirstWindow; tw != NULL; tw = tw->next) { |
|
513 |
if(match(winname, tw->class.res_class)) { |
|
514 |
break; |
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
515 |
}
|
516 |
}
|
|
517 |
}
|
|
503.1.74
by Matthew Fuller
Comment another block of functions. Do some minor code rearrangement |
518 |
|
519 |
/* Still didn't find? Beep at the user and bail. */
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
520 |
if(!tw) { |
521 |
XBell(dpy, 0); |
|
522 |
return; |
|
523 |
}
|
|
503.1.74
by Matthew Fuller
Comment another block of functions. Do some minor code rearrangement |
524 |
|
525 |
/* If WarpUnmapped isn't set and this isn't mapped, beep and bail */
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
526 |
if((! Scr->WarpUnmapped) && (! tw->mapped)) { |
527 |
XBell(dpy, 0); |
|
528 |
return; |
|
529 |
}
|
|
503.1.74
by Matthew Fuller
Comment another block of functions. Do some minor code rearrangement |
530 |
|
531 |
/* Move it here if it's not */
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
532 |
if(! OCCUPY(tw, vs->wsw->currentwspc)) { |
533 |
newoccupation = tw->occupation | (1 << vs->wsw->currentwspc->number); |
|
534 |
ChangeOccupation(tw, newoccupation); |
|
535 |
}
|
|
536 |
||
503.1.74
by Matthew Fuller
Comment another block of functions. Do some minor code rearrangement |
537 |
/* If we get here, WarpUnmapped is set, so map it if we need to */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
538 |
if(! tw->mapped) { |
539 |
DeIconify(tw); |
|
540 |
}
|
|
503.1.74
by Matthew Fuller
Comment another block of functions. Do some minor code rearrangement |
541 |
|
542 |
/* And go */
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
543 |
WarpToWindow(tw, Scr->RaiseOnWarp); |
544 |
}
|
|
545 |
||
546 |
||
503.1.102
by Matthew Fuller
Rearrange the functions in occupation.c so they're ordered and grouped |
547 |
/* f.occupyall backend */
|
548 |
void
|
|
549 |
OccupyAll(TwmWindow *twm_win) |
|
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; |
|
564 |
ChangeOccupation(twm_win, fullOccupation); |
|
565 |
Scr->iconmgr = save; |
|
566 |
}
|
|
567 |
||
568 |
||
569 |
||
570 |
/*
|
|
571 |
****************************************************************
|
|
572 |
*
|
|
573 |
* Pieces related to the Occupy window
|
|
574 |
*
|
|
575 |
****************************************************************
|
|
576 |
*/
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
577 |
|
578 |
static ColorPair occupyButtoncp; |
|
579 |
||
580 |
static char *ok_string = "OK", |
|
581 |
*cancel_string = "Cancel", |
|
582 |
*everywhere_string = "All"; |
|
583 |
||
584 |
/*
|
|
503.1.75
by Matthew Fuller
Quick comment on the last couple functions. |
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 |
*
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
590 |
* There is only one Occupy window (per Screen), it is reparented to each
|
591 |
* virtual screen as needed.
|
|
592 |
*/
|
|
593 |
void
|
|
594 |
CreateOccupyWindow(void) |
|
595 |
{
|
|
503.1.84
by Matthew Fuller
Most of these remaining vars are actually just shorthands for values |
596 |
int width; // Caculated and altered, unlike most others |
503.1.82
by Matthew Fuller
Move all the shorthand vars together and comment. |
597 |
int Dummy = 1; |
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
598 |
TwmWindow *tmp_win; |
503.1.84
by Matthew Fuller
Most of these remaining vars are actually just shorthands for values |
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 |
||
574.1.1
by Matthew Fuller
Like the workspace manager, there's no point trying to create the |
613 |
/* There isn't anything we should do without workspaces... */
|
614 |
if(!Scr->workSpaceManagerActive) { |
|
615 |
return; |
|
616 |
}
|
|
617 |
||
503.1.84
by Matthew Fuller
Most of these remaining vars are actually just shorthands for values |
618 |
/* Initialize font and colorpair bits */
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
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) { |
|
626 |
GetShadeColors(&occwin->cp); |
|
627 |
}
|
|
628 |
#endif
|
|
503.1.83
by Matthew Fuller
name and icon_name shorthands were also only used once, so it's not |
629 |
|
503.1.87
by Matthew Fuller
We know what these should be at the start of the func, so initialize |
630 |
/* We already know that these should be too */
|
631 |
occwin->lines = lines; |
|
632 |
occwin->columns = columns; |
|
633 |
||
503.1.78
by Matthew Fuller
Localize a bunch of vars in CreateOccupyWindow(). |
634 |
|
503.1.86
by Matthew Fuller
Start commenting up the first block here. Eliminate unnecessary |
635 |
/*
|
636 |
* Work out the necessary size of the OK/Cancel/All buttons at the
|
|
637 |
* bottom.
|
|
638 |
*/
|
|
503.1.78
by Matthew Fuller
Localize a bunch of vars in CreateOccupyWindow(). |
639 |
{
|
640 |
XRectangle inc_rect; |
|
641 |
XRectangle logical_rect; |
|
503.1.86
by Matthew Fuller
Start commenting up the first block here. Eliminate unnecessary |
642 |
MyFont font = occwin->font; |
512.1.3
by Matthew Fuller
Comment var declarations. |
643 |
int bbwidth; // Bottom button width |
644 |
/* Window min width based on bottom vs. workspace btns */
|
|
645 |
int bb_width, ws_width; |
|
503.1.78
by Matthew Fuller
Localize a bunch of vars in CreateOccupyWindow(). |
646 |
|
503.1.86
by Matthew Fuller
Start commenting up the first block here. Eliminate unnecessary |
647 |
/* Buttons gotta be as wide as the biggest of the three strings */
|
503.1.78
by Matthew Fuller
Localize a bunch of vars in CreateOccupyWindow(). |
648 |
XmbTextExtents(font.font_set, ok_string, strlen(ok_string), |
649 |
&inc_rect, &logical_rect); |
|
512.1.2
by Matthew Fuller
Use separate local vars for the min size based on the bottom buttons |
650 |
bbwidth = logical_rect.width; |
503.1.86
by Matthew Fuller
Start commenting up the first block here. Eliminate unnecessary |
651 |
|
503.1.78
by Matthew Fuller
Localize a bunch of vars in CreateOccupyWindow(). |
652 |
XmbTextExtents(font.font_set, cancel_string, strlen(cancel_string), |
653 |
&inc_rect, &logical_rect); |
|
512.1.2
by Matthew Fuller
Use separate local vars for the min size based on the bottom buttons |
654 |
bbwidth = MAX(bbwidth, logical_rect.width); |
503.1.86
by Matthew Fuller
Start commenting up the first block here. Eliminate unnecessary |
655 |
|
503.1.78
by Matthew Fuller
Localize a bunch of vars in CreateOccupyWindow(). |
656 |
XmbTextExtents(font.font_set, everywhere_string, |
657 |
strlen(everywhere_string), |
|
658 |
&inc_rect, &logical_rect); |
|
512.1.2
by Matthew Fuller
Use separate local vars for the min size based on the bottom buttons |
659 |
bbwidth = MAX(bbwidth, logical_rect.width); |
503.1.86
by Matthew Fuller
Start commenting up the first block here. Eliminate unnecessary |
660 |
|
661 |
/* Plus the padding width */
|
|
512.1.2
by Matthew Fuller
Use separate local vars for the min size based on the bottom buttons |
662 |
bbwidth += hspace; |
503.1.86
by Matthew Fuller
Start commenting up the first block here. Eliminate unnecessary |
663 |
|
664 |
/*
|
|
503.1.88
by Matthew Fuller
Further commenting on the sizing block, and some code |
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 |
*/
|
|
512.1.2
by Matthew Fuller
Use separate local vars for the min size based on the bottom buttons |
672 |
occwin->owidth = bbwidth + 2 * Scr->WMgrButtonShadowDepth + 2; |
503.1.88
by Matthew Fuller
Further commenting on the sizing block, and some code |
673 |
|
674 |
/*
|
|
675 |
* The whole thing has to be at least triple the min width of
|
|
512.1.1
by Matthew Fuller
Add extra hspace to the width planning here, since there's padding on |
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 |
*/
|
|
512.1.2
by Matthew Fuller
Use separate local vars for the min size based on the bottom buttons |
680 |
bb_width = 3 * (bbwidth + hspace) + hspace; |
503.1.85
by Matthew Fuller
Slightly expand an inner scope so we can move these two vars into it. |
681 |
|
503.1.86
by Matthew Fuller
Start commenting up the first block here. Eliminate unnecessary |
682 |
/*
|
512.1.2
by Matthew Fuller
Use separate local vars for the min size based on the bottom buttons |
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.
|
|
503.1.86
by Matthew Fuller
Start commenting up the first block here. Eliminate unnecessary |
686 |
*/
|
512.1.2
by Matthew Fuller
Use separate local vars for the min size based on the bottom buttons |
687 |
ws_width = columns * (bwidth + hspace) + hspace; |
503.1.86
by Matthew Fuller
Start commenting up the first block here. Eliminate unnecessary |
688 |
|
512.1.2
by Matthew Fuller
Use separate local vars for the min size based on the bottom buttons |
689 |
/* So the window has to be as wide as the wider of those */
|
690 |
width = MAX(bb_width, ws_width); |
|
503.1.85
by Matthew Fuller
Slightly expand an inner scope so we can move these two vars into it. |
691 |
}
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
692 |
|
503.1.89
by Matthew Fuller
Start commenting making the window and buttons. Eliminate one |
693 |
|
694 |
/* Now we know the size, so make the window */
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
695 |
w = occwin->w = XCreateSimpleWindow(dpy, Scr->Root, 0, 0, width, height, |
503.1.79
by Matthew Fuller
This var was a shortcut for a single use; don't bother. |
696 |
1, Scr->Black, occwin->cp.back); |
503.1.89
by Matthew Fuller
Start commenting making the window and buttons. Eliminate one |
697 |
|
514.1.3
by Matthew Fuller
Stash up the minimum size for the window and bail out of Resize early |
698 |
/* Take those base sizes as a minimum */
|
699 |
occwin->minwidth = width; |
|
700 |
occwin->minheight = height; |
|
701 |
||
503.1.89
by Matthew Fuller
Start commenting making the window and buttons. Eliminate one |
702 |
|
703 |
/*
|
|
704 |
* Make subwindows as buttons for the workspaces. They're laid out
|
|
705 |
* in a grid mirroring the workspace manager's.
|
|
706 |
*/
|
|
503.1.78
by Matthew Fuller
Localize a bunch of vars in CreateOccupyWindow(). |
707 |
{
|
708 |
int i = 0, j = 0; |
|
503.1.81
by Matthew Fuller
These two uses of ws are independent, so move one into the existing |
709 |
WorkSpace *ws; |
710 |
||
503.1.89
by Matthew Fuller
Start commenting making the window and buttons. Eliminate one |
711 |
occwin->obuttonw = calloc(Scr->workSpaceMgr.count, sizeof(Window)); |
712 |
||
503.1.78
by Matthew Fuller
Localize a bunch of vars in CreateOccupyWindow(). |
713 |
for(ws = Scr->workSpaceMgr.workSpaceList; ws != NULL; ws = ws->next) { |
503.1.89
by Matthew Fuller
Start commenting making the window and buttons. Eliminate one |
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, |
|
503.1.92
by Matthew Fuller
Let make indent rejigger this. |
722 |
Dummy /* x */, |
723 |
Dummy /* y */, |
|
724 |
Dummy /* width */, |
|
725 |
Dummy /* height */, |
|
726 |
0, Scr->Black, ws->cp.back); |
|
503.1.89
by Matthew Fuller
Start commenting making the window and buttons. Eliminate one |
727 |
XMapWindow(dpy, occwin->obuttonw[idx]); |
728 |
||
729 |
/* Inc around to the next location */
|
|
503.1.78
by Matthew Fuller
Localize a bunch of vars in CreateOccupyWindow(). |
730 |
i++; |
731 |
if(i == columns) { |
|
732 |
i = 0; |
|
733 |
j++; |
|
734 |
}
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
735 |
}
|
736 |
}
|
|
503.1.78
by Matthew Fuller
Localize a bunch of vars in CreateOccupyWindow(). |
737 |
|
503.1.90
by Matthew Fuller
Comment up through setting various properties. |
738 |
|
739 |
/*
|
|
740 |
* Now start putting together the OK/Cancel/All buttons
|
|
741 |
*/
|
|
742 |
||
743 |
/* Background for them is hardcoded */
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
744 |
GetColor(Scr->Monochrome, &(occupyButtoncp.back), "gray50"); |
503.1.90
by Matthew Fuller
Comment up through setting various properties. |
745 |
|
746 |
/* Foreground (not used here) is too */
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
747 |
occupyButtoncp.fore = Scr->White; |
503.1.90
by Matthew Fuller
Comment up through setting various properties. |
748 |
|
749 |
/* Override (probably historical */
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
750 |
if(!Scr->BeNiceToColormap) { |
751 |
GetShadeColors(&occupyButtoncp); |
|
752 |
}
|
|
753 |
||
503.1.90
by Matthew Fuller
Comment up through setting various properties. |
754 |
/* Make 'em */
|
503.1.78
by Matthew Fuller
Localize a bunch of vars in CreateOccupyWindow(). |
755 |
{
|
756 |
Window tw; |
|
757 |
||
758 |
tw = XCreateSimpleWindow(dpy, w, Dummy, Dummy, Dummy, Dummy, 0, |
|
759 |
Scr->Black, occupyButtoncp.back); |
|
760 |
XMapWindow(dpy, tw); |
|
761 |
occwin->OK = tw; |
|
762 |
||
763 |
tw = XCreateSimpleWindow(dpy, w, Dummy, Dummy, Dummy, Dummy, 0, |
|
764 |
Scr->Black, occupyButtoncp.back); |
|
765 |
XMapWindow(dpy, tw); |
|
766 |
occwin->cancel = tw; |
|
767 |
||
768 |
tw = XCreateSimpleWindow(dpy, w, Dummy, Dummy, Dummy, Dummy, 0, |
|
769 |
Scr->Black, occupyButtoncp.back); |
|
770 |
XMapWindow(dpy, tw); |
|
771 |
occwin->allworkspc = tw; |
|
772 |
}
|
|
773 |
||
503.1.90
by Matthew Fuller
Comment up through setting various properties. |
774 |
|
505.1.1
by Matthew Fuller
Replace XSetStandardProperties(); XSetWMHints() calls with |
775 |
/* Setup various window properties */
|
503.1.78
by Matthew Fuller
Localize a bunch of vars in CreateOccupyWindow(). |
776 |
{
|
777 |
XSizeHints sizehints; |
|
505.1.1
by Matthew Fuller
Replace XSetStandardProperties(); XSetWMHints() calls with |
778 |
XWMHints wmhints; |
503.1.90
by Matthew Fuller
Comment up through setting various properties. |
779 |
|
514.1.5
by Matthew Fuller
Go ahead and set the size to max as well. Resizing the occupy window |
780 |
sizehints.flags = PBaseSize | PMinSize | PMaxSize; |
512.1.10
by Matthew Fuller
De-bogusize the size hints for the Occupy window. The principle |
781 |
sizehints.min_width = width; |
782 |
sizehints.min_height = height; |
|
783 |
sizehints.base_width = width; |
|
784 |
sizehints.base_height = height; |
|
514.1.5
by Matthew Fuller
Go ahead and set the size to max as well. Resizing the occupy window |
785 |
sizehints.max_width = width; |
786 |
sizehints.max_height = height; |
|
503.1.90
by Matthew Fuller
Comment up through setting various properties. |
787 |
|
503.1.78
by Matthew Fuller
Localize a bunch of vars in CreateOccupyWindow(). |
788 |
wmhints.flags = InputHint | StateHint; |
789 |
wmhints.input = True; |
|
790 |
wmhints.initial_state = NormalState; |
|
505.1.1
by Matthew Fuller
Replace XSetStandardProperties(); XSetWMHints() calls with |
791 |
|
792 |
XmbSetWMProperties(dpy, w, occwin->name, occwin->icon_name, |
|
505.1.6
by Matthew Fuller
make indent |
793 |
NULL, 0, &sizehints, &wmhints, NULL); |
503.1.78
by Matthew Fuller
Localize a bunch of vars in CreateOccupyWindow(). |
794 |
}
|
795 |
||
503.1.91
by Matthew Fuller
Comment a little further, and move an assignment up way earlier. |
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 |
*/
|
|
512.1.7
by Matthew Fuller
Add a new AddWindow() type for the Occupy window. |
802 |
tmp_win = AddWindow(w, AWT_OCCUPY, Scr->iconmgr, Scr->currentvs); |
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
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 |
||
503.1.91
by Matthew Fuller
Comment a little further, and move an assignment up way earlier. |
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 |
*/
|
|
503.1.78
by Matthew Fuller
Localize a bunch of vars in CreateOccupyWindow(). |
818 |
{
|
819 |
unsigned long attrmask; |
|
820 |
XSetWindowAttributes attr; |
|
821 |
XWindowAttributes wattr; |
|
822 |
||
823 |
attr.cursor = Scr->ButtonCursor; |
|
824 |
attrmask = CWCursor; |
|
825 |
XChangeWindowAttributes(dpy, w, attrmask, &attr); |
|
826 |
||
827 |
XGetWindowAttributes(dpy, w, &wattr); |
|
828 |
attrmask = wattr.your_event_mask | KeyPressMask | KeyReleaseMask |
|
829 |
| ExposureMask; |
|
830 |
XSelectInput(dpy, w, attrmask); |
|
831 |
}
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
832 |
|
503.1.93
by Matthew Fuller
Comment this setting up of events and contexts, and use macros to |
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 |
||
503.1.81
by Matthew Fuller
These two uses of ws are independent, so move one into the existing |
846 |
for(WorkSpace *ws = Scr->workSpaceMgr.workSpaceList |
847 |
; ws != NULL ; ws = ws->next) { |
|
503.1.93
by Matthew Fuller
Comment this setting up of events and contexts, and use macros to |
848 |
BTN_IPT_CTX(occwin->obuttonw[ws->number]); |
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
849 |
}
|
503.1.91
by Matthew Fuller
Comment a little further, and move an assignment up way earlier. |
850 |
|
503.1.93
by Matthew Fuller
Comment this setting up of events and contexts, and use macros to |
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
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
857 |
|
503.1.94
by Matthew Fuller
Little commenting toward the end. |
858 |
|
859 |
/* Mark that we're not mapped */
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
860 |
SetMapStateProp(tmp_win, WithdrawnState); |
503.1.94
by Matthew Fuller
Little commenting toward the end. |
861 |
|
862 |
/* Now call that func that sizes all the buttons */
|
|
863 |
ResizeOccupyWindow(tmp_win); |
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
864 |
}
|
865 |
||
866 |
||
503.1.75
by Matthew Fuller
Quick comment on the last couple functions. |
867 |
/*
|
503.1.102
by Matthew Fuller
Rearrange the functions in occupation.c so they're ordered and grouped |
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 |
*/
|
|
873 |
void
|
|
874 |
ResizeOccupyWindow(TwmWindow *win) |
|
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 |
||
514.1.3
by Matthew Fuller
Stash up the minimum size for the window and bail out of Resize early |
884 |
/* Floor at the original size */
|
885 |
neww = MAX(win->attr.width, occwin->minwidth); |
|
886 |
newh = MAX(win->attr.height, occwin->minheight); |
|
503.1.102
by Matthew Fuller
Rearrange the functions in occupation.c so they're ordered and grouped |
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 |
||
514.1.4
by Matthew Fuller
Don't call PAintOccupyWindow() at the end of the resize operation. It |
946 |
/* Don't need to repaint it; it'll get expose events */
|
503.1.102
by Matthew Fuller
Rearrange the functions in occupation.c so they're ordered and grouped |
947 |
}
|
948 |
||
949 |
||
950 |
/*
|
|
503.1.75
by Matthew Fuller
Quick comment on the last couple functions. |
951 |
* Draw the window when we need to (e.g., on expose)
|
952 |
*/
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
953 |
void
|
954 |
PaintOccupyWindow(void) |
|
955 |
{
|
|
956 |
WorkSpace *ws; |
|
957 |
OccupyWindow *occwin; |
|
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]; |
|
503.1.100
by Matthew Fuller
Use intermediate vars for these states, instead of duplicating the |
968 |
ButtonState bs = (occwin->tmpOccupation & (1 << ws->number)) ? on : off; |
969 |
||
970 |
PaintWsButton(OCCUPYWINDOW, NULL, bw, ws->label, ws->cp, bs); |
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
971 |
}
|
972 |
PaintWsButton(OCCUPYBUTTON, NULL, occwin->OK, ok_string, |
|
973 |
occupyButtoncp, off); |
|
974 |
PaintWsButton(OCCUPYBUTTON, NULL, occwin->cancel, cancel_string, |
|
975 |
occupyButtoncp, off); |
|
976 |
PaintWsButton(OCCUPYBUTTON, NULL, occwin->allworkspc, everywhere_string, |
|
977 |
occupyButtoncp, off); |
|
978 |
}
|
|
979 |
||
980 |
||
981 |
/*
|
|
503.1.102
by Matthew Fuller
Rearrange the functions in occupation.c so they're ordered and grouped |
982 |
* Somebody clicked in the Occupy window
|
983 |
*/
|
|
984 |
void
|
|
985 |
OccupyHandleButtonEvent(XEvent *event) |
|
986 |
{
|
|
987 |
WorkSpace *ws; |
|
988 |
OccupyWindow *occupyW; |
|
989 |
Window buttonW; |
|
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, |
|
1012 |
ButtonPressMask | ButtonReleaseMask, |
|
1013 |
GrabModeAsync, GrabModeAsync, |
|
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) { |
|
1064 |
XUngrabPointer(dpy, CurrentTime); |
|
1065 |
}
|
|
1066 |
}
|
|
1067 |
||
1068 |
||
1069 |
/*
|
|
1070 |
* f.occupy backend - pop up Occupy control for some window
|
|
1071 |
*/
|
|
1072 |
void
|
|
1073 |
Occupy(TwmWindow *twm_win) |
|
1074 |
{
|
|
1075 |
int x, y; |
|
1076 |
unsigned int width, height; |
|
1077 |
Window w; |
|
1078 |
struct OccupyWindow *occupyWindow; |
|
1079 |
TwmWindow *occupy_twm; |
|
1080 |
||
1081 |
/* Don't pop up on stuff we can't change */
|
|
1082 |
if(!CanChangeOccupation(&twm_win)) { |
|
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 */
|
|
1092 |
XGetGeometry(dpy, w, &JunkRoot, &JunkX, &JunkY, &width, &height, |
|
1093 |
&JunkBW, &JunkDepth); |
|
1094 |
XQueryPointer(dpy, Scr->Root, &JunkRoot, &JunkRoot, &JunkX, &JunkY, |
|
1095 |
&x, &y, &JunkMask); |
|
614.1.18
by Maxime Soulé
f.occupy window now uses layout |
1096 |
|
1097 |
occupy_twm = occupyWindow->twm_win; |
|
1098 |
occupy_twm->occupation = twm_win->occupation; |
|
1099 |
||
1100 |
width += 2 * (occupy_twm->frame_bw3D + occupy_twm->frame_bw); |
|
1101 |
height += 2 * (occupy_twm->frame_bw3D + occupy_twm->frame_bw); |
|
503.1.102
by Matthew Fuller
Rearrange the functions in occupation.c so they're ordered and grouped |
1102 |
x -= (width / 2); |
1103 |
y -= (height / 2); |
|
614.1.18
by Maxime Soulé
f.occupy window now uses layout |
1104 |
|
1105 |
/* Clip to screen */
|
|
1106 |
ConstrainByLayout(Scr->BorderedLayout, -1, &x, width, &y, height); |
|
503.1.102
by Matthew Fuller
Rearrange the functions in occupation.c so they're ordered and grouped |
1107 |
|
1108 |
/* Move the occupy window to where it should be */
|
|
1109 |
if(occupy_twm->parent_vs != twm_win->parent_vs) { |
|
1110 |
occupy_twm->vs = twm_win->parent_vs; |
|
1111 |
occupy_twm->frame_x = x; |
|
1112 |
occupy_twm->frame_y = y; |
|
507.1.8
by Matthew Fuller
Leave a comment about a possibly-questionable function usage. |
1113 |
/*
|
1114 |
* XXX Should this be using DisplayWin() like everything else,
|
|
1115 |
* rather than manually grubbing beneath it?
|
|
1116 |
*/
|
|
503.1.102
by Matthew Fuller
Rearrange the functions in occupation.c so they're ordered and grouped |
1117 |
ReparentFrameAndIcon(occupy_twm); |
1118 |
}
|
|
1119 |
else { |
|
1120 |
XMoveWindow(dpy, occupyWindow->twm_win->frame, x, y); |
|
1121 |
}
|
|
1122 |
||
1123 |
/* And show it */
|
|
1124 |
SetMapStateProp(occupy_twm, NormalState); |
|
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" */
|
|
1129 |
OtpSetPriority(occupy_twm, WinWin, 0, Above); |
|
1130 |
||
1131 |
/* Mark it shown, and stash what window we're showing it for */
|
|
1132 |
occupyWindow->twm_win->mapped = true; |
|
1133 |
occupyWin = twm_win; |
|
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 |
*/
|
|
1154 |
void
|
|
1155 |
ChangeOccupation(TwmWindow *tmp_win, int newoccupation) |
|
1156 |
{
|
|
1157 |
TwmWindow *t; |
|
1158 |
WorkSpace *ws; |
|
1159 |
int oldoccupation; |
|
1160 |
int changedoccupation; |
|
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 */
|
|
511.1.9
by Matthew Fuller
Use mask_out_event{_mask}() and restore_mask() in place of manually |
1174 |
eventMask = mask_out_event(tmp_win->w, PropertyChangeMask); |
503.1.102
by Matthew Fuller
Rearrange the functions in occupation.c so they're ordered and grouped |
1175 |
|
1176 |
len = GetPropertyFromMask(tmp_win->occupation, &namelist); |
|
1177 |
XChangeProperty(dpy, tmp_win->w, XA_WM_OCCUPATION, XA_STRING, 8, |
|
1178 |
PropModeReplace, (unsigned char *) namelist, len); |
|
1179 |
free(namelist); |
|
1180 |
#ifdef EWMH
|
|
1181 |
EwmhSet_NET_WM_DESKTOP(tmp_win); |
|
1182 |
#endif
|
|
1183 |
||
1184 |
/* Reset event mask */
|
|
511.1.9
by Matthew Fuller
Use mask_out_event{_mask}() and restore_mask() in place of manually |
1185 |
restore_mask(tmp_win->w, eventMask); |
503.1.102
by Matthew Fuller
Rearrange the functions in occupation.c so they're ordered and grouped |
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; |
|
1204 |
AddIconManager(tmp_win); |
|
1205 |
tmp_win->occupation = newoccupation; |
|
1206 |
RemoveIconManager(tmp_win); |
|
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; |
|
1242 |
RemoveWindowFromRegion(tmp_win); |
|
1243 |
if(PlaceWindowInRegion(tmp_win, &final_x, &final_y)) { |
|
1244 |
XMoveWindow(dpy, tmp_win->frame, final_x, final_y); |
|
1245 |
}
|
|
1246 |
}
|
|
1247 |
break; |
|
1248 |
}
|
|
1249 |
}
|
|
1250 |
||
511.1.9
by Matthew Fuller
Use mask_out_event{_mask}() and restore_mask() in place of manually |
1251 |
/* Now set the WM_OCCUPATION property */
|
503.1.102
by Matthew Fuller
Rearrange the functions in occupation.c so they're ordered and grouped |
1252 |
{
|
1253 |
char *namelist; |
|
1254 |
int len; |
|
1255 |
long eventMask; |
|
1256 |
||
511.1.9
by Matthew Fuller
Use mask_out_event{_mask}() and restore_mask() in place of manually |
1257 |
eventMask = mask_out_event(tmp_win->w, PropertyChangeMask); |
503.1.102
by Matthew Fuller
Rearrange the functions in occupation.c so they're ordered and grouped |
1258 |
|
1259 |
len = GetPropertyFromMask(newoccupation, &namelist); |
|
1260 |
XChangeProperty(dpy, tmp_win->w, XA_WM_OCCUPATION, XA_STRING, 8, |
|
1261 |
PropModeReplace, (unsigned char *) namelist, len); |
|
1262 |
free(namelist); |
|
1263 |
#ifdef EWMH
|
|
1264 |
EwmhSet_NET_WM_DESKTOP(tmp_win); |
|
1265 |
#endif
|
|
1266 |
||
511.1.9
by Matthew Fuller
Use mask_out_event{_mask}() and restore_mask() in place of manually |
1267 |
restore_mask(tmp_win->w, eventMask); |
503.1.102
by Matthew Fuller
Rearrange the functions in occupation.c so they're ordered and grouped |
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 |
*/
|
|
1281 |
if(!WMapWindowMayBeAdded(tmp_win)) { |
|
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 |
*/
|
|
1292 |
if(oldoccupation == fullOccupation) { |
|
1293 |
oldoccupation = 0; |
|
1294 |
}
|
|
1295 |
}
|
|
1296 |
||
1297 |
/* Flip the ones that need flipping */
|
|
1298 |
changedoccupation = oldoccupation ^ newoccupation; |
|
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 */
|
|
510.1.90
by Matthew Fuller
Rename several of these funcs for adding/removing windows to the WSM |
1304 |
WMapAddWindowToWorkspace(tmp_win, ws); |
503.1.102
by Matthew Fuller
Rearrange the functions in occupation.c so they're ordered and grouped |
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 |
*/
|
|
510.1.90
by Matthew Fuller
Rename several of these funcs for adding/removing windows to the WSM |
1312 |
WMapRemoveWindowFromWorkspace(tmp_win, ws); |
503.1.102
by Matthew Fuller
Rearrange the functions in occupation.c so they're ordered and grouped |
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 |
*/
|
|
1350 |
static bool |
|
1351 |
CanChangeOccupation(TwmWindow **twm_winp) |
|
1352 |
{
|
|
1353 |
TwmWindow *twm_win; |
|
1354 |
||
1355 |
/* No workspaces config'd? Changing is nonsensical. */
|
|
1356 |
if(!Scr->workSpaceManagerActive) { |
|
1357 |
return false; |
|
1358 |
}
|
|
1359 |
||
512.1.4
by Matthew Fuller
Fix up losing the occupation window by iconifying it. |
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) { |
|
503.1.102
by Matthew Fuller
Rearrange the functions in occupation.c so they're ordered and grouped |
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 |
*/
|
|
1394 |
twm_win = GetTwmWindow(twm_win->group); |
|
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 |
*/
|
|
1411 |
bool
|
|
1412 |
AddToClientsList(char *workspace, char *client) |
|
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 |
/*
|
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
1444 |
* Turn a ctwm.workspace resource string into an occupation mask. n.b.;
|
1445 |
* this changes the 'res' arg in-place.
|
|
1446 |
*/
|
|
1447 |
static int |
|
1448 |
GetMaskFromResource(TwmWindow *win, char *res) |
|
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 |
||
1491 |
ws = GetWorkspace(wrkSpcName); |
|
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 |
*/
|
|
1523 |
unsigned int |
|
1524 |
GetMaskFromProperty(unsigned char *_prop, unsigned long len) |
|
1525 |
{
|
|
503.1.103
by Matthew Fuller
Use safe_strncpy() here to be sure we can't overflow the buffer. |
1526 |
char wrkSpcName[256]; |
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
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) { |
|
503.1.103
by Matthew Fuller
Use safe_strncpy() here to be sure we can't overflow the buffer. |
1536 |
/* If you have WS names longer than 256 chars, that's just Too Bad */
|
1537 |
safe_strncpy(wrkSpcName, prop, 256); |
|
503.1.62
by Matthew Fuller
Pull piles of occupation handling out of workmgr.c and into a new |
1538 |
l += strlen(prop) + 1; |
1539 |
prop += strlen(prop) + 1; |
|
1540 |
if(strcmp(wrkSpcName, "all") == 0) { |
|
1541 |
mask = fullOccupation; |
|
1542 |
break; |
|
1543 |
}
|
|
1544 |
||
1545 |
ws = GetWorkspace(wrkSpcName); |
|
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 |
*/
|
|
1570 |
int
|
|
1571 |
GetPropertyFromMask(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
|
|
1624 |
static char * |
|
1625 |
mk_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
|