~profzoom/ubuntu/quantal/wmaker/bug-1079925

« back to all changes in this revision

Viewing changes to src/client.c

  • Committer: Bazaar Package Importer
  • Author(s): Marcelo E. Magallon
  • Date: 2004-11-10 14:05:30 UTC
  • Revision ID: james.westby@ubuntu.com-20041110140530-qpd66b5lm38x7apk
Tags: upstream-0.91.0
ImportĀ upstreamĀ versionĀ 0.91.0

Show diffs side-by-side

added added

removed removed

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