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

« back to all changes in this revision

Viewing changes to src/placement.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
/* placement.c - window and icon placement on screen
 
2
 *
 
3
 *  Window Maker window manager
 
4
 *
 
5
 *  Copyright (c) 1997-2003 Alfredo K. Kojima
 
6
 *
 
7
 *  This program is free software; you can redistribute it and/or modify
 
8
 *  it under the terms of the GNU General Public License as published by
 
9
 *  the Free Software Foundation; either version 2 of the License, or
 
10
 *  (at your option) any later version.
 
11
 *
 
12
 *  This program is distributed in the hope that it will be useful,
 
13
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 *  GNU General Public License for more details.
 
16
 *
 
17
 *  You should have received a copy of the GNU General Public License
 
18
 *  along with this program; if not, write to the Free Software
 
19
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
 
20
 *  USA.
 
21
 */
 
22
 
 
23
#include "wconfig.h"
 
24
 
 
25
#include <X11/Xlib.h>
 
26
#include <stdlib.h>
 
27
#include <stdio.h>
 
28
#include <string.h>
 
29
#include <limits.h>
 
30
 
 
31
#include "WindowMaker.h"
 
32
#include "wcore.h"
 
33
#include "framewin.h"
 
34
#include "window.h"
 
35
#include "icon.h"
 
36
#include "appicon.h"
 
37
#include "actions.h"
 
38
#include "funcs.h"
 
39
#include "application.h"
 
40
#include "appicon.h"
 
41
#include "dock.h"
 
42
#include "xinerama.h"
 
43
 
 
44
 
 
45
extern WPreferences wPreferences;
 
46
 
 
47
 
 
48
#define X_ORIGIN WMAX(usableArea.x1,\
 
49
    wPreferences.window_place_origin.x)
 
50
 
 
51
#define Y_ORIGIN WMAX(usableArea.y1,\
 
52
    wPreferences.window_place_origin.y)
 
53
 
 
54
 
 
55
/*
 
56
 * interactive window placement is in moveres.c
 
57
 */
 
58
 
 
59
extern void InteractivePlaceWindow(WWindow *wwin, int *x_ret, int *y_ret,
 
60
                                   unsigned width, unsigned height);
 
61
 
 
62
 
 
63
/*
 
64
 * Returns True if it is an icon and is in this workspace.
 
65
 */
 
66
static Bool
 
67
iconPosition(WCoreWindow *wcore, int sx1, int sy1, int sx2, int sy2,
 
68
             int workspace, int *retX, int *retY)
 
69
{
 
70
    void *parent;
 
71
    int ok = 0;
 
72
 
 
73
    parent = wcore->descriptor.parent;
 
74
 
 
75
    /* if it is an application icon */
 
76
    if (wcore->descriptor.parent_type == WCLASS_APPICON
 
77
        && !((WAppIcon*)parent)->docked) {
 
78
        *retX = ((WAppIcon*)parent)->x_pos;
 
79
        *retY = ((WAppIcon*)parent)->y_pos;
 
80
 
 
81
        ok = 1;
 
82
    } else if (wcore->descriptor.parent_type == WCLASS_MINIWINDOW &&
 
83
               (((WIcon*)parent)->owner->frame->workspace == workspace
 
84
                || IS_OMNIPRESENT(((WIcon*)parent)->owner)
 
85
                || wPreferences.sticky_icons)
 
86
               && ((WIcon*)parent)->mapped) {
 
87
 
 
88
        *retX = ((WIcon*)parent)->owner->icon_x;
 
89
        *retY = ((WIcon*)parent)->owner->icon_y;
 
90
 
 
91
        ok = 1;
 
92
    } else if (wcore->descriptor.parent_type == WCLASS_WINDOW
 
93
               && ((WWindow*)parent)->flags.icon_moved
 
94
               && (((WWindow*)parent)->frame->workspace == workspace
 
95
                   || IS_OMNIPRESENT((WWindow*)parent)
 
96
                   || wPreferences.sticky_icons)) {
 
97
        *retX = ((WWindow*)parent)->icon_x;
 
98
        *retY = ((WWindow*)parent)->icon_y;
 
99
 
 
100
        ok = 1;
 
101
    }
 
102
 
 
103
 
 
104
    /*
 
105
     * Check if it is inside the screen.
 
106
     */
 
107
    if (ok) {
 
108
        if (*retX < sx1-wPreferences.icon_size)
 
109
            ok = 0;
 
110
        else if (*retX > sx2)
 
111
            ok = 0;
 
112
 
 
113
        if (*retY < sy1-wPreferences.icon_size)
 
114
            ok = 0;
 
115
        else if (*retY > sy2)
 
116
            ok = 0;
 
117
    }
 
118
 
 
119
    return ok;
 
120
}
 
