1 /* -*-c-*- */
2 /* This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, see: <http://www.gnu.org/licenses/>
14 */
15
16 /* ---------------------------- included header files ---------------------- */
17
18 #include "config.h"
19
20 #include <stdio.h>
21 #include <X11/Xproto.h>
22 #include <X11/Xatom.h>
23
24 #include "libs/fvwmlib.h"
25 #include "libs/FShape.h"
26 #include "libs/Parse.h"
27 #include "libs/lang-strings.h"
28 #include "fvwm.h"
29 #include "externs.h"
30 #include "execcontext.h"
31 #include "commands.h"
32 #include "misc.h"
33 #include "screen.h"
34 #include "update.h"
35 #include "style.h"
36 #include "geometry.h"
37 #include "decorations.h"
38
39 /* ---------------------------- local definitions -------------------------- */
40
41 /* Motif window hints */
42 #define MWM_HINTS_FUNCTIONS (1L << 0)
43 #define MWM_HINTS_DECORATIONS (1L << 1)
44
45 /* bit definitions for MwmHints.functions */
46 #define MWM_FUNC_ALL (1L << 0)
47 #define MWM_FUNC_RESIZE (1L << 1)
48 #define MWM_FUNC_MOVE (1L << 2)
49 #define MWM_FUNC_MINIMIZE (1L << 3)
50 #define MWM_FUNC_MAXIMIZE (1L << 4)
51 #define MWM_FUNC_CLOSE (1L << 5)
52
53 /* bit definitions for MwmHints.decorations */
54 #if 0
55 #define MWM_DECOR_ALL (1L << 0)
56 #define MWM_DECOR_BORDER (1L << 1)
57 #define MWM_DECOR_RESIZEH (1L << 2)
58 #define MWM_DECOR_TITLE (1L << 3)
59 #define MWM_DECOR_MENU (1L << 4)
60 #define MWM_DECOR_MINIMIZE (1L << 5)
61 #define MWM_DECOR_MAXIMIZE (1L << 6)
62 #endif
63
64 #define PROP_MOTIF_WM_HINTS_ELEMENTS 4
65 #define PROP_MWM_HINTS_ELEMENTS PROP_MOTIF_WM_HINTS_ELEMENTS
66
67 /* bit definitions for OL hints; I just
68 * made these up, OL stores hints as atoms */
69 #define OL_DECOR_CLOSE (1L << 0)
70 #define OL_DECOR_RESIZEH (1L << 1)
71 #define OL_DECOR_HEADER (1L << 2)
72 #define OL_DECOR_ICON_NAME (1L << 3)
73 #define OL_DECOR_ALL \
74 (OL_DECOR_CLOSE | OL_DECOR_RESIZEH | OL_DECOR_HEADER | OL_DECOR_ICON_NAME)
75 /* indicates if there are any OL hints */
76 #define OL_ANY_HINTS (1L << 7)
77
78 /* ---------------------------- local macros ------------------------------- */
79
80 /* ---------------------------- imports ------------------------------------ */
81
82 extern Atom _XA_MwmAtom;
83
84 /* ---------------------------- included code files ------------------------ */
85
86 /* ---------------------------- local types -------------------------------- */
87
88 /* Motif window hints */
89 typedef struct
90 {
91 long flags;
92 long functions;
93 long decorations;
94 long inputMode;
95 } PropMotifWmHints;
96
97 typedef PropMotifWmHints PropMwmHints;
98
99 /* ---------------------------- forward declarations ----------------------- */
100
101 /* ---------------------------- local variables ---------------------------- */
102
103 /* ---------------------------- exported variables (globals) --------------- */
104
105 /* ---------------------------- local functions ---------------------------- */
106
107 /* ---------------------------- interface functions ------------------------ */
108
109 /*
110 *
111 * Reads the property MOTIF_WM_HINTS
112 *
113 */
GetMwmHints(FvwmWindow * t)114 void GetMwmHints(FvwmWindow *t)
115 {
116 int actual_format;
117 Atom actual_type;
118 unsigned long nitems, bytesafter;
119
120 if (t->mwm_hints)
121 {
122 XFree((char *)t->mwm_hints);
123 t->mwm_hints = NULL;
124 }
125 if (XGetWindowProperty(
126 dpy, FW_W(t), _XA_MwmAtom, 0L, 32L, False,
127 _XA_MwmAtom, &actual_type, &actual_format, &nitems,
128 &bytesafter,(unsigned char **)&t->mwm_hints)==Success)
129 {
130 if (nitems >= PROP_MOTIF_WM_HINTS_ELEMENTS)
131 {
132 return;
133 }
134 }
135
136 t->mwm_hints = NULL;
137
138 return;
139 }
140
141 /*
142 *
143 * Reads the openlook properties _OL_WIN_ATTR, _OL_DECOR_ADD, _OL_DECOR_DEL
144 *
145 * _OL_WIN_ATTR - the win_type field is the either the first atom if the
146 * property has length three or the second atom if the property has
147 * length five. It can be any of:
148 * _OL_WT_BASE (no changes)
149 * _OL_WT_CMD (no minimize decoration)
150 * _OL_WT_HELP (no minimize, maximize or resize handle decorations)
151 * _OL_WT_NOTICE (no minimize, maximize, system menu, resize handle
152 * or titlebar decorations)
153 * _OL_WT_OTHER (no minimize, maximize, system menu, resize handle
154 * or titlebar decorations)
155 * In addition, if the _OL_WIN_ATTR property is in the three atom format
156 * or if the type is _OL_WT_OTHER, then the icon name is not displayed
157 * (same behavior as olvwm).
158 *
159 * _OL_DECOR_ADD or _OL_DECOR_DEL - indivdually add or remove minimize
160 * button (_OL_DECOR_CLOSE), resize handles (_OL_DECOR_RESIZE), title bar
161 * (_OL_DECOR_HEADER), or icon name (_OL_DECOR_ICON_NAME).
162 *
163 * The documentation for the Open Look hints was taken from "Advanced X
164 * Window Application Programming", Eric F. Johnson and Kevin Reichard
165 * (M&T Books), and the olvwm source code (available at ftp.x.org in
166 * /R5contrib).
167 */
GetOlHints(FvwmWindow * t)168 void GetOlHints(FvwmWindow *t)
169 {
170 int actual_format;
171 Atom actual_type;
172 unsigned long nitems, bytesafter;
173 Atom *hints;
174 int i;
175 Atom win_type;
176
177 t->ol_hints = OL_DECOR_ALL;
178
179 if (XGetWindowProperty(
180 dpy, FW_W(t), _XA_OL_WIN_ATTR, 0L, 32L, False,
181 _XA_OL_WIN_ATTR, &actual_type, &actual_format,
182 &nitems, &bytesafter, (unsigned char **)&hints) == Success)
183 {
184 if (nitems > 0)
185 {
186 t->ol_hints |= OL_ANY_HINTS;
187
188 if (nitems == 3)
189 {
190 win_type = hints[0];
191 }
192 else
193 {
194 win_type = hints[1];
195 }
196
197 /* got this from olvwm and sort of mapped it to
198 * fvwm/MWM hints */
199 if (win_type == _XA_OL_WT_BASE)
200 {
201 t->ol_hints = OL_DECOR_ALL;
202 }
203 else if (win_type == _XA_OL_WT_CMD)
204 {
205 t->ol_hints = OL_DECOR_ALL & ~OL_DECOR_CLOSE;
206 }
207 else if (win_type == _XA_OL_WT_HELP)
208 {
209 t->ol_hints = OL_DECOR_ALL &
210 ~(OL_DECOR_CLOSE | OL_DECOR_RESIZEH);
211 }
212 else if (win_type == _XA_OL_WT_NOTICE)
213 {
214 t->ol_hints = OL_DECOR_ALL &
215 ~(OL_DECOR_CLOSE | OL_DECOR_RESIZEH |
216 OL_DECOR_HEADER | OL_DECOR_ICON_NAME);
217 }
218 else if (win_type == _XA_OL_WT_OTHER)
219 {
220 t->ol_hints = 0;
221 }
222 else
223 {
224 t->ol_hints = OL_DECOR_ALL;
225 }
226
227 if (nitems == 3)
228 {
229 t->ol_hints &= ~OL_DECOR_ICON_NAME;
230 }
231 }
232
233 if (hints)
234 {
235 XFree (hints);
236 }
237 }
238
239 if (XGetWindowProperty(
240 dpy, FW_W(t), _XA_OL_DECOR_ADD, 0L, 32L, False,
241 XA_ATOM, &actual_type, &actual_format, &nitems,
242 &bytesafter,(unsigned char **)&hints)==Success)
243 {
244 for (i = 0; i < nitems; i++)
245 {
246 t->ol_hints |= OL_ANY_HINTS;
247 if (hints[i] == _XA_OL_DECOR_CLOSE)
248 {
249 t->ol_hints |= OL_DECOR_CLOSE;
250 }
251 else if (hints[i] == _XA_OL_DECOR_RESIZE)
252 {
253 t->ol_hints |= OL_DECOR_RESIZEH;
254 }
255 else if (hints[i] == _XA_OL_DECOR_HEADER)
256 {
257 t->ol_hints |= OL_DECOR_HEADER;
258 }
259 else if (hints[i] == _XA_OL_DECOR_ICON_NAME)
260 {
261 t->ol_hints |= OL_DECOR_ICON_NAME;
262 }
263 }
264 if (hints)
265 {
266 XFree (hints);
267 }
268 }
269
270 if (XGetWindowProperty(
271 dpy, FW_W(t), _XA_OL_DECOR_DEL, 0L, 32L, False,
272 XA_ATOM, &actual_type, &actual_format, &nitems,
273 &bytesafter,(unsigned char **)&hints)==Success)
274 {
275 for (i = 0; i < nitems; i++)
276 {
277 t->ol_hints |= OL_ANY_HINTS;
278 if (hints[i] == _XA_OL_DECOR_CLOSE)
279 {
280 t->ol_hints &= ~OL_DECOR_CLOSE;
281 }
282 else if (hints[i] == _XA_OL_DECOR_RESIZE)
283 {
284 t->ol_hints &= ~OL_DECOR_RESIZEH;
285 }
286 else if (hints[i] == _XA_OL_DECOR_HEADER)
287 {
288 t->ol_hints &= ~OL_DECOR_HEADER;
289 }
290 else if (hints[i] == _XA_OL_DECOR_ICON_NAME)
291 {
292 t->ol_hints &= ~OL_DECOR_ICON_NAME;
293 }
294 }
295 if (hints)
296 {
297 XFree (hints);
298 }
299 }
300
301 return;
302 }
303
304
305 /*
306 *
307 * Interprets the property MOTIF_WM_HINTS, sets decoration and functions
308 * accordingly
309 *
310 */
SelectDecor(FvwmWindow * t,window_style * pstyle,short * buttons)311 void SelectDecor(FvwmWindow *t, window_style *pstyle, short *buttons)
312 {
313 int decor;
314 int i;
315 int border_width;
316 int handle_width;
317 int used_width;
318 PropMwmHints *prop;
319 style_flags *sflags = &(pstyle->flags);
320
321 border_width = (SHAS_BORDER_WIDTH(sflags)) ?
322 SGET_BORDER_WIDTH(*pstyle) : DEFAULT_BORDER_WIDTH;
323 if (border_width > MAX_BORDER_WIDTH)
324 {
325 border_width = MAX_BORDER_WIDTH;
326 }
327 handle_width = (SHAS_HANDLE_WIDTH(sflags)) ?
328 SGET_HANDLE_WIDTH(*pstyle) : DEFAULT_HANDLE_WIDTH;
329 if (handle_width > MAX_HANDLE_WIDTH)
330 {
331 handle_width = MAX_HANDLE_WIDTH;
332 }
333
334 *buttons = (1 << NUMBER_OF_TITLE_BUTTONS) - 1;
335
336 decor = MWM_DECOR_ALL;
337 t->functions = MWM_FUNC_ALL;
338 if (t->mwm_hints)
339 {
340 prop = (PropMwmHints *)t->mwm_hints;
341 if (SHAS_MWM_DECOR(sflags))
342 {
343 if (prop->flags & MWM_HINTS_DECORATIONS)
344 {
345 decor = 0;
346 if (prop->decorations & 0x1)
347 {
348 decor |= MWM_DECOR_ALL;
349 }
350 if (prop->decorations & 0x2)
351 {
352 decor |= MWM_DECOR_BORDER;
353 }
354 if (prop->decorations & 0x4)
355 {
356 decor |= MWM_DECOR_RESIZEH;
357 }
358 if (prop->decorations & 0x8)
359 {
360 decor |= MWM_DECOR_TITLE;
361 }
362 if (prop->decorations & 0x10)
363 {
364 decor |= MWM_DECOR_MENU;
365 }
366 if (prop->decorations & 0x20)
367 {
368 decor |= MWM_DECOR_MINIMIZE;
369 }
370 if (prop->decorations & 0x40)
371 {
372 decor |= MWM_DECOR_MAXIMIZE;
373 }
374 }
375 }
376 if (SHAS_MWM_FUNCTIONS(sflags))
377 {
378 if (prop->flags & MWM_HINTS_FUNCTIONS)
379 {
380 t->functions = prop->functions;
381 }
382 }
383 }
384
385 /* functions affect the decorations! if the user says
386 * no iconify function, then the iconify button doesn't show
387 * up. */
388 if (t->functions & MWM_FUNC_ALL)
389 {
390 /* If we get ALL + some other things, that means to use
391 * ALL except the other things... */
392 t->functions &= ~MWM_FUNC_ALL;
393 t->functions =
394 (MWM_FUNC_RESIZE | MWM_FUNC_MOVE | MWM_FUNC_MINIMIZE |
395 MWM_FUNC_MAXIMIZE | MWM_FUNC_CLOSE) &
396 (~(t->functions));
397 }
398 if (SHAS_MWM_FUNCTIONS(sflags) && IS_TRANSIENT(t))
399 {
400 t->functions &= ~(MWM_FUNC_MAXIMIZE|MWM_FUNC_MINIMIZE);
401 }
402
403 if (decor & MWM_DECOR_ALL)
404 {
405 /* If we get ALL + some other things, that means to use
406 * ALL except the other things... */
407 decor &= ~MWM_DECOR_ALL;
408 decor = MWM_DECOR_EVERYTHING & (~decor);
409 }
410
411 /* now add/remove any functions specified in the OL hints */
412 if (SHAS_OL_DECOR(sflags) && (t->ol_hints & OL_ANY_HINTS))
413 {
414 if (t->ol_hints & OL_DECOR_CLOSE)
415 {
416 t->functions |= MWM_FUNC_MINIMIZE;
417 decor |= MWM_FUNC_MINIMIZE;
418 }
419 else
420 {
421 t->functions &= ~MWM_FUNC_MINIMIZE;
422 decor &= ~MWM_FUNC_MINIMIZE;
423 }
424 if (t->ol_hints & OL_DECOR_RESIZEH)
425 {
426 t->functions |= (MWM_FUNC_RESIZE | MWM_FUNC_MAXIMIZE);
427 decor |= (MWM_FUNC_RESIZE | MWM_FUNC_MAXIMIZE);
428 }
429 else
430 {
431 t->functions &= ~(MWM_FUNC_RESIZE | MWM_FUNC_MAXIMIZE);
432 decor &= ~(MWM_FUNC_RESIZE | MWM_FUNC_MAXIMIZE);
433 }
434 if (t->ol_hints & OL_DECOR_HEADER)
435 {
436 t->functions |= (MWM_DECOR_MENU | MWM_FUNC_MINIMIZE |
437 MWM_FUNC_MAXIMIZE | MWM_DECOR_TITLE);
438 decor |= (MWM_DECOR_MENU | MWM_FUNC_MINIMIZE |
439 MWM_FUNC_MAXIMIZE | MWM_DECOR_TITLE);
440 }
441 else
442 {
443 t->functions &= ~(MWM_DECOR_MENU | MWM_FUNC_MINIMIZE |
444 MWM_FUNC_MAXIMIZE | MWM_DECOR_TITLE);
445 decor &= ~(MWM_DECOR_MENU | MWM_FUNC_MINIMIZE |
446 MWM_FUNC_MAXIMIZE | MWM_DECOR_TITLE);
447 }
448 if (t->ol_hints & OL_DECOR_ICON_NAME)
449 {
450 SET_HAS_NO_ICON_TITLE(t, 0);
451 }
452 else
453 {
454 SET_HAS_NO_ICON_TITLE(t, 1);
455 }
456 }
457
458 /* Now I have the un-altered decor and functions, but with the
459 * ALL attribute cleared and interpreted. I need to modify the
460 * decorations that are affected by the functions */
461 if (!(t->functions & MWM_FUNC_RESIZE))
462 {
463 decor &= ~MWM_DECOR_RESIZEH;
464 }
465 /* MWM_FUNC_MOVE has no impact on decorations. */
466 if (!(t->functions & MWM_FUNC_MINIMIZE))
467 {
468 decor &= ~MWM_DECOR_MINIMIZE;
469 }
470 if (!(t->functions & MWM_FUNC_MAXIMIZE))
471 {
472 decor &= ~MWM_DECOR_MAXIMIZE;
473 }
474 /* MWM_FUNC_CLOSE has no impact on decorations. */
475
476 /* This rule is implicit, but its easier to deal with if
477 * I take care of it now */
478 if (decor & (MWM_DECOR_MENU| MWM_DECOR_MINIMIZE | MWM_DECOR_MAXIMIZE))
479 {
480 decor |= MWM_DECOR_TITLE;
481 }
482
483 /* Selected the mwm-decor field, now trim down, based on
484 * .fvwmrc entries */
485 if (SHAS_NO_TITLE(sflags) ||
486 (!SDO_DECORATE_TRANSIENT(sflags) && IS_TRANSIENT(t)))
487 {
488 decor &= ~MWM_DECOR_TITLE;
489 }
490
491 if (SHAS_NO_HANDLES(sflags) ||
492 (!SDO_DECORATE_TRANSIENT(sflags) && IS_TRANSIENT(t)))
493 {
494 decor &= ~MWM_DECOR_RESIZEH;
495 }
496
497 if (SHAS_MWM_DECOR(sflags) && IS_TRANSIENT(t))
498 {
499 decor &= ~(MWM_DECOR_MAXIMIZE|MWM_DECOR_MINIMIZE);
500 }
501
502 if (FShapesSupported)
503 {
504 if (t->wShaped)
505 {
506 decor &= ~(MWM_DECOR_BORDER|MWM_DECOR_RESIZEH);
507 }
508 }
509 if (IS_EWMH_FULLSCREEN(t))
510 {
511 decor &=~(MWM_DECOR_BORDER|MWM_DECOR_RESIZEH|MWM_DECOR_TITLE);
512 }
513
514 /* Assume no decorations, and build up */
515 SET_HAS_TITLE(t, 0);
516 SET_HAS_HANDLES(t, 0);
517
518 used_width = 0;
519 if (decor & MWM_DECOR_BORDER)
520 {
521 /* A narrow border is displayed (5 pixels - 2 relief, 1 top,
522 * (2 shadow) */
523 used_width = border_width;
524 }
525 if (decor & MWM_DECOR_TITLE)
526 {
527 /* A title bar with no buttons in it
528 * window gets a 1 pixel wide black border. */
529 SET_HAS_TITLE(t, 1);
530 }
531 if (decor & MWM_DECOR_RESIZEH)
532 {
533 /* A wide border, with corner tiles is desplayed
534 * (10 pixels - 2 relief, 2 shadow) */
535 SET_HAS_HANDLES(t, 1);
536 used_width = handle_width;
537 }
538 SET_HAS_NO_BORDER(t, S_HAS_NO_BORDER(SFC(*sflags)) || used_width <= 0);
539 if (HAS_NO_BORDER(t))
540 {
541 used_width = 0;
542 }
543 SET_HAS_HANDLES(t, (!HAS_NO_BORDER(t) && HAS_HANDLES(t)));
544 set_window_border_size(t, used_width);
545 if (!(decor & MWM_DECOR_MENU))
546 {
547 /* title-bar menu button omitted
548 * window gets 1 pixel wide black border */
549 /* disable any buttons with the MWMDecorMenu flag */
550 int i;
551 for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; ++i)
552 {
553 if (TB_HAS_MWM_DECOR_MENU(GetDecor(t, buttons[i])))
554 {
555 *buttons &= ~(1 << i);
556 }
557 }
558 }
559 if (!(decor & MWM_DECOR_MINIMIZE))
560 {
561 /* title-bar + iconify button, no menu button.
562 * window gets 1 pixel wide black border */
563 /* disable any buttons with the MWMDecorMinimize/MWMDecorShaded
564 * flag */
565 int i;
566 for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; ++i)
567 {
568 if (TB_HAS_MWM_DECOR_MINIMIZE(GetDecor(t, buttons[i])))
569 {
570 *buttons &= ~(1 << i);
571 }
572 }
573 }
574 if (!(decor & MWM_DECOR_MAXIMIZE))
575 {
576 /* title-bar + maximize button, no menu button, no iconify.
577 * window has 1 pixel wide black border */
578 /* disable any buttons with the MWMDecorMaximize flag */
579 int i;
580 for (i = 0; i < NUMBER_OF_TITLE_BUTTONS; ++i)
581 {
582 if (TB_HAS_MWM_DECOR_MAXIMIZE(GetDecor(t, buttons[i])))
583 {
584 *buttons &= ~(1 << i);
585 }
586 }
587 }
588 for (i = (1 << (NUMBER_OF_TITLE_BUTTONS - 1)); i; i >>= 1)
589 {
590 if (t->buttons & i)
591 *buttons &= ~i;
592 }
593
594 t->nr_left_buttons = Scr.nr_left_buttons;
595 t->nr_right_buttons = Scr.nr_right_buttons;
596
597 for (i = 0; i / 2 < Scr.nr_left_buttons; i += 2)
598 {
599 if ((*buttons & (1 << i)) == 0)
600 t->nr_left_buttons--;
601 }
602 for (i = 1; i / 2 < Scr.nr_right_buttons; i += 2)
603 {
604 if ((*buttons & (1 << i)) == 0)
605 t->nr_right_buttons--;
606 }
607
608 return;
609 }
610
__is_resize_allowed(const FvwmWindow * t,int functions,request_origin_t request_origin)611 static Bool __is_resize_allowed(
612 const FvwmWindow *t, int functions, request_origin_t request_origin)
613 {
614 if (!HAS_OVERRIDE_SIZE_HINTS(t) &&
615 t->hints.min_width == t->hints.max_width &&
616 t->hints.min_height == t->hints.max_height)
617 {
618 return False;
619 }
620 if (request_origin && IS_SIZE_FIXED(t))
621 {
622 return False;
623 }
624 else if (!request_origin && IS_PSIZE_FIXED(t))
625 {
626 return False;
627 }
628 if (request_origin && !(functions & MWM_FUNC_RESIZE))
629 {
630 return False;
631 }
632
633 return True;
634 }
635
636 /*
637 ** seemed kind of silly to have check_allowed_function and
638 ** check_allowed_function2 partially overlapping in their checks, so I
639 ** combined them here and made them wrapper functions instead.
640 */
is_function_allowed(int function,char * action_string,const FvwmWindow * t,request_origin_t request_origin,Bool do_allow_override_mwm_hints)641 Bool is_function_allowed(
642 int function, char *action_string, const FvwmWindow *t,
643 request_origin_t request_origin, Bool do_allow_override_mwm_hints)
644 {
645 unsigned int functions;
646 char *functionlist[] = {
647 MOVE_STRING,
648 RESIZE_STRING1,
649 RESIZE_STRING2,
650 MINIMIZE_STRING,
651 MINIMIZE_STRING2,
652 MAXIMIZE_STRING,
653 CLOSE_STRING1,
654 CLOSE_STRING2,
655 CLOSE_STRING3,
656 CLOSE_STRING4,
657 NULL
658 };
659
660 if (t == NULL)
661 {
662 return True; /* this logic come from animated menu */
663 }
664 if (do_allow_override_mwm_hints && HAS_MWM_OVERRIDE_HINTS(t))
665 {
666 /* allow everything */
667 functions = ~0;
668 }
669 else
670 {
671 /* restrict by mwm hints */
672 functions = t->functions;
673 }
674
675 /* Hate to do it, but for lack of a better idea, check based on the
676 * menu entry name */
677 /* Complex functions are a little tricky, ignore them if no menu item*/
678 if (function == F_FUNCTION && action_string != NULL)
679 {
680 int i;
681
682 /* remap to regular actions */
683
684 i = GetTokenIndex(action_string, functionlist, -1, NULL);
685 switch (i)
686 {
687 case 0:
688 function = F_MOVE;
689 break;
690 case 1:
691 function = F_RESIZE;
692 break;
693 case 2:
694 function = F_RESIZE;
695 break;
696 case 3:
697 function = F_ICONIFY;
698 break;
699 case 4:
700 function = F_ICONIFY;
701 break;
702 case 5:
703 function = F_MAXIMIZE;
704 break;
705 case 6:
706 function = F_CLOSE;
707 break;
708 case 7:
709 function = F_DELETE;
710 break;
711 case 8:
712 function = F_DESTROY;
713 break;
714 case 9:
715 function = F_QUIT;
716 break;
717 default:
718 break;
719 }
720 }
721 /* now do the real checks */
722 switch(function)
723 {
724 case F_DELETE:
725 if (IS_UNCLOSABLE(t))
726 {
727 return False;
728 }
729 if (IS_TEAR_OFF_MENU(t))
730 {
731 /* always allow this on tear off menus */
732 break;
733 }
734 if (!WM_DELETES_WINDOW(t))
735 {
736 return False;
737 }
738 /* fall through to close clause */
739 case F_CLOSE:
740 if (IS_UNCLOSABLE(t))
741 {
742 return False;
743 }
744 if (IS_TEAR_OFF_MENU(t))
745 {
746 /* always allow this on tear off menus */
747 break;
748 }
749 if (!(functions & MWM_FUNC_CLOSE))
750 {
751 return False;
752 }
753 break;
754 case F_DESTROY: /* shouldn't destroy always be allowed??? */
755 if (IS_UNCLOSABLE(t))
756 {
757 return False;
758 }
759 if (IS_TEAR_OFF_MENU(t))
760 {
761 /* always allow this on tear off menus */
762 break;
763 }
764 if (!(functions & MWM_FUNC_CLOSE))
765 {
766 return False;
767 }
768 break;
769 case F_RESIZE:
770 if(!__is_resize_allowed(t, functions, request_origin))
771 {
772 return False;
773 }
774 break;
775 case F_ICONIFY:
776 if ((!IS_ICONIFIED(t) && !(functions & MWM_FUNC_MINIMIZE)) ||
777 IS_UNICONIFIABLE(t))
778 {
779 return False;
780 }
781 break;
782 case F_MAXIMIZE:
783 if (IS_MAXIMIZE_FIXED_SIZE_DISALLOWED(t) &&
784 !__is_resize_allowed(t, functions, request_origin))
785 {
786 return False;
787 }
788 if ((request_origin && !(functions & MWM_FUNC_MAXIMIZE)) ||
789 IS_UNMAXIMIZABLE(t))
790 {
791 return False;
792 }
793 break;
794 case F_MOVE:
795 /* Move is a funny hint. Keeps it out of the menu, but you're
796 * still allowed to move. */
797 if (request_origin && IS_FIXED(t))
798 {
799 return False;
800 }
801 else if (!request_origin && IS_FIXED_PPOS(t))
802 {
803 return False;
804 }
805 if (request_origin && !(functions & MWM_FUNC_MOVE))
806 {
807 return False;
808 }
809 break;
810 case F_FUNCTION:
811 default:
812 break;
813 } /* end of switch */
814
815 /* if we fell through, just return True */
816 return True;
817 }
818