523.1.1
by Matthew Fuller
Inagurate a win_utils.c with GetWindowSizeHints(). |
1 |
/*
|
2 |
* Window-handling utility funcs
|
|
3 |
*/
|
|
4 |
||
5 |
#include "ctwm.h" |
|
6 |
||
7 |
#include <stdio.h> |
|
523.1.10
by Matthew Fuller
Move {Get,Free}WMPropertyString into win_utils. |
8 |
#include <stdlib.h> |
9 |
||
10 |
#include <X11/Xatom.h> |
|
11 |
||
12 |
#include "add_window.h" // NoName |
|
523.1.2
by Matthew Fuller
Move FetchWmProtocols() over to win_utils as well. |
13 |
#include "ctwm_atoms.h" |
523.1.23
by Matthew Fuller
Move DisplayPosition() off into win_utils as well. Stick some |
14 |
#include "drawing.h" |
539.1.18
by Matthew Fuller
WarpToWindow() also has no relation to menus and is broadly used |
15 |
#include "events.h" |
615.1.4
by Matthew Fuller
Split out all the code to support "window name has changed, do stuff |
16 |
#include "event_internal.h" // Temp? |
615.1.22
by Matthew Fuller
Add StrictWinNameEncoding support code. |
17 |
#ifdef EWMH
|
18 |
# include "ewmh_atoms.h"
|
|
19 |
#endif
|
|
523.1.20
by Matthew Fuller
Getting and setting WM_STATE props is pretty obviously a window util, |
20 |
#include "icons.h" |
625.1.1
by Matthew Fuller
Extract the adjustment of wmhints stuff into a separate function for |
21 |
#include "list.h" |
615.1.4
by Matthew Fuller
Split out all the code to support "window name has changed, do stuff |
22 |
#include "occupation.h" |
23 |
#include "otp.h" |
|
614.1.1
by Maxime Soulé
First step of xrandr integration |
24 |
#include "r_area.h" |
614.1.27
by Maxime Soulé
Monitor edge detection reworked: corrects some 1-pixel-wide-problems |
25 |
#include "r_area_list.h" |
614.2.4
by Matthew Fuller
r_layout.h includes r_structs.h, so including it in screen.h |
26 |
#include "r_layout.h" |
523.1.1
by Matthew Fuller
Inagurate a win_utils.c with GetWindowSizeHints(). |
27 |
#include "screen.h" |
523.1.24
by Matthew Fuller
Move these Pack/Push/Grid funcs into win_utils, since they're about |
28 |
#include "util.h" |
538.1.3
by Matthew Fuller
Rename the decorations*.h to win_decorations*.h. |
29 |
#include "win_decorations.h" |
539.1.18
by Matthew Fuller
WarpToWindow() also has no relation to menus and is broadly used |
30 |
#include "win_ops.h" |
523.1.1
by Matthew Fuller
Inagurate a win_utils.c with GetWindowSizeHints(). |
31 |
#include "win_utils.h" |
539.1.18
by Matthew Fuller
WarpToWindow() also has no relation to menus and is broadly used |
32 |
#include "workspace_utils.h" |
523.1.1
by Matthew Fuller
Inagurate a win_utils.c with GetWindowSizeHints(). |
33 |
|
34 |
||
35 |
/*
|
|
36 |
* Fill in size hints for a window from WM_NORMAL_HINTS prop.
|
|
37 |
*
|
|
38 |
* Formerly in add_window.c
|
|
39 |
*/
|
|
40 |
void
|
|
41 |
GetWindowSizeHints(TwmWindow *tmp) |
|
42 |
{
|
|
43 |
long supplied = 0; |
|
44 |
XSizeHints *hints = &tmp->hints; |
|
45 |
||
46 |
if(!XGetWMNormalHints(dpy, tmp->w, hints, &supplied)) { |
|
47 |
hints->flags = 0; |
|
48 |
}
|
|
49 |
||
50 |
if(hints->flags & PResizeInc) { |
|
51 |
if(hints->width_inc == 0) { |
|
52 |
hints->width_inc = 1; |
|
53 |
}
|
|
54 |
if(hints->height_inc == 0) { |
|
55 |
hints->height_inc = 1; |
|
56 |
}
|
|
57 |
}
|
|
58 |
||
59 |
if(!(supplied & PWinGravity) && (hints->flags & USPosition)) { |
|
60 |
static int gravs[] = { SouthEastGravity, SouthWestGravity, |
|
61 |
NorthEastGravity, NorthWestGravity |
|
62 |
};
|
|
63 |
int right = tmp->attr.x + tmp->attr.width + 2 * tmp->old_bw; |
|
64 |
int bottom = tmp->attr.y + tmp->attr.height + 2 * tmp->old_bw; |
|
65 |
hints->win_gravity = |
|
66 |
gravs[((Scr->rooth - bottom < |
|
67 |
tmp->title_height + 2 * tmp->frame_bw3D) ? 0 : 2) | |
|
68 |
((Scr->rootw - right < |
|
69 |
tmp->title_height + 2 * tmp->frame_bw3D) ? 0 : 1)]; |
|
70 |
hints->flags |= PWinGravity; |
|
71 |
}
|
|
72 |
||
73 |
/* Check for min size < max size */
|
|
74 |
if((hints->flags & (PMinSize | PMaxSize)) == (PMinSize | PMaxSize)) { |
|
75 |
if(hints->max_width < hints->min_width) { |
|
76 |
if(hints->max_width > 0) { |
|
77 |
hints->min_width = hints->max_width; |
|
78 |
}
|
|
79 |
else if(hints->min_width > 0) { |
|
80 |
hints->max_width = hints->min_width; |
|
81 |
}
|
|
82 |
else { |
|
83 |
hints->max_width = hints->min_width = 1; |
|
84 |
}
|
|
85 |
}
|
|
86 |
||
87 |
if(hints->max_height < hints->min_height) { |
|
88 |
if(hints->max_height > 0) { |
|
89 |
hints->min_height = hints->max_height; |
|
90 |
}
|
|
91 |
else if(hints->min_height > 0) { |
|
92 |
hints->max_height = hints->min_height; |
|
93 |
}
|
|
94 |
else { |
|
95 |
hints->max_height = hints->min_height = 1; |
|
96 |
}
|
|
97 |
}
|
|
98 |
}
|
|
99 |
}
|
|
523.1.2
by Matthew Fuller
Move FetchWmProtocols() over to win_utils as well. |
100 |
|
101 |
||
102 |
/*
|
|
103 |
* Fill in info from WM_PROTOCOLS property
|
|
104 |
*
|
|
105 |
* Formerly in add_window.c
|
|
106 |
*/
|
|
107 |
void
|
|
108 |
FetchWmProtocols(TwmWindow *tmp) |
|
109 |
{
|
|
110 |
unsigned long flags = 0L; |
|
111 |
Atom *protocols = NULL; |
|
112 |
int n; |
|
113 |
||
114 |
if(XGetWMProtocols(dpy, tmp->w, &protocols, &n)) { |
|
115 |
int i; |
|
116 |
Atom *ap; |
|
117 |
||
118 |
for(i = 0, ap = protocols; i < n; i++, ap++) { |
|
119 |
if(*ap == XA_WM_TAKE_FOCUS) { |
|
120 |
flags |= DoesWmTakeFocus; |
|
121 |
}
|
|
122 |
if(*ap == XA_WM_SAVE_YOURSELF) { |
|
123 |
flags |= DoesWmSaveYourself; |
|
124 |
}
|
|
125 |
if(*ap == XA_WM_DELETE_WINDOW) { |
|
126 |
flags |= DoesWmDeleteWindow; |
|
127 |
}
|
|
128 |
}
|
|
129 |
if(protocols) { |
|
130 |
XFree(protocols); |
|
131 |
}
|
|
132 |
}
|
|
133 |
tmp->protocols = flags; |
|
134 |
}
|
|
523.1.3
by Matthew Fuller
Move GetGravityOffsets() into win_utils and give it a more descriptive |
135 |
|
136 |
||
137 |
/*
|
|
138 |
* Figure signs for calculating location offsets for a window dependent
|
|
139 |
* on its gravity.
|
|
140 |
*
|
|
141 |
* Depending on how its gravity is set, offsets to window coordinates for
|
|
142 |
* e.g. border widths may need to move either down (right) or up (left).
|
|
143 |
* Or possibly not at all. So we write multipliers into passed vars for
|
|
144 |
* callers.
|
|
145 |
*
|
|
146 |
* Formerly in add_window.c
|
|
147 |
*/
|
|
148 |
void
|
|
149 |
GetGravityOffsets(TwmWindow *tmp, int *xp, int *yp) |
|
150 |
{
|
|
151 |
static struct _gravity_offset { |
|
152 |
int x, y; |
|
523.1.4
by Matthew Fuller
Use C99 designated initializer instead of hopefully-correct comments. |
153 |
} gravity_offsets[] = { |
154 |
[ForgetGravity] = { 0, 0 }, |
|
155 |
[NorthWestGravity] = { -1, -1 }, |
|
156 |
[NorthGravity] = { 0, -1 }, |
|
157 |
[NorthEastGravity] = { 1, -1 }, |
|
158 |
[WestGravity] = { -1, 0 }, |
|
159 |
[CenterGravity] = { 0, 0 }, |
|
160 |
[EastGravity] = { 1, 0 }, |
|
161 |
[SouthWestGravity] = { -1, 1 }, |
|
162 |
[SouthGravity] = { 0, 1 }, |
|
163 |
[SouthEastGravity] = { 1, 1 }, |
|
164 |
[StaticGravity] = { 0, 0 }, |
|
523.1.3
by Matthew Fuller
Move GetGravityOffsets() into win_utils and give it a more descriptive |
165 |
};
|
166 |
int g = ((tmp->hints.flags & PWinGravity) |
|
167 |
? tmp->hints.win_gravity : NorthWestGravity); |
|
168 |
||
169 |
if(g < ForgetGravity || g > StaticGravity) { |
|
170 |
*xp = *yp = 0; |
|
171 |
}
|
|
172 |
else { |
|
173 |
*xp = gravity_offsets[g].x; |
|
174 |
*yp = gravity_offsets[g].y; |
|
175 |
}
|
|
176 |
}
|
|
523.1.5
by Matthew Fuller
GetTwmWindow() is pretty obvious _utils fodder. |
177 |
|
178 |
||
179 |
/*
|
|
180 |
* Finds the TwmWindow structure associated with a Window (if any), or
|
|
181 |
* NULL.
|
|
182 |
*
|
|
183 |
* This is a relatively cheap function since it does not involve
|
|
184 |
* communication with the server. Probably faster than walking the list
|
|
185 |
* of TwmWindows, since the lookup is by a hash table.
|
|
523.1.9
by Matthew Fuller
Mark up GetTwmWindow() provenance. |
186 |
*
|
187 |
* Formerly in add_window.c
|
|
523.1.5
by Matthew Fuller
GetTwmWindow() is pretty obvious _utils fodder. |
188 |
*/
|
189 |
TwmWindow * |
|
190 |
GetTwmWindow(Window w) |
|
191 |
{
|
|
192 |
TwmWindow *twmwin; |
|
193 |
int stat; |
|
194 |
||
195 |
stat = XFindContext(dpy, w, TwmContext, (XPointer *)&twmwin); |
|
196 |
if(stat == XCNOENT) { |
|
197 |
twmwin = NULL; |
|
198 |
}
|
|
199 |
||
200 |
return twmwin; |
|
201 |
}
|
|
523.1.10
by Matthew Fuller
Move {Get,Free}WMPropertyString into win_utils. |
202 |
|
203 |
||
204 |
/***********************************************************************
|
|
205 |
*
|
|
206 |
* Procedure:
|
|
207 |
* GetWMPropertyString - Get Window Manager text property and
|
|
208 |
* convert it to a string.
|
|
209 |
*
|
|
210 |
* Returned Value:
|
|
211 |
* (char *) - pointer to the malloc'd string or NULL
|
|
212 |
*
|
|
213 |
* Inputs:
|
|
214 |
* w - the id of the window whose property is to be retrieved
|
|
215 |
* prop - property atom (typically WM_NAME or WM_ICON_NAME)
|
|
216 |
*
|
|
217 |
***********************************************************************
|
|
218 |
*
|
|
219 |
* Formerly in util.c
|
|
220 |
*/
|
|
544.1.5
by Matthew Fuller
Switch GetWMPropertyString() over to returning char * rather than |
221 |
char * |
523.1.10
by Matthew Fuller
Move {Get,Free}WMPropertyString into win_utils. |
222 |
GetWMPropertyString(Window w, Atom prop) |
223 |
{
|
|
224 |
XTextProperty text_prop; |
|
544.1.5
by Matthew Fuller
Switch GetWMPropertyString() over to returning char * rather than |
225 |
char *stringptr; |
523.1.10
by Matthew Fuller
Move {Get,Free}WMPropertyString into win_utils. |
226 |
|
544.1.2
by Matthew Fuller
GCC some remaining (void) return casts. |
227 |
XGetTextProperty(dpy, w, &text_prop, prop); |
615.1.10
by Matthew Fuller
Invert this test; if there's nothing, all we're gonna do is return the |
228 |
if(text_prop.value == NULL) { |
229 |
return NULL; |
|
230 |
}
|
|
231 |
||
615.1.11
by Matthew Fuller
Reindent after sense swap. |
232 |
if(text_prop.encoding == XA_STRING |
615.1.12
by Matthew Fuller
Enable accepting UTF8_STRING for the WM_NAME (and related) properties. |
233 |
|| text_prop.encoding == XA_UTF8_STRING |
615.1.11
by Matthew Fuller
Reindent after sense swap. |
234 |
|| text_prop.encoding == XA_COMPOUND_TEXT) { |
235 |
/* property is encoded as compound text - convert to locale string */
|
|
615.1.17
by Matthew Fuller
Move vars to the inner scope where they're used. |
236 |
char **text_list; |
237 |
int text_list_count; |
|
615.1.19
by Matthew Fuller
Split up declaring and using this var for coming changes. |
238 |
int status; |
239 |
||
615.1.22
by Matthew Fuller
Add StrictWinNameEncoding support code. |
240 |
/* Check historical strictness */
|
241 |
if(Scr->StrictWinNameEncoding) { |
|
242 |
bool fail = false; |
|
243 |
||
615.1.53
by Matthew Fuller
Add stricture checks for the _ICON_NAME properties too. |
244 |
if((prop == XA_WM_NAME || prop == XA_WM_ICON_NAME) |
615.1.22
by Matthew Fuller
Add StrictWinNameEncoding support code. |
245 |
&& text_prop.encoding != XA_STRING |
246 |
&& text_prop.encoding != XA_COMPOUND_TEXT) { |
|
247 |
fail = true; |
|
248 |
}
|
|
249 |
||
250 |
#ifdef EWMH
|
|
615.1.53
by Matthew Fuller
Add stricture checks for the _ICON_NAME properties too. |
251 |
if((prop == XA__NET_WM_NAME || prop == XA__NET_WM_ICON_NAME) |
615.1.22
by Matthew Fuller
Add StrictWinNameEncoding support code. |
252 |
&& text_prop.encoding != XA_UTF8_STRING) { |
253 |
fail = true; |
|
254 |
}
|
|
255 |
#endif // EWMH |
|
256 |
||
257 |
if(fail) { |
|
258 |
fprintf(stderr, "%s: Invalid encoding for property %s " |
|
259 |
"of window 0x%lx\n", ProgramName, |
|
260 |
XGetAtomName(dpy, prop), w); |
|
261 |
XFree(text_prop.value); |
|
262 |
return NULL; |
|
263 |
}
|
|
264 |
}
|
|
265 |
||
615.1.19
by Matthew Fuller
Split up declaring and using this var for coming changes. |
266 |
|
267 |
status = XmbTextPropertyToTextList(dpy, &text_prop, &text_list, |
|
268 |
&text_list_count); |
|
615.1.16
by Matthew Fuller
Compress down these error cases into an early return. |
269 |
if(text_list_count == 0 |
270 |
|| text_list == NULL |
|
271 |
|| text_list[0] == NULL) { |
|
615.1.18
by Matthew Fuller
Comment these branches. |
272 |
// Got nothing
|
615.1.16
by Matthew Fuller
Compress down these error cases into an early return. |
273 |
XFree(text_prop.value); |
274 |
return NULL; |
|
615.1.11
by Matthew Fuller
Reindent after sense swap. |
275 |
}
|
276 |
else if(status < 0 || text_list_count < 0) { |
|
615.1.18
by Matthew Fuller
Comment these branches. |
277 |
// Got an error statuf
|
615.1.11
by Matthew Fuller
Reindent after sense swap. |
278 |
switch(status) { |
279 |
case XConverterNotFound: |
|
280 |
fprintf(stderr, |
|
281 |
"%s: Converter not found; unable to convert property %s of window ID %lx.\n", |
|
282 |
ProgramName, XGetAtomName(dpy, prop), w); |
|
283 |
break; |
|
284 |
case XNoMemory: |
|
285 |
fprintf(stderr, |
|
286 |
"%s: Insufficient memory; unable to convert property %s of window ID %lx.\n", |
|
287 |
ProgramName, XGetAtomName(dpy, prop), w); |
|
288 |
break; |
|
289 |
case XLocaleNotSupported: |
|
290 |
fprintf(stderr, |
|
291 |
"%s: Locale not supported; unable to convert property %s of window ID %lx.\n", |
|
292 |
ProgramName, XGetAtomName(dpy, prop), w); |
|
293 |
break; |
|
294 |
}
|
|
295 |
stringptr = NULL; |
|
296 |
/*
|
|
297 |
don't call XFreeStringList - text_list appears to have
|
|
298 |
invalid address if status is bad
|
|
299 |
XFreeStringList(text_list);
|
|
300 |
*/
|
|
523.1.10
by Matthew Fuller
Move {Get,Free}WMPropertyString into win_utils. |
301 |
}
|
302 |
else { |
|
615.1.18
by Matthew Fuller
Comment these branches. |
303 |
// Actually got the data!
|
615.1.11
by Matthew Fuller
Reindent after sense swap. |
304 |
stringptr = strdup(text_list[0]); |
305 |
XFreeStringList(text_list); |
|
523.1.10
by Matthew Fuller
Move {Get,Free}WMPropertyString into win_utils. |
306 |
}
|
615.1.11
by Matthew Fuller
Reindent after sense swap. |
307 |
}
|
308 |
else { |
|
309 |
/* property is encoded in a format we don't understand */
|
|
310 |
fprintf(stderr, |
|
311 |
"%s: Encoding not STRING or COMPOUND_TEXT; unable to decode property %s of window ID %lx.\n", |
|
312 |
ProgramName, XGetAtomName(dpy, prop), w); |
|
313 |
stringptr = NULL; |
|
314 |
}
|
|
315 |
XFree(text_prop.value); |
|
523.1.10
by Matthew Fuller
Move {Get,Free}WMPropertyString into win_utils. |
316 |
|
317 |
return stringptr; |
|
318 |
}
|
|
319 |
||
320 |
||
321 |
/*
|
|
322 |
* Cleanup something stored that we got from the above originally.
|
|
323 |
*
|
|
324 |
* Formerly in util.c
|
|
325 |
*/
|
|
326 |
void
|
|
327 |
FreeWMPropertyString(char *prop) |
|
328 |
{
|
|
544.1.3
by Matthew Fuller
Don't need to cast this to the type it already is. |
329 |
if(prop && prop != NoName) { |
523.1.10
by Matthew Fuller
Move {Get,Free}WMPropertyString into win_utils. |
330 |
free(prop); |
331 |
}
|
|
332 |
}
|
|
523.1.16
by Matthew Fuller
Move visible() into win_utils. |
333 |
|
334 |
||
335 |
/*
|
|
336 |
* Window mapped on some virtual screen?
|
|
337 |
*
|
|
338 |
* Formerly in util.c
|
|
339 |
*/
|
|
340 |
bool
|
|
341 |
visible(const TwmWindow *tmp_win) |
|
342 |
{
|
|
343 |
return (tmp_win->vs != NULL); |
|
344 |
}
|
|
523.1.18
by Matthew Fuller
Move the masking funcs into win_util and GC util.h from the files only |
345 |
|
346 |
||
347 |
/*
|
|
348 |
* Various code paths do a dance of "mask off notifications of event type
|
|
349 |
* ; do something that triggers that event (but we're doing it, so we
|
|
350 |
* don't need the notification) ; restore previous mask". So have some
|
|
351 |
* util funcs to make it more visually obvious.
|
|
352 |
*
|
|
353 |
* e.g.:
|
|
354 |
* long prev_mask = mask_out_event(w, PropertyChangeMask);
|
|
355 |
* do_something_that_changes_properties();
|
|
356 |
* restore_mask(prev_mask);
|
|
357 |
*
|
|
358 |
* We're cheating a little with the -1 return on mask_out_event(), as
|
|
359 |
* that's theoretically valid for the data type. It's not as far as I
|
|
360 |
* can tell for X or us though; having all the bits set (well, I guess
|
|
361 |
* I'm assuming 2s-complement too) is pretty absurd, and there are only
|
|
362 |
* 25 defined bits in Xlib, so even on 32-bit systems, it shouldn't fill
|
|
363 |
* up long.
|
|
364 |
*/
|
|
365 |
long
|
|
366 |
mask_out_event(Window w, long ignore_event) |
|
367 |
{
|
|
368 |
XWindowAttributes wattr; |
|
369 |
||
370 |
/* Get current mask */
|
|
371 |
if(XGetWindowAttributes(dpy, w, &wattr) == 0) { |
|
372 |
return -1; |
|
373 |
}
|
|
374 |
||
375 |
/*
|
|
376 |
* If we're ignoring nothing, nothing to do. This is probably not
|
|
377 |
* strictly speaking a useful thing to ask for in general, but it's
|
|
378 |
* the right thing for us to do if we're asked to do nothing.
|
|
379 |
*/
|
|
380 |
if(ignore_event == 0) { |
|
381 |
return wattr.your_event_mask; |
|
382 |
}
|
|
383 |
||
384 |
/* Delegate */
|
|
385 |
return mask_out_event_mask(w, ignore_event, wattr.your_event_mask); |
|
386 |
}
|
|
387 |
||
388 |
long
|
|
389 |
mask_out_event_mask(Window w, long ignore_event, long curmask) |
|
390 |
{
|
|
391 |
/* Set to the current, minus what we're wanting to ignore */
|
|
392 |
XSelectInput(dpy, w, (curmask & ~ignore_event)); |
|
393 |
||
394 |
/* Return what it was */
|
|
395 |
return curmask; |
|
396 |
}
|
|
397 |
||
398 |
int
|
|
399 |
restore_mask(Window w, long restore) |
|
400 |
{
|
|
401 |
return XSelectInput(dpy, w, restore); |
|
402 |
}
|
|
523.1.20
by Matthew Fuller
Getting and setting WM_STATE props is pretty obviously a window util, |
403 |
|
404 |
||
405 |
/*
|
|
406 |
* Setting and getting WM_STATE property.
|
|
407 |
*
|
|
408 |
* x-ref ICCCM section 4.1.3.1
|
|
409 |
* https://tronche.com/gui/x/icccm/sec-4.html#s-4.1.3.1
|
|
523.1.21
by Matthew Fuller
Leave comment asking for renaming. |
410 |
*
|
411 |
* XXX These should probably be named more alike, as they're
|
|
412 |
* complementary ops.
|
|
523.1.20
by Matthew Fuller
Getting and setting WM_STATE props is pretty obviously a window util, |
413 |
*/
|
414 |
void
|
|
415 |
SetMapStateProp(TwmWindow *tmp_win, int state) |
|
416 |
{
|
|
417 |
unsigned long data[2]; /* "suggested" by ICCCM version 1 */ |
|
418 |
||
419 |
data[0] = (unsigned long) state; |
|
420 |
data[1] = (unsigned long)(tmp_win->iconify_by_unmapping ? None : |
|
421 |
(tmp_win->icon ? tmp_win->icon->w : None)); |
|
422 |
||
423 |
XChangeProperty(dpy, tmp_win->w, XA_WM_STATE, XA_WM_STATE, 32, |
|
424 |
PropModeReplace, (unsigned char *) data, 2); |
|
425 |
}
|
|
426 |
||
427 |
||
428 |
bool
|
|
429 |
GetWMState(Window w, int *statep, Window *iwp) |
|
430 |
{
|
|
431 |
Atom actual_type; |
|
432 |
int actual_format; |
|
433 |
unsigned long nitems, bytesafter; |
|
434 |
unsigned long *datap = NULL; |
|
435 |
bool retval = false; |
|
436 |
||
437 |
if(XGetWindowProperty(dpy, w, XA_WM_STATE, 0L, 2L, False, XA_WM_STATE, |
|
438 |
&actual_type, &actual_format, &nitems, &bytesafter, |
|
439 |
(unsigned char **) &datap) != Success || !datap) { |
|
440 |
return false; |
|
441 |
}
|
|
442 |
||
443 |
if(nitems <= 2) { /* "suggested" by ICCCM version 1 */ |
|
444 |
*statep = (int) datap[0]; |
|
445 |
*iwp = (Window) datap[1]; |
|
446 |
retval = true; |
|
447 |
}
|
|
448 |
||
449 |
XFree(datap); |
|
450 |
return retval; |
|
451 |
}
|
|
523.1.23
by Matthew Fuller
Move DisplayPosition() off into win_utils as well. Stick some |
452 |
|
453 |
||
454 |
/*
|
|
455 |
* Display a window's position in the dimensions window. This is used
|
|
456 |
* during various window positioning (during new window popups, moves,
|
|
457 |
* etc).
|
|
458 |
*
|
|
459 |
* This reuses the same window for the position as is used during
|
|
460 |
* resizing for the dimesions of the window in DisplaySize(). The
|
|
461 |
* innards of the funcs can probably be collapsed together a little, and
|
|
462 |
* the higher-level knowledge of Scr->SizeWindow (e.g., for unmapping
|
|
463 |
* after ths op is done) should probably be encapsulated a bit better.
|
|
464 |
*/
|
|
465 |
void
|
|
466 |
DisplayPosition(const TwmWindow *_unused_tmp_win, int x, int y) |
|
467 |
{
|
|
468 |
char str [100]; |
|
469 |
char signx = '+'; |
|
470 |
char signy = '+'; |
|
471 |
||
472 |
if(x < 0) { |
|
473 |
x = -x; |
|
474 |
signx = '-'; |
|
475 |
}
|
|
476 |
if(y < 0) { |
|
477 |
y = -y; |
|
478 |
signy = '-'; |
|
479 |
}
|
|
480 |
sprintf(str, " %c%-4d %c%-4d ", signx, x, signy, y); |
|
481 |
XRaiseWindow(dpy, Scr->SizeWindow); |
|
482 |
||
483 |
Draw3DBorder(Scr->SizeWindow, 0, 0, |
|
484 |
Scr->SizeStringOffset + Scr->SizeStringWidth + SIZE_HINDENT, |
|
485 |
Scr->SizeFont.height + SIZE_VINDENT * 2, |
|
486 |
2, Scr->DefaultC, off, false, false); |
|
487 |
||
488 |
FB(Scr->DefaultC.fore, Scr->DefaultC.back); |
|
489 |
XmbDrawImageString(dpy, Scr->SizeWindow, Scr->SizeFont.font_set, |
|
490 |
Scr->NormalGC, Scr->SizeStringOffset, |
|
551
by Matthew Fuller
make indent |
491 |
Scr->SizeFont.ascent + SIZE_VINDENT, str, 13); |
523.1.23
by Matthew Fuller
Move DisplayPosition() off into win_utils as well. Stick some |
492 |
}
|
523.1.24
by Matthew Fuller
Move these Pack/Push/Grid funcs into win_utils, since they're about |
493 |
|
614.1.28
by Maxime Soulé
If CenterFeedbackWindow, feedback window centered in current monitor |
494 |
void
|
495 |
MoveResizeSizeWindow(int x, int y, unsigned int width, unsigned int height) |
|
496 |
{
|
|
497 |
XResizeWindow(dpy, Scr->SizeWindow, width, height); |
|
498 |
||
499 |
if(Scr->CenterFeedbackWindow) { |
|
500 |
RArea monitor = RLayoutGetAreaAtXY(Scr->BorderedLayout, x, y); |
|
501 |
||
502 |
XMoveWindow(dpy, Scr->SizeWindow, |
|
503 |
monitor.x + monitor.width / 2 - width / 2, |
|
504 |
monitor.y + monitor.height / 2 - height / 2); |
|
505 |
}
|
|
506 |
}
|
|
507 |
||
523.1.24
by Matthew Fuller
Move these Pack/Push/Grid funcs into win_utils, since they're about |
508 |
|
509 |
/*
|
|
510 |
* Various funcs for adjusting coordinates for windows based on
|
|
511 |
* resistances etc.
|
|
512 |
*
|
|
513 |
* XXX In desperate need of better commenting.
|
|
514 |
*/
|
|
614.1.12
by Maxime Soulé
f.fill, f.pack & f.jump* functions detect inter-monitors edges |
515 |
static void |
614.1.93
by Matthew Fuller
const-ify the callback func for RAreaListForeach(). |
516 |
_tryToPack(RArea *final, const RArea *cur_win) |
614.1.27
by Maxime Soulé
Monitor edge detection reworked: corrects some 1-pixel-wide-problems |
517 |
{
|
518 |
if(final->x >= cur_win->x + cur_win->width) { |
|
519 |
return; |
|
520 |
}
|
|
521 |
if(final->y >= cur_win->y + cur_win->height) { |
|
522 |
return; |
|
523 |
}
|
|
524 |
if(final->x + final->width <= cur_win->x) { |
|
525 |
return; |
|
526 |
}
|
|
527 |
if(final->y + final->height <= cur_win->y) { |
|
528 |
return; |
|
529 |
}
|
|
530 |
||
531 |
if(final->x + Scr->MovePackResistance > cur_win->x + |
|
532 |
cur_win->width) { /* left */ |
|
533 |
final->x = MAX(final->x, cur_win->x + cur_win->width); |
|
534 |
return; |
|
535 |
}
|
|
536 |
if(final->x + final->width < cur_win->x + |
|
537 |
Scr->MovePackResistance) { /* right */ |
|
538 |
final->x = MIN(final->x, cur_win->x - final->width); |
|
539 |
return; |
|
540 |
}
|
|
541 |
if(final->y + Scr->MovePackResistance > cur_win->y + |
|
542 |
cur_win->height) { /* top */ |
|
543 |
final->y = MAX(final->y, cur_win->y + cur_win->height); |
|
544 |
return; |
|
545 |
}
|
|
546 |
if(final->y + final->height < cur_win->y + |
|
547 |
Scr->MovePackResistance) { /* bottom */ |
|
548 |
final->y = MIN(final->y, cur_win->y - final->height); |
|
549 |
}
|
|
550 |
}
|
|
551 |
||
614.1.63
by Matthew Fuller
The RAreaListForeach() callback's return value is used as a boolean, |
552 |
static bool |
614.1.93
by Matthew Fuller
const-ify the callback func for RAreaListForeach(). |
553 |
_tryToPackVsEachMonitor(const RArea *monitor_area, void *vfinal) |
614.1.27
by Maxime Soulé
Monitor edge detection reworked: corrects some 1-pixel-wide-problems |
554 |
{
|
555 |
_tryToPack((RArea *)vfinal, monitor_area); |
|
614.1.63
by Matthew Fuller
The RAreaListForeach() callback's return value is used as a boolean, |
556 |
return false; |
614.1.12
by Maxime Soulé
f.fill, f.pack & f.jump* functions detect inter-monitors edges |
557 |
}
|
558 |
||
523.1.24
by Matthew Fuller
Move these Pack/Push/Grid funcs into win_utils, since they're about |
559 |
void
|
560 |
TryToPack(TwmWindow *tmp_win, int *x, int *y) |
|
561 |
{
|
|
562 |
TwmWindow *t; |
|
614.1.12
by Maxime Soulé
f.fill, f.pack & f.jump* functions detect inter-monitors edges |
563 |
RArea cur_win; |
614.1.27
by Maxime Soulé
Monitor edge detection reworked: corrects some 1-pixel-wide-problems |
564 |
RArea final = RAreaNew(*x, *y, |
565 |
tmp_win->frame_width + 2 * tmp_win->frame_bw, |
|
566 |
tmp_win->frame_height + 2 * tmp_win->frame_bw); |
|
614.1.12
by Maxime Soulé
f.fill, f.pack & f.jump* functions detect inter-monitors edges |
567 |
|
568 |
/* Global layout is not a single rectangle, check against the
|
|
569 |
* monitor borders */
|
|
570 |
if(Scr->BorderedLayout->horiz->len > 1) { |
|
614.1.27
by Maxime Soulé
Monitor edge detection reworked: corrects some 1-pixel-wide-problems |
571 |
RAreaListForeach( |
572 |
Scr->BorderedLayout->monitors, _tryToPackVsEachMonitor, &final); |
|
614.1.12
by Maxime Soulé
f.fill, f.pack & f.jump* functions detect inter-monitors edges |
573 |
}
|
574 |
||
523.1.24
by Matthew Fuller
Move these Pack/Push/Grid funcs into win_utils, since they're about |
575 |
for(t = Scr->FirstWindow; t != NULL; t = t->next) { |
576 |
if(t == tmp_win) { |
|
577 |
continue; |
|
578 |
}
|
|
700.1.11
by Matthew Fuller
Hide these TwmWindow winbox-related fields behind an ifdef along with |
579 |
#ifdef WINBOX
|
523.1.24
by Matthew Fuller
Move these Pack/Push/Grid funcs into win_utils, since they're about |
580 |
if(t->winbox != tmp_win->winbox) { |
581 |
continue; |
|
582 |
}
|
|
700.1.11
by Matthew Fuller
Hide these TwmWindow winbox-related fields behind an ifdef along with |
583 |
#endif
|
523.1.24
by Matthew Fuller
Move these Pack/Push/Grid funcs into win_utils, since they're about |
584 |
if(t->vs != tmp_win->vs) { |
585 |
continue; |
|
586 |
}
|
|
587 |
if(!t->mapped) { |
|
588 |
continue; |
|
589 |
}
|
|
590 |
||
614.1.25
by Maxime Soulé
RArea struct is never malloc()ed anymore |
591 |
cur_win = RAreaNew(t->frame_x, t->frame_y, |
592 |
t->frame_width + 2 * t->frame_bw, |
|
593 |
t->frame_height + 2 * t->frame_bw); |
|
523.1.24
by Matthew Fuller
Move these Pack/Push/Grid funcs into win_utils, since they're about |
594 |
|
614.1.27
by Maxime Soulé
Monitor edge detection reworked: corrects some 1-pixel-wide-problems |
595 |
_tryToPack(&final, &cur_win); |
523.1.24
by Matthew Fuller
Move these Pack/Push/Grid funcs into win_utils, since they're about |
596 |
}
|
614.1.27
by Maxime Soulé
Monitor edge detection reworked: corrects some 1-pixel-wide-problems |
597 |
|
598 |
*x = final.x; |
|
599 |
*y = final.y; |
|
523.1.24
by Matthew Fuller
Move these Pack/Push/Grid funcs into win_utils, since they're about |
600 |
}
|
601 |
||
602 |
||
603 |
/*
|
|
604 |
* Directionals for TryToPush_be(). These differ from the specs for
|
|
605 |
* jump/pack/fill in functions. because there's an indeterminate option.
|
|
606 |
*/
|
|
607 |
typedef enum { |
|
608 |
PD_ANY, |
|
609 |
PD_BOTTOM, |
|
610 |
PD_LEFT, |
|
611 |
PD_RIGHT, |
|
612 |
PD_TOP, |
|
613 |
} PushDirection; |
|
614 |
static void TryToPush_be(TwmWindow *tmp_win, int x, int y, PushDirection dir); |
|
615 |
||
616 |
void
|
|
617 |
TryToPush(TwmWindow *tmp_win, int x, int y) |
|
618 |
{
|
|
619 |
TryToPush_be(tmp_win, x, y, PD_ANY); |
|
620 |
}
|
|
621 |
||
622 |
static void |
|
623 |
TryToPush_be(TwmWindow *tmp_win, int x, int y, PushDirection dir) |
|
624 |
{
|
|
625 |
TwmWindow *t; |
|
626 |
int newx, newy, ndir; |
|
627 |
bool move; |
|
628 |
int w, h; |
|
629 |
int winw = tmp_win->frame_width + 2 * tmp_win->frame_bw; |
|
630 |
int winh = tmp_win->frame_height + 2 * tmp_win->frame_bw; |
|
631 |
||
632 |
for(t = Scr->FirstWindow; t != NULL; t = t->next) { |
|
633 |
if(t == tmp_win) { |
|
634 |
continue; |
|
635 |
}
|
|
700.1.11
by Matthew Fuller
Hide these TwmWindow winbox-related fields behind an ifdef along with |
636 |
#ifdef WINBOX
|
523.1.24
by Matthew Fuller
Move these Pack/Push/Grid funcs into win_utils, since they're about |
637 |
if(t->winbox != tmp_win->winbox) { |
638 |
continue; |
|
639 |
}
|
|
700.1.11
by Matthew Fuller
Hide these TwmWindow winbox-related fields behind an ifdef along with |
640 |
#endif
|
523.1.24
by Matthew Fuller
Move these Pack/Push/Grid funcs into win_utils, since they're about |
641 |
if(t->vs != tmp_win->vs) { |
642 |
continue; |
|
643 |
}
|
|
644 |
if(!t->mapped) { |
|
645 |
continue; |
|
646 |
}
|
|
647 |
||
648 |
w = t->frame_width + 2 * t->frame_bw; |
|
649 |
h = t->frame_height + 2 * t->frame_bw; |
|
650 |
if(x >= t->frame_x + w) { |
|
651 |
continue; |
|
652 |
}
|
|
653 |
if(y >= t->frame_y + h) { |
|
654 |
continue; |
|
655 |
}
|
|
656 |
if(x + winw <= t->frame_x) { |
|
657 |
continue; |
|
658 |
}
|
|
659 |
if(y + winh <= t->frame_y) { |
|
660 |
continue; |
|
661 |
}
|
|
662 |
||
663 |
move = false; |
|
664 |
if((dir == PD_ANY || dir == PD_LEFT) && |
|
665 |
(x + Scr->MovePackResistance > t->frame_x + w)) { |
|
666 |
newx = x - w; |
|
667 |
newy = t->frame_y; |
|
668 |
ndir = PD_LEFT; |
|
669 |
move = true; |
|
670 |
}
|
|
671 |
else if((dir == PD_ANY || dir == PD_RIGHT) && |
|
672 |
(x + winw < t->frame_x + Scr->MovePackResistance)) { |
|
673 |
newx = x + winw; |
|
674 |
newy = t->frame_y; |
|
675 |
ndir = PD_RIGHT; |
|
676 |
move = true; |
|
677 |
}
|
|
678 |
else if((dir == PD_ANY || dir == PD_TOP) && |
|
679 |
(y + Scr->MovePackResistance > t->frame_y + h)) { |
|
680 |
newx = t->frame_x; |
|
681 |
newy = y - h; |
|
682 |
ndir = PD_TOP; |
|
683 |
move = true; |
|
684 |
}
|
|
685 |
else if((dir == PD_ANY || dir == PD_BOTTOM) && |
|
686 |
(y + winh < t->frame_y + Scr->MovePackResistance)) { |
|
687 |
newx = t->frame_x; |
|
688 |
newy = y + winh; |
|
689 |
ndir = PD_BOTTOM; |
|
690 |
move = true; |
|
691 |
}
|
|
692 |
if(move) { |
|
693 |
TryToPush_be(t, newx, newy, ndir); |
|
694 |
TryToPack(t, &newx, &newy); |
|
695 |
ConstrainByBorders(tmp_win, |
|
696 |
&newx, t->frame_width + 2 * t->frame_bw, |
|
697 |
&newy, t->frame_height + 2 * t->frame_bw); |
|
698 |
SetupWindow(t, newx, newy, t->frame_width, t->frame_height, -1); |
|
699 |
}
|
|
700 |
}
|
|
701 |
}
|
|
702 |
||
703 |
||
704 |
void
|
|
705 |
TryToGrid(TwmWindow *tmp_win, int *x, int *y) |
|
706 |
{
|
|
707 |
int w = tmp_win->frame_width + 2 * tmp_win->frame_bw; |
|
708 |
int h = tmp_win->frame_height + 2 * tmp_win->frame_bw; |
|
709 |
int grav = ((tmp_win->hints.flags & PWinGravity) |
|
710 |
? tmp_win->hints.win_gravity : NorthWestGravity); |
|
711 |
||
712 |
switch(grav) { |
|
713 |
case ForgetGravity : |
|
714 |
case StaticGravity : |
|
715 |
case NorthWestGravity : |
|
716 |
case NorthGravity : |
|
717 |
case WestGravity : |
|
718 |
case CenterGravity : |
|
719 |
*x = ((*x - Scr->BorderLeft) / Scr->XMoveGrid) * Scr->XMoveGrid |
|
720 |
+ Scr->BorderLeft; |
|
721 |
*y = ((*y - Scr->BorderTop) / Scr->YMoveGrid) * Scr->YMoveGrid |
|
722 |
+ Scr->BorderTop; |
|
723 |
break; |
|
724 |
case NorthEastGravity : |
|
725 |
case EastGravity : |
|
726 |
*x = (((*x + w - Scr->BorderLeft) / Scr->XMoveGrid) * |
|
727 |
Scr->XMoveGrid) - w + Scr->BorderLeft; |
|
728 |
*y = ((*y - Scr->BorderTop) / Scr->YMoveGrid) * |
|
729 |
Scr->YMoveGrid + Scr->BorderTop; |
|
730 |
break; |
|
731 |
case SouthWestGravity : |
|
732 |
case SouthGravity : |
|
733 |
*x = ((*x - Scr->BorderLeft) / Scr->XMoveGrid) * Scr->XMoveGrid |
|
734 |
+ Scr->BorderLeft; |
|
735 |
*y = (((*y + h - Scr->BorderTop) / Scr->YMoveGrid) * Scr->YMoveGrid) |
|
736 |
- h + Scr->BorderTop; |
|
737 |
break; |
|
738 |
case SouthEastGravity : |
|
739 |
*x = (((*x + w - Scr->BorderLeft) / Scr->XMoveGrid) * |
|
740 |
Scr->XMoveGrid) - w + Scr->BorderLeft; |
|
741 |
*y = (((*y + h - Scr->BorderTop) / Scr->YMoveGrid) * |
|
742 |
Scr->YMoveGrid) - h + Scr->BorderTop; |
|
743 |
break; |
|
744 |
}
|
|
745 |
}
|
|
523.1.26
by Matthew Fuller
Move these Constrain funcs to keeping windows on-screen to win_utils. |
746 |
|
747 |
||
748 |
||
700.1.11
by Matthew Fuller
Hide these TwmWindow winbox-related fields behind an ifdef along with |
749 |
#ifdef WINBOX
|
523.1.26
by Matthew Fuller
Move these Constrain funcs to keeping windows on-screen to win_utils. |
750 |
/*
|
751 |
* Functions related to keeping windows from being placed off-screen (or
|
|
752 |
* off-screen too far). Involved in handling of params like DontMoveOff
|
|
753 |
* and MoveOffResistance, etc.
|
|
754 |
*/
|
|
755 |
static void ConstrainLeftTop(int *value, int border); |
|
756 |
static void ConstrainRightBottom(int *value, int size1, int border, int size2); |
|
700.1.11
by Matthew Fuller
Hide these TwmWindow winbox-related fields behind an ifdef along with |
757 |
#endif
|
523.1.26
by Matthew Fuller
Move these Constrain funcs to keeping windows on-screen to win_utils. |
758 |
|
614.1.2
by Maxime Soulé
Menus are now clipped using layout |
759 |
bool
|
760 |
ConstrainByLayout(RLayout *layout, int move_off_res, int *left, int width, |
|
761 |
int *top, int height) |
|
523.1.26
by Matthew Fuller
Move these Constrain funcs to keeping windows on-screen to win_utils. |
762 |
{
|
614.1.27
by Maxime Soulé
Monitor edge detection reworked: corrects some 1-pixel-wide-problems |
763 |
RArea area = RAreaNew(*left, *top, width, height); |
614.1.3
by Maxime Soulé
Be more C standard conservative |
764 |
int limit; |
614.1.2
by Maxime Soulé
Menus are now clipped using layout |
765 |
bool clipped = false; |
614.1.1
by Maxime Soulé
First step of xrandr integration |
766 |
|
614.1.3
by Maxime Soulé
Be more C standard conservative |
767 |
limit = RLayoutFindBottomEdge(layout, &area) - height + 1; |
614.1.1
by Maxime Soulé
First step of xrandr integration |
768 |
if(area.y > limit) { |
614.1.2
by Maxime Soulé
Menus are now clipped using layout |
769 |
if(move_off_res >= 0 && area.y >= limit + move_off_res) { |
770 |
area.y -= move_off_res; |
|
614.1.1
by Maxime Soulé
First step of xrandr integration |
771 |
}
|
772 |
else { |
|
773 |
area.y = limit; |
|
614.1.2
by Maxime Soulé
Menus are now clipped using layout |
774 |
clipped = true; |
614.1.1
by Maxime Soulé
First step of xrandr integration |
775 |
}
|
776 |
}
|
|
777 |
||
614.1.2
by Maxime Soulé
Menus are now clipped using layout |
778 |
limit = RLayoutFindRightEdge(layout, &area) - width + 1; |
614.1.1
by Maxime Soulé
First step of xrandr integration |
779 |
if(area.x > limit) { |
614.1.2
by Maxime Soulé
Menus are now clipped using layout |
780 |
if(move_off_res >= 0 && area.x >= limit + move_off_res) { |
781 |
area.x -= move_off_res; |
|
614.1.1
by Maxime Soulé
First step of xrandr integration |
782 |
}
|
783 |
else { |
|
784 |
area.x = limit; |
|
614.1.2
by Maxime Soulé
Menus are now clipped using layout |
785 |
clipped = true; |
614.1.1
by Maxime Soulé
First step of xrandr integration |
786 |
}
|
787 |
}
|
|
788 |
||
614.1.2
by Maxime Soulé
Menus are now clipped using layout |
789 |
limit = RLayoutFindLeftEdge(layout, &area); |
614.1.1
by Maxime Soulé
First step of xrandr integration |
790 |
if(area.x < limit) { |
614.1.2
by Maxime Soulé
Menus are now clipped using layout |
791 |
if(move_off_res >= 0 && area.x <= limit - move_off_res) { |
792 |
area.x += move_off_res; |
|
614.1.1
by Maxime Soulé
First step of xrandr integration |
793 |
}
|
794 |
else { |
|
795 |
area.x = limit; |
|
614.1.2
by Maxime Soulé
Menus are now clipped using layout |
796 |
clipped = true; |
614.1.1
by Maxime Soulé
First step of xrandr integration |
797 |
}
|
798 |
}
|
|
799 |
||
614.1.2
by Maxime Soulé
Menus are now clipped using layout |
800 |
limit = RLayoutFindTopEdge(layout, &area); |
614.1.1
by Maxime Soulé
First step of xrandr integration |
801 |
if(area.y < limit) { |
614.1.2
by Maxime Soulé
Menus are now clipped using layout |
802 |
if(move_off_res >= 0 && area.y <= limit - move_off_res) { |
803 |
area.y += move_off_res; |
|
614.1.1
by Maxime Soulé
First step of xrandr integration |
804 |
}
|
805 |
else { |
|
806 |
area.y = limit; |
|
614.1.2
by Maxime Soulé
Menus are now clipped using layout |
807 |
clipped = true; |
614.1.1
by Maxime Soulé
First step of xrandr integration |
808 |
}
|
809 |
}
|
|
810 |
||
811 |
*left = area.x; |
|
812 |
*top = area.y; |
|
614.1.2
by Maxime Soulé
Menus are now clipped using layout |
813 |
|
814 |
return clipped; |
|
815 |
}
|
|
816 |
||
817 |
void
|
|
818 |
ConstrainByBorders1(int *left, int width, int *top, int height) |
|
819 |
{
|
|
820 |
ConstrainByLayout(Scr->BorderedLayout, Scr->MoveOffResistance, |
|
821 |
left, width, top, height); |
|
523.1.26
by Matthew Fuller
Move these Constrain funcs to keeping windows on-screen to win_utils. |
822 |
}
|
823 |
||
824 |
void
|
|
825 |
ConstrainByBorders(TwmWindow *twmwin, int *left, int width, |
|
826 |
int *top, int height) |
|
827 |
{
|
|
700.1.11
by Matthew Fuller
Hide these TwmWindow winbox-related fields behind an ifdef along with |
828 |
if(false) { |
829 |
// Dummy
|
|
830 |
}
|
|
831 |
#ifdef WINBOX
|
|
832 |
else if(twmwin->winbox) { |
|
523.1.26
by Matthew Fuller
Move these Constrain funcs to keeping windows on-screen to win_utils. |
833 |
XWindowAttributes attr; |
834 |
XGetWindowAttributes(dpy, twmwin->winbox->window, &attr); |
|
835 |
ConstrainRightBottom(left, width, 0, attr.width); |
|
836 |
ConstrainLeftTop(left, 0); |
|
837 |
ConstrainRightBottom(top, height, 0, attr.height); |
|
838 |
ConstrainLeftTop(top, 0); |
|
839 |
}
|
|
700.1.11
by Matthew Fuller
Hide these TwmWindow winbox-related fields behind an ifdef along with |
840 |
#endif
|
523.1.26
by Matthew Fuller
Move these Constrain funcs to keeping windows on-screen to win_utils. |
841 |
else { |
842 |
ConstrainByBorders1(left, width, top, height); |
|
843 |
}
|
|
844 |
}
|
|
845 |
||
700.1.11
by Matthew Fuller
Hide these TwmWindow winbox-related fields behind an ifdef along with |
846 |
#ifdef WINBOX
|
523.1.26
by Matthew Fuller
Move these Constrain funcs to keeping windows on-screen to win_utils. |
847 |
static void |
848 |
ConstrainLeftTop(int *value, int border) |
|
849 |
{
|
|
850 |
if(*value < border) { |
|
851 |
if(Scr->MoveOffResistance < 0 || |
|
852 |
*value > border - Scr->MoveOffResistance) { |
|
853 |
*value = border; |
|
854 |
}
|
|
855 |
else if(Scr->MoveOffResistance > 0 && |
|
856 |
*value <= border - Scr->MoveOffResistance) { |
|
857 |
*value = *value + Scr->MoveOffResistance; |
|
858 |
}
|
|
859 |
}
|
|
860 |
}
|
|
861 |
||
862 |
static void |
|
863 |
ConstrainRightBottom(int *value, int size1, int border, int size2) |
|
864 |
{
|
|
865 |
if(*value + size1 > size2 - border) { |
|
866 |
if(Scr->MoveOffResistance < 0 || |
|
867 |
*value + size1 < size2 - border + Scr->MoveOffResistance) { |
|
868 |
*value = size2 - size1 - border; |
|
869 |
}
|
|
870 |
else if(Scr->MoveOffResistance > 0 && |
|
871 |
*value + size1 >= size2 - border + Scr->MoveOffResistance) { |
|
872 |
*value = *value - Scr->MoveOffResistance; |
|
873 |
}
|
|
874 |
}
|
|
875 |
}
|
|
700.1.11
by Matthew Fuller
Hide these TwmWindow winbox-related fields behind an ifdef along with |
876 |
#endif
|
539.1.18
by Matthew Fuller
WarpToWindow() also has no relation to menus and is broadly used |
877 |
|
878 |
||
879 |
/*
|
|
880 |
* Zoom over to a particular window.
|
|
881 |
*/
|
|
882 |
void
|
|
883 |
WarpToWindow(TwmWindow *t, bool must_raise) |
|
884 |
{
|
|
885 |
int x, y; |
|
886 |
||
887 |
if(t->ring.cursor_valid) { |
|
888 |
x = t->ring.curs_x; |
|
889 |
y = t->ring.curs_y; |
|
890 |
#ifdef DEBUG
|
|
891 |
fprintf(stderr, "WarpToWindow: cursor_valid; x == %d, y == %d\n", x, y); |
|
892 |
#endif
|
|
893 |
||
894 |
/*
|
|
895 |
* XXX is this correct with 3D borders? Easier check possible?
|
|
896 |
* frame_bw is for the left border.
|
|
897 |
*/
|
|
898 |
if(x < t->frame_bw) { |
|
899 |
x = t->frame_bw; |
|
900 |
}
|
|
901 |
if(x >= t->frame_width + t->frame_bw) { |
|
902 |
x = t->frame_width + t->frame_bw - 1; |
|
903 |
}
|
|
904 |
if(y < t->title_height + t->frame_bw) { |
|
905 |
y = t->title_height + t->frame_bw; |
|
906 |
}
|
|
907 |
if(y >= t->frame_height + t->frame_bw) { |
|
908 |
y = t->frame_height + t->frame_bw - 1; |
|
909 |
}
|
|
910 |
#ifdef DEBUG
|
|
911 |
fprintf(stderr, "WarpToWindow: adjusted ; x := %d, y := %d\n", x, y); |
|
912 |
#endif
|
|
913 |
}
|
|
914 |
else { |
|
915 |
x = t->frame_width / 2; |
|
916 |
y = t->frame_height / 2; |
|
917 |
#ifdef DEBUG
|
|
918 |
fprintf(stderr, "WarpToWindow: middle; x := %d, y := %d\n", x, y); |
|
919 |
#endif
|
|
920 |
}
|
|
921 |
#if 0
|
|
922 |
int dest_x, dest_y;
|
|
923 |
Window child;
|
|
924 |
||
925 |
/*
|
|
926 |
* Check if the proposed position actually is visible. If not, raise the window.
|
|
927 |
* "If the coordinates are contained in a mapped
|
|
928 |
* child of dest_w, that child is returned to child_return."
|
|
929 |
* We'll need to check for the right child window; the frame probably.
|
|
930 |
* (What about XXX window boxes?)
|
|
931 |
*
|
|
932 |
* Alternatively, use XQueryPointer() which returns the root window
|
|
933 |
* the pointer is in, but XXX that won't work for VirtualScreens.
|
|
934 |
*/
|
|
935 |
if(XTranslateCoordinates(dpy, t->frame, Scr->Root, x, y, &dest_x, &dest_y,
|
|
936 |
&child)) {
|
|
937 |
if(child != t->frame) {
|
|
938 |
must_raise = true;
|
|
939 |
}
|
|
940 |
}
|
|
941 |
#endif
|
|
942 |
if(t->auto_raise || must_raise) { |
|
943 |
AutoRaiseWindow(t); |
|
944 |
}
|
|
945 |
if(! visible(t)) { |
|
946 |
WorkSpace *wlist; |
|
947 |
||
948 |
for(wlist = Scr->workSpaceMgr.workSpaceList; wlist != NULL; |
|
949 |
wlist = wlist->next) { |
|
950 |
if(OCCUPY(t, wlist)) { |
|
951 |
break; |
|
952 |
}
|
|
953 |
}
|
|
954 |
if(wlist != NULL) { |
|
955 |
GotoWorkSpace(Scr->currentvs, wlist); |
|
956 |
}
|
|
957 |
}
|
|
958 |
||
959 |
XWarpPointer(dpy, None, Scr->Root, 0, 0, 0, 0, x + t->frame_x, y + t->frame_y); |
|
960 |
SetFocus(t, EventTime); |
|
961 |
||
962 |
#ifdef DEBUG
|
|
963 |
{
|
|
964 |
Window root_return; |
|
965 |
Window child_return; |
|
966 |
int root_x_return; |
|
967 |
int root_y_return; |
|
968 |
int win_x_return; |
|
969 |
int win_y_return; |
|
970 |
unsigned int mask_return; |
|
971 |
||
972 |
if(XQueryPointer(dpy, t->frame, &root_return, &child_return, &root_x_return, |
|
973 |
&root_y_return, &win_x_return, &win_y_return, &mask_return)) { |
|
974 |
fprintf(stderr, |
|
975 |
"XQueryPointer: root_return=%x, child_return=%x, root_x_return=%d, root_y_return=%d, win_x_return=%d, win_y_return=%d\n", |
|
976 |
root_return, child_return, root_x_return, root_y_return, win_x_return, |
|
977 |
win_y_return); |
|
978 |
}
|
|
979 |
}
|
|
980 |
#endif
|
|
981 |
}
|
|
539.1.22
by Matthew Fuller
send_clientmessage() probably belongs better in win_utils than util. |
982 |
|
983 |
||
984 |
/*
|
|
985 |
* ICCCM Client Messages - Section 4.2.8 of the ICCCM dictates that all
|
|
986 |
* client messages will have the following form:
|
|
987 |
*
|
|
988 |
* event type ClientMessage
|
|
989 |
* message type XA_WM_PROTOCOLS
|
|
990 |
* window tmp->w
|
|
991 |
* format 32
|
|
992 |
* data[0] message atom
|
|
993 |
* data[1] time stamp
|
|
994 |
*/
|
|
995 |
void
|
|
996 |
send_clientmessage(Window w, Atom a, Time timestamp) |
|
997 |
{
|
|
998 |
XClientMessageEvent ev; |
|
999 |
||
1000 |
ev.type = ClientMessage; |
|
1001 |
ev.window = w; |
|
1002 |
ev.message_type = XA_WM_PROTOCOLS; |
|
1003 |
ev.format = 32; |
|
1004 |
ev.data.l[0] = a; |
|
1005 |
ev.data.l[1] = timestamp; |
|
1006 |
XSendEvent(dpy, w, False, 0L, (XEvent *) &ev); |
|
1007 |
}
|
|
557.1.4
by Matthew Fuller
Move creating the synthetic hints into a function so we can reuse it. |
1008 |
|
1009 |
||
1010 |
/*
|
|
1011 |
* Create synthetic WM_HINTS info for windows. When a window specifies
|
|
1012 |
* stuff, we should probably pay attention to it (though we don't
|
|
1013 |
* always; x-ref comments in AddWindow() especially about focus).
|
|
1014 |
* However, when it doesn't tell us anything at all, we should assume
|
|
1015 |
* something useful. "Window managers are free to assume convenient
|
|
1016 |
* values for all fields of the WM_HINTS property if a window is mapped
|
|
1017 |
* without one." (ICCCM Ch. 4,
|
|
1018 |
* <https://www.x.org/releases/X11R7.7/doc/xorg-docs/icccm/icccm.html#Client_Properties>).
|
|
1019 |
*
|
|
557.1.9
by Matthew Fuller
Tweak comment. |
1020 |
* Specifically, we assume it wants us to give it focus. It's fairly
|
1021 |
* bogus for a window not to tell us anything, but e.g current versions
|
|
1022 |
* of Chrome do (don't do) just that. So we better make up something
|
|
1023 |
* useful.
|
|
557.1.4
by Matthew Fuller
Move creating the synthetic hints into a function so we can reuse it. |
1024 |
*
|
557.1.9
by Matthew Fuller
Tweak comment. |
1025 |
* Should probably be some configurability for this, so make the func
|
1026 |
* take the window, even though we don't currently do anything useful
|
|
1027 |
* with it...
|
|
557.1.4
by Matthew Fuller
Move creating the synthetic hints into a function so we can reuse it. |
1028 |
*/
|
1029 |
XWMHints * |
|
1030 |
gen_synthetic_wmhints(TwmWindow *win) |
|
1031 |
{
|
|
1032 |
XWMHints *hints; |
|
1033 |
||
1034 |
hints = XAllocWMHints(); |
|
1035 |
if(!hints) { |
|
1036 |
return NULL; |
|
1037 |
}
|
|
1038 |
||
1039 |
/*
|
|
1040 |
* Reasonable defaults. Takes input, in normal state.
|
|
1041 |
*
|
|
1042 |
* XXX Make configurable?
|
|
1043 |
*/
|
|
1044 |
hints->flags = InputHint | StateHint; |
|
1045 |
hints->input = True; |
|
1046 |
hints->initial_state = NormalState; |
|
1047 |
||
1048 |
return hints; |
|
1049 |
}
|
|
615.1.4
by Matthew Fuller
Split out all the code to support "window name has changed, do stuff |
1050 |
|
1051 |
||
615.1.54
by Matthew Fuller
As long as we're writing these funcs and their comments fresh, might |
1052 |
/**
|
625.1.1
by Matthew Fuller
Extract the adjustment of wmhints stuff into a separate function for |
1053 |
* Perform whatever adaptations of WM_HINTS info we do.
|
1054 |
*
|
|
1055 |
* Most of these relate to focus, but we also fiddle with group
|
|
1056 |
* membership.
|
|
1057 |
*/
|
|
1058 |
XWMHints * |
|
1059 |
munge_wmhints(TwmWindow *win, XWMHints *hints) |
|
1060 |
{
|
|
1061 |
/*
|
|
1062 |
* If we have WM_HINTS, but they don't tell us anything about focus,
|
|
1063 |
* force it to true for our purposes.
|
|
1064 |
*
|
|
1065 |
* CL: Having with not willing focus cause problems with AutoSqueeze
|
|
1066 |
* and a few others things. So I suppress it. And the whole focus
|
|
1067 |
* thing is buggy anyway.
|
|
1068 |
*/
|
|
625.1.2
by Matthew Fuller
Consistently work on the passed in hints, not what's in the window |
1069 |
if(!(hints->flags & InputHint)) { |
1070 |
hints->input = True; |
|
625.1.1
by Matthew Fuller
Extract the adjustment of wmhints stuff into a separate function for |
1071 |
}
|
1072 |
||
1073 |
/*
|
|
1074 |
* Now we're expecting to give the window focus if it asked for it
|
|
1075 |
* via WM_HINTS, if it didn't say anything one way or the other in
|
|
1076 |
* WM_HINTS, or if it didn't give us any WM_HINTS at all. But if it
|
|
1077 |
* explicitly asked not to, we don't give it unless overridden by
|
|
1078 |
* config.
|
|
1079 |
*/
|
|
1080 |
if(Scr->ForceFocus || IsInList(Scr->ForceFocusL, win)) { |
|
625.1.2
by Matthew Fuller
Consistently work on the passed in hints, not what's in the window |
1081 |
hints->input = True; |
625.1.1
by Matthew Fuller
Extract the adjustment of wmhints stuff into a separate function for |
1082 |
}
|
1083 |
||
1084 |
||
1085 |
/* Setup group bits */
|
|
625.1.2
by Matthew Fuller
Consistently work on the passed in hints, not what's in the window |
1086 |
if(hints->flags & WindowGroupHint) { |
1087 |
win->group = hints->window_group; |
|
625.1.1
by Matthew Fuller
Extract the adjustment of wmhints stuff into a separate function for |
1088 |
if(win->group) { |
1089 |
/*
|
|
1090 |
* GTK windows often have a spurious "group leader" window which is
|
|
1091 |
* never reported to us and therefore does not really exist. This
|
|
1092 |
* is annoying because we treat group members a lot like transient
|
|
1093 |
* windows. Look for that here. It is in fact a duplicate of the
|
|
1094 |
* WM_CLIENT_LEADER property.
|
|
1095 |
*/
|
|
1096 |
if(win->group != win->w && !GetTwmWindow(win->group)) { |
|
1097 |
win->group = 0; |
|
1098 |
}
|
|
1099 |
}
|
|
1100 |
}
|
|
1101 |
else { |
|
1102 |
win->group = 0; |
|
1103 |
}
|
|
1104 |
||
1105 |
return hints; |
|
1106 |
}
|
|
1107 |
||
1108 |
||
1109 |
/**
|
|
615.1.54
by Matthew Fuller
As long as we're writing these funcs and their comments fresh, might |
1110 |
* [Re]set a window's name. This goes over the available naming sources
|
1111 |
* for the window and points the TwmWindow::name at the appropriate one.
|
|
1112 |
* It may also set a property to signal other EWMH-aware clients when
|
|
1113 |
* we're naming it a way they can't see themselves.
|
|
1114 |
*
|
|
1115 |
* \note This should rarely be called directly; apply_window_name()
|
|
1116 |
* should be used instead. It's split out because we need to do this
|
|
1117 |
* step individually in AddWindow().
|
|
1118 |
*
|
|
1119 |
* \note Note also that we never need to worry about freeing the
|
|
1120 |
* TwmWindow::name; it always points to one of the TwmWindow::names
|
|
1121 |
* values (which are free'd by the event handler when they change) or to
|
|
1122 |
* NoName (which is static). So we can just casually flip it around at
|
|
1123 |
* will.
|
|
615.1.4
by Matthew Fuller
Split out all the code to support "window name has changed, do stuff |
1124 |
*/
|
615.1.25
by Matthew Fuller
Split out setting ->name from doing the stuff that we do after |
1125 |
bool
|
1126 |
set_window_name(TwmWindow *win) |
|
615.1.4
by Matthew Fuller
Split out all the code to support "window name has changed, do stuff |
1127 |
{
|
615.1.25
by Matthew Fuller
Split out setting ->name from doing the stuff that we do after |
1128 |
char *newname = NULL; |
615.1.6
by Matthew Fuller
Build infrastructure to choose among multiple possible name sources, |
1129 |
#define TRY(fld) { \
|
615.1.13
by Matthew Fuller
Add extra {}'s here to make it easier to slot in debug statements. |
1130 |
if(newname == NULL && win->names.fld != NULL) { \
|
1131 |
newname = win->names.fld; \
|
|
1132 |
} \
|
|
615.1.6
by Matthew Fuller
Build infrastructure to choose among multiple possible name sources, |
1133 |
}
|
615.1.39
by Matthew Fuller
Add places for and handling of some properties for overriding |
1134 |
TRY(ctwm_wm_name) |
615.1.8
by Matthew Fuller
Add net_wm_name into the fields we're trying. Nothing's setting it |
1135 |
#ifdef EWMH
|
615.1.25
by Matthew Fuller
Split out setting ->name from doing the stuff that we do after |
1136 |
TRY(net_wm_name) |
615.1.8
by Matthew Fuller
Add net_wm_name into the fields we're trying. Nothing's setting it |
1137 |
#endif
|
615.1.25
by Matthew Fuller
Split out setting ->name from doing the stuff that we do after |
1138 |
TRY(wm_name) |
615.1.6
by Matthew Fuller
Build infrastructure to choose among multiple possible name sources, |
1139 |
#undef TRY
|
1140 |
||
615.1.25
by Matthew Fuller
Split out setting ->name from doing the stuff that we do after |
1141 |
if(newname == NULL) { |
1142 |
newname = NoName; |
|
1143 |
}
|
|
1144 |
if(win->name == newname) { |
|
1145 |
return false; // Nothing to do |
|
1146 |
}
|
|
1147 |
||
615.1.52
by Matthew Fuller
Implement EWMH _NET_WM_VISIBLE{,_ICON}_NAME, telling external |
1148 |
// Now we know what to call it
|
615.1.25
by Matthew Fuller
Split out setting ->name from doing the stuff that we do after |
1149 |
win->name = newname; |
615.1.52
by Matthew Fuller
Implement EWMH _NET_WM_VISIBLE{,_ICON}_NAME, telling external |
1150 |
|
1151 |
#ifdef EWMH
|
|
1152 |
// EWMH says we set an additional property on any windows where what
|
|
1153 |
// we consider the name isn't what's in _NET_WM_NAME, so pagers etc
|
|
1154 |
// can call it the same as we do.
|
|
1155 |
//
|
|
1156 |
// The parts of the text describing it conflict a little; at one
|
|
1157 |
// place, it implies this should be set unless we're using
|
|
1158 |
// _NET_WM_NAME, in another it seems to suggest WM_NAME should be
|
|
1159 |
// considered applicable too. I choose to implement it excluding
|
|
1160 |
// both, so this only gets set if we're overriding either standard
|
|
1161 |
// naming (probably rare).
|
|
1162 |
if(win->name != win->names.net_wm_name && win->name != win->names.wm_name) { |
|
1163 |
// XXX We're not doing any checking of the encoding here... I
|
|
1164 |
// don't see that Xlib helps us any, so we probably have to fall
|
|
1165 |
// back to iconv? That came into the base in POSIX 2008, but was
|
|
1166 |
// in XSI back into the 90's I believe?
|
|
1167 |
XChangeProperty(dpy, win->w, XA__NET_WM_VISIBLE_NAME, XA_UTF8_STRING, |
|
1168 |
8, PropModeReplace, (unsigned char *)win->name, |
|
1169 |
strlen(win->name)); |
|
1170 |
}
|
|
1171 |
else { |
|
1172 |
XDeleteProperty(dpy, win->w, XA__NET_WM_VISIBLE_NAME); |
|
1173 |
}
|
|
1174 |
#endif // EWMH |
|
1175 |
||
1176 |
// We set a name
|
|
615.1.25
by Matthew Fuller
Split out setting ->name from doing the stuff that we do after |
1177 |
return true; |
1178 |
}
|
|
1179 |
||
1180 |
||
615.1.54
by Matthew Fuller
As long as we're writing these funcs and their comments fresh, might |
1181 |
/**
|
615.1.25
by Matthew Fuller
Split out setting ->name from doing the stuff that we do after |
1182 |
* [Re]set and apply changes to a window's name. This is called after
|
1183 |
* we've received a new WM_NAME (or other name-setting) property, to
|
|
1184 |
* update our titlebars, icon managers, etc.
|
|
1185 |
*/
|
|
1186 |
void
|
|
1187 |
apply_window_name(TwmWindow *win) |
|
1188 |
{
|
|
1189 |
/* [Re]set ->name */
|
|
1190 |
if(set_window_name(win) == false) { |
|
1191 |
// No change
|
|
1192 |
return; |
|
1193 |
}
|
|
1194 |
win->nameChanged = true; |
|
1195 |
||
615.1.6
by Matthew Fuller
Build infrastructure to choose among multiple possible name sources, |
1196 |
|
615.1.4
by Matthew Fuller
Split out all the code to support "window name has changed, do stuff |
1197 |
/* Update the active name */
|
1198 |
{
|
|
1199 |
XRectangle inc_rect; |
|
1200 |
XRectangle logical_rect; |
|
1201 |
||
1202 |
XmbTextExtents(Scr->TitleBarFont.font_set, |
|
1203 |
win->name, strlen(win->name), |
|
1204 |
&inc_rect, &logical_rect); |
|
1205 |
win->name_width = logical_rect.width; |
|
1206 |
}
|
|
1207 |
||
1208 |
/* recompute the priority if necessary */
|
|
1209 |
if(Scr->AutoPriority) { |
|
1210 |
OtpRecomputePrefs(win); |
|
1211 |
}
|
|
1212 |
||
1213 |
SetupWindow(win, win->frame_x, win->frame_y, |
|
1214 |
win->frame_width, win->frame_height, -1); |
|
1215 |
||
1216 |
if(win->title_w) { |
|
1217 |
XClearArea(dpy, win->title_w, 0, 0, 0, 0, True); |
|
1218 |
}
|
|
1219 |
if(Scr->AutoOccupy) { |
|
1220 |
WmgrRedoOccupation(win); |
|
1221 |
}
|
|
1222 |
||
1223 |
#if 0
|
|
1224 |
/* Experimental, not yet working. */
|
|
1225 |
{
|
|
1226 |
ColorPair cp;
|
|
1227 |
int f, b;
|
|
1228 |
||
1229 |
f = GetColorFromList(Scr->TitleForegroundL, win->name,
|
|
1230 |
&win->class, &cp.fore);
|
|
1231 |
b = GetColorFromList(Scr->TitleBackgroundL, win->name,
|
|
1232 |
&win->class, &cp.back);
|
|
1233 |
if(f || b) {
|
|
1234 |
if(Scr->use3Dtitles && !Scr->BeNiceToColormap) {
|
|
1235 |
GetShadeColors(&cp);
|
|
1236 |
}
|
|
1237 |
win->title = cp;
|
|
1238 |
}
|
|
1239 |
f = GetColorFromList(Scr->BorderColorL, win->name,
|
|
1240 |
&win->class, &cp.fore);
|
|
1241 |
b = GetColorFromList(Scr->BorderColorL, win->name,
|
|
1242 |
&win->class, &cp.back);
|
|
1243 |
if(f || b) {
|
|
1244 |
if(Scr->use3Dborders && !Scr->BeNiceToColormap) {
|
|
1245 |
GetShadeColors(&cp);
|
|
1246 |
}
|
|
1247 |
win->borderC = cp;
|
|
1248 |
}
|
|
1249 |
||
1250 |
f = GetColorFromList(Scr->BorderTileForegroundL, win->name,
|
|
1251 |
&win->class, &cp.fore);
|
|
1252 |
b = GetColorFromList(Scr->BorderTileBackgroundL, win->name,
|
|
1253 |
&win->class, &cp.back);
|
|
1254 |
if(f || b) {
|
|
1255 |
if(Scr->use3Dborders && !Scr->BeNiceToColormap) {
|
|
1256 |
GetShadeColors(&cp);
|
|
1257 |
}
|
|
1258 |
win->border_tile = cp;
|
|
1259 |
}
|
|
1260 |
}
|
|
1261 |
#endif
|
|
1262 |
||
1263 |
/*
|
|
615.1.30
by Matthew Fuller
Shift the icon_name setting bits off into functions like we did for |
1264 |
* If we haven't set a separate icon name, we use the window name, so
|
1265 |
* we need to update it.
|
|
615.1.4
by Matthew Fuller
Split out all the code to support "window name has changed, do stuff |
1266 |
*/
|
615.1.30
by Matthew Fuller
Shift the icon_name setting bits off into functions like we did for |
1267 |
if(win->names.icon_set == false) { |
1268 |
apply_window_icon_name(win); |
|
615.1.4
by Matthew Fuller
Split out all the code to support "window name has changed, do stuff |
1269 |
}
|
1270 |
AutoPopupMaybe(win); |
|
615.1.5
by Matthew Fuller
Explicit return. |
1271 |
|
1272 |
return; |
|
615.1.4
by Matthew Fuller
Split out all the code to support "window name has changed, do stuff |
1273 |
}
|
615.1.30
by Matthew Fuller
Shift the icon_name setting bits off into functions like we did for |
1274 |
|
1275 |
||
615.1.54
by Matthew Fuller
As long as we're writing these funcs and their comments fresh, might |
1276 |
/**
|
1277 |
* [Re]set a window's icon name. As with the window name version in
|
|
1278 |
* set_window_name(), this is mostly separate so the AddWindow() process
|
|
1279 |
* can call it.
|
|
1280 |
*
|
|
1281 |
* \note As with TwmWindow::name, we never want to try free()'ing or the
|
|
1282 |
* like TwmWindow::icon_name.
|
|
1283 |
*
|
|
1284 |
* \sa set_window_name() for details; this is just the icon name
|
|
1285 |
* equivalent of it.
|
|
615.1.30
by Matthew Fuller
Shift the icon_name setting bits off into functions like we did for |
1286 |
*/
|
1287 |
bool
|
|
1288 |
set_window_icon_name(TwmWindow *win) |
|
1289 |
{
|
|
1290 |
char *newname = NULL; |
|
1291 |
#define TRY(fld) { \
|
|
1292 |
if(newname == NULL && win->names.fld != NULL) { \
|
|
1293 |
newname = win->names.fld; \
|
|
1294 |
win->names.icon_set = true; \
|
|
1295 |
} \
|
|
1296 |
}
|
|
615.1.39
by Matthew Fuller
Add places for and handling of some properties for overriding |
1297 |
TRY(ctwm_wm_icon_name) |
615.1.30
by Matthew Fuller
Shift the icon_name setting bits off into functions like we did for |
1298 |
#ifdef EWMH
|
1299 |
TRY(net_wm_icon_name) |
|
1300 |
#endif
|
|
1301 |
TRY(wm_icon_name) |
|
1302 |
#undef TRY
|
|
1303 |
||
1304 |
// Our fallback for icon names is the window name. Flag when we're
|
|
1305 |
// doing that, so the window name handler can know when it needs to
|
|
1306 |
// call us.
|
|
1307 |
if(newname == NULL) { |
|
1308 |
newname = win->name; |
|
1309 |
win->names.icon_set = false; |
|
1310 |
}
|
|
1311 |
if(win->icon_name == newname) { |
|
1312 |
return false; // Nothing to do |
|
1313 |
}
|
|
1314 |
||
615.1.52
by Matthew Fuller
Implement EWMH _NET_WM_VISIBLE{,_ICON}_NAME, telling external |
1315 |
// A name is chosen
|
615.1.30
by Matthew Fuller
Shift the icon_name setting bits off into functions like we did for |
1316 |
win->icon_name = newname; |
615.1.52
by Matthew Fuller
Implement EWMH _NET_WM_VISIBLE{,_ICON}_NAME, telling external |
1317 |
|
1318 |
#ifdef EWMH
|
|
1319 |
// EWMH asks for _NET_WM_VISIBLE_ICON_NAME in various cases where
|
|
1320 |
// we're not using 'standard' properties' values. x-ref comments above in
|
|
1321 |
// set_window_name() about the parallel property for the window name
|
|
1322 |
// for various caveats.
|
|
1323 |
if(win->icon_name != win->names.net_wm_icon_name |
|
1324 |
&& win->icon_name != win->names.wm_icon_name) { |
|
1325 |
// XXX Still encoding questionable; x-ref above.
|
|
1326 |
XChangeProperty(dpy, win->w, XA__NET_WM_VISIBLE_ICON_NAME, |
|
1327 |
XA_UTF8_STRING, |
|
1328 |
8, PropModeReplace, (unsigned char *)win->icon_name, |
|
1329 |
strlen(win->icon_name)); |
|
1330 |
}
|
|
1331 |
else { |
|
1332 |
XDeleteProperty(dpy, win->w, XA__NET_WM_VISIBLE_ICON_NAME); |
|
1333 |
}
|
|
1334 |
#endif // EWMH |
|
1335 |
||
1336 |
// Did it
|
|
615.1.30
by Matthew Fuller
Shift the icon_name setting bits off into functions like we did for |
1337 |
return true; |
1338 |
}
|
|
1339 |
||
1340 |
||
615.1.54
by Matthew Fuller
As long as we're writing these funcs and their comments fresh, might |
1341 |
/**
|
1342 |
* [Re]set and apply changes to a window's icon name. This is called
|
|
1343 |
* after we've received a new WM_ICON_NAME (or other name-setting)
|
|
1344 |
* property, to update our titlebars, icon managers, etc.
|
|
1345 |
*
|
|
1346 |
* \sa apply_window_name() which does the same for the window title.
|
|
615.1.30
by Matthew Fuller
Shift the icon_name setting bits off into functions like we did for |
1347 |
*/
|
1348 |
void
|
|
1349 |
apply_window_icon_name(TwmWindow *win) |
|
1350 |
{
|
|
1351 |
/* [Re]set ->icon_name */
|
|
1352 |
if(set_window_icon_name(win) == false) { |
|
1353 |
// No change
|
|
1354 |
return; |
|
1355 |
}
|
|
1356 |
||
1357 |
||
1358 |
/* Lot less to do for icons... */
|
|
1359 |
RedoIcon(Tmp_win); |
|
1360 |
AutoPopupMaybe(Tmp_win); |
|
1361 |
||
1362 |
return; |
|
1363 |
}
|