121
 
 
122
 
 
123
 
 
124
 
 
125
void
 
126
PlaceIcon(WScreen *scr, int *x_ret, int *y_ret, int head)
 
127
{
 
128
    int pf;                            /* primary axis */
 
129
    int sf;                            /* secondary axis */
 
130
    int fullW;
 
131
    int fullH;
 
132
    char *map;
 
133
    int pi, si;
 
134
    WCoreWindow *obj;
 
135
    int sx1, sx2, sy1, sy2;            /* screen boundary */
 
136
    int sw, sh;
 
137
    int xo, yo;
 
138
    int xs, ys;
 
139
    int x, y;
 
140
    int isize = wPreferences.icon_size;
 
141
    int done = 0;
 
142
    WMBagIterator iter;
 
143
    WArea area = wGetUsableAreaForHead(scr, head, NULL, False);
 
144
 
 
145
    /* Find out screen boundaries. */
 
146
 
 
147
    /* Allows each head to have miniwindows */
 
148
 
 
149
    sx1 = area.x1;
 
150
    sy1 = area.y1;
 
151
    sx2 = area.x2;
 
152
    sy2 = area.y2;
 
153
    sw = sx2-sx1;
 
154
    sh = sy2-sy1;
 
155
 
 
156
#if 0
 
157
    if (scr->dock) {
 
158
        if (scr->dock->on_right_side)
 
159
            sx2 -= isize + DOCK_EXTRA_SPACE;
 
160
        else
 
161
            sx1 += isize + DOCK_EXTRA_SPACE;
 
162
    }
 
163
#endif
 
164
 
 
165
    sw = isize * (sw/isize);
 
166
    sh = isize * (sh/isize);
 
167
    fullW = (sx2-sx1)/isize;
 
168
    fullH = (sy2-sy1)/isize;
 
169
 
 
170
    /* icon yard boundaries */
 
171
    if (wPreferences.icon_yard & IY_VERT) {
 
172
        pf = fullH;
 
173
        sf = fullW;
 
174
    } else {
 
175
        pf = fullW;
 
176
        sf = fullH;
 
177
    }
 
178
    if (wPreferences.icon_yard & IY_RIGHT) {
 
179
        xo = sx2 - isize;
 
180
        xs = -1;
 
181
    } else {
 
182
        xo = sx1;
 
183
        xs = 1;
 
184
    }
 
185
    if (wPreferences.icon_yard & IY_TOP) {
 
186
        yo = sy1;
 
187
        ys = 1;
 
188
    } else {
 
189
        yo = sy2 - isize;
 
190
        ys = -1;
 
191
    }
 
192
 
 
193
    /*
 
194
     * Create a map with the occupied slots. 1 means the slot is used
 
195
     * or at least partially used.
 
196
     * The slot usage can be optimized by only marking fully used slots
 
197
     * or slots that have most of it covered.
 
198
     * Space usage is worse than the fvwm algorithm (used in the old version)
 
199
     * but complexity is much better (faster) than it.
 
200
     */
 
201
    map = wmalloc((sw+2) * (sh+2));
 
202
    memset(map, 0, (sw+2) * (sh+2));
 
203
 
 
204
#define INDEX(x,y)      (((y)+1)*(sw+2) + (x) + 1)
 
205
 
 
206
    WM_ETARETI_BAG(scr->stacking_list, obj, iter) {
 
207
 
 
208
        while (obj) {
 
209
            int x, y;
 
210
 
 
211
            if (iconPosition(obj, sx1, sy1, sx2, sy2, scr->current_workspace,
 
212
                             &x, &y)) {
 
213
                int xdi, ydi;          /* rounded down */
 
214
                int xui, yui;          /* rounded up */
 
215
 
 
216
                xdi = x/isize;
 
217
                ydi = y/isize;
 
218
                xui = (x+isize/2)/isize;
 
219
                yui = (y+isize/2)/isize;
 
220
                map[INDEX(xdi,ydi)] = 1;
 
221
                map[INDEX(xdi,yui)] = 1;
 
222
                map[INDEX(xui,ydi)] = 1;
 
223
                map[INDEX(xui,yui)] = 1;
 
224
            }
 
225
            obj = obj->stacking->under;
 
226
        }
 
227
    }
 
228
    /*
 
229
     * Default position
 
230
     */
 
231
    *x_ret = 0;
 
232
    *y_ret = 0;
 
233
 
 
234
    /*
 
235
     * Look for an empty slot
 
236
     */
 
237
    for (si=0; si<sf; si++) {
 
238
        for (pi=0; pi<pf; pi++) {
 
239
            if (wPreferences.icon_yard & IY_VERT) {
 
240
                x = xo + xs*(si*isize);
 
241
                y = yo + ys*(pi*isize);
 
242
            } else {
 
243
                x = xo + xs*(pi*isize);
 
244
                y = yo + ys*(si*isize);
 
245
            }
 
246
            if (!map[INDEX(x/isize, y/isize)]) {
 
247
                *x_ret = x;
 
248
                *y_ret = y;
 
249
                done = 1;
 
250
                break;
 
251
            }
 
252
        }
 
253
        if (done)
 
254
            break;
 
255
    }
 
256
 
 
257
    wfree(map);
 
258
}
 
