Change to the linux kernel coding style
[wmaker-crm.git] / src / client.c
1 /*
2  *  Window Maker window manager
3  *
4  *  Copyright (c) 1997-2003 Alfredo K. Kojima
5  *
6  *  This program is free software; you can redistribute it and/or modify
7  *  it under the terms of the GNU General Public License as published by
8  *  the Free Software Foundation; either version 2 of the License, or
9  *  (at your option) any later version.
10  *
11  *  This program is distributed in the hope that it will be useful,
12  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  *  GNU General Public License for more details.
15  *
16  *  You should have received a copy of the GNU General Public License
17  *  along with this program; if not, write to the Free Software
18  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
19  *  USA.
20  */
21 #include "wconfig.h"
22
23 #include <X11/Xlib.h>
24 #include <X11/Xutil.h>
25 #include <X11/Xatom.h>
26 #ifdef SHAPE
27 #include <X11/extensions/shape.h>
28 #endif
29
30 #include <stdlib.h>
31 #include <stdio.h>
32 #include <string.h>
33
34 #include "WindowMaker.h"
35 #include "wcore.h"
36 #include "framewin.h"
37 #include "window.h"
38 #include "properties.h"
39 #include "actions.h"
40 #include "icon.h"
41 #include "client.h"
42 #include "funcs.h"
43 #include "stacking.h"
44 #include "appicon.h"
45 #include "appmenu.h"
46 #ifdef NETWM_HINTS
47 # include "wmspec.h"
48 #endif
49
50 /****** Global Variables ******/
51
52 /* contexts */
53 extern XContext wWinContext;
54
55 extern Atom _XA_WM_STATE;
56 extern Atom _XA_WM_PROTOCOLS;
57 extern Atom _XA_WM_COLORMAP_WINDOWS;
58
59 extern Atom _XA_WINDOWMAKER_MENU;
60
61 extern Atom _XA_GNUSTEP_WM_ATTR;
62 extern Atom _XA_GNUSTEP_WM_RESIZEBAR;
63
64 #ifdef SHAPE
65 extern Bool wShapeSupported;
66 #endif
67
68 /*
69  *--------------------------------------------------------------------
70  * wClientRestore--
71  *      Reparent the window back to the root window.
72  *
73  *--------------------------------------------------------------------
74  */
75 void wClientRestore(WWindow * wwin)
76 {
77 #if 0
78         int gx, gy;
79
80         wClientGetGravityOffsets(wwin, &gx, &gy);
81         /* set the positio of the frame on screen */
82         wwin->frame_x -= gx * FRAME_BORDER_WIDTH;
83         wwin->frame_y -= gy * FRAME_BORDER_WIDTH;
84         /* if gravity is to the south, account for the border sizes */
85         if (gy > 0)
86                 wwin->frame_y += (wwin->frame->top_width + wwin->frame->bottom_width);
87 #endif
88         XSetWindowBorderWidth(dpy, wwin->client_win, wwin->old_border_width);
89         XReparentWindow(dpy, wwin->client_win, wwin->screen_ptr->root_win, wwin->frame_x, wwin->frame_y);
90
91         /* don't let the window get iconified after restart */
92         /*
93            if (wwin->flags.shaded)
94            wClientSetState(wwin, NormalState, None);
95          */
96 }
97
98 /*
99  *----------------------------------------------------------------------
100  * wClientSetState--
101  *      Set the state of the client window to one of the window
102  * states defined in ICCCM (Iconic, Withdrawn, Normal)
103  *
104  * Side effects:
105  *      The WM_STATE property of the window is updated as well as the
106  * WWindow.state variable.
107  *----------------------------------------------------------------------
108  */
109 void wClientSetState(WWindow * wwin, int state, Window icon_win)
110 {
111         CARD32 data[2];
112
113         wwin->state = state;
114
115         data[0] = (unsigned long)state;
116         data[1] = (unsigned long)icon_win;
117
118         XChangeProperty(dpy, wwin->client_win, _XA_WM_STATE, _XA_WM_STATE, 32,
119                         PropModeReplace, (unsigned char *)data, 2);
120 }
121
122 void wClientGetGravityOffsets(WWindow * wwin, int *ofs_x, int *ofs_y)
123 {
124         switch (wwin->normal_hints->win_gravity) {
125         case ForgetGravity:
126         case CenterGravity:
127         case StaticGravity:
128                 *ofs_x = 0;
129                 *ofs_y = 0;
130                 break;
131         case NorthWestGravity:
132                 *ofs_x = -1;
133                 *ofs_y = -1;
134                 break;
135         case NorthGravity:
136                 *ofs_x = 0;
137                 *ofs_y = -1;
138                 break;
139         case NorthEastGravity:
140                 *ofs_x = 1;
141                 *ofs_y = -1;
142                 break;
143         case WestGravity:
144                 *ofs_x = -1;
145                 *ofs_y = 0;
146                 break;
147         case EastGravity:
148                 *ofs_x = 1;
149                 *ofs_y = 0;
150                 break;
151         case SouthWestGravity:
152                 *ofs_x = -1;
153                 *ofs_y = 1;
154                 break;
155         case SouthGravity:
156                 *ofs_x = 0;
157                 *ofs_y = 1;
158                 break;
159         case SouthEastGravity:
160                 *ofs_x = 1;
161                 *ofs_y = 1;
162                 break;
163         }
164 }
165
166 void wClientConfigure(WWindow * wwin, XConfigureRequestEvent * xcre)
167 {
168         XWindowChanges xwc;
169         int nx, ny, nwidth, nheight;
170         int ofs_x, ofs_y;
171
172         /*  printf("configure event: %d %d %d %d\n", xcre->x, xcre->y, xcre->width, xcre->height); */
173
174         if (wwin == NULL) {
175                 /*
176                  * configure a window that was not mapped by us
177                  */
178                 xwc.x = xcre->x;
179                 xwc.y = xcre->y;
180                 xwc.width = xcre->width;
181                 xwc.height = xcre->height;
182                 xwc.border_width = xcre->border_width;
183                 xwc.stack_mode = xcre->detail;
184                 xwc.sibling = xcre->above;
185                 XConfigureWindow(dpy, xcre->window, xcre->value_mask, &xwc);
186                 return;
187         }
188 #ifdef SHAPE
189         if (wShapeSupported) {
190                 int junk;
191                 unsigned int ujunk;
192                 int b_shaped;
193
194                 XShapeSelectInput(dpy, wwin->client_win, ShapeNotifyMask);
195                 XShapeQueryExtents(dpy, wwin->client_win, &b_shaped, &junk, &junk,
196                                    &ujunk, &ujunk, &junk, &junk, &junk, &ujunk, &ujunk);
197                 wwin->flags.shaped = b_shaped;
198         }
199 #endif
200         if (xcre->value_mask & CWStackMode) {
201                 WObjDescriptor *desc;
202                 WWindow *sibling;
203
204                 if ((xcre->value_mask & CWSibling) &&
205                     (XFindContext(dpy, xcre->above, wWinContext, (XPointer *) & desc) == XCSUCCESS)
206                     && (desc->parent_type == WCLASS_WINDOW)) {
207                         sibling = desc->parent;
208                         xwc.sibling = sibling->frame->core->window;
209                 } else {
210                         xwc.sibling = xcre->above;
211                 }
212                 xwc.stack_mode = xcre->detail;
213                 XConfigureWindow(dpy, wwin->frame->core->window,
214                                  xcre->value_mask & (CWSibling | CWStackMode), &xwc);
215                 /* fix stacking order */
216                 RemakeStackList(wwin->screen_ptr);
217         }
218
219         wClientGetGravityOffsets(wwin, &ofs_x, &ofs_y);
220
221         if (xcre->value_mask & CWBorderWidth) {
222                 wwin->old_border_width = xcre->border_width;
223         }
224
225         if (!wwin->flags.shaded) {
226                 /* If the window is shaded, wrong height will be set for the window */
227                 if (xcre->value_mask & CWX) {
228                         nx = xcre->x;
229                         /* Subtracting the border makes the window shift by 1 pixel -Dan */
230                         /*if (HAS_BORDER(wwin)) {
231                            nx -= FRAME_BORDER_WIDTH;
232                            } */
233                 } else {
234                         nx = wwin->frame_x;
235                 }
236
237                 if (xcre->value_mask & CWY) {
238                         ny = xcre->y - ((ofs_y < 0) ? 0 : wwin->frame->top_width);
239                         /* Subtracting the border makes the window shift by 1 pixel -Dan */
240                         /*if (HAS_BORDER(wwin)) {
241                            ny -= FRAME_BORDER_WIDTH;
242                            } */
243                 } else {
244                         ny = wwin->frame_y;
245                 }
246
247                 if (xcre->value_mask & CWWidth)
248                         nwidth = xcre->width;
249                 else
250                         nwidth = wwin->frame->core->width;
251
252                 if (xcre->value_mask & CWHeight)
253                         nheight = xcre->height;
254                 else
255                         nheight = wwin->frame->core->height - wwin->frame->top_width - wwin->frame->bottom_width;
256
257                 wWindowConfigure(wwin, nx, ny, nwidth, nheight);
258                 wwin->old_geometry.x = nx;
259                 wwin->old_geometry.y = ny;
260                 wwin->old_geometry.width = nwidth;
261                 wwin->old_geometry.height = nheight;
262         }
263 }
264
265 void wClientSendProtocol(WWindow * wwin, Atom protocol, Time time)
266 {
267         XEvent event;
268
269         event.xclient.type = ClientMessage;
270         event.xclient.message_type = _XA_WM_PROTOCOLS;
271         event.xclient.format = 32;
272         event.xclient.display = dpy;
273         event.xclient.window = wwin->client_win;
274         event.xclient.data.l[0] = protocol;
275         event.xclient.data.l[1] = time;
276         event.xclient.data.l[2] = 0;
277         event.xclient.data.l[3] = 0;
278         XSendEvent(dpy, wwin->client_win, False, NoEventMask, &event);
279         XSync(dpy, False);
280 }
281
282 void wClientKill(WWindow * wwin)
283 {
284         XKillClient(dpy, wwin->client_win);
285
286         XFlush(dpy);
287 }
288
289 /*
290  *----------------------------------------------------------------------
291  * wClientCheckProperty--
292  *      Handles PropertyNotify'es, verifying which property was
293  * changed and updating internal state according to that, like redrawing
294  * the icon title when it is changed.
295  *
296  * Side effects:
297  *      Depends on the changed property.
298  *
299  * TODO: _GNUSTEP_WM_ATTR
300  *----------------------------------------------------------------------
301  */
302 void wClientCheckProperty(WWindow * wwin, XPropertyEvent * event)
303 {
304         XWindowAttributes attribs;
305         XWMHints *new_hints;
306         int i, g1, g2;
307         char *tmp = NULL;
308
309         switch (event->atom) {
310         case XA_WM_NAME:
311                 if (!wwin->flags.net_has_title) {
312                         /* window title was changed */
313                         if (!wFetchName(dpy, wwin->client_win, &tmp)) {
314                                 wWindowUpdateName(wwin, NULL);
315                         } else {
316                                 wWindowUpdateName(wwin, tmp);
317                         }
318                         if (tmp)
319                                 XFree(tmp);
320                 }
321                 break;
322
323         case XA_WM_ICON_NAME:
324                 if (!wwin->flags.net_has_icon_title) {
325                         if (!wwin->icon)
326                                 break;
327                         else {
328                                 char *new_title;
329
330                                 /* icon title was changed */
331                                 wGetIconName(dpy, wwin->client_win, &new_title);
332                                 wIconChangeTitle(wwin->icon, new_title);
333                         }
334                 }
335                 break;
336
337         case XA_WM_COMMAND:
338                 if (wwin->main_window != None) {
339                         WApplication *wapp = wApplicationOf(wwin->main_window);
340                         char *command;
341
342                         if (!wapp || !wapp->app_icon || wapp->app_icon->docked)
343                                 break;
344
345                         command = GetCommandForWindow(wwin->main_window);
346                         if (command) {
347                                 if (wapp->app_icon->command)
348                                         wfree(wapp->app_icon->command);
349                                 wapp->app_icon->command = command;
350                         }
351                 }
352                 break;
353
354         case XA_WM_HINTS:
355                 /* WM_HINTS */
356
357                 new_hints = XGetWMHints(dpy, wwin->client_win);
358
359                 /* group leader update
360                  *
361                  * This means that the window is setting the leader after
362                  * it was mapped, changing leaders or removing the leader.
363                  *
364                  * Valid state transitions are:
365                  *
366                  *          _1            __2
367                  *         / \           /  \
368                  *         v |           v  |
369                  *         (GC)         (GC')
370                  *        /  ^          /   ^
371                  *       3|  |4        5|   |6
372                  *        |  |          |   |
373                  *        v  /          v   /
374                  *        (G'C)        (G'C')
375                  *
376                  * Where G is the window_group hint, C is CLIENT_LEADER property
377                  * and ' indicates the hint is unset.
378                  *
379                  * 1,2 - change group leader to new value of window_group
380                  * 3 - change leader to value of CLIENT_LEADER
381                  * 4 - change leader to value of window_group
382                  * 5 - destroy application
383                  * 6 - create application
384                  */
385                 if (new_hints && (new_hints->flags & WindowGroupHint)
386                     && new_hints->window_group != None) {
387                         g2 = 1;
388                 } else {
389                         g2 = 0;
390                 }
391                 if (wwin->wm_hints && (wwin->wm_hints->flags & WindowGroupHint)
392                     && wwin->wm_hints->window_group != None) {
393                         g1 = 1;
394                 } else {
395                         g1 = 0;
396                 }
397
398                 if (wwin->client_leader) {
399                         if (g1 && g2 && wwin->wm_hints->window_group != new_hints->window_group) {
400                                 i = 1;
401                         } else if (g1 && !g2) {
402                                 i = 3;
403                         } else if (!g1 && g2) {
404                                 i = 4;
405                         } else {
406                                 i = 0;
407                         }
408                 } else {
409                         if (g1 && g2 && wwin->wm_hints->window_group != new_hints->window_group) {
410                                 i = 2;
411                         } else if (g1 && !g2) {
412                                 i = 5;
413                         } else if (!g1 && g2) {
414                                 i = 6;
415                         } else {
416                                 i = 0;
417                         }
418                 }
419
420                 /* Handling this may require more work. -Dan */
421                 if (wwin->fake_group != NULL) {
422                         i = 7;
423                 }
424
425                 if (wwin->wm_hints)
426                         XFree(wwin->wm_hints);
427
428                 wwin->wm_hints = new_hints;
429
430                 /* do action according to state transition */
431                 switch (i) {
432                         /* 3 - change leader to value of CLIENT_LEADER */
433                 case 3:
434                         wApplicationDestroy(wApplicationOf(wwin->main_window));
435                         wwin->main_window = wwin->client_leader;
436                         wwin->group_id = None;
437                         wApplicationCreate(wwin);
438                         break;
439
440                         /* 1,2,4 - change leader to new value of window_group */
441                 case 1:
442                 case 2:
443                 case 4:
444                         wApplicationDestroy(wApplicationOf(wwin->main_window));
445                         wwin->main_window = new_hints->window_group;
446                         wwin->group_id = wwin->main_window;
447                         wApplicationCreate(wwin);
448                         break;
449
450                         /* 5 - destroy application */
451                 case 5:
452                         wApplicationDestroy(wApplicationOf(wwin->main_window));
453                         wwin->main_window = None;
454                         wwin->group_id = None;
455                         break;
456
457                         /* 6 - create application */
458                 case 6:
459                         wwin->main_window = new_hints->window_group;
460                         wwin->group_id = wwin->main_window;
461                         wApplicationCreate(wwin);
462                         break;
463                         /* 7 - we have a fake window group id, so just ignore anything else */
464                 case 7:
465                         break;
466                 }
467 #ifdef DEBUG
468                 if (i) {
469                         printf("window leader update caused state transition %i\n", i);
470                 }
471 #endif
472
473                 if (wwin->wm_hints) {
474                         /* update icon */
475                         if ((wwin->wm_hints->flags & IconPixmapHint)
476                             || (wwin->wm_hints->flags & IconWindowHint)) {
477                                 WApplication *wapp;
478
479                                 if (wwin->flags.miniaturized && wwin->icon) {
480                                         wIconUpdate(wwin->icon);
481                                 }
482                                 wapp = wApplicationOf(wwin->main_window);
483                                 if (wapp && wapp->app_icon) {
484                                         wIconUpdate(wapp->app_icon->icon);
485                                 }
486                         }
487
488                         if (wwin->wm_hints->flags & UrgencyHint)
489                                 wwin->flags.urgent = 1;
490                         else
491                                 wwin->flags.urgent = 0;
492                         /*} else if (wwin->fake_group!=NULL) {
493                            wwin->group_id = wwin->fake_group->leader; */
494                 } else {
495                         wwin->group_id = None;
496                 }
497                 break;
498
499         case XA_WM_NORMAL_HINTS:
500                 /* normal (geometry) hints */
501                 {
502                         int foo;
503                         unsigned bar;
504
505                         XGetWindowAttributes(dpy, wwin->client_win, &attribs);
506                         wClientGetNormalHints(wwin, &attribs, False, &foo, &foo, &bar, &bar);
507                         /* TODO: should we check for consistency of the current
508                          * size against the new geometry hints? */
509                 }
510                 break;
511
512         case XA_WM_TRANSIENT_FOR:
513                 {
514                         Window new_owner;
515                         WWindow *owner;
516
517                         if (!XGetTransientForHint(dpy, wwin->client_win, &new_owner)) {
518                                 new_owner = None;
519                         } else {
520                                 if (new_owner == 0 || new_owner == wwin->client_win) {
521                                         new_owner = wwin->screen_ptr->root_win;
522                                 }
523                         }
524                         if (new_owner != wwin->transient_for) {
525                                 owner = wWindowFor(wwin->transient_for);
526                                 if (owner) {
527                                         if (owner->flags.semi_focused) {
528                                                 owner->flags.semi_focused = 0;
529                                                 if ((owner->flags.mapped || owner->flags.shaded)
530                                                     && owner->frame)
531                                                         wFrameWindowPaint(owner->frame);
532                                         }
533                                 }
534                                 owner = wWindowFor(new_owner);
535                                 if (owner) {
536                                         if (!owner->flags.semi_focused) {
537                                                 owner->flags.semi_focused = 1;
538                                                 if ((owner->flags.mapped || owner->flags.shaded)
539                                                     && owner->frame)
540                                                         wFrameWindowPaint(owner->frame);
541                                         }
542                                 }
543                                 wwin->transient_for = new_owner;
544                                 if (new_owner == None) {
545                                         if (WFLAGP(wwin, no_miniaturizable)) {
546                                                 WSETUFLAG(wwin, no_miniaturizable, 0);
547                                                 WSETUFLAG(wwin, no_miniaturize_button, 0);
548                                                 if (wwin->frame)
549                                                         wWindowConfigureBorders(wwin);
550                                         }
551                                 } else if (!WFLAGP(wwin, no_miniaturizable)) {
552                                         WSETUFLAG(wwin, no_miniaturizable, 1);
553                                         WSETUFLAG(wwin, no_miniaturize_button, 1);
554                                         if (wwin->frame)
555                                                 wWindowConfigureBorders(wwin);
556                                 }
557                         }
558                 }
559                 break;
560
561         default:
562                 if (event->atom == _XA_WM_PROTOCOLS) {
563
564                         PropGetProtocols(wwin->client_win, &wwin->protocols);
565
566                         WSETUFLAG(wwin, kill_close, !wwin->protocols.DELETE_WINDOW);
567
568                         if (wwin->frame)
569                                 wWindowUpdateButtonImages(wwin);
570
571                 } else if (event->atom == _XA_WM_COLORMAP_WINDOWS) {
572
573                         GetColormapWindows(wwin);
574                         wColormapInstallForWindow(wwin->screen_ptr, wwin);
575
576                 } else if (event->atom == _XA_WINDOWMAKER_MENU) {
577                         WApplication *wapp;
578
579                         wapp = wApplicationOf(wwin->main_window);
580                         if (wapp) {
581                                 if (wapp->menu) {
582                                         /* update menu */
583                                         /* TODO: remake appmenu update */
584                                         wAppMenuDestroy(wapp->menu);
585                                 }
586                                 if (wwin->fake_group) {
587                                         extern WPreferences wPreferences;
588                                         WScreen *scr = wwin->screen_ptr;
589                                         WWindow *foo = scr->focused_window;
590                                         WFakeGroupLeader *fPtr = wwin->fake_group;
591
592                                         wApplicationDestroy(wapp);
593                                         while (foo) {
594                                                 if (foo->fake_group && foo->fake_group == fPtr) {
595                                                         WSETUFLAG(foo, shared_appicon, 0);
596                                                         foo->fake_group = NULL;
597                                                         if (foo->group_id != None)
598                                                                 foo->main_window = foo->group_id;
599                                                         else if (foo->client_leader != None)
600                                                                 foo->main_window = foo->client_leader;
601                                                         else if (WFLAGP(foo, emulate_appicon))
602                                                                 foo->main_window = foo->client_win;
603                                                         else
604                                                                 foo->main_window = None;
605                                                         if (foo->main_window) {
606                                                                 wapp = wApplicationCreate(foo);
607                                                         }
608                                                 }
609                                                 foo = foo->prev;
610                                         }
611
612                                         if (fPtr->leader != None)
613                                                 XDestroyWindow(dpy, fPtr->leader);
614                                         fPtr->retainCount = 0;
615                                         fPtr->leader = None;
616                                         fPtr->origLeader = None;
617
618                                         wapp = wApplicationOf(wwin->main_window);
619                                         if (wapp) {
620                                                 wapp->menu = wAppMenuGet(scr, wwin->main_window);
621                                         }
622                                         if (wPreferences.auto_arrange_icons) {
623                                                 wArrangeIcons(wwin->screen_ptr, True);
624                                         }
625                                 } else {
626                                         wapp->menu = wAppMenuGet(wwin->screen_ptr, wwin->main_window);
627                                 }
628                                 /* make the appmenu be mapped */
629                                 wSetFocusTo(wwin->screen_ptr, NULL);
630                                 wSetFocusTo(wwin->screen_ptr, wwin->screen_ptr->focused_window);
631                         }
632                 } else if (event->atom == _XA_GNUSTEP_WM_ATTR) {
633                         GNUstepWMAttributes *attr;
634
635                         PropGetGNUstepWMAttr(wwin->client_win, &attr);
636
637                         wWindowUpdateGNUstepAttr(wwin, attr);
638
639                         XFree(attr);
640                 } else {
641 #ifdef NETWM_HINTS
642                         wNETWMCheckClientHintChange(wwin, event);
643 #endif
644                 }
645         }
646 }
647
648 /*
649  *----------------------------------------------------------------------
650  * wClientGetNormalHints--
651  *      Get size (normal) hints and a default geometry for the client
652  * window. The hints are also checked for inconsistency. If geometry is
653  * True, the returned data will account for client specified initial
654  * geometry.
655  *
656  * Side effects:
657  *      normal_hints is filled with valid data.
658  *----------------------------------------------------------------------
659  */
660 void
661 wClientGetNormalHints(WWindow * wwin, XWindowAttributes * wattribs, Bool geometry,
662                       int *x, int *y, unsigned *width, unsigned *height)
663 {
664         int pre_icccm = 0;      /* not used */
665
666         /* find a position for the window */
667         if (!wwin->normal_hints)
668                 wwin->normal_hints = XAllocSizeHints();
669
670         if (!PropGetNormalHints(wwin->client_win, wwin->normal_hints, &pre_icccm)) {
671                 wwin->normal_hints->flags = 0;
672         }
673         *x = wattribs->x;
674         *y = wattribs->y;
675
676         *width = wattribs->width;
677         *height = wattribs->height;
678
679         if (!(wwin->normal_hints->flags & PWinGravity)) {
680                 wwin->normal_hints->win_gravity = NorthWestGravity;
681         }
682         if (!(wwin->normal_hints->flags & PMinSize)) {
683                 wwin->normal_hints->min_width = MIN_WINDOW_SIZE;
684                 wwin->normal_hints->min_height = MIN_WINDOW_SIZE;
685         }
686         if (!(wwin->normal_hints->flags & PBaseSize)) {
687                 wwin->normal_hints->base_width = 0;
688                 wwin->normal_hints->base_height = 0;
689         }
690         if (!(wwin->normal_hints->flags & PMaxSize)) {
691                 wwin->normal_hints->max_width = wwin->screen_ptr->scr_width * 2;
692                 wwin->normal_hints->max_height = wwin->screen_ptr->scr_height * 2;
693         }
694
695         /* some buggy apps set weird hints.. */
696         if (wwin->normal_hints->min_width <= 0)
697                 wwin->normal_hints->min_width = MIN_WINDOW_SIZE;
698
699         if (wwin->normal_hints->min_height <= 0)
700                 wwin->normal_hints->min_height = MIN_WINDOW_SIZE;
701
702         if (wwin->normal_hints->max_width < wwin->normal_hints->min_width)
703                 wwin->normal_hints->max_width = wwin->normal_hints->min_width;
704
705         if (wwin->normal_hints->max_height < wwin->normal_hints->min_height)
706                 wwin->normal_hints->max_height = wwin->normal_hints->min_height;
707
708         if (!(wwin->normal_hints->flags & PResizeInc)) {
709                 wwin->normal_hints->width_inc = 1;
710                 wwin->normal_hints->height_inc = 1;
711         } else {
712                 if (wwin->normal_hints->width_inc <= 0)
713                         wwin->normal_hints->width_inc = 1;
714                 if (wwin->normal_hints->height_inc <= 0)
715                         wwin->normal_hints->height_inc = 1;
716         }
717
718         if (wwin->normal_hints->flags & PAspect) {
719                 if (wwin->normal_hints->min_aspect.x < 1)
720                         wwin->normal_hints->min_aspect.x = 1;
721                 if (wwin->normal_hints->min_aspect.y < 1)
722                         wwin->normal_hints->min_aspect.y = 1;
723
724                 if (wwin->normal_hints->max_aspect.x < 1)
725                         wwin->normal_hints->max_aspect.x = 1;
726                 if (wwin->normal_hints->max_aspect.y < 1)
727                         wwin->normal_hints->max_aspect.y = 1;
728         }
729
730         if (wwin->normal_hints->min_height > wwin->normal_hints->max_height) {
731                 wwin->normal_hints->min_height = wwin->normal_hints->max_height;
732         }
733         if (wwin->normal_hints->min_width > wwin->normal_hints->max_width) {
734                 wwin->normal_hints->min_width = wwin->normal_hints->max_width;
735         }
736 #ifdef IGNORE_PPOSITION
737         wwin->normal_hints->flags &= ~PPosition;
738 #endif
739
740         if (pre_icccm && !wwin->screen_ptr->flags.startup && geometry) {
741                 if (wwin->normal_hints->flags & (USPosition | PPosition)) {
742                         *x = wwin->normal_hints->x;
743                         *y = wwin->normal_hints->y;
744                 }
745                 if (wwin->normal_hints->flags & (USSize | PSize)) {
746                         *width = wwin->normal_hints->width;
747                         *height = wwin->normal_hints->height;
748                 }
749         }
750 }
751
752 void GetColormapWindows(WWindow * wwin)
753 {
754 #ifndef NO_CRASHES
755         if (wwin->cmap_windows) {
756                 XFree(wwin->cmap_windows);
757         }
758
759         wwin->cmap_windows = NULL;
760         wwin->cmap_window_no = 0;
761
762         if (!XGetWMColormapWindows(dpy, wwin->client_win, &(wwin->cmap_windows), &(wwin->cmap_window_no))
763             || !wwin->cmap_windows) {
764                 wwin->cmap_window_no = 0;
765                 wwin->cmap_windows = NULL;
766         }
767 #endif
768 }