1 /*
2 * Copyright (C) 2000 Sasha Vasko <sasha at aftercode.net>
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 *
18 */
19
20 #include "../configure.h"
21
22 #define LOCAL_DEBUG
23 #include "asapp.h"
24 #include "afterstep.h"
25 #include "asdatabase.h"
26 #include "screen.h"
27 #include "functions.h"
28 #include "clientprops.h"
29 #include "hints.h"
30 #include "desktop_category.h"
31 #include "freestor.h"
32 #include "../libAfterImage/afterimage.h"
33
34
35 /*********************************************************************************
36 * Raw Hints must be aggregated into usable forma :
37 *********************************************************************************/
init_ashints(ASHints * hints)38 static void init_ashints (ASHints * hints)
39 {
40 if (hints) { /* some defaults to start with : */
41 hints->flags =
42 AS_HitPager | AS_Gravity | AS_AcceptsFocus | AS_Titlebar |
43 AS_IconTitle | AS_Handles | AS_Border;
44 /* can't gracefully close the window if it does not support WM_DELETE_WINDOW */
45 hints->function_mask = ~(AS_FuncClose | AS_FuncPinMenu);
46 hints->gravity = NorthWestGravity;
47 hints->border_width = 1;
48 }
49 }
50
get_asdb_hint_mask(ASDatabaseRecord * db_rec)51 ASFlagType get_asdb_hint_mask (ASDatabaseRecord * db_rec)
52 {
53 ASFlagType hint_mask = ASFLAGS_EVERYTHING;
54
55 if (db_rec) {
56 if (get_flags (db_rec->set_flags, STYLE_GROUP_HINTS)
57 && !get_flags (db_rec->flags, STYLE_GROUP_HINTS))
58 clear_flags (hint_mask, (0x01 << HINTS_GroupLead));
59 if (get_flags (db_rec->set_flags, STYLE_TRANSIENT_HINTS)
60 && !get_flags (db_rec->flags, STYLE_TRANSIENT_HINTS))
61 clear_flags (hint_mask, (0x01 << HINTS_Transient));
62 if (get_flags (db_rec->set_flags, STYLE_MOTIF_HINTS)
63 && !get_flags (db_rec->flags, STYLE_MOTIF_HINTS))
64 clear_flags (hint_mask, (0x01 << HINTS_Motif));
65 if (get_flags (db_rec->set_flags, STYLE_GNOME_HINTS)
66 && !get_flags (db_rec->flags, STYLE_GNOME_HINTS))
67 clear_flags (hint_mask, (0x01 << HINTS_Gnome));
68 if (get_flags (db_rec->set_flags, STYLE_EXTWM_HINTS)
69 && !get_flags (db_rec->flags, STYLE_EXTWM_HINTS))
70 clear_flags (hint_mask, (0x01 << HINTS_ExtendedWM));
71 if (get_flags (db_rec->set_flags, STYLE_KDE_HINTS)
72 && !get_flags (db_rec->flags, STYLE_KDE_HINTS))
73 clear_flags (hint_mask, (0x01 << HINTS_KDE));
74 if (get_flags (db_rec->set_flags, STYLE_XRESOURCES_HINTS)
75 && !get_flags (db_rec->flags, STYLE_XRESOURCES_HINTS))
76 clear_flags (hint_mask, (0x01 << HINTS_XResources));
77 }
78 return hint_mask;
79 }
80
81 static ASFlagType
get_afterstep_resources(XrmDatabase db,ASStatusHints * status)82 get_afterstep_resources (XrmDatabase db, ASStatusHints * status)
83 {
84 ASFlagType found = 0;
85
86 if (db != NULL && status) {
87 if (read_int_resource
88 (db, "afterstep*desk", "AS*Desk", &(status->desktop)))
89 set_flags (found, AS_StartDesktop);
90 if (read_int_resource
91 (db, "afterstep*layer", "AS*Layer", &(status->layer)))
92 set_flags (found, AS_StartLayer);
93 if (read_int_resource
94 (db, "afterstep*viewportx", "AS*ViewportX", &(status->viewport_x)))
95 set_flags (found, AS_StartViewportX);
96 if (read_int_resource
97 (db, "afterstep*viewporty", "AS*ViewportY", &(status->viewport_y)))
98 set_flags (found, AS_StartViewportY);
99 set_flags (status->flags, found);
100 }
101 return found;
102 }
103
104 void
merge_command_line(ASHints * clean,ASStatusHints * status,ASRawHints * raw)105 merge_command_line (ASHints * clean, ASStatusHints * status,
106 ASRawHints * raw)
107 {
108 static XrmOptionDescRec xrm_cmd_opts[] = {
109 /* Want to accept -xrm "afterstep*desk:N" as options
110 * to specify the desktop. Have to include dummy options that
111 * are meaningless since Xrm seems to allow -x to match -xrm
112 * if there would be no ambiguity. */
113 {"-xrnblahblah", NULL, XrmoptionResArg, (caddr_t) NULL},
114 {"-xrm", NULL, XrmoptionResArg, (caddr_t) NULL},
115 };
116
117 if (raw == NULL)
118 return;
119 if (raw->wm_cmd_argc > 0 && raw->wm_cmd_argv != NULL) {
120 XrmDatabase cmd_db = NULL; /* otherwise it will try to use value as if it was database */
121 ASFlagType found;
122
123 init_xrm ();
124
125 XrmParseCommand (&cmd_db, xrm_cmd_opts, 2, "afterstep",
126 &(raw->wm_cmd_argc), raw->wm_cmd_argv);
127 if (status != NULL) {
128 found = get_afterstep_resources (cmd_db, status);
129
130 if (!get_flags (found, AS_StartDesktop)) { /* checking for CDE workspace specification */
131 if (read_int_resource
132 (cmd_db, "*workspaceList", "*WorkspaceList",
133 &(status->desktop)))
134 set_flags (status->flags, AS_StartDesktop);
135 }
136 XrmDestroyDatabase (cmd_db);
137 }
138 if (raw->wm_client_machine && clean)
139 clean->client_host = text_property2string (raw->wm_client_machine);
140
141 if (raw->wm_cmd_argc > 0 && clean) {
142 int i;
143 int len = 0;
144
145 /* there still are some args left ! lets save it for future use : */
146 /* first check to remove any geometry settings : */
147 for (i = 0; i < raw->wm_cmd_argc; i++)
148 if (raw->wm_cmd_argv[i]) {
149 if (i + 1 < raw->wm_cmd_argc)
150 if (raw->wm_cmd_argv[i + 1] != NULL) {
151 register char *g = raw->wm_cmd_argv[i + 1];
152
153 if (isdigit ((int)*g)
154 || ((*g == '-' || *g == '+') && isdigit ((int)*(g + 1))))
155 if (mystrcasecmp (raw->wm_cmd_argv[i], "-g") == 0
156 || mystrcasecmp (raw->wm_cmd_argv[i],
157 "-geometry") == 0) {
158 raw->wm_cmd_argv[i] = NULL;
159 raw->wm_cmd_argv[++i] = NULL;
160 continue;
161 }
162 }
163 len += strlen (raw->wm_cmd_argv[i]) + 1;
164 }
165 if (len > 0) {
166 register char *trg, *src;
167
168 if (clean->client_cmd)
169 free (clean->client_cmd);
170 trg = clean->client_cmd =
171 safecalloc (1, len + raw->wm_cmd_argc * 2 + 1);
172 for (i = 0; i < raw->wm_cmd_argc; i++)
173 if ((src = raw->wm_cmd_argv[i]) != NULL) {
174 register int k;
175 Bool add_quotes = False;
176
177 for (k = 0; src[k]; k++)
178 if (isspace (src[k]) ||
179 src[k] == '#' ||
180 src[k] == '*' ||
181 src[k] == '$' ||
182 src[k] == ';' ||
183 src[k] == '&' || src[k] == '<' || src[k] == '>'
184 || src[k] == '|' || iscntrl (src[k])) {
185 add_quotes = True;
186 break;
187 }
188
189 if (add_quotes) {
190 trg[0] = '"';
191 ++trg;
192 }
193 for (k = 0; src[k]; k++)
194 trg[k] = src[k];
195 if (add_quotes) {
196 trg[k] = '"';
197 ++k;
198 }
199 trg[k] = ' ';
200 trg += k + 1;
201 }
202 if (trg > clean->client_cmd)
203 trg--;
204 *trg = '\0';
205 }
206 }
207 }
208 }
209
210 void
check_hints_sanity(ScreenInfo * scr,ASHints * clean,ASStatusHints * status,Window client)211 check_hints_sanity (ScreenInfo * scr, ASHints * clean,
212 ASStatusHints * status, Window client)
213 {
214 if (clean) {
215 if (clean->border_width == 0
216 || clean->border_width > scr->MyDisplayHeight / 2)
217 clear_flags (clean->flags, AS_Border);
218
219 if (clean->handle_width > scr->MyDisplayHeight / 2)
220 clean->handle_width = 0;
221
222 if (get_flags (clean->flags, AS_SizeInc)) {
223 if (clean->width_inc == 0)
224 clean->width_inc = 1;
225 if (clean->height_inc == 0)
226 clean->height_inc = 1;
227 }
228
229 if (get_flags (clean->flags, AS_Aspect))
230 if ((clean->min_aspect.x == 0 || clean->min_aspect.y == 0) &&
231 (clean->max_aspect.x == 0 || clean->max_aspect.y == 0))
232 clear_flags (clean->flags, AS_Aspect);
233
234 if (get_flags (clean->flags, AS_Icon))
235 if (clean->icon_file == NULL && clean->icon.pixmap == None)
236 clear_flags (clean->flags, AS_Icon);
237
238 if (status && status->width <= 2 && status->height <= 2) {
239 if (clean->res_class
240 && strcasecmp (clean->res_class, "DockApp") == 0)
241 set_flags (clean->flags, AS_WMDockApp);
242 }
243
244 if (clean->icon.window == client) {
245 clean->icon.window = None;
246 clear_flags (clean->function_mask, AS_FuncMinimize);
247 clear_flags (clean->client_icon_flags, AS_ClientIcon);
248 }
249
250
251 if (clean->frame_name == NULL)
252 clear_flags (clean->flags, AS_Frame);
253 if (clean->windowbox_name == NULL)
254 clear_flags (clean->flags, AS_Windowbox);
255 }
256 }
257
check_status_sanity(ScreenInfo * scr,ASStatusHints * status)258 void check_status_sanity (ScreenInfo * scr, ASStatusHints * status)
259 {
260 if (status) {
261 /* we want to limit user specifyed layers to AS_LayerDesktop < layer < AS_LayerMenu
262 * which is reasonable, since you cannot be lower then Desktop and higher then Menu
263 */
264 if (get_flags (status->flags, AS_StartPositionUser))
265 set_flags (status->flags, AS_StartPosition);
266
267 if (status->layer <= AS_LayerDesktop)
268 status->layer = AS_LayerDesktop + 1;
269 else if (status->layer >= AS_LayerMenu)
270 status->layer = AS_LayerMenu - 1;
271
272 if (status->desktop == INVALID_DESK)
273 clear_flags (status->flags, AS_StartDesktop);
274 LOCAL_DEBUG_OUT ("viewport_x = %d", status->viewport_x);
275 status->viewport_x = FIT_IN_RANGE (0, status->viewport_x, scr->VxMax);
276 LOCAL_DEBUG_OUT ("viewport_x = %d", status->viewport_x);
277 status->viewport_y = FIT_IN_RANGE (0, status->viewport_y, scr->VyMax);
278 if (status->width < 2)
279 status->width = 2;
280 if (status->height < 2)
281 status->height = 2;
282 if (status->border_width == 0
283 || status->border_width > scr->MyDisplayHeight / 2)
284 clear_flags (status->flags, AS_StartBorderWidth);
285 }
286 }
287
get_hint_name_encoding(ASHints * hints,int name_idx)288 unsigned char get_hint_name_encoding (ASHints * hints, int name_idx)
289 {
290 if (hints && name_idx >= 0 && name_idx <= MAX_WINDOW_NAMES)
291 return hints->names_encoding[name_idx];
292 return AS_Text_ASCII;
293 }
294
295 /* Hints merging functions : */
merge_hints(ASRawHints * raw,ASDatabase * db,ASStatusHints * status,ASSupportedHints * list,ASFlagType what,ASHints * reusable_memory,Window client)296 ASHints *merge_hints (ASRawHints * raw, ASDatabase * db,
297 ASStatusHints * status, ASSupportedHints * list,
298 ASFlagType what, ASHints * reusable_memory,
299 Window client)
300 {
301 ASHints *clean = NULL;
302 ASDatabaseRecord db_rec, *pdb_rec;
303 int i;
304 ASFlagType hints_types = ASFLAGS_EVERYTHING;
305
306 if (raw == NULL || list == NULL || what == 0)
307 return NULL;
308 if ((clean = reusable_memory) == NULL)
309 clean = (ASHints *) safecalloc (1, sizeof (ASHints));
310 else
311 memset (clean, 0x00, sizeof (ASHints));
312 if (status)
313 memset (status, 0x00, sizeof (ASStatusHints));
314
315 init_ashints (clean);
316
317 /* collect the names first */
318 if (get_flags (what, HINT_NAME)) {
319 for (i = 0; i < list->hints_num; i++)
320 (list->merge_funcs[i]) (clean, raw, NULL, status, HINT_NAME);
321
322 what &= ~HINT_NAME;
323 }
324 if (clean->names[0] == NULL) {
325 clean->names[0] = mystrdup (""); /* must have at least one valid name string - even if empty */
326 clean->names_encoding[0] = AS_Text_ASCII;
327 }
328 /* we want to make sure that we have Icon Name at all times, if at all possible */
329 if (clean->icon_name == NULL) {
330 clean->icon_name = clean->names[0];
331 clean->icon_name_idx = 0;
332 }
333 /* we don't want to do anything else if all that was requested are names */
334 if (what == 0)
335 return clean;
336
337 pdb_rec = fill_asdb_record (db, clean->names, &db_rec, False);
338
339 if (clean->matched_name0)
340 free (clean->matched_name0);
341 clean->matched_name0 = mystrdup (clean->names[0]);
342 clean->matched_name0_encoding = clean->names_encoding[0];
343
344
345 LOCAL_DEBUG_OUT ("printing db record %p for names %p and db %p", pdb_rec,
346 clean->names, db);
347 if (is_output_level_under_threshold (OUTPUT_LEVEL_DATABASE))
348 print_asdb_matched_rec (NULL, NULL, db, pdb_rec);
349
350 hints_types = get_asdb_hint_mask (pdb_rec);
351 hints_types &=
352 raw->hints_types | (0x01 << HINTS_ASDatabase) | (0x01 <<
353 HINTS_XResources);
354
355 /* now do the rest : */
356 if (what != 0)
357 for (i = 0; i < list->hints_num; i++) { /* only do work if needed */
358 if (get_flags (hints_types, (0x01 << list->hints_types[i]))) {
359 (list->merge_funcs[i]) (clean, raw, pdb_rec, status, what);
360 LOCAL_DEBUG_OUT ("merging hints %d (of %d ) - flags == 0x%lX", i,
361 list->hints_num, clean->flags);
362 }
363 }
364 if (get_flags (what, HINT_STARTUP))
365 merge_command_line (clean, status, raw);
366
367 check_hints_sanity (raw->scr, clean, status, client);
368 check_status_sanity (raw->scr, status);
369
370 /* this is needed so if user changes the list of supported hints -
371 * we could track what was used, and if we need to remerge them
372 */
373 clean->hints_types_raw = raw->hints_types;
374 clean->hints_types_clean =
375 get_flags (raw->hints_types, list->hints_flags);
376
377 return clean;
378 }
379
380 /*
381 * few function - shortcuts to implement update of selected hints :
382 */
383 /* returns True if protocol/function hints actually changed :*/
384 Bool
update_protocols(ScreenInfo * scr,Window w,ASSupportedHints * list,ASFlagType * pprots,ASFlagType * pfuncs)385 update_protocols (ScreenInfo * scr, Window w, ASSupportedHints * list,
386 ASFlagType * pprots, ASFlagType * pfuncs)
387 {
388 ASRawHints raw;
389 ASHints clean;
390 Bool changed = False;
391
392 if (w == None)
393 return False;
394
395 if (collect_hints (scr, w, HINT_PROTOCOL, &raw) != NULL) {
396 if (merge_hints (&raw, NULL, NULL, list, HINT_PROTOCOL, &clean, w) !=
397 NULL) {
398 if (pprots)
399 if ((changed = (*pprots != clean.protocols)))
400 *pprots = clean.protocols;
401 if (pfuncs)
402 if ((changed = (*pfuncs != clean.function_mask)))
403 *pfuncs = clean.function_mask;
404 destroy_hints (&clean, True);
405 }
406 destroy_raw_hints (&raw, True);
407 }
408 return changed;
409 }
410
411 /* returns True if protocol/function hints actually changed :*/
412 Bool
update_colormaps(ScreenInfo * scr,Window w,ASSupportedHints * list,CARD32 ** pcmap_windows)413 update_colormaps (ScreenInfo * scr, Window w, ASSupportedHints * list,
414 CARD32 ** pcmap_windows)
415 {
416 ASRawHints raw;
417 ASHints clean;
418 Bool changed = False;
419 register CARD32 *old_win, *new_win;
420
421
422 if (w == None || pcmap_windows == NULL)
423 return False;
424
425 if (collect_hints (scr, w, HINT_COLORMAP, &raw) != NULL) {
426 if (merge_hints (&raw, NULL, NULL, list, HINT_COLORMAP, &clean, w) !=
427 NULL) {
428 old_win = *pcmap_windows;
429 new_win = clean.cmap_windows;
430 changed = (old_win != new_win);
431 if (new_win != NULL && old_win != NULL) {
432 while (*old_win == *new_win && *old_win != None) {
433 old_win++;
434 new_win++;
435 }
436 changed = (*old_win != *new_win);
437 }
438 if (changed) {
439 if (*pcmap_windows != NULL)
440 free (*pcmap_windows);
441 *pcmap_windows = clean.cmap_windows;
442 clean.cmap_windows = NULL;
443 }
444 destroy_hints (&clean, True);
445 }
446 destroy_raw_hints (&raw, True);
447 }
448 return changed;
449 }
450
451 /****************************************************************************
452 * The following functions actually implement hints merging :
453 ****************************************************************************/
454 static int
add_name_to_list(ASHints * hints,char * name,unsigned char encoding,Bool to_front)455 add_name_to_list (ASHints * hints, char *name, unsigned char encoding,
456 Bool to_front)
457 {
458 register int i;
459 char **list = hints->names;
460 unsigned char *encoding_list = hints->names_encoding;
461
462 if (name == NULL)
463 return -1;
464
465 for (i = 0; i < MAX_WINDOW_NAMES; i++) {
466 if (list[i] == NULL)
467 break;
468 if (encoding_list[i] == encoding && strcmp (name, list[i]) == 0) {
469 free (name);
470 return i;
471 }
472 }
473 if (i >= MAX_WINDOW_NAMES) { /* tough luck - no more space */
474 free (name);
475 return -1;
476 }
477
478 if (to_front) {
479 for (; i > 0; i--) {
480 list[i] = list[i - 1];
481 encoding_list[i] = encoding_list[i - 1];
482 }
483 if (hints->res_name_idx >= 0)
484 ++(hints->res_name_idx);
485 if (hints->res_class_idx >= 0)
486 ++(hints->res_class_idx);
487 if (hints->icon_name_idx >= 0)
488 ++(hints->icon_name_idx);
489 }
490 list[i] = name;
491 encoding_list[i] = encoding;
492 return i;
493 }
494
pointer_name_to_index_in_list(char ** list,char * name)495 static int pointer_name_to_index_in_list (char **list, char *name)
496 {
497 register int i;
498
499 if (name)
500 for (i = 0; i < MAX_WINDOW_NAMES; i++) {
501 if (list[i] == NULL)
502 break;
503 if (name == list[i])
504 return i;
505 }
506 return MAX_WINDOW_NAMES;
507 }
508
509
510 static void
merge_icccm_hints(ASHints * clean,ASRawHints * raw,ASDatabaseRecord * db_rec,ASStatusHints * status,ASFlagType what)511 merge_icccm_hints (ASHints * clean, ASRawHints * raw,
512 ASDatabaseRecord * db_rec, ASStatusHints * status,
513 ASFlagType what)
514 {
515 if (raw == NULL)
516 return;
517 if (get_flags (what, HINT_NAME)) { /* adding all the possible window names in order of increasing importance */
518 if (raw->wm_name)
519 add_name_to_list (clean, text_property2string (raw->wm_name),
520 AS_Text_ASCII, True);
521 if (raw->wm_icon_name) {
522 clean->icon_name_idx =
523 add_name_to_list (clean,
524 text_property2string (raw->wm_icon_name),
525 AS_Text_ASCII, False);
526 clean->icon_name =
527 (clean->icon_name_idx <
528 0) ? NULL : clean->names[clean->icon_name_idx];
529 }
530 if (raw->wm_class) {
531 if (raw->wm_class->res_class) {
532 clean->res_class_idx =
533 add_name_to_list (clean, stripcpy (raw->wm_class->res_class),
534 AS_Text_ASCII, False);
535 clean->res_class =
536 (clean->res_class_idx <
537 0) ? NULL : clean->names[clean->res_class_idx];
538 }
539 if (raw->wm_class->res_name) {
540 clean->res_name_idx =
541 add_name_to_list (clean, stripcpy (raw->wm_class->res_name),
542 AS_Text_ASCII, False);
543 clean->res_name =
544 (clean->res_name_idx <
545 0) ? NULL : clean->names[clean->res_name_idx];
546 }
547 }
548 }
549
550 if (get_flags (what, HINT_STARTUP) && status != NULL) {
551 Bool position_user = False;
552
553 if (raw->wm_hints) {
554 if (get_flags (raw->wm_hints->flags, StateHint)) {
555 if (raw->wm_hints->input == IconicState)
556 set_flags (status->flags, AS_StartsIconic);
557 else
558 clear_flags (status->flags, AS_StartsIconic);
559 }
560 if (get_flags (raw->wm_hints->flags, UrgencyHint)) {
561 status->layer = AS_LayerUrgent;
562 set_flags (status->flags, AS_StartLayer);
563 set_flags (status->flags, AS_Urgent);
564 }
565 }
566
567 if (raw->wm_normal_hints)
568 position_user =
569 (get_flags (raw->wm_normal_hints->flags, USPosition));
570
571 if (!get_flags (status->flags, AS_StartPositionUser) || position_user) {
572 status->x = raw->placement.x;
573 status->y = raw->placement.y;
574 set_flags (status->flags, AS_StartPosition);
575 if (position_user)
576 set_flags (status->flags, AS_StartPositionUser);
577 }
578 status->width = raw->placement.width;
579 status->height = raw->placement.height;
580 set_flags (status->flags, AS_StartSize);
581 status->border_width = raw->border_width;
582 set_flags (status->flags, AS_StartBorderWidth);
583 if (status->border_width > 0) {
584 clean->border_width = status->border_width;
585 set_flags (clean->flags, AS_Border);
586 }
587
588 if (raw->wm_state == IconicState)
589 set_flags (status->flags, AS_StartsIconic);
590 if (raw->wm_state_icon_win != None)
591 status->icon_window = raw->wm_state_icon_win;
592 }
593
594 if (get_flags (what, HINT_GENERAL)) {
595 if (raw->wm_hints) {
596 XWMHints *wmh = raw->wm_hints;
597
598 if (get_flags (wmh->flags, InputHint)) {
599 if (wmh->input)
600 set_flags (clean->flags, AS_AcceptsFocus);
601 else
602 clear_flags (clean->flags, AS_AcceptsFocus);
603 }
604
605 if (get_flags (wmh->flags, IconWindowHint)
606 && wmh->icon_window != None) {
607 clean->icon.window = wmh->icon_window;
608 set_flags (clean->client_icon_flags, AS_ClientIcon);
609 clear_flags (clean->client_icon_flags, AS_ClientIconPixmap);
610 if (get_flags (wmh->flags, IconWindowIsChildHint))
611 set_flags (clean->flags, AS_WMDockApp);
612 } else if (get_flags (wmh->flags, IconPixmapHint)
613 && wmh->icon_pixmap != None) {
614 clean->icon.pixmap = wmh->icon_pixmap;
615 if (get_flags (wmh->flags, IconMaskHint) && wmh->icon_mask != None)
616 clean->icon_mask = wmh->icon_mask;
617 set_flags (clean->client_icon_flags, AS_ClientIcon);
618 set_flags (clean->client_icon_flags, AS_ClientIconPixmap);
619 }
620
621 if (get_flags (wmh->flags, IconPositionHint)) {
622 clean->icon_x = wmh->icon_x;
623 clean->icon_y = wmh->icon_y;
624 set_flags (clean->client_icon_flags, AS_ClientIconPosition);
625 }
626 }
627
628 if (raw->wm_normal_hints) {
629 XSizeHints *nh = raw->wm_normal_hints;
630
631 if (get_flags (nh->flags, PMinSize)) {
632 clean->min_width = nh->min_width;
633 clean->min_height = nh->min_height;
634 set_flags (clean->flags, AS_MinSize);
635 }
636 if (get_flags (nh->flags, PMaxSize)) {
637 clean->max_width = nh->max_width;
638 clean->max_height = nh->max_height;
639 set_flags (clean->flags, AS_MaxSize);
640 }
641 if (get_flags (nh->flags, PResizeInc)) {
642 clean->width_inc = nh->width_inc;
643 clean->height_inc = nh->height_inc;
644 set_flags (clean->flags, AS_SizeInc);
645 }
646 if (get_flags (nh->flags, PAspect)) {
647 clean->min_aspect.x = nh->min_aspect.x;
648 clean->min_aspect.y = nh->min_aspect.y;
649 clean->max_aspect.x = nh->max_aspect.x;
650 clean->max_aspect.y = nh->max_aspect.y;
651 set_flags (clean->flags, AS_Aspect);
652 }
653 if (get_flags (nh->flags, PBaseSize)) {
654 clean->base_width = nh->base_width;
655 clean->base_height = nh->base_height;
656 set_flags (clean->flags, AS_BaseSize);
657 }
658 if (get_flags (nh->flags, PWinGravity)) {
659 clean->gravity = nh->win_gravity;
660 set_flags (clean->flags, AS_Gravity);
661 }
662 }
663
664 }
665
666 if (get_flags (what, HINT_COLORMAP)) {
667 if (raw->wm_cmap_windows && raw->wm_cmap_win_count > 0) {
668 register int i;
669
670 if (clean->cmap_windows)
671 free (clean->cmap_windows);
672 clean->cmap_windows =
673 safecalloc (raw->wm_cmap_win_count + 1, sizeof (CARD32));
674 for (i = 0; i < raw->wm_cmap_win_count; i++)
675 clean->cmap_windows[i] = raw->wm_cmap_windows[i];
676 clean->cmap_windows[i] = None;
677 }
678 }
679
680 if (get_flags (what, HINT_PROTOCOL)) {
681 clean->protocols |= raw->wm_protocols;
682 if (get_flags (clean->protocols, AS_DoesWmDeleteWindow))
683 set_flags (clean->function_mask, AS_FuncClose);
684 }
685 }
686
687 static void
merge_parent_hints(ASParentHints * hints,ASStatusHints * status)688 merge_parent_hints (ASParentHints * hints, ASStatusHints * status)
689 {
690 if (get_flags (hints->flags, AS_StartDesktop))
691 status->desktop = hints->desktop;
692 if (get_flags (hints->flags, AS_StartViewportX))
693 status->viewport_x = hints->viewport_x;
694 if (get_flags (hints->flags, AS_StartViewportY))
695 status->viewport_y = hints->viewport_y;
696 set_flags (status->flags, hints->flags);
697 }
698
699 static void
merge_group_hints(ASHints * clean,ASRawHints * raw,ASDatabaseRecord * db_rec,ASStatusHints * status,ASFlagType what)700 merge_group_hints (ASHints * clean, ASRawHints * raw,
701 ASDatabaseRecord * db_rec, ASStatusHints * status,
702 ASFlagType what)
703 {
704 if (raw == NULL)
705 return;
706 if (raw->group_leader) {
707 if (get_flags (what, HINT_STARTUP) && status != NULL)
708 merge_parent_hints (raw->group_leader, status);
709
710 if (get_flags (what, HINT_GENERAL))
711 clean->group_lead = raw->group_leader->parent;
712 }
713 }
714
715 static void
merge_transient_hints(ASHints * clean,ASRawHints * raw,ASDatabaseRecord * db_rec,ASStatusHints * status,ASFlagType what)716 merge_transient_hints (ASHints * clean, ASRawHints * raw,
717 ASDatabaseRecord * db_rec, ASStatusHints * status,
718 ASFlagType what)
719 {
720 if (raw == NULL)
721 return;
722 if (raw->transient_for) {
723 if (get_flags (what, HINT_STARTUP) && status != NULL)
724 merge_parent_hints (raw->transient_for, status);
725
726 if (get_flags (what, HINT_GENERAL)) {
727 clean->transient_for = raw->transient_for->parent;
728 set_flags (clean->flags, AS_Transient);
729 set_flags (clean->flags, AS_ShortLived);
730 }
731 }
732 }
733
734 static void
decode_flags(ASFlagType * dst_flags,ASFlagsXref * xref,ASFlagType set_flags,ASFlagType flags)735 decode_flags (ASFlagType * dst_flags, ASFlagsXref * xref,
736 ASFlagType set_flags, ASFlagType flags)
737 {
738 if (dst_flags == NULL || set_flags == 0)
739 return;
740 LOCAL_DEBUG_CALLER_OUT
741 ("dst_flags = %lX, set_flags = %lX, flags = 0x%lX", *dst_flags,
742 set_flags, flags);
743 while ((*xref)[0] != 0) {
744 ASFlagType to_set;
745 ASFlagType to_clear;
746 int point;
747
748 if (get_flags (set_flags, (*xref)[0])) {
749 point = (get_flags (flags, (*xref)[0])) ? 1 : 3;
750 to_set = (*xref)[point];
751 to_clear = (*xref)[point + 1];
752 if (to_set != 0)
753 set_flags (*dst_flags, to_set);
754 if (to_clear != 0)
755 clear_flags (*dst_flags, to_clear);
756 }
757 xref++;
758 }
759 }
760
761 static void
encode_flags(ASFlagType * dst_flags,ASFlagsXref * xref,ASFlagType set_flags,ASFlagType flags)762 encode_flags (ASFlagType * dst_flags, ASFlagsXref * xref,
763 ASFlagType set_flags, ASFlagType flags)
764 {
765 if (dst_flags == NULL || set_flags == 0)
766 return;
767
768 while ((*xref)[0] != 0) {
769 if (get_flags (set_flags, (*xref)[0])) {
770 if (((flags & (*xref)[1]) == (*xref)[1])
771 && (flags & (*xref)[2]) == 0)
772 set_flags (*dst_flags, (*xref)[0]);
773 else if (((flags & (*xref)[3]) == (*xref)[3])
774 && (flags & (*xref)[4]) == 0)
775 clear_flags (*dst_flags, (*xref)[0]);
776 }
777 xref++;
778 }
779 }
780
781 #define decode_simple_flags(dst,xref,flags) decode_flags((dst),(xref),ASFLAGS_EVERYTHING,(flags))
782 #define encode_simple_flags(dst,xref,flags) encode_flags((dst),(xref),ASFLAGS_EVERYTHING,(flags))
783
check_motif_hints_sanity(MwmHints * motif_hints)784 void check_motif_hints_sanity (MwmHints * motif_hints)
785 {
786
787 if (get_flags (motif_hints->decorations, MWM_DECOR_ALL))
788 motif_hints->decorations =
789 MWM_DECOR_EVERYTHING & ~(motif_hints->decorations);
790
791 /* Now I have the un-altered decor and functions, but with the
792 * ALL attribute cleared and interpreted. I need to modify the
793 * decorations that are affected by the functions */
794 if (get_flags (motif_hints->flags, MWM_HINTS_FUNCTIONS)) {
795 if (get_flags (motif_hints->functions, MWM_FUNC_ALL))
796 motif_hints->functions =
797 MWM_FUNC_EVERYTHING & ~(motif_hints->functions);
798 if (!get_flags (motif_hints->functions, MWM_FUNC_RESIZE))
799 motif_hints->decorations &= ~MWM_DECOR_RESIZEH;
800 /* MWM_FUNC_MOVE has no impact on decorations. */
801 if (!get_flags (motif_hints->functions, MWM_FUNC_MINIMIZE))
802 motif_hints->decorations &= ~MWM_DECOR_MINIMIZE;
803 if (!get_flags (motif_hints->functions, MWM_FUNC_MAXIMIZE))
804 motif_hints->decorations &= ~MWM_DECOR_MAXIMIZE;
805 /* MWM_FUNC_CLOSE has no impact on decorations. */
806 }
807 /* This rule is implicit, but its easier to deal with if
808 * I take care of it now */
809 if (motif_hints->decorations & (MWM_DECOR_MENU | MWM_DECOR_MINIMIZE |
810 MWM_DECOR_MAXIMIZE))
811 motif_hints->decorations |= MWM_DECOR_TITLE;
812 }
813
814 static ASFlagsXref mwm_decor_xref[] = { /*Flag Set if Set ,Clear if Set,Set if Clear, Clear if Clear */
815 {MWM_DECOR_BORDER, AS_Border, 0, 0, AS_Border | AS_Frame},
816 {MWM_DECOR_RESIZEH, AS_Handles, 0, 0, AS_Handles},
817 {MWM_DECOR_TITLE, AS_Titlebar, 0, 0, AS_Titlebar},
818 {0, 0, 0, 0, 0}
819 };
820
821 static ASFlagsXref mwm_decor_func_xref[] = { /*Flag Set if Set, Clear if Set, Set if Clear, Clear if Clear */
822 {MWM_DECOR_RESIZEH, AS_FuncResize, 0, 0, AS_Handles},
823 {MWM_DECOR_MENU, AS_FuncPopup, 0, 0, AS_FuncPopup},
824 {MWM_DECOR_MINIMIZE, AS_FuncMinimize, 0, 0, AS_FuncMinimize},
825 {MWM_DECOR_MAXIMIZE, AS_FuncMaximize, 0, 0, AS_FuncMaximize},
826 {0, 0, 0, 0, 0}
827 };
828
829 static ASFlagsXref mwm_func_xref[] = { /*Flag Set if Set, Clear if Set, Set if Clear, Clear if Clear */
830 {MWM_FUNC_RESIZE, AS_FuncResize, 0, 0, AS_FuncResize},
831 {MWM_FUNC_MOVE, AS_FuncMove, 0, 0, AS_FuncMove},
832 {MWM_FUNC_MINIMIZE, AS_FuncMinimize, 0, 0, AS_FuncMinimize},
833 {MWM_FUNC_MAXIMIZE, AS_FuncMaximize, 0, 0, AS_FuncMaximize},
834 {MWM_FUNC_CLOSE, AS_FuncClose | AS_FuncKill, 0, 0,
835 AS_FuncClose | AS_FuncKill},
836 {0, 0, 0, 0, 0}
837 };
838
839 static void
merge_motif_hints(ASHints * clean,ASRawHints * raw,ASDatabaseRecord * db_rec,ASStatusHints * status,ASFlagType what)840 merge_motif_hints (ASHints * clean, ASRawHints * raw,
841 ASDatabaseRecord * db_rec, ASStatusHints * status,
842 ASFlagType what)
843 {
844 CARD32 decor = MWM_DECOR_EVERYTHING;
845 CARD32 funcs = MWM_FUNC_EVERYTHING;
846
847 if (raw == NULL)
848 return;
849 if (raw->motif_hints) {
850 INT32 input_mode = 0;
851
852 if (get_flags (raw->motif_hints->flags, MWM_HINTS_INPUT_MODE))
853 input_mode = raw->motif_hints->inputMode;
854
855 if (get_flags (what, HINT_STARTUP) && status && input_mode != 0) {
856 if (input_mode == MWM_INPUT_SYSTEM_MODAL) {
857 status->layer = AS_LayerUrgent;
858 set_flags (status->flags, AS_StartLayer);
859 set_flags (status->flags, AS_StartsSticky);
860 }
861 if (input_mode == MWM_INPUT_FULL_APPLICATION_MODAL) {
862 status->layer = AS_LayerTop;
863 set_flags (status->flags, AS_StartLayer);
864 }
865 }
866
867 check_motif_hints_sanity (raw->motif_hints);
868
869 if (get_flags (raw->motif_hints->flags, MWM_HINTS_FUNCTIONS))
870 funcs = raw->motif_hints->functions;
871 if (get_flags (raw->motif_hints->flags, MWM_HINTS_DECORATIONS))
872 decor = raw->motif_hints->decorations;
873
874 /* finally we can apply conglomerated hints to our flags : */
875 if (get_flags (what, HINT_GENERAL)) {
876 decode_simple_flags (&(clean->flags), mwm_decor_xref, decor);
877 LOCAL_DEBUG_OUT ("motif decor = 0x%lX, clean_flags = 0x%lX", decor,
878 clean->flags);
879 }
880 if (get_flags (what, HINT_PROTOCOL)) {
881 decode_simple_flags (&(clean->function_mask), mwm_decor_func_xref,
882 decor);
883 decode_simple_flags (&(clean->function_mask), mwm_func_xref, funcs);
884 }
885 }
886 }
887
888 static ASFlagsXref gnome_state_xref[] = { /*Flag Set if Set, Clear if Set, Set if Clear, Clear if Clear */
889 {WIN_STATE_STICKY, AS_StartsSticky, 0, 0, 0},
890 {WIN_STATE_MINIMIZED, AS_StartsIconic, 0, 0, 0},
891 {WIN_STATE_MAXIMIZED_VERT, AS_StartsMaximizedY, 0, 0, 0},
892 {WIN_STATE_MAXIMIZED_HORIZ, AS_StartsMaximizedX, 0, 0, 0},
893 {WIN_STATE_HIDDEN, 0, 0, 0, 0},
894 {WIN_STATE_SHADED, AS_StartsShaded, 0, 0, 0},
895 {WIN_STATE_HID_WORKSPACE, 0, 0, 0, 0},
896 {WIN_STATE_HID_TRANSIENT, 0, 0, 0, 0},
897 {WIN_STATE_FIXED_POSITION, 0, 0, 0, 0},
898 {WIN_STATE_ARRANGE_IGNORE, 0, 0, 0, 0},
899 {0, 0, 0, 0, 0}
900 };
901
902 static ASFlagsXref gnome_hints_xref[] = { /*Flag Set if Set, Clear if Set, Set if Clear, Clear if Clear */
903 {WIN_HINTS_SKIP_FOCUS, 0, AS_AcceptsFocus, 0, 0},
904 {WIN_HINTS_SKIP_WINLIST, AS_SkipWinList, 0, 0, 0},
905 {WIN_HINTS_SKIP_TASKBAR, AS_SkipWinList, 0, 0, 0},
906 {WIN_HINTS_GROUP_TRANSIENT, 0, 0, 0, 0},
907 {WIN_HINTS_FOCUS_ON_CLICK, AS_ClickToFocus, 0, 0, 0},
908 {0, 0, 0, 0, 0}
909 };
910
911 #define GNOME_AFFECTED_STATE (AS_StartsSticky|AS_StartsIconic| \
912 AS_StartsMaximizedY|AS_StartsMaximizedX| \
913 AS_StartsShaded)
914
915 Bool
decode_gnome_state(ASFlagType state,ASHints * clean,ASStatusHints * status)916 decode_gnome_state (ASFlagType state, ASHints * clean,
917 ASStatusHints * status)
918 {
919 Bool changed = False;
920 ASFlagType new_state = 0, disable_func = 0;
921
922 decode_simple_flags (&new_state, gnome_state_xref, state);
923 if ((new_state ^ (status->flags & GNOME_AFFECTED_STATE)) != 0) {
924 changed = True;
925 status->flags = new_state | (status->flags & ~GNOME_AFFECTED_STATE);
926 }
927 if (get_flags (new_state, WIN_STATE_FIXED_POSITION))
928 disable_func = AS_FuncMove;
929
930 if ((disable_func ^ (clean->function_mask & AS_FuncMove)) != 0) {
931 changed = True;
932 clean->function_mask =
933 disable_func | (clean->function_mask & ~AS_FuncMove);
934 }
935 return changed;
936 }
937
938 static ASFlagType
encode_gnome_state(ASHints * clean,ASStatusHints * status)939 encode_gnome_state (ASHints * clean, ASStatusHints * status)
940 {
941 ASFlagType new_state = 0;
942
943 if (status)
944 encode_simple_flags (&new_state, gnome_state_xref, status->flags);
945
946 if (get_flags (clean->function_mask, AS_FuncMove))
947 set_flags (new_state, WIN_STATE_FIXED_POSITION);
948
949 return new_state;
950 }
951
952 static void
merge_gnome_hints(ASHints * clean,ASRawHints * raw,ASDatabaseRecord * db_rec,ASStatusHints * status,ASFlagType what)953 merge_gnome_hints (ASHints * clean, ASRawHints * raw,
954 ASDatabaseRecord * db_rec, ASStatusHints * status,
955 ASFlagType what)
956 {
957 register GnomeHints *gh;
958
959 if (raw == NULL)
960 return;
961 gh = &(raw->gnome_hints);
962 if (gh->flags == 0)
963 return;
964
965 if (get_flags (what, HINT_STARTUP) && status != NULL) {
966 if (get_flags (gh->flags, GNOME_LAYER)) {
967 status->layer = gh->layer; /*No clue why we used to do that : (gh->layer - WIN_LAYER_NORMAL) >> 1; */
968 set_flags (status->flags, AS_StartLayer);
969 }
970 if (get_flags (gh->flags, GNOME_WORKSPACE)) {
971 status->desktop = gh->workspace;
972 set_flags (status->flags, AS_StartDesktop);
973 }
974 if (get_flags (gh->flags, GNOME_STATE) && gh->state != 0) {
975 decode_gnome_state (gh->state, clean, status);
976 }
977 }
978
979 if (get_flags (what, HINT_GENERAL)) {
980 if (get_flags (gh->flags, GNOME_HINTS) && gh->hints != 0) {
981 decode_simple_flags (&(clean->flags), gnome_hints_xref, gh->hints);
982 if (get_flags (gh->hints, WIN_HINTS_SKIP_FOCUS))
983 clear_flags (clean->protocols, AS_DoesWmTakeFocus);
984 }
985 }
986 }
987
988 static void
merge_kde_hints(ASHints * clean,ASRawHints * raw,ASDatabaseRecord * db_rec,ASStatusHints * status,ASFlagType what)989 merge_kde_hints (ASHints * clean, ASRawHints * raw,
990 ASDatabaseRecord * db_rec, ASStatusHints * status,
991 ASFlagType what)
992 {
993 register KDEHints *kh;
994
995 if (raw == NULL)
996 return;
997 kh = &(raw->kde_hints);
998 if (kh->flags == 0)
999 return;
1000
1001 if (get_flags (what, HINT_STARTUP) && status != NULL) {
1002 if (get_flags (kh->flags, KDE_SysTrayWindowFor))
1003 set_flags (status->flags, AS_StartsSticky);
1004 }
1005
1006 if (get_flags (what, HINT_GENERAL)) {
1007 if (get_flags (kh->flags, KDE_DesktopWindow))
1008 set_flags (clean->protocols, AS_DoesKIPC);
1009 if (get_flags (kh->flags, KDE_SysTrayWindowFor)) {
1010 set_flags (clean->flags, AS_SkipWinList | AS_DontCirculate);
1011 clear_flags (clean->flags, AS_Handles | AS_Frame);
1012 }
1013 }
1014 }
1015
1016 static ASFlagsXref extwm_state_xref[] = { /*Flag Set if Set, Clear if Set, Set if Clear, Clear if Clear */
1017 {EXTWM_StateSticky, AS_StartsSticky, 0, 0, 0},
1018 {EXTWM_StateMaximizedV, AS_StartsMaximizedY, 0, 0, 0},
1019 {EXTWM_StateMaximizedH, AS_StartsMaximizedX, 0, 0, 0},
1020 {EXTWM_StateShaded, AS_StartsShaded, 0, 0, 0},
1021 {EXTWM_StateFullscreen, AS_Fullscreen, 0, 0, 0},
1022 {EXTWM_StateDemandsAttention, AS_Urgent, 0, 0, 0},
1023 {0, 0, 0, 0, 0}
1024 };
1025
1026 #define EXTWM_AFFECTED_STATE (AS_StartsSticky|AS_StartsMaximizedY| \
1027 AS_StartsMaximizedX|AS_StartsShaded|AS_Fullscreen)
1028
1029 static ASFlagType extwm_types_start_properties[][3] = {
1030 {EXTWM_TypeDesktop, AS_LayerOtherDesktop, AS_StartsSticky},
1031 {EXTWM_TypeDock, AS_LayerService, AS_StartsSticky},
1032 {EXTWM_TypeToolbar, AS_LayerNormal, 0},
1033 {EXTWM_TypeMenu, AS_LayerUrgent, AS_StartsSticky},
1034 {EXTWM_TypeDialog, AS_LayerTop, 0},
1035 {EXTWM_TypeNormal, AS_LayerNormal, 0},
1036 {EXTWM_TypeUtility, AS_LayerTop, 0},
1037 {EXTWM_TypeSplash, AS_LayerTop, AS_ShortLived},
1038 {EXTWM_TypeASModule, AS_LayerNormal, AS_StartsSticky},
1039 {0, 0, 0}
1040 };
1041
1042 static ASFlagType extwm_states_start_properties[][3] = {
1043 {EXTWM_StateFullscreen, AS_LayerUrgent, AS_Fullscreen},
1044 {EXTWM_StateAbove, AS_LayerTop, 0},
1045 {EXTWM_StateBelow, AS_LayerBack, 0},
1046 {EXTWM_StateDemandsAttention, AS_LayerUrgent, 0},
1047 {0, 0, 0}
1048 };
1049
1050 static ASFlagsXref extwm_type_xref[] = { /*Flag Set if Set, Clear if Set, Set if Clear, Clear if Clear */
1051 {EXTWM_TypeDesktop, AS_SkipWinList | AS_DontCirculate,
1052 AS_Titlebar | AS_Handles | AS_Frame, 0, 0},
1053 {EXTWM_TypeDock, AS_AvoidCover, AS_Handles | AS_Frame | AS_Titlebar, 0,
1054 0},
1055 {EXTWM_TypeToolbar, 0, AS_Handles | AS_Frame, 0, 0},
1056 {EXTWM_TypeMenu, AS_SkipWinList | AS_DontCirculate,
1057 AS_Handles | AS_Frame, 0, 0},
1058 {EXTWM_TypeDialog, AS_ShortLived, 0 /*may need to remove handles */ , 0,
1059 0},
1060 {EXTWM_TypeASModule, AS_Module, 0, 0, AS_Module},
1061 {0, 0, 0, 0, 0}
1062 };
1063
1064 static ASFlagsXref extwm_type_func_mask[] = { /*Flag Set if Set, Clear if Set, Set if Clear , Clear if Clear */
1065 {EXTWM_TypeDesktop, 0,
1066 AS_FuncResize | AS_FuncMinimize | AS_FuncMaximize | AS_FuncMove, 0, 0},
1067 {EXTWM_TypeDock, 0, AS_FuncResize | AS_FuncMinimize | AS_FuncMaximize, 0,
1068 0},
1069 {EXTWM_TypeToolbar, 0, AS_FuncResize, 0, 0},
1070 {EXTWM_TypeMenu, 0, AS_FuncResize | AS_FuncMinimize | AS_FuncMaximize, 0,
1071 0},
1072 {0, 0, 0, 0, 0}
1073 };
1074
extwm_state2as_state_flags(ASFlagType extwm_flags)1075 ASFlagType extwm_state2as_state_flags (ASFlagType extwm_flags)
1076 {
1077 ASFlagType as_flags = 0;
1078
1079 decode_simple_flags (&as_flags, extwm_state_xref, extwm_flags);
1080 return as_flags;
1081 }
1082
select_client_icon_argb(CARD32 * icon,int icon_length)1083 static CARD32 *select_client_icon_argb (CARD32 * icon, int icon_length)
1084 {
1085 int offset = 0;
1086 CARD32 *res = NULL;
1087
1088 if (icon == NULL || icon_length <= 2)
1089 return NULL;
1090 while (res == NULL && offset + 2 < icon_length) {
1091 int width = icon[offset];
1092 int height = icon[offset + 1];
1093 int len = width * height;
1094
1095 if (len < 0)
1096 break;
1097 if (len <= (icon_length - offset - 2))
1098 if (width == 48 && height == 48) {
1099 res = safemalloc ((2 + len) * sizeof (CARD32));
1100 memcpy (res, &(icon[offset]), (2 + len) * sizeof (CARD32));
1101 }
1102 offset += 2 + len;
1103 }
1104 offset = 0;
1105 while (res == NULL && offset + 2 < icon_length) {
1106 int width = icon[offset];
1107 int height = icon[offset + 1];
1108 int len = width * height;
1109
1110 if (len < 0)
1111 break;
1112 if (len <= (icon_length - offset - 2))
1113 if (width >= 32 && height >= 32) {
1114 res = safemalloc ((2 + len) * sizeof (CARD32));
1115 memcpy (res, &(icon[offset]), (2 + len) * sizeof (CARD32));
1116 }
1117 offset += 2 + len;
1118 }
1119 if (res == NULL) {
1120 int width = icon[0];
1121 int height = icon[1];
1122 int size = width * height;
1123
1124 icon_length -= 2;
1125 if (size > 0) {
1126 if (size + 2 > icon_length) {
1127 for (width = 128; width > 0; width -= 8)
1128 if (icon_length > width * width) {
1129 height = width;
1130 size = width * width;
1131 break;
1132 }
1133 }
1134 res = safecalloc (size + 2, sizeof (CARD32));
1135 memcpy (res + 2, &(icon[2]), size * sizeof (CARD32));
1136 res[0] = width;
1137 res[1] = height;
1138 }
1139 }
1140 return res;
1141 }
1142
1143 static void
merge_extwm_hints(ASHints * clean,ASRawHints * raw,ASDatabaseRecord * db_rec,ASStatusHints * status,ASFlagType what)1144 merge_extwm_hints (ASHints * clean, ASRawHints * raw,
1145 ASDatabaseRecord * db_rec, ASStatusHints * status,
1146 ASFlagType what)
1147 {
1148
1149 register ExtendedWMHints *eh;
1150
1151 if (raw == NULL)
1152 return;
1153 eh = &(raw->extwm_hints);
1154
1155 if (get_flags (what, HINT_NAME)) {
1156 if (eh->name)
1157 add_name_to_list (clean, stripcpy ((const char *)(eh->name->value)),
1158 AS_Text_UTF8, True);
1159 if (eh->visible_name)
1160 add_name_to_list (clean,
1161 stripcpy ((const char *)(eh->visible_name->value)),
1162 AS_Text_UTF8, True);
1163 if (eh->icon_name)
1164 clean->icon_name_idx =
1165 add_name_to_list (clean,
1166 stripcpy ((const char *)(eh->
1167 icon_name->value)),
1168 AS_Text_UTF8, False);
1169 if (eh->visible_icon_name)
1170 clean->icon_name_idx =
1171 add_name_to_list (clean,
1172 stripcpy ((const char
1173 *)(eh->visible_icon_name->value)),
1174 AS_Text_UTF8, False);
1175 clean->icon_name =
1176 (clean->icon_name_idx <
1177 0) ? NULL : clean->names[clean->icon_name_idx];
1178 }
1179
1180 if (get_flags (what, HINT_STARTUP) && status != NULL) {
1181 if (get_flags (eh->flags, EXTWM_DESKTOP)) {
1182 LOCAL_DEBUG_OUT ("EXTWM Hints Desktop = 0x%X", eh->desktop);
1183 if (eh->desktop == 0xFFFFFFFF)
1184 set_flags (status->flags, AS_StartsSticky);
1185 else {
1186 status->desktop = eh->desktop;
1187 set_flags (status->flags, AS_StartDesktop);
1188 }
1189 }
1190 /* window state hints : */
1191 if (get_flags (eh->flags, EXTWM_StateSet)) {
1192 if (get_flags (eh->state_flags, EXTWM_StateModal)) {
1193 status->layer = AS_LayerTop;
1194 set_flags (status->flags, AS_StartLayer);
1195 }
1196 decode_simple_flags (&(status->flags), extwm_state_xref,
1197 eh->state_flags);
1198 }
1199 /* window type hints : */
1200 if (get_flags
1201 (eh->type_flags, (EXTWM_TypeEverything & (~EXTWM_TypeNormal)))) {
1202 register int i;
1203
1204 for (i = 0; extwm_types_start_properties[i][0] != 0; i++)
1205 if (get_flags (eh->type_flags, extwm_types_start_properties[i][0])) {
1206 if (!get_flags (status->flags, AS_StartLayer)
1207 || status->layer < extwm_types_start_properties[i][1])
1208 status->layer = extwm_types_start_properties[i][1];
1209 set_flags (status->flags, AS_StartLayer);
1210 set_flags (status->flags, extwm_types_start_properties[i][2]);
1211 }
1212 }
1213 if (get_flags
1214 (eh->state_flags,
1215 EXTWM_StateFullscreen | EXTWM_StateAbove | EXTWM_StateBelow)) {
1216 register int i;
1217
1218 for (i = 0; extwm_states_start_properties[i][0] != 0; i++)
1219 if (get_flags
1220 (eh->state_flags, extwm_states_start_properties[i][0])) {
1221 if (!get_flags (status->flags, AS_StartLayer)
1222 || status->layer < extwm_states_start_properties[i][1])
1223 status->layer = extwm_states_start_properties[i][1];
1224 set_flags (status->flags, AS_StartLayer);
1225 set_flags (status->flags, extwm_states_start_properties[i][2]);
1226 }
1227 }
1228 }
1229 if (get_flags (what, HINT_GENERAL)) {
1230 if (get_flags (eh->flags, EXTWM_PID)) {
1231 clean->pid = eh->pid;
1232 set_flags (clean->flags, AS_PID);
1233 }
1234 if (get_flags (eh->flags, EXTWM_WINDOW_OPACITY)) {
1235 clean->window_opacity = eh->window_opacity;
1236 set_flags (clean->flags, AS_WindowOpacity);
1237 }
1238 if (get_flags (eh->flags, EXTWM_ICON)) {
1239 if (clean->icon_argb)
1240 free (clean->icon_argb);
1241 clean->icon_argb =
1242 select_client_icon_argb (eh->icon, eh->icon_length);
1243 set_flags (clean->flags, AS_Icon);
1244 set_flags (clean->client_icon_flags,
1245 AS_ClientIcon | AS_ClientIconARGB);
1246 }
1247 if (get_flags (eh->state_flags, EXTWM_StateSkipTaskbar))
1248 set_flags (clean->flags, AS_SkipWinList);
1249
1250 if (get_flags (eh->flags, EXTWM_TypeSet)) {
1251 clean->extwm_window_type = eh->type_flags;
1252 decode_simple_flags (&(clean->flags), extwm_type_xref,
1253 eh->type_flags);
1254 }
1255 }
1256 if (get_flags (what, HINT_PROTOCOL)) {
1257 if (get_flags (eh->flags, EXTWM_DoesWMPing))
1258 set_flags (clean->protocols, AS_DoesWmPing);
1259 if (get_flags (eh->flags, EXTWM_NAME) && eh->name != NULL)
1260 set_flags (clean->protocols, AS_NeedsVisibleName);
1261 if (get_flags (eh->flags, EXTWM_VISIBLE_NAME)
1262 && eh->visible_name != NULL)
1263 set_flags (clean->protocols, AS_NeedsVisibleName);
1264 if (get_flags (eh->flags, EXTWM_TypeSet))
1265 decode_simple_flags (&(clean->function_mask), extwm_type_func_mask,
1266 eh->type_flags);
1267 }
1268 }
1269
1270 static void
merge_xresources_hints(ASHints * clean,ASRawHints * raw,ASDatabaseRecord * db_rec,ASStatusHints * status,ASFlagType what)1271 merge_xresources_hints (ASHints * clean, ASRawHints * raw,
1272 ASDatabaseRecord * db_rec, ASStatusHints * status,
1273 ASFlagType what)
1274 {
1275 XrmDatabase db = NULL;
1276 extern XrmDatabase as_xrm_user_db;
1277 char *rm_string;
1278
1279
1280 if (raw == NULL || status == NULL || !get_flags (what, HINT_STARTUP))
1281 return;
1282
1283 init_xrm ();
1284
1285 if ((rm_string = XResourceManagerString (dpy)) != NULL)
1286 db = XrmGetStringDatabase (rm_string);
1287 else
1288 db = as_xrm_user_db;
1289
1290 if (db) {
1291 get_afterstep_resources (db, status);
1292 if (db != as_xrm_user_db)
1293 XrmDestroyDatabase (db);
1294 }
1295 }
1296
1297 CARD32
set_hints_window_opacity_percent(ASHints * clean,int opaque_percent)1298 set_hints_window_opacity_percent (ASHints * clean, int opaque_percent)
1299 {
1300 CARD32 res = NET_WM_WINDOW_OPACITY_OPAQUE;
1301
1302 if (opaque_percent <= 0)
1303 res = 0;
1304 else if (opaque_percent < 100)
1305 res = (NET_WM_WINDOW_OPACITY_OPAQUE / 100) * opaque_percent;
1306 if (clean) {
1307 clean->window_opacity = res;
1308 set_flags (clean->flags, AS_WindowOpacity);
1309 }
1310 return res;
1311 }
1312
1313
1314 void
merge_asdb_hints(ASHints * clean,ASRawHints * raw,ASDatabaseRecord * db_rec,ASStatusHints * status,ASFlagType what)1315 merge_asdb_hints (ASHints * clean, ASRawHints * raw,
1316 ASDatabaseRecord * db_rec, ASStatusHints * status,
1317 ASFlagType what)
1318 {
1319 static ASFlagsXref asdb_startup_xref[] = { /*Flag Set if Set ,Clear if Set , Set if Clear, Clear if Clear */
1320 {STYLE_STICKY, AS_StartsSticky, 0, 0, AS_StartsSticky},
1321 {STYLE_START_ICONIC, AS_StartsIconic, 0, 0, AS_StartsIconic},
1322 {STYLE_PPOSITION, AS_StartPositionUser, 0, 0, AS_StartPosition},
1323 {STYLE_FULLSCREEN, AS_Fullscreen, 0, 0, AS_Fullscreen},
1324 {0, 0, 0, 0, 0}
1325 };
1326 static ASFlagsXref asdb_hints_xref[] = { /*Flag Set if Set ,Clear if Set ,Set if Clear ,Clear if Clear */
1327 {STYLE_TITLE, AS_Titlebar, 0, 0, AS_Titlebar},
1328 {STYLE_CIRCULATE, 0, AS_DontCirculate, AS_DontCirculate, 0},
1329 {STYLE_WINLIST, 0, AS_SkipWinList, AS_SkipWinList, 0},
1330 {STYLE_ICON_TITLE, AS_IconTitle, 0, 0, AS_IconTitle},
1331 {STYLE_FOCUS, AS_AcceptsFocus, 0, 0, AS_AcceptsFocus},
1332 {STYLE_AVOID_COVER, AS_AvoidCover, 0, 0, AS_AvoidCover},
1333 {STYLE_VERTICAL_TITLE, AS_VerticalTitle, 0, 0, AS_VerticalTitle},
1334 {STYLE_HANDLES, AS_Handles, 0, 0, AS_Handles},
1335 {STYLE_FOCUS_ON_MAP, AS_FocusOnMap, 0, 0, AS_FocusOnMap},
1336 {STYLE_LONG_LIVING, 0, AS_ShortLived, AS_ShortLived, 0},
1337 {STYLE_IGNORE_CONFIG, AS_IgnoreConfigRequest, 0, 0,
1338 AS_IgnoreConfigRequest},
1339 {STYLE_IGNORE_RESTACK, AS_IgnoreRestackRequest, 0, 0,
1340 AS_IgnoreRestackRequest},
1341 {STYLE_CURRENT_VIEWPORT, AS_UseCurrentViewport, 0, 0,
1342 AS_UseCurrentViewport},
1343 {STYLE_PAGER, AS_HitPager, 0, 0, AS_HitPager},
1344 {0, 0, 0, 0, 0}
1345 };
1346
1347 LOCAL_DEBUG_CALLER_OUT ("0x%lX", what);
1348
1349 if (db_rec == NULL)
1350 return;
1351 if (get_flags (what, HINT_STARTUP) && status != NULL) {
1352 if (get_flags (db_rec->set_data_flags, STYLE_STARTUP_DESK)) {
1353 status->desktop = db_rec->desk;
1354 set_flags (status->flags, AS_StartDesktop);
1355 }
1356 if (get_flags (db_rec->set_data_flags, STYLE_VIEWPORTX)) {
1357 status->viewport_x = db_rec->viewport_x;
1358 LOCAL_DEBUG_OUT ("viewport_x = %d", status->viewport_x);
1359 set_flags (status->flags, AS_StartViewportX);
1360 }
1361 if (get_flags (db_rec->set_data_flags, STYLE_VIEWPORTY)) {
1362 status->viewport_y = db_rec->viewport_y;
1363 set_flags (status->flags, AS_StartViewportY);
1364 }
1365 if (get_flags (db_rec->set_data_flags, STYLE_LAYER)) {
1366 status->layer = db_rec->layer;
1367 set_flags (status->flags, AS_StartLayer);
1368 }
1369
1370 /*not exactly clean solution for the default geometry, but I don't see any other way : */
1371 if (raw != NULL
1372 && get_flags (db_rec->set_data_flags, STYLE_DEFAULT_GEOMETRY)
1373 && !get_flags (status->flags, AS_StartPositionUser)) {
1374 register ASGeometry *g = &(db_rec->default_geometry);
1375
1376 if (get_flags (g->flags, WidthValue))
1377 status->width = g->width;
1378 else if (!get_flags (status->flags, AS_StartSize)) /* defaulting to the startup width */
1379 status->width = raw->placement.width;
1380
1381 if (get_flags (g->flags, HeightValue))
1382 status->height = g->height;
1383 else if (!get_flags (status->flags, AS_StartSize)) /* defaulting to the startup height */
1384 status->height = raw->placement.height;
1385
1386 set_flags (status->flags, AS_StartSize);
1387
1388 if (get_flags (g->flags, XValue))
1389 status->x = get_flags (g->flags, XNegative) ?
1390 raw->scr->MyDisplayWidth - raw->border_width * 2 -
1391 status->width - g->x : g->x;
1392 else if (!get_flags (status->flags, AS_StartPosition))
1393 status->x = raw->placement.x;
1394
1395 if (get_flags (g->flags, YValue))
1396 status->y = get_flags (g->flags, YNegative) ?
1397 raw->scr->MyDisplayHeight - raw->border_width * 2 -
1398 status->height - g->y : g->y;
1399 else if (!get_flags (status->flags, AS_StartPosition))
1400 status->y = raw->placement.y;
1401
1402 if (get_flags (g->flags, YValue | XValue))
1403 set_flags (status->flags, AS_StartPosition | AS_StartPositionUser);
1404 }
1405 /* taking care of startup status flags : */
1406 decode_flags (&(status->flags), asdb_startup_xref, db_rec->set_flags,
1407 db_rec->flags);
1408 }
1409 if (get_flags (what, HINT_GENERAL)) {
1410 if (get_flags (db_rec->set_data_flags, STYLE_ICON))
1411 set_string_value (&(clean->icon_file), mystrdup (db_rec->icon_file),
1412 &(clean->flags), AS_Icon);
1413 /* the following should fix NoIcon handling in the database : */
1414 if (get_flags (db_rec->set_flags, STYLE_ICON)) {
1415 if (get_flags (db_rec->flags, STYLE_ICON))
1416 set_flags (clean->flags, AS_Icon);
1417 else
1418 clear_flags (clean->flags, AS_Icon);
1419 }
1420 if (get_flags (db_rec->set_data_flags, STYLE_BORDER_WIDTH)) {
1421 clean->border_width = db_rec->border_width;
1422 set_flags (clean->flags, AS_Border);
1423 }
1424 if (get_flags (db_rec->set_data_flags, STYLE_HANDLE_WIDTH)) {
1425 clean->handle_width = db_rec->resize_width;
1426 set_flags (clean->flags, AS_Handles);
1427 }
1428 if (get_flags (db_rec->set_data_flags, STYLE_GRAVITY)) {
1429 clean->gravity = db_rec->gravity;
1430 set_flags (clean->flags, AS_Gravity);
1431 }
1432 if (get_flags (db_rec->set_data_flags, STYLE_WINDOW_OPACITY))
1433 set_hints_window_opacity_percent (clean, db_rec->window_opacity);
1434
1435 if (get_flags (db_rec->set_data_flags, STYLE_FRAME))
1436 set_string_value (&(clean->frame_name),
1437 mystrdup (db_rec->frame_name), &(clean->flags),
1438 AS_Frame);
1439 if (get_flags (db_rec->set_data_flags, STYLE_WINDOWBOX))
1440 set_string_value (&(clean->windowbox_name),
1441 mystrdup (db_rec->windowbox_name), &(clean->flags),
1442 AS_Windowbox);
1443 if (get_flags (db_rec->set_data_flags, STYLE_MYSTYLES)) {
1444 register int i;
1445
1446 for (i = 0; i < BACK_STYLES; i++)
1447 if (db_rec->window_styles[i])
1448 set_string (&(clean->mystyle_names[i]),
1449 mystrdup (db_rec->window_styles[i]));
1450 }
1451 /* taking care of flags : */
1452 decode_flags (&(clean->flags), asdb_hints_xref, db_rec->set_flags,
1453 db_rec->flags);
1454 if (get_flags (db_rec->set_flags, STYLE_FOCUS)
1455 && !get_flags (db_rec->flags, STYLE_FOCUS))
1456 clear_flags (clean->protocols, AS_DoesWmTakeFocus);
1457
1458 clean->disabled_buttons = (~(db_rec->buttons)) & (db_rec->set_buttons);
1459 }
1460 }
1461
1462 /* Don't forget to Cleanup after yourself : */
destroy_hints(ASHints * clean,Bool reusable)1463 void destroy_hints (ASHints * clean, Bool reusable)
1464 {
1465 if (clean) {
1466 register int i;
1467
1468 for (i = 0; i < MAX_WINDOW_NAMES; i++)
1469 if (clean->names[i] == NULL)
1470 break;
1471 else
1472 free (clean->names[i]);
1473
1474 if (clean->matched_name0)
1475 free (clean->matched_name0);
1476
1477 if (clean->cmap_windows)
1478 free (clean->cmap_windows);
1479 if (clean->icon_file)
1480 free (clean->icon_file);
1481 if (clean->icon_argb)
1482 free (clean->icon_argb);
1483 if (clean->frame_name)
1484 free (clean->frame_name);
1485 if (clean->windowbox_name)
1486 free (clean->windowbox_name);
1487 for (i = 0; i < BACK_STYLES; i++)
1488 if (clean->mystyle_names[i])
1489 free (clean->mystyle_names[i]);
1490
1491 if (clean->client_host)
1492 free (clean->client_host);
1493 if (clean->client_cmd)
1494 free (clean->client_cmd);
1495
1496 if (reusable) /* we are being paranoid */
1497 memset (clean, 0x00, sizeof (ASHints));
1498 else
1499 free (clean);
1500 }
1501 }
1502
1503 Bool
update_property_hints(Window w,Atom property,ASHints * hints,ASStatusHints * status)1504 update_property_hints (Window w, Atom property, ASHints * hints,
1505 ASStatusHints * status)
1506 {
1507 ASRawHints raw;
1508 Bool changed = False;
1509
1510 if (status == NULL || hints == NULL)
1511 return False;
1512 memset (&raw, 0x00, sizeof (ASRawHints));
1513 raw.wm_state_icon_win = status->icon_window;
1514 raw.scr = ASDefaultScr;
1515 if (handle_client_property_update (w, property, &raw)) {
1516 /* Here we are only interested in properties updtaed by the Window Manager : */
1517 if (property == _XA_WM_STATE) {
1518 unsigned long new_state =
1519 (raw.wm_state == IconicState) ? AS_Iconic : 0;
1520
1521 if ((changed = ((new_state ^ (status->flags & AS_Iconic)) != 0 ||
1522 raw.wm_state_icon_win != status->icon_window))) {
1523 status->icon_window = raw.wm_state_icon_win;
1524 status->flags = (status->flags & (~AS_Iconic)) | new_state;
1525 }
1526 } else if (property == _XA_WIN_LAYER) {
1527 if ((changed = (raw.gnome_hints.layer != status->layer)))
1528 status->layer = raw.gnome_hints.layer;
1529 } else if (property == _XA_WIN_STATE) {
1530 changed = decode_gnome_state (raw.gnome_hints.state, hints, status);
1531 } else if (property == _XA_WIN_WORKSPACE) {
1532 if ((changed = (raw.gnome_hints.workspace != status->desktop)))
1533 status->desktop = raw.gnome_hints.workspace;
1534 } else if (property == _XA_NET_WM_DESKTOP) { /* Extended WM-Hints : */
1535 if ((changed = (raw.extwm_hints.desktop != status->desktop)))
1536 status->desktop = raw.extwm_hints.desktop;
1537 } else if (property == _XA_NET_WM_STATE) {
1538 ASFlagType new_state = 0;
1539
1540 decode_simple_flags (&new_state, extwm_state_xref,
1541 raw.extwm_hints.state_flags);
1542 if ((changed =
1543 (((status->flags & EXTWM_AFFECTED_STATE) ^ new_state) != 0)))
1544 status->flags = new_state | (status->flags & EXTWM_AFFECTED_STATE);
1545 }
1546 destroy_raw_hints (&raw, True);
1547
1548 }
1549 return changed;
1550 }
1551
1552 /* same as above only for window manager : */
1553 void
update_cmd_line_hints(Window w,Atom property,ASHints * hints,ASStatusHints * status)1554 update_cmd_line_hints (Window w, Atom property, ASHints * hints,
1555 ASStatusHints * status)
1556 {
1557 ASRawHints raw;
1558
1559 memset (&raw, 0x00, sizeof (ASRawHints));
1560 raw.scr = ASDefaultScr;
1561 show_debug (__FILE__, __FUNCTION__, __LINE__,
1562 "trying to handle property change for WM_COMMAND");
1563 if (handle_manager_property_update (w, property, &raw)) {
1564 merge_command_line (hints, status, &raw);
1565 destroy_raw_hints (&raw, True);
1566 }
1567 }
1568
1569 /* same as above only for window manager : */
1570 Bool
update_property_hints_manager(Window w,Atom property,ASSupportedHints * list,ASDatabase * db,ASHints * hints,ASStatusHints * status)1571 update_property_hints_manager (Window w, Atom property,
1572 ASSupportedHints * list, ASDatabase * db,
1573 ASHints * hints, ASStatusHints * status)
1574 {
1575 ASRawHints raw;
1576 Bool changed = False;
1577
1578 memset (&raw, 0x00, sizeof (ASRawHints));
1579 raw.scr = ASDefaultScr;
1580 if (status)
1581 raw.wm_state_icon_win = status->icon_window;
1582 show_debug (__FILE__, __FUNCTION__, __LINE__,
1583 "trying to handle property change");
1584 if (handle_manager_property_update (w, property, &raw)) {
1585 ASHints clean;
1586
1587 memset (&clean, 0x00, sizeof (ASHints));
1588 clean.res_name_idx = clean.res_class_idx = clean.icon_name_idx = -1;
1589
1590 show_debug (__FILE__, __FUNCTION__, __LINE__,
1591 "property update handled");
1592 if (property == _XA_WM_STATE) {
1593 if (status) {
1594 unsigned long new_state =
1595 (raw.wm_state == IconicState) ? AS_Iconic : 0;
1596
1597 if ((changed = ((new_state ^ (status->flags & AS_Iconic)) != 0 ||
1598 raw.wm_state_icon_win != status->icon_window))) {
1599 status->icon_window = raw.wm_state_icon_win;
1600 status->flags = (status->flags & (~AS_Iconic)) | new_state;
1601 }
1602 }
1603 return changed;
1604 }
1605 if (hints
1606 && merge_hints (&raw, db, NULL, list, HINT_ANY, &clean,
1607 w) != NULL) {
1608 show_debug (__FILE__, __FUNCTION__, __LINE__, "hints merged");
1609 if (IsNameProp (property)) {
1610 int i;
1611
1612 if (hints->names_encoding[0] == clean.names_encoding[0] &&
1613 mystrcmp (hints->names[0], clean.names[0]) != 0)
1614 changed = True;
1615 else if (mystrcmp (hints->res_name, clean.res_name) != 0)
1616 changed = True;
1617 else if (mystrcmp (hints->res_class, clean.res_class) != 0)
1618 changed = True;
1619 else if (mystrcmp (hints->icon_name, clean.icon_name) != 0)
1620 changed = True;
1621
1622 for (i = 0; i <= MAX_WINDOW_NAMES; ++i)
1623 if (hints->names[i] != NULL) {
1624 free (hints->names[i]);
1625 hints->names[i] = NULL;
1626 } else
1627 break;
1628
1629 for (i = 0; i <= MAX_WINDOW_NAMES; ++i) {
1630 hints->names_encoding[i] = clean.names_encoding[i];
1631 hints->names[i] = clean.names[i];
1632 clean.names[i] = NULL;
1633 }
1634 hints->res_name = clean.res_name;
1635 hints->res_name_idx = clean.res_name_idx;
1636 hints->res_class = clean.res_class;
1637 hints->res_class_idx = clean.res_class_idx;
1638 hints->icon_name = clean.icon_name;
1639 hints->icon_name_idx = clean.icon_name_idx;
1640 show_debug (__FILE__, __FUNCTION__, __LINE__, "names set");
1641
1642 /* Must not do that as it requires sugnificant changes in decorations and stuff :
1643 * and should be done only when FollowTitleChanges is requested */
1644 /* hints->flags = clean.flags ;
1645 hints->function_mask = clean.function_mask ;
1646 */
1647 } else if (property == XA_WM_HINTS) {
1648
1649 } else if (property == XA_WM_NORMAL_HINTS) {
1650
1651 } else if (property == _XA_WM_PROTOCOLS) {
1652
1653 } else if (property == _XA_WM_COLORMAP_WINDOWS) {
1654 }
1655 }
1656 destroy_hints (&clean, True);
1657 destroy_raw_hints (&raw, True);
1658 } else
1659 show_debug (__FILE__, __FUNCTION__, __LINE__,
1660 "failed to handle property update");
1661
1662 return changed;
1663 }
1664
compare_strings(char * str1,char * str2)1665 static Bool compare_strings (char *str1, char *str2)
1666 {
1667 if (str1 != NULL && str2 != NULL)
1668 return (strcmp (str1, str2) != 0);
1669 return (str1 != str2);
1670 }
1671
compare_names(ASHints * old,ASHints * hints)1672 Bool compare_names (ASHints * old, ASHints * hints)
1673 {
1674 register int i;
1675
1676 if (old != NULL && hints != NULL) {
1677 for (i = 0; i < MAX_WINDOW_NAMES; i++)
1678 if (compare_strings (old->names[i], hints->names[i]))
1679 return True;
1680 else if (old->names[i] == NULL)
1681 break;
1682 } else if (old != hints)
1683 return True;
1684
1685 return False;
1686 }
1687
compare_hints(ASHints * old,ASHints * hints)1688 ASFlagType compare_hints (ASHints * old, ASHints * hints)
1689 {
1690 ASFlagType changed = 0;
1691
1692 if (old != NULL && hints != NULL) {
1693 if (compare_strings (old->names[0], hints->names[0]))
1694 set_flags (changed, AS_HintChangeName);
1695 if (compare_strings (old->res_class, hints->res_class))
1696 set_flags (changed, AS_HintChangeClass);
1697 if (compare_strings (old->res_name, hints->res_name))
1698 set_flags (changed, AS_HintChangeResName);
1699 if (compare_strings (old->icon_name, hints->icon_name))
1700 set_flags (changed, AS_HintChangeIconName);
1701 } else if (old != hints)
1702 changed = AS_HintChangeEverything;
1703 return changed;
1704 }
1705
function2mask(int function)1706 ASFlagType function2mask (int function)
1707 {
1708 static ASFlagType as_function_masks[F_PIN_MENU + 1 -
1709 F_WINDOW_FUNC_START] = {
1710 AS_FuncMove, /* F_MOVE, 30 */
1711 AS_FuncResize, /* F_RESIZE, */
1712 0, /* F_RAISE, */
1713 0, /* F_LOWER, */
1714 0, /* F_RAISELOWER, */
1715 0, /* F_PUTONTOP, */
1716 0, /* F_PUTONBACK, */
1717 0, /* F_SETLAYER, */
1718 0, /* F_TOGGLELAYER, */
1719 0, /* F_SHADE, */
1720 AS_FuncKill, /* F_DELETE, */
1721 0, /* F_DESTROY, */
1722 AS_FuncClose, /* F_CLOSE, */
1723 AS_FuncMinimize, /* F_ICONIFY, */
1724 AS_FuncMaximize, /* F_MAXIMIZE, */
1725 AS_FuncMaximize, /* F_FULLSCREEN, */
1726 0, /* F_STICK, */
1727 0, /* F_FOCUS, */
1728 0, /* F_CHANGEWINDOW_UP */
1729 0, /* F_CHANGEWINDOW_DOWN */
1730 0, /* F_GOTO_BOOKMARK */
1731 0, /* F_GETHELP, */
1732 0, /* F_PASTE_SELECTION, */
1733 0, /* F_CHANGE_WINDOWS_DESK, */
1734 0, /* F_BOOKMARK_WINDOW, */
1735 AS_FuncPinMenu /* F_PIN_MENU */
1736 };
1737
1738 if (function == F_POPUP)
1739 return AS_FuncPopup;
1740 if (function <= F_WINDOW_FUNC_START || function > F_PIN_MENU)
1741 return 0;
1742 return as_function_masks[function - (F_WINDOW_FUNC_START + 1)];
1743 }
1744
1745 /****************************************************************************
1746 * Initial placement/anchor management code
1747 ****************************************************************************/
1748
1749 void
constrain_size(ASHints * hints,ASStatusHints * status,int max_width,int max_height)1750 constrain_size (ASHints * hints, ASStatusHints * status, int max_width,
1751 int max_height)
1752 {
1753 int minWidth = 1, minHeight = 1;
1754 int xinc = 1, yinc = 1, delta;
1755 int baseWidth = 0, baseHeight = 0;
1756 int clean_width =
1757 status->width - (status->frame_size[FR_W] +
1758 status->frame_size[FR_E]);
1759 int clean_height =
1760 status->height - (status->frame_size[FR_N] +
1761 status->frame_size[FR_S]);
1762
1763 if (get_flags (hints->flags, AS_MinSize)) {
1764 if (minWidth < hints->min_width)
1765 minWidth = hints->min_width;
1766 if (minHeight < hints->min_height)
1767 minHeight = hints->min_height;
1768 } else if (get_flags (hints->flags, AS_BaseSize)) {
1769 if (minWidth < hints->base_width)
1770 minWidth = hints->base_width;
1771 if (minHeight < hints->base_height)
1772 minHeight = hints->base_height;
1773 }
1774
1775 if (get_flags (hints->flags, AS_BaseSize)) {
1776 baseWidth = hints->base_width;
1777 baseHeight = hints->base_height;
1778 } else if (get_flags (hints->flags, AS_MinSize)) {
1779 baseWidth = minWidth;
1780 baseHeight = minHeight;
1781 }
1782
1783 if (get_flags (hints->flags, AS_MaxSize)
1784 && !get_flags (status->flags, AS_Fullscreen)) {
1785 if (max_width == 0 || max_width > hints->max_width)
1786 max_width = hints->max_width;
1787 if (max_height == 0 || max_height > hints->max_height)
1788 max_height = hints->max_height;
1789 } else {
1790 if (max_width == 0)
1791 max_width = MAX ((unsigned int)minWidth, clean_width);
1792 if (max_height == 0)
1793 max_height = MAX ((unsigned int)minHeight, clean_height);
1794 }
1795 LOCAL_DEBUG_OUT
1796 ("base_size = %dx%d, min_size = %dx%d, curr_size = %dx%d, max_size = %dx%d",
1797 baseWidth, baseHeight, minWidth, minHeight, clean_width,
1798 clean_height, max_width, max_height);
1799 /* First, clamp to min and max values */
1800 clean_width = FIT_IN_RANGE (minWidth, clean_width, max_width);
1801 clean_height = FIT_IN_RANGE (minHeight, clean_height, max_height);
1802 LOCAL_DEBUG_OUT ("clumped_size = %dx%d", clean_width, clean_height);
1803
1804 /* Second, fit to base + N * inc */
1805 if (get_flags (hints->flags, AS_SizeInc)) {
1806 xinc = hints->width_inc;
1807 yinc = hints->height_inc;
1808 clean_width = (((clean_width - baseWidth) / xinc) * xinc) + baseWidth;
1809 clean_height =
1810 (((clean_height - baseHeight) / yinc) * yinc) + baseHeight;
1811 LOCAL_DEBUG_OUT ("inced_size = %dx%d", clean_width, clean_height);
1812 }
1813
1814 /* Third, adjust for aspect ratio */
1815 #define maxAspectX hints->max_aspect.x
1816 #define maxAspectY hints->max_aspect.y
1817 #define minAspectX hints->min_aspect.x
1818 #define minAspectY hints->min_aspect.y
1819 #define makemult(a,b) ((b==1) ? (a) : (((int)((a)/(b))) * (b)) )
1820
1821 /* The math looks like this:
1822
1823 * minAspectX dwidth maxAspectX
1824 * ---------- <= ------- <= ----------
1825 * minAspectY dheight maxAspectY
1826 *
1827 * If that is multiplied out, then the width and height are
1828 * invalid in the following situations:
1829 *
1830 * minAspectX * dheight > minAspectY * dwidth
1831 * maxAspectX * dheight < maxAspectY * dwidth
1832 *
1833 */
1834
1835 if (get_flags (hints->flags, AS_Aspect)) {
1836 if ((minAspectX * clean_height > minAspectY * clean_width)) {
1837 delta =
1838 makemult (minAspectX * clean_height / minAspectY - clean_width,
1839 xinc);
1840 if (clean_width + delta <= max_width)
1841 clean_width += delta;
1842 else {
1843 delta =
1844 makemult (clean_height - clean_width * minAspectY / minAspectX,
1845 yinc);
1846 if (clean_height - delta >= minHeight)
1847 clean_height -= delta;
1848 }
1849 }
1850 if (maxAspectX * clean_height < maxAspectY * clean_width) {
1851 delta =
1852 makemult (clean_width * maxAspectY / maxAspectX - clean_height,
1853 yinc);
1854 if (clean_height + delta <= max_height)
1855 clean_height += delta;
1856 else {
1857 delta =
1858 makemult (clean_width - maxAspectX * clean_height / maxAspectY,
1859 xinc);
1860 if (clean_width - delta >= minWidth)
1861 clean_width -= delta;
1862 }
1863 }
1864 LOCAL_DEBUG_OUT ("aspected_size = %dx%d", clean_width, clean_height);
1865 }
1866 status->width =
1867 clean_width + status->frame_size[FR_W] + status->frame_size[FR_E];
1868 status->height =
1869 clean_height + status->frame_size[FR_N] + status->frame_size[FR_S];
1870 }
1871
1872 static int _as_gravity_offsets[11][2] = {
1873 {0, 0}, /* ForgetGravity */
1874 {-1, -1}, /* NorthWestGravity */
1875 {2, -1}, /* NorthGravity */
1876 {1, -1}, /* NorthEastGravity */
1877 {-1, 2}, /* WestGravity */
1878 {0, 0}, /* CenterGravity */
1879 {1, 2}, /* EastGravity */
1880 {-1, 1}, /* SouthWestGravity */
1881 {2, 1}, /* SouthGravity */
1882 {1, 1}, /* SouthEastGravity */
1883 {2, 2} /* StaticGravity */
1884 };
1885
get_gravity_offsets(ASHints * hints,int * xp,int * yp)1886 void get_gravity_offsets (ASHints * hints, int *xp, int *yp)
1887 {
1888 register int g = NorthWestGravity;
1889
1890 if (get_flags (hints->flags, AS_Gravity))
1891 g = hints->gravity;
1892
1893 if (g < ForgetGravity || g > StaticGravity)
1894 *xp = *yp = 0;
1895 else {
1896 *xp = (int)_as_gravity_offsets[g][0];
1897 *yp = (int)_as_gravity_offsets[g][1];
1898 }
1899 }
1900
1901 int
translate_asgeometry(ScreenInfo * scr,ASGeometry * asg,int * px,int * py,unsigned int * pwidth,unsigned int * pheight)1902 translate_asgeometry (ScreenInfo * scr, ASGeometry * asg, int *px, int *py,
1903 unsigned int *pwidth, unsigned int *pheight)
1904 {
1905 int grav = NorthWestGravity;
1906 unsigned int width = 1, height = 1;
1907
1908 if (scr == NULL)
1909 scr = ASDefaultScr;
1910
1911 if (asg) {
1912 if (get_flags (asg->flags, XNegative)) {
1913 if (get_flags (asg->flags, YNegative))
1914 grav = SouthEastGravity;
1915 else
1916 grav = NorthEastGravity;
1917 } else if (get_flags (asg->flags, YNegative))
1918 grav = SouthWestGravity;
1919 }
1920 if (asg && get_flags (asg->flags, WidthValue)) {
1921 width = asg->width;
1922 if (pwidth)
1923 *pwidth = width;
1924 } else if (pwidth)
1925 width = *pwidth;
1926
1927 if (asg && get_flags (asg->flags, HeightValue)) {
1928 height = asg->height;
1929 if (pheight)
1930 *pheight = height;
1931 } else if (pheight)
1932 height = *pheight;
1933 if (asg) {
1934 if (get_flags (asg->flags, XValue) && px) {
1935 if (get_flags (asg->flags, XNegative)) {
1936 if (asg->x <= 0)
1937 *px = scr->MyDisplayWidth + asg->x;
1938 else
1939 *px = scr->MyDisplayWidth - asg->x;
1940 *px -= width;
1941 } else
1942 *px = asg->x;
1943 }
1944 if (get_flags (asg->flags, YValue) && py) {
1945 if (get_flags (asg->flags, YNegative)) {
1946 if (asg->x <= 0)
1947 *py = scr->MyDisplayHeight + asg->y;
1948 else
1949 *py = scr->MyDisplayHeight - asg->y;
1950 *py -= height;
1951 } else
1952 *py = asg->y;
1953 }
1954 } else {
1955 if (px)
1956 *px = 0;
1957 if (py)
1958 *py = 0;
1959 }
1960
1961 return grav;
1962 }
1963
1964 int
make_anchor_pos(ASStatusHints * status,int pos,int size,int vpos,int grav,int max_pos)1965 make_anchor_pos (ASStatusHints * status, int pos, int size, int vpos,
1966 int grav, int max_pos)
1967 { /* anchor position is always in virtual coordinates */
1968 int bw = 0;
1969
1970 if (get_flags (status->flags, AS_StartBorderWidth))
1971 bw = status->border_width;
1972
1973 /* position of the sticky window is stored in real coordinates */
1974 if (!get_flags (status->flags, AS_Sticky))
1975 pos += vpos;
1976
1977 /* trying to place window partly on screen, unless user really wants it */
1978 if (!get_flags (status->flags, AS_StartPositionUser)) {
1979 if (pos > max_pos)
1980 pos = max_pos;
1981 else if (pos + size < 16)
1982 pos = 16 - size;
1983 }
1984
1985 switch (grav) {
1986 case 0: /* Center */
1987 pos += bw + (size >> 1);
1988 break;
1989 case 1: /* East */
1990 pos += bw + size + bw;
1991 break;
1992 case 2: /* Static */
1993 pos += bw;
1994 break;
1995 default: /* West */
1996 break;
1997 }
1998 return pos;
1999 }
2000
2001 /* reverse transformation */
2002 int
make_status_pos(ASStatusHints * status,int pos,unsigned int size,int vpos,int grav)2003 make_status_pos (ASStatusHints * status, int pos, unsigned int size,
2004 int vpos, int grav)
2005 { /* status position is always in real coordinates */
2006 unsigned int bw = 0;
2007
2008 if (get_flags (status->flags, AS_StartBorderWidth))
2009 bw = status->border_width;
2010
2011 /* position of the sticky window is stored in real coordinates */
2012 if (!get_flags (status->flags, AS_Sticky))
2013 pos -= vpos;
2014
2015 switch (grav) {
2016 case 0: /* Center */
2017 pos -= bw + (size >> 1);
2018 break;
2019 case 1: /* East */
2020 pos -= bw + size + bw;
2021 break;
2022 case 2: /* Static */
2023 pos -= bw;
2024 break;
2025 default: /* West */
2026 break;
2027 }
2028 return pos;
2029 }
2030
2031 void
make_detach_pos(ASHints * hints,ASStatusHints * status,XRectangle * anchor,int * detach_x,int * detach_y)2032 make_detach_pos (ASHints * hints, ASStatusHints * status,
2033 XRectangle * anchor, int *detach_x, int *detach_y)
2034 {
2035 unsigned int bw = 0;
2036 int x = 0, y = 0;
2037 int grav_x, grav_y;
2038
2039 if (hints == NULL || status == NULL || anchor == NULL)
2040 return;
2041
2042 if (get_flags (status->flags, AS_StartBorderWidth))
2043 bw = status->border_width;
2044
2045 get_gravity_offsets (hints, &grav_x, &grav_y);
2046
2047 /* position of the sticky window is stored in real coordinates */
2048 x = anchor->x;
2049 y = anchor->y;
2050 if (!get_flags (status->flags, AS_Sticky)) {
2051 x -= status->viewport_x;
2052 y -= status->viewport_y;
2053 }
2054
2055 if (detach_x) {
2056 APPLY_GRAVITY (grav_x, x, anchor->width, bw, bw);
2057 *detach_x = x;
2058 }
2059 if (detach_y) {
2060 APPLY_GRAVITY (grav_y, y, anchor->height, bw, bw);
2061 *detach_y = y;
2062 }
2063 }
2064
2065 /***** New Code : *****************************************************/
2066
2067 /*
2068 * frame_size[] must be set to the real frame decoration size if window
2069 * is being moved by us or to border_width if moved by client.
2070 *
2071 * width and height must be that of a client
2072 *
2073 * x, y are of top left corner of the client.
2074 * North Central South Static
2075 * y -FR_N +height/2 +height+FR_S +0
2076 *
2077 * West Central East Static
2078 * x -FR_W +width/2 +width+FR_E +0
2079 */
2080
2081 void
status2anchor(XRectangle * anchor,ASHints * hints,ASStatusHints * status,int vwidth,int vheight)2082 status2anchor (XRectangle * anchor, ASHints * hints,
2083 ASStatusHints * status, int vwidth, int vheight)
2084 {
2085 if (get_flags (status->flags, AS_Size)) {
2086 int w, h;
2087
2088 constrain_size (hints, status, vwidth, vheight);
2089 w = (int)status->width - ((int)status->frame_size[FR_W] +
2090 (int)status->frame_size[FR_E]);
2091 if (w > 0)
2092 anchor->width = w;
2093 h = (int)status->height - ((int)status->frame_size[FR_N] +
2094 (int)status->frame_size[FR_S]);
2095 if (h > 0)
2096 anchor->height = h;
2097 }
2098
2099 if (get_flags (status->flags, AS_Position)) {
2100 int grav_x = -1, grav_y = -1;
2101 int offset;
2102
2103 get_gravity_offsets (hints, &grav_x, &grav_y);
2104
2105 LOCAL_DEBUG_OUT
2106 ("grav_x = %d, width = %d, bw1 = %d, bw2 = %d, status_x = %d",
2107 grav_x, anchor->width, status->frame_size[FR_W],
2108 status->frame_size[FR_E], status->x);
2109 offset = 0;
2110 APPLY_GRAVITY (grav_x, offset, anchor->width,
2111 status->frame_size[FR_W] + status->frame_border_width,
2112 status->frame_size[FR_E] + status->frame_border_width);
2113 anchor->x = status->x - offset;
2114
2115 LOCAL_DEBUG_OUT
2116 ("grav_y = %d, height = %d, bw1 = %d, bw2 = %d, status_y = %d",
2117 grav_y, anchor->height, status->frame_size[FR_N],
2118 status->frame_size[FR_S], status->y);
2119
2120 offset = 0;
2121 APPLY_GRAVITY (grav_y, offset, anchor->height,
2122 status->frame_size[FR_N] + status->frame_border_width,
2123 status->frame_size[FR_S] + status->frame_border_width);
2124 anchor->y = status->y - offset;
2125
2126 LOCAL_DEBUG_OUT ("anchor = %+d%+d", anchor->x, anchor->y);
2127 if (!get_flags (status->flags, AS_Sticky)) {
2128 anchor->x += (int)status->viewport_x;
2129 anchor->y += (int)status->viewport_y;
2130 }
2131 LOCAL_DEBUG_OUT ("anchor = %+d%+d", anchor->x, anchor->y);
2132 }
2133 }
2134
2135 void
anchor2status(ASStatusHints * status,ASHints * hints,XRectangle * anchor)2136 anchor2status (ASStatusHints * status, ASHints * hints,
2137 XRectangle * anchor)
2138 {
2139 int grav_x = -1, grav_y = -1;
2140 int offset;
2141
2142 status->width =
2143 anchor->width + status->frame_size[FR_W] + status->frame_size[FR_E];
2144 status->height =
2145 anchor->height + status->frame_size[FR_N] + status->frame_size[FR_S];
2146 set_flags (status->flags, AS_Size);
2147
2148 get_gravity_offsets (hints, &grav_x, &grav_y);
2149
2150 LOCAL_DEBUG_OUT
2151 ("grav_x = %d, width = %d, bw1 = %d, bw2 = %d, anchor_x = %d",
2152 grav_x, anchor->width, status->frame_size[FR_W],
2153 status->frame_size[FR_E], anchor->x);
2154 offset = 0;
2155 APPLY_GRAVITY (grav_x, offset, anchor->width,
2156 status->frame_size[FR_W] + status->frame_border_width,
2157 status->frame_size[FR_E] + status->frame_border_width);
2158 status->x = anchor->x + offset;
2159
2160 LOCAL_DEBUG_OUT
2161 ("grav_y = %d, height = %d, bw1 = %d, bw2 = %d, anchor_y = %d",
2162 grav_y, anchor->height, status->frame_size[FR_N],
2163 status->frame_size[FR_S], anchor->y);
2164
2165 offset = 0;
2166 APPLY_GRAVITY (grav_y, offset, anchor->height,
2167 status->frame_size[FR_N] + status->frame_border_width,
2168 status->frame_size[FR_S] + status->frame_border_width);
2169 status->y = anchor->y + offset;
2170
2171 LOCAL_DEBUG_OUT ("status = %+d%+d", status->x, status->y);
2172 if (!get_flags (status->flags, AS_Sticky)) {
2173 status->x -= (int)status->viewport_x;
2174 status->y -= (int)status->viewport_y;
2175 }
2176 LOCAL_DEBUG_OUT ("status = %+d%+d", status->x, status->y);
2177 set_flags (status->flags, AS_Position);
2178 }
2179
2180
2181 /***** Old Code : *****************************************************/
2182
2183 ASFlagType
change_placement(ScreenInfo * scr,ASHints * hints,ASStatusHints * status,XPoint * anchor,ASStatusHints * new_status,int vx,int vy,ASFlagType what)2184 change_placement (ScreenInfo * scr, ASHints * hints,
2185 ASStatusHints * status, XPoint * anchor,
2186 ASStatusHints * new_status, int vx, int vy,
2187 ASFlagType what)
2188 {
2189 ASFlagType todo = 0;
2190 int grav_x, grav_y;
2191 register int max_x = scr->MyDisplayWidth - 16;
2192 register int max_y = scr->MyDisplayHeight - 16;
2193 int new_x, new_y;
2194
2195 if (!get_flags (what, AS_Size | AS_Position) || status == NULL
2196 || new_status == NULL)
2197 return 0;
2198
2199 new_x = status->x - (vx - status->viewport_x);
2200 new_y = status->y - (vy - status->viewport_y);
2201 get_gravity_offsets (hints, &grav_x, &grav_y);
2202 if (!get_flags (status->flags, AS_Sticky)) {
2203 max_x += scr->VxMax;
2204 max_y += scr->VyMax;
2205 }
2206
2207 if (get_flags (what, AS_Size)) {
2208 constrain_size (hints, new_status, scr->VxMax + scr->MyDisplayWidth,
2209 scr->VyMax + scr->MyDisplayHeight);
2210 if (new_status->width != status->width) {
2211 status->width = new_status->width;
2212 set_flags (todo, TODO_RESIZE_X);
2213 if (grav_x == 0 || grav_x == 1)
2214 set_flags (todo, TODO_MOVE_X);
2215 }
2216 if (new_status->height != status->height) {
2217 status->height = new_status->height;
2218 set_flags (todo, TODO_RESIZE_Y);
2219 if (grav_y == 0 || grav_y == 1)
2220 set_flags (todo, TODO_MOVE_Y);
2221 }
2222 }
2223
2224 if (!get_flags (what, AS_BorderWidth)
2225 && new_status->border_width != status->border_width) {
2226 status->border_width = new_status->border_width;
2227 set_flags (todo, TODO_MOVE);
2228 }
2229
2230 if (!get_flags (status->flags, AS_Sticky)
2231 && (status->viewport_x != vx || status->viewport_y != vy))
2232 set_flags (todo, TODO_MOVE);
2233
2234 if (get_flags (what, AS_Position)) {
2235 if (status->x != new_status->x) {
2236 new_x = new_status->x;
2237 set_flags (todo, TODO_MOVE_X);
2238 } else
2239 if (make_anchor_pos
2240 (status, new_x, status->width, vx, max_x, grav_x) != anchor->x)
2241 set_flags (todo, TODO_MOVE_X);
2242
2243 if (status->y != new_status->y) {
2244 new_y = new_status->y;
2245 set_flags (todo, TODO_MOVE_Y);
2246 } else
2247 if (make_anchor_pos
2248 (status, new_y, status->height, vy, max_y,
2249 grav_y) != anchor->y)
2250 set_flags (todo, TODO_MOVE_Y);
2251 }
2252 if (get_flags (todo, TODO_MOVE_X)) {
2253 anchor->x =
2254 make_anchor_pos (status, new_x, status->width, vx, max_x, grav_x);
2255 status->x =
2256 make_status_pos (status, anchor->x, status->width, vx, grav_x);
2257 }
2258 if (get_flags (todo, TODO_MOVE_Y)) {
2259 anchor->y =
2260 make_anchor_pos (status, new_y, status->height, vy, max_y, grav_y);
2261 status->y =
2262 make_status_pos (status, anchor->y, status->height, vy, grav_y);
2263 }
2264 if (!get_flags (status->flags, AS_Sticky)) {
2265 status->viewport_x = vx;
2266 status->viewport_y = vy;
2267 }
2268
2269 return what;
2270 }
2271
2272 int
calculate_viewport(int * ppos,int size,int scr_vpos,int scr_size,int max_viewport)2273 calculate_viewport (int *ppos, int size, int scr_vpos, int scr_size,
2274 int max_viewport)
2275 {
2276 int viewport = -1;
2277 int pos = ppos ? *ppos : 0;
2278
2279 if (pos >= scr_size)
2280 viewport = pos / scr_size;
2281 else if (pos + size < 0) {
2282 if (pos + scr_vpos > 0)
2283 viewport = (scr_vpos + pos) / scr_size;
2284 else
2285 viewport = 0;
2286 } else
2287 return scr_vpos;
2288
2289 viewport *= scr_size;
2290 viewport = MIN (viewport, max_viewport);
2291 if (ppos)
2292 *ppos = pos + (scr_vpos - viewport);
2293 return viewport;
2294 }
2295
2296 int
gravitate_position(int pos,unsigned int size,unsigned int scr_size,int grav,unsigned int bw)2297 gravitate_position (int pos, unsigned int size, unsigned int scr_size,
2298 int grav, unsigned int bw)
2299 {
2300 if (pos < 0 || pos + size > scr_size)
2301 return pos;
2302 if (grav == 1) /* East or South gravity */
2303 pos = (int)scr_size - (int)(pos + bw + size + bw);
2304
2305 return pos;
2306 }
2307
2308 /***********************************************************************************
2309 * we build a command line here, so we can restart an app with exactly the same
2310 * parameters:
2311 ***********************************************************************************/
format_geometry_string(int x,int y,int width,int height,int unit_width,int unit_height,int screen_size_x,int screen_size_y,int gravity)2312 static char *format_geometry_string (int x, int y, int width, int height,
2313 int unit_width, int unit_height,
2314 int screen_size_x, int screen_size_y,
2315 int gravity)
2316 {
2317 char *g =
2318 safemalloc (15 + 1 + 15 + 1 + 15 + 1 + 15 + 1 /* large enough */ );
2319 char x_sign = '+';
2320 char y_sign = '+';
2321 int x2 = x + width, y2 = y + height;
2322
2323 #define FGS_CHECK_SIGN(d) do{if(d<0){d = 0;/* d##_sign = '-';*/} }while(0)
2324 #define FGS_APPLY_NEGATIVE_GRAV(d) do{ d = screen_size_##d - d##2; if(d<0) d=0; d##_sign = '-' ;}while(0)
2325 if (gravity == SouthWestGravity) {
2326 FGS_APPLY_NEGATIVE_GRAV (y);
2327 FGS_CHECK_SIGN (x);
2328 } else if (gravity == SouthEastGravity) {
2329 FGS_APPLY_NEGATIVE_GRAV (x);
2330 FGS_APPLY_NEGATIVE_GRAV (y);
2331 } else if (gravity == NorthEastGravity) {
2332 FGS_APPLY_NEGATIVE_GRAV (x);
2333 FGS_CHECK_SIGN (y);
2334 } else {
2335 FGS_CHECK_SIGN (x);
2336 FGS_CHECK_SIGN (y);
2337 }
2338 #undef FGS_CHECK_SIGN
2339 #undef FGS_APPLY_NEGATIVE_GRAV
2340
2341 sprintf (g, "%dx%d%c%d%c%d ", unit_width, unit_height, x_sign, x, y_sign,
2342 y);
2343 return g;
2344 }
2345
make_client_geometry_string(ScreenInfo * scr,ASHints * hints,ASStatusHints * status,XRectangle * anchor,int vx,int vy,char ** pure_geometry)2346 char *make_client_geometry_string (ScreenInfo * scr, ASHints * hints,
2347 ASStatusHints * status,
2348 XRectangle * anchor, int vx, int vy,
2349 char **pure_geometry)
2350 {
2351 char *geom = NULL;
2352 int detach_x, detach_y;
2353 int grav_x, grav_y;
2354 int bw = 0;
2355 int width, height, unit_width, unit_height;
2356
2357 if (hints == NULL || status == NULL || anchor == NULL)
2358 return NULL;
2359
2360 if (get_flags (status->flags, AS_StartBorderWidth))
2361 bw = status->border_width;
2362
2363 make_detach_pos (hints, status, anchor, &detach_x, &detach_y);
2364
2365 vx = calculate_viewport (&detach_x, anchor->width, vx,
2366 scr->MyDisplayWidth, scr->VxMax);
2367 vy = calculate_viewport (&detach_y, anchor->height, vy,
2368 scr->MyDisplayHeight, scr->VyMax);
2369
2370 get_gravity_offsets (hints, &grav_x, &grav_y);
2371
2372 detach_x =
2373 gravitate_position (detach_x, anchor->width, bw, scr->MyDisplayWidth,
2374 grav_x);
2375 detach_y =
2376 gravitate_position (detach_y, anchor->height, bw,
2377 scr->MyDisplayHeight, grav_y);
2378
2379 width = anchor->width;
2380 height = anchor->height;
2381
2382 unit_width =
2383 (hints->width_inc >
2384 0) ? (width - hints->base_width) / hints->width_inc : width;
2385 unit_height =
2386 (hints->height_inc >
2387 0) ? (height - hints->base_height) / hints->height_inc : height;
2388
2389 if (pure_geometry) {
2390 *pure_geometry =
2391 format_geometry_string (detach_x, detach_y, width, height, width,
2392 height, scr->MyDisplayWidth,
2393 scr->MyDisplayHeight, hints->gravity);
2394 }
2395 geom =
2396 format_geometry_string (detach_x, detach_y, width, height,
2397 unit_width, unit_height, scr->MyDisplayWidth,
2398 scr->MyDisplayHeight, hints->gravity);;
2399 return geom;
2400 }
2401
make_client_command(ScreenInfo * scr,ASHints * hints,ASStatusHints * status,XRectangle * anchor,int vx,int vy)2402 char *make_client_command (ScreenInfo * scr, ASHints * hints,
2403 ASStatusHints * status, XRectangle * anchor,
2404 int vx, int vy)
2405 {
2406 char *client_cmd = NULL;
2407 char *geom =
2408 make_client_geometry_string (scr, hints, status, anchor, vx, vy,
2409 NULL);
2410
2411 if (hints->client_cmd == NULL || geom == NULL)
2412 return NULL;
2413
2414 /* supplying everything as : -xrm "afterstep*desk:N" */
2415 client_cmd =
2416 safemalloc (strlen (hints->client_cmd) + 11 + strlen (geom) + 1 + 1);
2417 sprintf (client_cmd, "%s -geometry %s ", hints->client_cmd, geom);
2418 /*, status->desktop, status->layer, status->viewport_x, status->viewport_y */
2419 return client_cmd;
2420 }
2421
2422 /***********************************************************************
2423 * Setrting Hints on the window :
2424 ***********************************************************************/
2425 static Bool
client_hints2wm_hints(XWMHints * wm_hints,ASHints * hints,ASStatusHints * status)2426 client_hints2wm_hints (XWMHints * wm_hints, ASHints * hints,
2427 ASStatusHints * status)
2428 {
2429 memset (wm_hints, 0x00, sizeof (XWMHints));
2430
2431 if (status) {
2432 wm_hints->flags = StateHint;
2433 if (get_flags (status->flags, AS_StartsIconic))
2434 wm_hints->initial_state = IconicState;
2435 else
2436 wm_hints->initial_state = WithdrawnState;
2437 }
2438 /* does this application rely on the window manager to get keyboard input? */
2439 if (get_flags (hints->flags, AS_AcceptsFocus)) {
2440 set_flags (wm_hints->flags, InputHint);
2441 wm_hints->input = True;
2442 }
2443
2444 /* window to be used as icon */
2445 if (get_flags (hints->client_icon_flags, AS_ClientIcon)) {
2446 if (!get_flags (hints->client_icon_flags, AS_ClientIconPixmap)) {
2447 wm_hints->icon_window = hints->icon.window;
2448 set_flags (wm_hints->flags, IconWindowHint);
2449 } else { /* pixmap to be used as icon */
2450 set_flags (wm_hints->flags, IconPixmapHint);
2451 wm_hints->icon_pixmap = hints->icon.pixmap;
2452
2453 if (hints->icon_mask) { /* pixmap to be used as mask for icon_pixmap */
2454 set_flags (wm_hints->flags, IconMaskHint);
2455 wm_hints->icon_mask = hints->icon_mask;
2456 }
2457 }
2458 }
2459
2460 /* initial position of icon */
2461 if (get_flags (hints->client_icon_flags, AS_ClientIconPosition)) {
2462 set_flags (wm_hints->flags, IconPositionHint);
2463 wm_hints->icon_x = hints->icon_x;
2464 wm_hints->icon_y = hints->icon_y;
2465 }
2466
2467 if (hints->group_lead) {
2468 set_flags (wm_hints->flags, WindowGroupHint);
2469 wm_hints->window_group = hints->group_lead;
2470 }
2471
2472 /* if( get_flags( hints->flags, AS_AvoidCover ) )
2473 set_flags( wm_hints->flags, UrgencyHint );
2474 */
2475 return (wm_hints->flags != StateHint
2476 || wm_hints->initial_state == IconicState);
2477 }
2478
2479 static Bool
client_hints2size_hints(XSizeHints * size_hints,ASHints * hints,ASStatusHints * status)2480 client_hints2size_hints (XSizeHints * size_hints, ASHints * hints,
2481 ASStatusHints * status)
2482 {
2483 memset (size_hints, 0x00, sizeof (XSizeHints));
2484 if (status) {
2485 if (get_flags (status->flags, AS_StartPosition | AS_StartPositionUser)) {
2486 if (get_flags (status->flags, AS_StartPositionUser))
2487 set_flags (size_hints->flags, USPosition);
2488 else
2489 set_flags (size_hints->flags, PPosition);
2490 }
2491
2492 if (get_flags (status->flags, AS_StartSize | AS_StartSizeUser)) {
2493 if (get_flags (status->flags, AS_StartSizeUser))
2494 set_flags (size_hints->flags, USSize);
2495 else
2496 set_flags (size_hints->flags, PSize);
2497 }
2498 }
2499 if (get_flags (hints->flags, AS_MinSize)) {
2500 size_hints->min_width = hints->min_width;
2501 size_hints->min_height = hints->min_height;
2502 set_flags (size_hints->flags, PMinSize);
2503 }
2504 if (get_flags (hints->flags, AS_MaxSize)) {
2505 size_hints->max_width = hints->max_width;
2506 size_hints->max_height = hints->max_height;
2507 set_flags (size_hints->flags, PMaxSize);
2508 }
2509 if (get_flags (hints->flags, AS_SizeInc)) {
2510 size_hints->width_inc = hints->width_inc;
2511 size_hints->height_inc = hints->height_inc;
2512 set_flags (size_hints->flags, PResizeInc);
2513 }
2514 if (get_flags (hints->flags, AS_Aspect)) {
2515 size_hints->min_aspect.x = hints->min_aspect.x;
2516 size_hints->min_aspect.y = hints->min_aspect.y;
2517 size_hints->max_aspect.x = hints->max_aspect.x;
2518 size_hints->max_aspect.y = hints->max_aspect.y;
2519 set_flags (size_hints->flags, PAspect);
2520 }
2521 if (get_flags (hints->flags, AS_BaseSize)) {
2522 size_hints->base_width = hints->base_width;
2523 size_hints->base_height = hints->base_height;
2524 set_flags (size_hints->flags, PBaseSize);
2525 }
2526 if (get_flags (hints->flags, AS_Gravity)) {
2527 size_hints->win_gravity = hints->gravity;
2528 set_flags (size_hints->flags, PWinGravity);
2529 }
2530 return (size_hints->flags != 0);
2531 }
2532
2533 static Bool
client_hints2wm_protocols(ASFlagType * protocols,ASHints * hints)2534 client_hints2wm_protocols (ASFlagType * protocols, ASHints * hints)
2535 {
2536 if (protocols == NULL || hints == NULL)
2537 return False;
2538
2539 *protocols =
2540 hints->protocols & (AS_DoesWmDeleteWindow | AS_DoesWmTakeFocus);
2541 return (*protocols != 0);
2542 }
2543
2544 static Bool
client_hints2motif_hints(MwmHints * motif_hints,ASHints * hints,ASStatusHints * status)2545 client_hints2motif_hints (MwmHints * motif_hints, ASHints * hints,
2546 ASStatusHints * status)
2547 {
2548 ASFlagType tmp;
2549
2550 memset (motif_hints, 0x00, sizeof (MwmHints));
2551
2552 if (status) {
2553 if (get_flags (status->flags, AS_StartLayer)) {
2554 if (status->layer == AS_LayerUrgent
2555 && get_flags (status->flags, AS_StartsSticky)) {
2556 motif_hints->inputMode = MWM_INPUT_SYSTEM_MODAL;
2557 set_flags (motif_hints->flags, MWM_HINTS_INPUT_MODE);
2558 } else if (status->layer == AS_LayerTop) {
2559 motif_hints->inputMode = MWM_INPUT_SYSTEM_MODAL;
2560 set_flags (motif_hints->flags, MWM_INPUT_FULL_APPLICATION_MODAL);
2561 }
2562 }
2563 }
2564 /* finally we can apply conglomerated hints to our flags : */
2565 tmp = motif_hints->decorations;
2566 encode_simple_flags (&tmp, mwm_decor_xref, hints->flags);
2567 encode_simple_flags (&tmp, mwm_decor_func_xref, hints->function_mask);
2568 motif_hints->decorations = tmp;
2569 tmp = motif_hints->functions;
2570 encode_simple_flags (&tmp, mwm_func_xref, hints->function_mask);
2571 motif_hints->functions = tmp;
2572
2573 check_motif_hints_sanity (motif_hints);
2574
2575 if (motif_hints->functions != 0)
2576 set_flags (motif_hints->flags, MWM_HINTS_FUNCTIONS);
2577 if (motif_hints->decorations != 0)
2578 set_flags (motif_hints->flags, MWM_HINTS_DECORATIONS);
2579
2580 return (motif_hints->flags != 0);
2581 }
2582
2583 static Bool
client_hints2gnome_hints(GnomeHints * gnome_hints,ASHints * hints,ASStatusHints * status)2584 client_hints2gnome_hints (GnomeHints * gnome_hints, ASHints * hints,
2585 ASStatusHints * status)
2586 {
2587 ASFlagType tmp = 0;
2588
2589 memset (gnome_hints, 0x00, sizeof (GnomeHints));
2590
2591 if (status) {
2592 if (get_flags (status->flags, AS_StartLayer)) {
2593 gnome_hints->layer = (status->layer << 1) + WIN_LAYER_NORMAL;
2594 set_flags (gnome_hints->flags, GNOME_LAYER);
2595 }
2596
2597 if (get_flags (status->flags, AS_StartDesktop)) {
2598 gnome_hints->workspace = status->desktop;
2599 set_flags (gnome_hints->flags, GNOME_WORKSPACE);
2600 }
2601 }
2602 gnome_hints->state = encode_gnome_state (hints, status);
2603 if (gnome_hints->state != 0)
2604 set_flags (gnome_hints->flags, GNOME_STATE);
2605
2606 tmp = gnome_hints->hints;
2607 encode_simple_flags (&tmp, gnome_hints_xref, hints->flags);
2608 gnome_hints->hints = tmp;
2609 if (gnome_hints->hints != 0)
2610 set_flags (gnome_hints->flags, GNOME_HINTS);
2611
2612 return (gnome_hints->flags != 0);
2613 }
2614
2615 static Bool
client_hints2extwm_hints(ExtendedWMHints * extwm_hints,ASHints * hints,ASStatusHints * status)2616 client_hints2extwm_hints (ExtendedWMHints * extwm_hints, ASHints * hints,
2617 ASStatusHints * status)
2618 {
2619 memset (extwm_hints, 0x00, sizeof (ExtendedWMHints));
2620
2621 if (status) {
2622 if (get_flags (status->flags, AS_StartsSticky)) {
2623 extwm_hints->desktop = 0xFFFFFFFF;
2624 set_flags (extwm_hints->flags, EXTWM_DESKTOP);
2625 } else if (get_flags (status->flags, AS_StartDesktop)) {
2626 extwm_hints->desktop = status->desktop;
2627 set_flags (extwm_hints->flags, EXTWM_DESKTOP);
2628 }
2629 /* window state hints : */
2630 if (get_flags (status->flags, AS_StartLayer)
2631 && status->layer >= AS_LayerTop) {
2632 set_flags (extwm_hints->state_flags, EXTWM_StateModal);
2633 set_flags (extwm_hints->flags, EXTWM_StateSet);
2634 encode_simple_flags (&(extwm_hints->state_flags), extwm_state_xref,
2635 status->flags);
2636 }
2637 if (get_flags (status->flags, AS_SkipWinList)) {
2638 set_flags (extwm_hints->state_flags, EXTWM_StateSkipTaskbar);
2639 set_flags (extwm_hints->flags, EXTWM_StateSet);
2640 }
2641
2642 /* window type hints : */
2643 if (get_flags (status->flags, AS_StartLayer)
2644 && status->layer != AS_LayerNormal) {
2645 register int i;
2646
2647 for (i = 0; extwm_types_start_properties[i][0] != 0; i++)
2648 if (status->layer == extwm_types_start_properties[i][1] &&
2649 (get_flags (status->flags, extwm_types_start_properties[i][2])
2650 || extwm_types_start_properties[i][2] == 0)) {
2651 set_flags (extwm_hints->type_flags,
2652 extwm_types_start_properties[i][0]);
2653 }
2654 }
2655 }
2656
2657 encode_simple_flags (&(extwm_hints->type_flags), extwm_type_xref,
2658 hints->flags);
2659 encode_simple_flags (&(extwm_hints->type_flags), extwm_type_func_mask,
2660 hints->function_mask);
2661 if (extwm_hints->type_flags != 0)
2662 set_flags (extwm_hints->flags, EXTWM_TypeSet);
2663
2664 if (hints->pid >= 0 && get_flags (hints->flags, AS_PID)) {
2665 set_flags (extwm_hints->flags, EXTWM_PID);
2666 extwm_hints->pid = hints->pid;
2667 }
2668 if (hints->icon_argb != NULL
2669 && get_flags (hints->client_icon_flags, AS_ClientIcon)) {
2670 set_flags (extwm_hints->flags, EXTWM_ICON);
2671 extwm_hints->icon_length =
2672 hints->icon_argb[0] * hints->icon_argb[1] + 2;
2673 extwm_hints->icon =
2674 safemalloc (extwm_hints->icon_length * sizeof (CARD32));
2675 memcpy (extwm_hints->icon, hints->icon_argb,
2676 extwm_hints->icon_length * sizeof (CARD32));
2677 }
2678 if (get_flags (hints->protocols, AS_DoesWmPing))
2679 set_flags (extwm_hints->flags, EXTWM_DoesWMPing);
2680
2681 return (extwm_hints->flags != 0);
2682 }
2683
2684
2685 Bool
set_all_client_hints(Window w,ASHints * hints,ASStatusHints * status,Bool set_command)2686 set_all_client_hints (Window w, ASHints * hints, ASStatusHints * status,
2687 Bool set_command)
2688 {
2689 XWMHints wm_hints;
2690 XSizeHints size_hints;
2691 ASFlagType protocols = 0;
2692 MwmHints mwm_hints;
2693 GnomeHints gnome_hints;
2694 ExtendedWMHints extwm_hints;
2695
2696 if (w == None || hints == NULL)
2697 return False;
2698
2699 set_client_names (w, hints->names[0], hints->icon_name, hints->res_class,
2700 hints->res_name);
2701
2702 if (client_hints2wm_hints (&wm_hints, hints, status))
2703 XSetWMHints (dpy, w, &wm_hints);
2704
2705 if (get_flags (hints->flags, AS_Transient))
2706 XSetTransientForHint (dpy, w, hints->transient_for);
2707
2708 if (client_hints2size_hints (&size_hints, hints, status))
2709 XSetWMNormalHints (dpy, w, &size_hints);
2710
2711 if (client_hints2extwm_hints (&extwm_hints, hints, status))
2712 set_extwm_hints (w, &extwm_hints);
2713
2714 if (client_hints2wm_protocols (&protocols, hints)
2715 || get_flags (extwm_hints.flags, EXTWM_DoesWMPing))
2716 set_client_protocols (w, protocols, extwm_hints.flags);
2717
2718 #if 0
2719 if (set_command) {
2720 char *host_name = safecalloc (MAXHOSTNAME + 1, sizeof (char));
2721
2722 if (mygethostname (host_name, MAXHOSTNAME))
2723 set_text_property (w, XA_WM_CLIENT_MACHINE, &host_name, 1,
2724 TPE_String);
2725
2726 if (MyArgs.saved_argc > 0 && MyArgs.saved_argv)
2727 set_text_property (w, XA_WM_COMMAND, MyArgs.saved_argv,
2728 MyArgs.saved_argc, TPE_String);
2729 free (host_name);
2730 }
2731 #endif
2732 if (client_hints2motif_hints (&mwm_hints, hints, status))
2733 set_multi32bit_property (w, _XA_MwmAtom, XA_CARDINAL, 4,
2734 mwm_hints.flags, mwm_hints.functions,
2735 mwm_hints.decorations, mwm_hints.inputMode);
2736
2737 if (client_hints2gnome_hints (&gnome_hints, hints, status))
2738 set_gnome_hints (w, &gnome_hints);
2739
2740 return True;
2741 }
2742
2743
get_client_icon_image(ScreenInfo * scr,ASHints * hints,int desired_size)2744 ASImage *get_client_icon_image (ScreenInfo * scr, ASHints * hints,
2745 int desired_size)
2746 {
2747 ASImage *im = NULL;
2748
2749 if (hints) {
2750 char *icon_file = hints->icon_file;
2751 ASImage *icon_file_im = NULL;
2752 Bool icon_file_isDefault = False;
2753
2754 if (icon_file && Database) {
2755 if (Database->style_default.icon_file != NULL
2756 && strcmp (icon_file, Database->style_default.icon_file) == 0)
2757 icon_file_isDefault = True;
2758 }
2759 if (get_flags (hints->client_icon_flags, AS_ClientIcon)) {
2760 Bool use_client_icon = (hints->icon_file == NULL
2761 || Database == NULL);
2762
2763 if (!use_client_icon) {
2764 if (icon_file_isDefault)
2765 use_client_icon = True;
2766 else {
2767 icon_file_im =
2768 get_asimage (scr->image_manager, icon_file, 0xFFFFFFFF, 100);
2769 if (icon_file_im == NULL)
2770 use_client_icon = True;
2771 LOCAL_DEBUG_OUT ("loaded icon from file \"%s\" into %p",
2772 icon_file ? icon_file : "(null)", im);
2773 }
2774
2775 }
2776 if (use_client_icon) {
2777 /* first try ARGB icon If provided by the application : */
2778 if (get_flags (hints->client_icon_flags, AS_ClientIconARGB)
2779 && hints->icon_argb != NULL) {
2780 /* TODO: we also need to check for newfashioned ARGB icon from
2781 * extended WM specs here
2782 */
2783 int width = hints->icon_argb[0];
2784 int height = hints->icon_argb[1];
2785
2786 im = convert_argb2ASImage (scr->asv, width, height,
2787 hints->icon_argb + 2, NULL);
2788 LOCAL_DEBUG_OUT ("converted client's ARGB into an icon %dx%d %p",
2789 width, height, im);
2790
2791 }
2792 if (im == NULL && get_flags (hints->client_icon_flags, AS_ClientIconPixmap) && hints->icon.pixmap != None) { /* convert client's icon into ASImage */
2793 unsigned int width, height;
2794
2795 get_drawable_size (hints->icon.pixmap, &width, &height);
2796 im = picture2asimage (scr->asv, hints->icon.pixmap,
2797 hints->icon_mask, 0, 0, width, height,
2798 0xFFFFFFFF, False, 100);
2799
2800 LOCAL_DEBUG_OUT
2801 ("converted client's pixmap into an icon %dx%d %p", width,
2802 height, im);
2803 }
2804 }
2805 }
2806 LOCAL_DEBUG_OUT ("im = %p", im);
2807 if (im == NULL) {
2808 if (CombinedCategories != NULL) {
2809 ASDesktopEntry *de = NULL;
2810
2811 if (hints->names[0]) {
2812 char *name = hints->names[0];
2813 int i = 0;
2814 char old;
2815
2816 while (name[i] && !isspace (name[i]))
2817 ++i;
2818 if (i > 0) {
2819 old = name[i];
2820 name[i] = '\0';
2821 de = fetch_desktop_entry (CombinedCategories, name);
2822 LOCAL_DEBUG_OUT
2823 ("found desktop entry %p, for name[0] = \"%s\"", de, name);
2824 name[i] = old;
2825 }
2826 }
2827 LOCAL_DEBUG_OUT ("icon file = %p, default = %d", icon_file,
2828 icon_file_isDefault);
2829 if (de == NULL && (icon_file == NULL || icon_file_isDefault)) {
2830 LOCAL_DEBUG_OUT ("CombinedCategories = %p", CombinedCategories);
2831
2832 de = fetch_desktop_entry (CombinedCategories, hints->res_name);
2833 LOCAL_DEBUG_OUT ("found desktop entry %p, for res_name = \"%s\"",
2834 de, hints->res_name);
2835 if (de == NULL)
2836 de = fetch_desktop_entry (CombinedCategories,
2837 hints->res_class);
2838 LOCAL_DEBUG_OUT
2839 ("found desktop entry %p, for res_class = \"%s\"", de,
2840 hints->res_class);
2841 }
2842 if (de) {
2843 if (de && de->ref_count > 0 && de->Icon) {
2844 if (icon_file_im) {
2845 safe_asimage_destroy (icon_file_im);
2846 icon_file_im = NULL;
2847 }
2848 icon_file = de->Icon;
2849 }
2850 }
2851
2852 }
2853 if (icon_file) {
2854 if (icon_file_im)
2855 im = icon_file_im;
2856 else
2857 im = load_environment_icon_any (icon_file, desired_size);
2858 /*get_asimage (scr->image_manager, icon_file, 0xFFFFFFFF, 100); */
2859 LOCAL_DEBUG_OUT ("loaded icon from \"%s\" into %dx%d %p",
2860 icon_file, im ? im->width : 0,
2861 im ? im->height : 0, im);
2862 } else {
2863 LOCAL_DEBUG_OUT ("no icon to use %s", "");
2864 }
2865 }
2866 }
2867 return im;
2868 }
2869
2870
2871 /***********************************************************************************
2872 * Hints printing functions :
2873 ***********************************************************************************/
2874
print_clean_hints(stream_func func,void * stream,ASHints * clean)2875 void print_clean_hints (stream_func func, void *stream, ASHints * clean)
2876 {
2877 register int i;
2878
2879 if (!pre_print_check
2880 (&func, &stream, clean, "No hints available(NULL)."))
2881 return;
2882 for (i = 0; i < MAX_WINDOW_NAMES && clean->names[i]; i++) {
2883 func (stream, "CLEAN.NAMES[%d] = \"%s\";\n", i, clean->names[i]);
2884 func (stream, "CLEAN.NAMES_ENCODING[%d] = %d;\n", i,
2885 clean->names_encoding[i]);
2886 }
2887 if (clean->icon_name) {
2888 func (stream, "CLEAN.icon_name = \"%s\";\n", clean->icon_name);
2889 func (stream, "CLEAN.icon_name_encoding = %d;\n",
2890 clean->names_encoding[clean->icon_name_idx]);
2891 }
2892 if (clean->res_name) {
2893 func (stream, "CLEAN.res_name = \"%s\";\n", clean->res_name);
2894 func (stream, "CLEAN.res_name_encoding = %d;\n",
2895 clean->names_encoding[clean->res_name_idx]);
2896 }
2897 if (clean->res_class) {
2898 func (stream, "CLEAN.res_class = \"%s\";\n", clean->res_class);
2899 func (stream, "CLEAN.res_class_encoding = %d;\n",
2900 clean->names_encoding[clean->res_class_idx]);
2901 }
2902 func (stream, "CLEAN.flags = 0x%lX;\n", clean->flags);
2903 func (stream, "CLEAN.protocols = 0x%lX;\n", clean->protocols);
2904 func (stream, "CLEAN.function_mask = 0x%lX;\n", clean->function_mask);
2905
2906 if (get_flags (clean->flags, AS_Icon)) {
2907 if (get_flags (clean->client_icon_flags, AS_ClientIcon)) {
2908 if (get_flags (clean->client_icon_flags, AS_ClientIconARGB)
2909 && clean->icon_argb) {
2910 func (stream, "CLEAN.icon.argb.width = 0x%lX;\n",
2911 clean->icon_argb[0]);
2912 func (stream, "CLEAN.icon.argb.height = 0x%lX;\n",
2913 clean->icon_argb[1]);
2914 } else if (get_flags (clean->client_icon_flags, AS_ClientIconPixmap))
2915 func (stream, "CLEAN.icon.pixmap = 0x%lX;\n", clean->icon.pixmap);
2916 else
2917 func (stream, "CLEAN.icon.window = 0x%lX;\n", clean->icon.window);
2918 func (stream, "CLEAN.icon_mask = 0x%lX;\n", clean->icon_mask);
2919 if (get_flags (clean->client_icon_flags, AS_ClientIconPosition))
2920 func (stream, "CLEAN.icon_x = %d;\nCLEAN.icon_y = %d;\n",
2921 clean->icon_x, clean->icon_y);
2922 } else if (clean->icon_file)
2923 func (stream, "CLEAN.icon_file = \"%s\";\n", clean->icon_file);
2924 }
2925 if (get_flags (clean->flags, AS_MinSize))
2926 func (stream, "CLEAN.min_width = %u;\nCLEAN.min_height = %u;\n",
2927 clean->min_width, clean->min_height);
2928 if (get_flags (clean->flags, AS_MaxSize))
2929 func (stream, "CLEAN.max_width = %u;\nCLEAN.max_height = %u;\n",
2930 clean->max_width, clean->max_height);
2931 if (get_flags (clean->flags, AS_SizeInc))
2932 func (stream, "CLEAN.width_inc = %u;\nCLEAN.height_inc = %u;\n",
2933 clean->width_inc, clean->height_inc);
2934 if (get_flags (clean->flags, AS_Aspect)) {
2935 func (stream, "CLEAN.min_aspect.x = %d;\nCLEAN.min_aspect.y = %d;\n",
2936 clean->min_aspect.x, clean->min_aspect.y);
2937 func (stream, "CLEAN.max_aspect.x = %d;\nCLEAN.max_aspect.y = %d;\n",
2938 clean->max_aspect.x, clean->max_aspect.y);
2939 }
2940 if (get_flags (clean->flags, AS_BaseSize))
2941 func (stream, "CLEAN.base_width = %u;\nCLEAN.base_height = %u;\n",
2942 clean->base_width, clean->base_height);
2943 if (get_flags (clean->flags, AS_Gravity))
2944 func (stream, "CLEAN.gravity = %d;\n", clean->gravity);
2945 if (get_flags (clean->flags, AS_Border))
2946 func (stream, "CLEAN.border_width = %u;\n", clean->border_width);
2947 if (get_flags (clean->flags, AS_Handles))
2948 func (stream, "CLEAN.handle_width = %u;\n", clean->handle_width);
2949
2950 if (clean->group_lead)
2951 func (stream, "CLEAN.group_lead = 0x%lX;\n", clean->group_lead);
2952 if (get_flags (clean->flags, AS_Transient))
2953 func (stream, "CLEAN.transient_for = 0x%lX;\n", clean->transient_for);
2954
2955 if (clean->cmap_windows)
2956 for (i = 0; clean->cmap_windows[i] != None; i++)
2957 func (stream, "CLEAN.cmap_windows[%d] = 0x%lX;\n", i,
2958 clean->cmap_windows[i]);
2959
2960 if (get_flags (clean->flags, AS_PID))
2961 func (stream, "CLEAN.pid = %d;\n", clean->pid);
2962 if (clean->frame_name && get_flags (clean->flags, AS_Frame))
2963 func (stream, "CLEAN.frame_name = \"%s\";\n", clean->frame_name);
2964 if (clean->windowbox_name && get_flags (clean->flags, AS_Windowbox))
2965 func (stream, "CLEAN.windowbox_name = \"%s\";\n",
2966 clean->windowbox_name);
2967
2968 for (i = 0; i < BACK_STYLES; i++)
2969 if (clean->mystyle_names[i])
2970 func (stream, "CLEAN.mystyle_names[%d] = \"%s\";\n", i,
2971 clean->mystyle_names[i]);
2972
2973 func (stream, "CLEAN.disabled_buttons = 0x%lX;\n",
2974 clean->disabled_buttons);
2975
2976 func (stream, "CLEAN.hints_types_raw = 0x%lX;\n",
2977 clean->hints_types_raw);
2978 func (stream, "CLEAN.hints_types_clean = 0x%lX;\n",
2979 clean->hints_types_clean);
2980
2981 if (clean->client_host)
2982 func (stream, "CLEAN.client_host = \"%s\";\n", clean->client_host);
2983 if (clean->client_cmd)
2984 func (stream, "CLEAN.client_cmd = \"%s\";\n", clean->client_cmd);
2985
2986 func (stream, "CLEAN.extwm_window_type = \"%s\";\n", clean->extwm_window_type);
2987 }
2988
2989 void
print_status_hints(stream_func func,void * stream,ASStatusHints * status)2990 print_status_hints (stream_func func, void *stream, ASStatusHints * status)
2991 {
2992 if (!pre_print_check
2993 (&func, &stream, status, "No status available(NULL)."))
2994 return;
2995
2996 func (stream, "STATUS.flags = 0x%lX;\n", status->flags);
2997
2998 if (get_flags (status->flags, AS_StartPositionUser)) {
2999 func (stream, "STATUS.user_x = %d;\n", status->x);
3000 func (stream, "STATUS.user_y = %d;\n", status->y);
3001 } else {
3002 func (stream, "STATUS.x = %d;\n", status->x);
3003 func (stream, "STATUS.y = %d;\n", status->y);
3004 }
3005 if (get_flags (status->flags, AS_Size)) {
3006 func (stream, "STATUS.width = %d;\n", status->width);
3007 func (stream, "STATUS.height = %d;\n", status->height);
3008 }
3009 if (get_flags (status->flags, AS_Desktop))
3010 func (stream, "STATUS.desktop = %d;\n", status->desktop);
3011 if (get_flags (status->flags, AS_Layer))
3012 func (stream, "STATUS.layer = %d;\n", status->layer);
3013 if (get_flags (status->flags, AS_StartViewportX | AS_StartViewportX)) {
3014 func (stream, "STATUS.viewport_x = %d;\n", status->viewport_x);
3015 func (stream, "STATUS.viewport_y = %d;\n", status->viewport_y);
3016 }
3017 }
3018
3019 /*********************************************************************************
3020 * serialization for purpose of inter-module communications *
3021 *********************************************************************************/
serialize_string(char * string,ASVector * buf)3022 void serialize_string (char *string, ASVector * buf)
3023 {
3024 if (buf) {
3025 register CARD32 *ptr;
3026 register char *src = string;
3027 register int i = string ? strlen (string) >> 2 : 0; /* assume CARD32 == 4*CARD8 :)) */
3028
3029 append_vector (buf, NULL, 1 + i + 1);
3030 ptr = VECTOR_TAIL (CARD32, *buf);
3031 VECTOR_USED (*buf) += i + 1;
3032 ptr[0] = i + 1;
3033 ++ptr;
3034 if (string == NULL) {
3035 ptr[0] = 0;
3036 return;
3037 }
3038 src = &(string[i << 2]);
3039 /* unrolling loop here : */
3040 ptr[i] = src[0] & 0x0FF;
3041 if (src[0]) {
3042 if (src[1]) { /* we don't really want to use bitwise operations */
3043 /* so we get "true" number and later can do ENDIANNES transformations */
3044 ptr[i] |= (((CARD32) src[1]) << 8) & 0x0FF00;
3045 if (src[2])
3046 ptr[i] |= (((CARD32) src[2]) << 16) & 0x0FF0000;
3047 }
3048 }
3049 while (--i >= 0) {
3050 src -= 4;
3051 ptr[i] =
3052 (((CARD32) src[0]) & 0x0FF) | (((CARD32) src[1] << 8) & 0x0FF00)
3053 | (((CARD32) src[2] << 16) & 0x0FF0000)
3054 | (((CARD32) src[3] << 24) & 0xFF000000);
3055 }
3056 }
3057 }
3058
serialize_CARD32_zarray(CARD32 * array,ASVector * buf)3059 void serialize_CARD32_zarray (CARD32 * array, ASVector * buf)
3060 {
3061 register int i = 0;
3062 register CARD32 *ptr;
3063
3064 if (array)
3065 while (array[i])
3066 i++;
3067 i++;
3068 append_vector (buf, NULL, 1 + i);
3069 ptr = VECTOR_TAIL (CARD32, *buf);
3070 VECTOR_USED (*buf) += i;
3071 ptr[0] = i;
3072 ptr++;
3073 if (array == NULL)
3074 ptr[0] = 0;
3075 else
3076 while (--i >= 0)
3077 ptr[i] = array[i];
3078 }
3079
serialize_clean_hints(ASHints * clean,ASVector * buf)3080 Bool serialize_clean_hints (ASHints * clean, ASVector * buf)
3081 {
3082 register CARD32 *ptr;
3083 register int i = 0;
3084
3085 if (clean == NULL || buf == NULL)
3086 return False;
3087
3088 /* we expect CARD32 vector here : */
3089 if (VECTOR_UNIT (*buf) != sizeof (CARD32))
3090 return False;
3091
3092 append_vector (buf, NULL, ASHINTS_STATIC_DATA);
3093 ptr = VECTOR_TAIL (CARD32, *buf);
3094 ptr[i++] = clean->flags;
3095 ptr[i++] = clean->protocols;
3096 ptr[i++] = clean->function_mask;
3097 ptr[i++] = clean->icon.window;
3098 ptr[i++] = clean->icon_mask;
3099 ptr[i++] = clean->icon_x;
3100 ptr[i++] = clean->icon_y;
3101
3102 ptr[i++] = clean->min_width;
3103 ptr[i++] = clean->min_height;
3104 ptr[i++] = clean->max_width;
3105 ptr[i++] = clean->max_height;
3106 ptr[i++] = clean->width_inc;
3107 ptr[i++] = clean->height_inc;
3108 ptr[i++] = clean->min_aspect.x;
3109 ptr[i++] = clean->min_aspect.y;
3110 ptr[i++] = clean->max_aspect.x;
3111 ptr[i++] = clean->max_aspect.y;
3112 ptr[i++] = clean->base_width;
3113 ptr[i++] = clean->base_height;
3114
3115 ptr[i++] = clean->gravity;
3116 ptr[i++] = clean->border_width;
3117 ptr[i++] = clean->handle_width;
3118
3119 ptr[i++] = clean->group_lead;
3120 ptr[i++] = clean->transient_for;
3121
3122 ptr[i++] = clean->pid;
3123
3124 ptr[i++] = clean->disabled_buttons;
3125
3126 ptr[i++] = clean->hints_types_raw;
3127 ptr[i++] = clean->hints_types_clean;
3128 VECTOR_USED (*buf) += i;
3129
3130 serialize_CARD32_zarray (clean->cmap_windows, buf);
3131
3132 serialize_string (clean->icon_file, buf);
3133 serialize_string (clean->frame_name, buf);
3134 serialize_string (clean->windowbox_name, buf);
3135
3136 for (i = 0; i < BACK_STYLES; i++)
3137 serialize_string (clean->mystyle_names[i], buf);
3138
3139 serialize_string (clean->client_host, buf);
3140 serialize_string (clean->client_cmd, buf);
3141
3142 return True;
3143 }
3144
serialize_names(ASHints * clean,ASVector * buf)3145 Bool serialize_names (ASHints * clean, ASVector * buf)
3146 {
3147 CARD32 header[4];
3148 register int i;
3149
3150 if (clean == NULL || buf == NULL)
3151 return False;
3152 header[0] =
3153 pointer_name_to_index_in_list (clean->names, clean->res_name);
3154 header[1] =
3155 pointer_name_to_index_in_list (clean->names, clean->res_class);
3156 header[2] =
3157 pointer_name_to_index_in_list (clean->names, clean->icon_name);
3158 for (i = 0; clean->names[i] != NULL && i < MAX_WINDOW_NAMES; i++) ;
3159 header[3] = i;
3160 append_vector (buf, &(header[0]), 4);
3161
3162 for (i = 0; clean->names[i] != NULL && i < MAX_WINDOW_NAMES; i++)
3163 serialize_string (clean->names[i], buf);
3164
3165 return True;
3166 }
3167
serialize_status_hints(ASStatusHints * status,ASVector * buf)3168 Bool serialize_status_hints (ASStatusHints * status, ASVector * buf)
3169 {
3170 register CARD32 *ptr;
3171 register int i = 0;
3172
3173 if (status == NULL || buf == NULL)
3174 return False;
3175
3176 /* we expect CARD32 vector here : */
3177 if (VECTOR_UNIT (*buf) != sizeof (CARD32))
3178 return False;
3179
3180 append_vector (buf, NULL, ASSTATUSHINTS_STATIC_DATA);
3181 ptr = VECTOR_TAIL (CARD32, *buf);
3182 ptr[i++] = status->flags;
3183
3184 ptr[i++] = status->x;
3185 ptr[i++] = status->y;
3186 ptr[i++] = status->width;
3187 ptr[i++] = status->height;
3188 ptr[i++] = status->border_width;
3189 ptr[i++] = status->viewport_x;
3190 ptr[i++] = status->viewport_y;
3191 ptr[i++] = status->desktop;
3192 ptr[i++] = status->layer;
3193 ptr[i++] = status->icon_window;
3194 VECTOR_USED (*buf) += i;
3195
3196 return True;
3197 }
3198
3199 /*********************************************************************************
3200 * deserialization so that module can read out communications *
3201 *********************************************************************************/
deserialize_string(CARD32 ** pbuf,size_t * buf_size)3202 char *deserialize_string (CARD32 ** pbuf, size_t * buf_size)
3203 {
3204 char *string;
3205 CARD32 *buf = *pbuf;
3206 size_t len;
3207 register int i;
3208 register char *str;
3209
3210 if (*pbuf == NULL)
3211 return NULL;
3212 if (buf_size && *buf_size < 2)
3213 return NULL;
3214 len = buf[0];
3215 if (buf_size && len > *buf_size + 1)
3216 return NULL;
3217 buf++;
3218 str = string = safemalloc (len << 2);
3219 for (i = 0; i < len; i++) {
3220 str[0] = (buf[i] & 0x0FF);
3221 str[1] = (buf[i] >> 8) & 0x0FF;
3222 str[2] = (buf[i] >> 16) & 0x0FF;
3223 str[3] = (buf[i] >> 24) & 0x0FF;
3224 str += 4;
3225 }
3226
3227 if (buf_size)
3228 *buf_size -= len;
3229 *pbuf += len;
3230
3231 return string;
3232 }
3233
deserialize_CARD32_zarray(CARD32 ** pbuf,size_t * buf_size)3234 CARD32 *deserialize_CARD32_zarray (CARD32 ** pbuf, size_t * buf_size)
3235 {
3236 CARD32 *array;
3237 CARD32 *buf = *pbuf;
3238 size_t len;
3239 register int i;
3240
3241 if (*pbuf == NULL || *buf_size < 2)
3242 return NULL;
3243 len = buf[0];
3244 if (len > *buf_size + 1)
3245 return NULL;
3246 buf++;
3247 array = safemalloc (len * sizeof (CARD32));
3248 for (i = 0; i < len; i++)
3249 array[i] = buf[i];
3250
3251 *buf_size -= len;
3252 *pbuf += len;
3253
3254 return array;
3255 }
3256
deserialize_clean_hints(CARD32 ** pbuf,size_t * buf_size,ASHints * reusable_memory)3257 ASHints *deserialize_clean_hints (CARD32 ** pbuf, size_t * buf_size,
3258 ASHints * reusable_memory)
3259 {
3260 ASHints *clean = reusable_memory;
3261 register int i = 0;
3262 register CARD32 *buf = *pbuf;
3263
3264 if (buf == NULL || *buf_size < ASHINTS_STATIC_DATA)
3265 return False;
3266
3267 if (clean == NULL)
3268 clean = safecalloc (1, sizeof (ASHints));
3269
3270 clean->flags = buf[i++];
3271 clean->protocols = buf[i++];
3272 clean->function_mask = buf[i++];
3273
3274 clean->icon.window = buf[i++];
3275 clean->icon_mask = buf[i++];
3276 clean->icon_x = buf[i++];
3277 clean->icon_y = buf[i++];
3278
3279 clean->min_width = buf[i++];
3280 clean->min_height = buf[i++];
3281 clean->max_width = buf[i++];
3282 clean->max_height = buf[i++];
3283 clean->width_inc = buf[i++];
3284 clean->height_inc = buf[i++];
3285 clean->min_aspect.x = buf[i++];
3286 clean->min_aspect.y = buf[i++];
3287 clean->max_aspect.x = buf[i++];
3288 clean->max_aspect.y = buf[i++];
3289 clean->base_width = buf[i++];
3290 clean->base_height = buf[i++];
3291 clean->gravity = buf[i++];
3292 clean->border_width = buf[i++];
3293 clean->handle_width = buf[i++];
3294 clean->group_lead = buf[i++];
3295 clean->transient_for = buf[i++];
3296 clean->pid = buf[i++];
3297 clean->disabled_buttons = buf[i++];
3298
3299 clean->hints_types_raw = buf[i++];
3300 clean->hints_types_clean = buf[i++];
3301
3302 *buf_size -= i;
3303 *pbuf += i;
3304 if (clean->cmap_windows)
3305 free (clean->cmap_windows);
3306 clean->cmap_windows = deserialize_CARD32_zarray (pbuf, buf_size);
3307
3308 if (clean->icon_file)
3309 free (clean->icon_file);
3310 clean->icon_file = deserialize_string (pbuf, buf_size);
3311 if (clean->frame_name)
3312 free (clean->frame_name);
3313 clean->frame_name = deserialize_string (pbuf, buf_size);
3314 if (clean->windowbox_name)
3315 free (clean->windowbox_name);
3316 clean->windowbox_name = deserialize_string (pbuf, buf_size);
3317
3318 for (i = 0; i < BACK_STYLES; i++) {
3319 if (clean->mystyle_names[i])
3320 free (clean->mystyle_names[i]);
3321 clean->mystyle_names[i] = deserialize_string (pbuf, buf_size);
3322 }
3323 if (clean->client_host)
3324 free (clean->client_host);
3325 clean->client_host = deserialize_string (pbuf, buf_size);
3326 if (clean->client_cmd)
3327 free (clean->client_cmd);
3328 clean->client_cmd = deserialize_string (pbuf, buf_size);
3329
3330 return clean;
3331 }
3332
deserialize_names(ASHints * clean,CARD32 ** pbuf,size_t * buf_size)3333 Bool deserialize_names (ASHints * clean, CARD32 ** pbuf, size_t * buf_size)
3334 {
3335 CARD32 header[4];
3336 CARD32 *buf = *pbuf;
3337 register int i;
3338
3339 if (clean == NULL || buf == NULL || *buf_size < 4)
3340 return False;
3341
3342 header[0] = buf[0];
3343 header[1] = buf[1];
3344 header[2] = buf[2];
3345 header[3] = buf[3];
3346
3347 if (header[3] <= 0 || header[3] >= MAX_WINDOW_NAMES)
3348 return False;
3349
3350 *buf_size -= 4;
3351 *pbuf += 4;
3352
3353 for (i = 0; i < header[3]; i++) {
3354 if (clean->names[i])
3355 free (clean->names[i]);
3356 clean->names[i] = deserialize_string (pbuf, buf_size);
3357 }
3358 clean->res_name =
3359 (header[0] < MAX_WINDOW_NAMES) ? clean->names[header[0]] : NULL;
3360 clean->res_name_idx = 0;
3361 clean->res_class =
3362 (header[1] < MAX_WINDOW_NAMES) ? clean->names[header[1]] : NULL;
3363 clean->res_class_idx = 0;
3364 clean->icon_name =
3365 (header[2] < MAX_WINDOW_NAMES) ? clean->names[header[2]] : NULL;
3366 clean->icon_name_idx = 0;
3367
3368 return True;
3369 }
3370
3371
deserialize_status_hints(CARD32 ** pbuf,size_t * buf_size,ASStatusHints * reusable_memory)3372 ASStatusHints *deserialize_status_hints (CARD32 ** pbuf, size_t * buf_size,
3373 ASStatusHints * reusable_memory)
3374 {
3375 ASStatusHints *status = reusable_memory;
3376 register int i = 0;
3377 register CARD32 *buf = *pbuf;
3378
3379 if (buf == NULL || *buf_size < ASSTATUSHINTS_STATIC_DATA)
3380 return False;
3381
3382 if (status == NULL)
3383 status = safecalloc (1, sizeof (ASStatusHints));
3384
3385 status->flags = buf[i++];
3386 status->x = buf[i++];
3387 status->y = buf[i++];
3388 status->width = buf[i++];
3389 status->height = buf[i++];
3390 status->border_width = buf[i++];
3391 status->viewport_x = buf[i++];
3392 status->viewport_y = buf[i++];
3393 status->desktop = buf[i++];
3394 status->layer = buf[i++];
3395 status->icon_window = buf[i++];
3396 *buf_size -= i;
3397 *pbuf += i;
3398
3399 return status;
3400 }
3401
3402 /*********************************************************************************
3403 * List of Supported Hints management *
3404 *********************************************************************************/
create_hints_list()3405 ASSupportedHints *create_hints_list ()
3406 {
3407 ASSupportedHints *list;
3408
3409 list = (ASSupportedHints *) safecalloc (1, sizeof (ASSupportedHints));
3410 return list;
3411 }
3412
destroy_hints_list(ASSupportedHints ** plist)3413 void destroy_hints_list (ASSupportedHints ** plist)
3414 {
3415 if (*plist) {
3416 free (*plist);
3417 *plist = NULL;
3418 }
3419 }
3420
HintsTypes2Func(HintsTypes type)3421 static hints_merge_func HintsTypes2Func (HintsTypes type)
3422 {
3423 switch (type) {
3424 case HINTS_ICCCM:
3425 return merge_icccm_hints;
3426 case HINTS_GroupLead:
3427 return merge_group_hints;
3428 case HINTS_Transient:
3429 return merge_transient_hints;
3430 case HINTS_Motif:
3431 return merge_motif_hints;
3432 case HINTS_Gnome:
3433 return merge_gnome_hints;
3434 case HINTS_KDE:
3435 return merge_kde_hints;
3436 case HINTS_ExtendedWM:
3437 return merge_extwm_hints;
3438 case HINTS_XResources:
3439 return merge_xresources_hints;
3440 case HINTS_ASDatabase:
3441 return merge_asdb_hints;
3442 case HINTS_Supported:
3443 break;
3444 }
3445 return NULL;
3446 }
3447
Func2HintsTypes(hints_merge_func func)3448 HintsTypes Func2HintsTypes (hints_merge_func func)
3449 {
3450 if (func == merge_group_hints)
3451 return HINTS_GroupLead;
3452 else if (func == merge_transient_hints)
3453 return HINTS_Transient;
3454 else if (func == merge_motif_hints)
3455 return HINTS_Motif;
3456 else if (func == merge_gnome_hints)
3457 return HINTS_Gnome;
3458 else if (func == merge_extwm_hints)
3459 return HINTS_ExtendedWM;
3460 else if (func == merge_kde_hints)
3461 return HINTS_KDE;
3462 else if (func == merge_xresources_hints)
3463 return HINTS_XResources;
3464 else if (func == merge_asdb_hints)
3465 return HINTS_ASDatabase;
3466 return HINTS_ICCCM;
3467 }
3468
enable_hints_support(ASSupportedHints * list,HintsTypes type)3469 Bool enable_hints_support (ASSupportedHints * list, HintsTypes type)
3470 {
3471 if (list) {
3472 if (list->hints_num >= HINTS_Supported)
3473 list->hints_num = HINTS_Supported - 1; /* we are being paranoid */
3474
3475 if (get_flags (list->hints_flags, (0x01 << type))) /* checking for duplicates */
3476 return False;
3477
3478 if ((list->merge_funcs[list->hints_num] =
3479 HintsTypes2Func (type)) == NULL)
3480 return False;
3481
3482 list->hints_types[list->hints_num] = type;
3483 set_flags (list->hints_flags, (0x01 << type));
3484 list->hints_num++;
3485 return True;
3486 }
3487 return False;
3488 }
3489
disable_hints_support(ASSupportedHints * list,HintsTypes type)3490 Bool disable_hints_support (ASSupportedHints * list, HintsTypes type)
3491 {
3492 if (list) {
3493 register int i;
3494
3495 if (list->hints_num > HINTS_Supported)
3496 list->hints_num = HINTS_Supported; /* we are being paranoid */
3497 for (i = 0; i < list->hints_num; i++)
3498 if (list->hints_types[i] == type) {
3499 list->hints_num--;
3500 for (; i < list->hints_num; i++) {
3501 list->merge_funcs[i] = list->merge_funcs[i + 1];
3502 list->hints_types[i] = list->hints_types[i + 1];
3503 }
3504 list->merge_funcs[i] = NULL;
3505 list->hints_types[i] = HINTS_Supported;
3506 clear_flags (list->hints_flags, (0x01 << type));
3507 return True;
3508 }
3509 }
3510 return False;
3511 }
3512
supported_hints_types(ASSupportedHints * list,int * num_return)3513 HintsTypes *supported_hints_types (ASSupportedHints * list,
3514 int *num_return)
3515 {
3516 HintsTypes *types = NULL;
3517 int curr = 0;
3518
3519 if (list)
3520 if ((curr = list->hints_num) > 0)
3521 types = list->hints_types;
3522
3523 if (num_return)
3524 *num_return = curr;
3525 return types;
3526 }
3527