259
 
 
260
 
 
261
/*
 
262
 * This function calculates the length of the intersection of two
 
263
 * line sections. (Hey, is that english?)
 
264
 */
 
265
static int
 
266
calcIntersectionLength(int p1, int l1, int p2, int l2)
 
267
{
 
268
    int isect;
 
269
    int tmp;
 
270
 
 
271
    if (p1 > p2) {
 
272
        tmp = p1;
 
273
        p1 = p2;
 
274
        p2 = tmp;
 
275
        tmp = l1;
 
276
        l1 = l2;
 
277
        l2 = tmp;
 
278
    }
 
279
 
 
280
    if (p1 + l1 < p2)
 
281
        isect = 0;
 
282
    else if (p2 + l2 < p1 + l1)
 
283
        isect = l2;
 
284
    else
 
285
        isect = p1 + l1 - p2;
 
286
 
 
287
    return isect;
 
288
}
 
289
 
 
290
 
 
291
/*
 
292
 * This function calculates the area of the intersection of two rectangles.
 
293
 */
 
294
 
 
295
int
 
296
calcIntersectionArea(int x1, int y1, int w1, int h1,
 
297
                     int x2, int y2, int w2, int h2)
 
298
{
 
299
    return calcIntersectionLength(x1, w1, x2, w2)
 
300
        * calcIntersectionLength(y1, h1, y2, h2);
 
301
}
 
302
 
 
303
 
 
304
static int
 
305
calcSumOfCoveredAreas(WWindow *wwin, int x, int y, int w, int h)
 
306
{
 
307
    int sum_isect = 0;
 
308
    WWindow *test_window;
 
309
    int tw,tx,ty,th;
 
310
 
 
311
    test_window = wwin->screen_ptr->focused_window;
 
312
    for(;test_window != NULL && test_window->prev != NULL;)
 
313
        test_window = test_window->prev;
 
314
 
 
315
    for(; test_window != NULL; test_window = test_window->next) {
 
316
        if (test_window->frame->core->stacking->window_level
 
317
            < WMNormalLevel) {
 
318
            continue;
 
319
        }
 
320
 
 
321
#if 0
 
322
        tw = test_window->client.width;
 
323
        if (test_window->flags.shaded)
 
324
            th = test_window->frame->top_width;
 
325
        else
 
326
            th = test_window->client.height + extra_height;
 
327
#else
 
328
        tw = test_window->frame->core->width;
 
329
        th = test_window->frame->core->height;
 
330
#endif
 
331
        tx = test_window->frame_x;
 
332
        ty = test_window->frame_y;
 
333
 
 
334
        if (test_window->flags.mapped ||
 
335
            (test_window->flags.shaded &&
 
336
             !(test_window->flags.miniaturized ||
 
337
               test_window->flags.hidden))) {
 
338
            sum_isect += calcIntersectionArea(tx, ty, tw, th, x, y, w, h);
 
339
        }
 
340
    }
 
341
 
 
342
    return sum_isect;
 
343
}
 
344
 
 
345
 
 
346
static void
 
347
smartPlaceWindow(WWindow *wwin, int *x_ret, int *y_ret,
 
348
                 unsigned int width, unsigned int height,
 
349
                 WArea usableArea)
 
350
{
 
351
    int test_x = 0, test_y = Y_ORIGIN;
 
352
    int from_x, to_x, from_y, to_y;
 
353
    int sx;
 
354
    int min_isect, min_isect_x, min_isect_y;
 
355
    int sum_isect;
 
356
 
 
357
    if (wwin->frame) {
 
358
        height += wwin->frame->top_width + wwin->frame->bottom_width;
 
359
    } else {
 
360
        if (HAS_TITLEBAR(wwin)) height += 18;
 
361
        if (HAS_RESIZEBAR(wwin)) height += 8;
 
362
    }
 
363
    if (HAS_BORDER(wwin)) {
 
364
        height += 2;
 
365
        width += 2;
 
366
    }
 
367
    sx = X_ORIGIN;
 
368
 
 
369
    min_isect = INT_MAX;
 
370
    min_isect_x = sx;
 
371
    min_isect_y = test_y;
 
372
 
 
373
    while (((test_y + height) < usableArea.y2)) {
 
374
        test_x = sx;
 
375
        while ((test_x + width) < usableArea.x2) {
 
376
            sum_isect = calcSumOfCoveredAreas(wwin, test_x, test_y,
 
377
                                              width, height);
 
378
 
 
379
            if (sum_isect < min_isect) {
 
380
                min_isect = sum_isect;
 
381
                min_isect_x = test_x;
 
382
                min_isect_y = test_y;
 
383
            }
 
384
 
 
385
            test_x += PLACETEST_HSTEP;
 
386
        }
 
387
        test_y += PLACETEST_VSTEP;
 
388
    }
 
389
 
 
390
    from_x = min_isect_x - PLACETEST_HSTEP + 1;
 
391
    from_x = WMAX(from_x, X_ORIGIN);
 
392
    to_x = min_isect_x + PLACETEST_HSTEP;
 
393
    if (to_x + width > usableArea.x2)
 
394
        to_x = usableArea.x2 - width;
 
395
 
 
396
    from_y = min_isect_y - PLACETEST_VSTEP + 1;
 
397
    from_y = WMAX(from_y, Y_ORIGIN);
 
398
    to_y = min_isect_y + PLACETEST_VSTEP;
 
399
    if (to_y + height > usableArea.y2)
 
400
        to_y = usableArea.y2 - height;
 
401
 
 
402
    for (test_x = from_x; test_x < to_x; test_x++) {
 
403
        for (test_y = from_y; test_y < to_y; test_y++) {
 
404
            sum_isect = calcSumOfCoveredAreas(wwin, test_x, test_y,
 
405
                                              width, height);
 
406
 
 
407
            if (sum_isect < min_isect) {
 
408
                min_isect = sum_isect;
 
409
                min_isect_x = test_x;
 
410
                min_isect_y = test_y;
 
411
            }
 
412
        }
 
413
    }
 
414
 
 
415
    *x_ret = min_isect_x;
 
416
    *y_ret = min_isect_y;
 
417
}
 
418
 
 
419
 
 
420
static Bool
 
421
autoPlaceWindow(WWindow *wwin, int *x_ret, int *y_ret,
 
422
                unsigned int width, unsigned int height, int tryCount,
 
423
                WArea usableArea)
 
424
{
 
425
    WScreen *scr = wwin->screen_ptr;
 
426
    int test_x = 0, test_y = Y_ORIGIN;
 
427
    int loc_ok = False, tw,tx,ty,th;
 
428
    int swidth, sx;
 
429
    WWindow *test_window;
 
430
 
 
431
    if (wwin->frame) {
 
432
        height += wwin->frame->top_width + wwin->frame->bottom_width;
 
433
    } else {
 
434
        if (HAS_TITLEBAR(wwin)) height += 18;
 
435
        if (HAS_RESIZEBAR(wwin)) height += 8;
 
436
    }
 
437
    if (HAS_BORDER(wwin)) {
 
438
        height += 2;
 
439
        width += 2;
 
440
    }
 
441
 
 
442
    swidth = usableArea.x2-usableArea.x1;
 
443
    sx = X_ORIGIN;
 
444
 
 
445
    /* this was based on fvwm2's smart placement */
 
446
 
 
447
    while (((test_y + height) < (usableArea.y2 - usableArea.y1)) && !loc_ok) {
 
448
        test_x = sx;
 
449
 
 
450
        while (((test_x + width) < swidth) && (!loc_ok)) {
 
451
 
 
452
            loc_ok = True;
 
453
            test_window = scr->focused_window;
 
454
 
 
455
            while ((test_window != NULL) && (loc_ok == True)) {
 
456
 
 
457
                if (test_window->frame->core->stacking->window_level
 
458
                    < WMNormalLevel && tryCount > 0) {
 
459
                    test_window = test_window->next;
 
460
                    continue;
 
461
                }
 
462
#if 0
 
463
                tw = test_window->client.width;
 
464
                if (test_window->flags.shaded)
 
465
                    th = test_window->frame->top_width;
 
466
                else
 
467
                    th = test_window->client.height + extra_height;
 
468
#else
 
469
                tw = test_window->frame->core->width;
 
470
                th = test_window->frame->core->height;
 
471
#endif
 
472
                tx = test_window->frame_x;
 
473
                ty = test_window->frame_y;
 
474
 
 
475
                if ((tx < (test_x + width)) && ((tx + tw) > test_x) &&
 
476
                    (ty < (test_y + height)) && ((ty + th) > test_y) &&
 
477
                    (test_window->flags.mapped ||
 
478
                     (test_window->flags.shaded &&
 
479
                      test_window->frame->workspace==scr->current_workspace &&
 
480
                      !(test_window->flags.miniaturized ||
 
481
                        test_window->flags.hidden)))) {
 
482
 
 
483
                    loc_ok = False;
 
484
                }
 
485
                test_window = test_window->next;
 
486
            }
 
487
 
 
488
            test_window = scr->focused_window;
 
489
 
 
490
            while ((test_window != NULL) && (loc_ok == True))  {
 
491
 
 
492
                if (test_window->frame->core->stacking->window_level
 
493
                    < WMNormalLevel && tryCount > 0) {
 
494
                    test_window = test_window->prev;
 
495
                    continue;
 
496
                }
 
497
#if 0
 
498
                tw = test_window->client.width;
 
499
                if (test_window->flags.shaded)
 
500
                    th = test_window->frame->top_width;
 
501
                else
 
502
                    th = test_window->client.height + extra_height;
 
503
#else
 
504
                tw = test_window->frame->core->width;
 
505
                th = test_window->frame->core->height;
 
506
#endif
 
507
                tx = test_window->frame_x;
 
508
                ty = test_window->frame_y;
 
509
 
 
510
                if ((tx < (test_x + width)) && ((tx + tw) > test_x) &&
 
511
                    (ty < (test_y + height)) && ((ty + th) > test_y) &&
 
512
                    (test_window->flags.mapped ||
 
513
                     (test_window->flags.shaded &&
 
514
                      test_window->frame->workspace==scr->current_workspace &&
 
515
                      !(test_window->flags.miniaturized ||
 
516
                        test_window->flags.hidden)))) {
 
517
 
 
518
                    loc_ok = False;
 
519
                }
 
520
                test_window = test_window->prev;
 
521
            }
 
522
            if (loc_ok == True) {
 
523
                *x_ret = test_x;
 
524
                *y_ret = test_y;
 
525
                break;
 
526
            }
 
527
            test_x += PLACETEST_HSTEP;
 
528
        }
 
529
        test_y += PLACETEST_VSTEP;
 
530
    }
 
531
 
 
532
    return loc_ok;
 
533
}
 
534
 
 
535
 
 
536
static void
 
537
cascadeWindow(WScreen *scr, WWindow *wwin, int *x_ret, int *y_ret,
 
538
              unsigned int width, unsigned int height, int h,
 
539
              WArea usableArea)
 
540
{
 
541
    if (wwin->frame) {
 
542
        height += wwin->frame->top_width + wwin->frame->bottom_width;
 
543
    } else {
 
544
        if (HAS_TITLEBAR(wwin)) height += 18;
 
545
        if (HAS_RESIZEBAR(wwin)) height += 8;
 
546
    }
 
547
    if (HAS_BORDER(wwin)) {
 
548
        height += 2;
 
549
        width += 2;
 
550
    }
 
551
 
 
552
    *x_ret = h * scr->cascade_index + X_ORIGIN;
 
553
    *y_ret = h * scr->cascade_index + Y_ORIGIN;
 
554
 
 
555
    if (width + *x_ret > usableArea.x2 || height + *y_ret > usableArea.y2) {
 
556
        scr->cascade_index = 0;
 
557
        *x_ret = X_ORIGIN;
 
558
        *y_ret = Y_ORIGIN;
 
559
    }
 
560
}
 
561
 
 
562
 
 
563
static void
 
564
randomPlaceWindow(WScreen *scr, WWindow *wwin, int *x_ret, int *y_ret,
 
565
                  unsigned int width, unsigned int height,
 
566
                  WArea usableArea)
 
567
{
 
568
    int w, h;
 
569
 
 
570
    if (wwin->frame) {
 
571
        height += wwin->frame->top_width + wwin->frame->bottom_width;
 
572
    } else {
 
573
        if (HAS_TITLEBAR(wwin)) height += 18;
 
574
        if (HAS_RESIZEBAR(wwin)) height += 8;
 
575
    }
 
576
    if (HAS_BORDER(wwin)) {
 
577
        height += 2;
 
578
        width += 2;
 
579
    }
 
580
 
 
581
    w = ((usableArea.x2-X_ORIGIN) - width);
 
582
    h = ((usableArea.y2-Y_ORIGIN) - height);
 
583
    if (w<1) w = 1;
 
584
    if (h<1) h = 1;
 
585
    *x_ret = X_ORIGIN + rand()%w;
 
586
    *y_ret = Y_ORIGIN + rand()%h;
 
587
}
 
588
 
 
589
 
 
590
 
 
591
void
 
592
PlaceWindow(WWindow *wwin, int *x_ret, int *y_ret,
 
593
            unsigned width, unsigned height)
 
594
{
 
595
    WScreen *scr = wwin->screen_ptr;
 
596
    int h = WMFontHeight(scr->title_font) + (wPreferences.window_title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
 
597
    WArea usableArea = wGetUsableAreaForHead(scr,
 
598
                                             wGetHeadForPointerLocation(scr),
 
599
                                             NULL, True);
 
600
 
 
601
    switch (wPreferences.window_placement) {
 
602
    case WPM_MANUAL:
 
603
        InteractivePlaceWindow(wwin, x_ret, y_ret, width, height);
 
604
        break;
 
605
 
 
606
    case WPM_SMART:
 
607
        smartPlaceWindow(wwin, x_ret, y_ret, width, height, usableArea);
 
608
        break;
 
609
 
 
610
    case WPM_AUTO:
 
611
        if (autoPlaceWindow(wwin, x_ret, y_ret, width, height, 0,
 
612
                            usableArea)) {
 
613
            break;
 
614
        } else if (autoPlaceWindow(wwin, x_ret, y_ret, width, height, 1,
 
615
                                   usableArea)) {
 
616
            break;
 
617
        }
 
618
        /* there isn't a break here, because if we fail, it should fall
 
619
         through to cascade placement, as people who want tiling want
 
620
         automagicness aren't going to want to place their window */
 
621
 
 
622
    case WPM_CASCADE:
 
623
        if (wPreferences.window_placement == WPM_AUTO)
 
624
            scr->cascade_index++;
 
625
 
 
626
        cascadeWindow(scr, wwin, x_ret, y_ret, width, height, h, usableArea);
 
627
 
 
628
        if (wPreferences.window_placement == WPM_CASCADE)
 
629
            scr->cascade_index++;
 
630
        break;
 
631
 
 
632
    case WPM_RANDOM:
 
633
        randomPlaceWindow(scr, wwin, x_ret, y_ret, width, height, usableArea);
 
634
        break;
 
635
 
 
636
#ifdef DEBUG
 
637
    default:
 
638
        puts("Invalid window placement!!!");
 
639
        *x_ret = 0;
 
640
        *y_ret = 0;
 
641
#endif
 
642
    }
 
643
 
 
644
    /*
 
645
     * clip to usableArea instead of full screen
 
646
     * this will also take dock/clip etc.. into account
 
647
     * aswell as being xinerama friendly
 
648
     */
 
649
    if (*x_ret + width > usableArea.x2)
 
650
        *x_ret = usableArea.x2 - width;
 
651
    if (*x_ret < usableArea.x1)
 
652
        *x_ret = usableArea.x1;
 
653
 
 
654
    if (*y_ret + height > usableArea.y2)
 
655
        *y_ret = usableArea.y2 - height;
 
656
    if (*y_ret < usableArea.y1)
 
657
        *y_ret = usableArea.y1;
 
658
}
 
659
 
 
660