Change to the linux kernel coding style
[wmaker-crm.git] / src / placement.c
Commit [+]AuthorDateLineData
9d2e6ef9 scottc1998-09-29 22:36:29 +00001/* placement.c - window and icon placement on screen
6830b057 dan2004-10-12 21:28:27 +00002 *
9af1c6c4 dan1998-10-21 14:43:47 +00003 * Window Maker window manager
6830b057 dan2004-10-12 21:28:27 +00004 *
4153e2fd dan2003-01-16 23:30:45 +00005 * Copyright (c) 1997-2003 Alfredo K. Kojima
6830b057 dan2004-10-12 21:28:27 +00006 *
9d2e6ef9 scottc1998-09-29 22:36:29 +00007 * 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
6830b057 dan2004-10-12 21:28:27 +000019 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
9d2e6ef9 scottc1998-09-29 22:36:29 +000020 * 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>
3c046182 kojima1999-09-16 02:58:56 +000029#include <limits.h>
9d2e6ef9 scottc1998-09-29 22:36:29 +000030
31#include "WindowMaker.h"
32#include "wcore.h"
33#include "framewin.h"
34#include "window.h"
35#include "icon.h"
daeb6d67 kojima1999-04-30 23:31:00 +000036#include "appicon.h"
9d2e6ef9 scottc1998-09-29 22:36:29 +000037#include "actions.h"
38#include "funcs.h"
39#include "application.h"
40#include "appicon.h"
41#include "dock.h"
a10214a5 kojima2002-11-28 22:04:07 +000042#include "xinerama.h"
9d2e6ef9 scottc1998-09-29 22:36:29 +000043
44extern WPreferences wPreferences;
45
620a280d kojima2004-10-22 23:39:11 +000046#define X_ORIGIN WMAX(usableArea.x1,\
6830b057 dan2004-10-12 21:28:27 +000047 wPreferences.window_place_origin.x)
0261c326 dan1999-01-06 15:22:33 +000048
620a280d kojima2004-10-22 23:39:11 +000049#define Y_ORIGIN WMAX(usableArea.y1,\
6830b057 dan2004-10-12 21:28:27 +000050 wPreferences.window_place_origin.y)
9d2e6ef9 scottc1998-09-29 22:36:29 +000051
9d2e6ef9 scottc1998-09-29 22:36:29 +000052/*
53 * interactive window placement is in moveres.c
54 */
55
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020056extern void InteractivePlaceWindow(WWindow * wwin, int *x_ret, int *y_ret, unsigned width, unsigned height);
9d2e6ef9 scottc1998-09-29 22:36:29 +000057
58/*
59 * Returns True if it is an icon and is in this workspace.
60 */
61static Bool
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020062iconPosition(WCoreWindow * wcore, int sx1, int sy1, int sx2, int sy2, int workspace, int *retX, int *retY)
9d2e6ef9 scottc1998-09-29 22:36:29 +000063{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +020064 void *parent;
65 int ok = 0;
66
67 parent = wcore->descriptor.parent;
68
69 /* if it is an application icon */
70 if (wcore->descriptor.parent_type == WCLASS_APPICON && !((WAppIcon *) parent)->docked) {
71 *retX = ((WAppIcon *) parent)->x_pos;
72 *retY = ((WAppIcon *) parent)->y_pos;
73
74 ok = 1;
75 } else if (wcore->descriptor.parent_type == WCLASS_MINIWINDOW &&
76 (((WIcon *) parent)->owner->frame->workspace == workspace
77 || IS_OMNIPRESENT(((WIcon *) parent)->owner)
78 || wPreferences.sticky_icons)
79 && ((WIcon *) parent)->mapped) {
80
81 *retX = ((WIcon *) parent)->owner->icon_x;
82 *retY = ((WIcon *) parent)->owner->icon_y;
83
84 ok = 1;
85 } else if (wcore->descriptor.parent_type == WCLASS_WINDOW
86 && ((WWindow *) parent)->flags.icon_moved
87 && (((WWindow *) parent)->frame->workspace == workspace || IS_OMNIPRESENT((WWindow *) parent)
88 || wPreferences.sticky_icons)) {
89 *retX = ((WWindow *) parent)->icon_x;
90 *retY = ((WWindow *) parent)->icon_y;
91
92 ok = 1;
93 }
94
95 /*
96 * Check if it is inside the screen.
97 */
98 if (ok) {
99 if (*retX < sx1 - wPreferences.icon_size)
100 ok = 0;
101 else if (*retX > sx2)
102 ok = 0;
103
104 if (*retY < sy1 - wPreferences.icon_size)
105 ok = 0;
106 else if (*retY > sy2)
107 ok = 0;
108 }
109
110 return ok;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000111}
112
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200113void PlaceIcon(WScreen * scr, int *x_ret, int *y_ret, int head)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000114{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200115 int pf; /* primary axis */
116 int sf; /* secondary axis */
117 int fullW;
118 int fullH;
119 char *map;
120 int pi, si;
121 WCoreWindow *obj;
122 int sx1, sx2, sy1, sy2; /* screen boundary */
123 int sw, sh;
124 int xo, yo;
125 int xs, ys;
126 int x, y;
127 int isize = wPreferences.icon_size;
128 int done = 0;
129 WMBagIterator iter;
130 WArea area = wGetUsableAreaForHead(scr, head, NULL, False);
131
132 /* Find out screen boundaries. */
133
134 /* Allows each head to have miniwindows */
135
136 sx1 = area.x1;
137 sy1 = area.y1;
138 sx2 = area.x2;
139 sy2 = area.y2;
140 sw = sx2 - sx1;
141 sh = sy2 - sy1;
a10214a5 kojima2002-11-28 22:04:07 +0000142
27a396d7 dan2003-06-06 04:11:00 +0000143#if 0
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200144 if (scr->dock) {
145 if (scr->dock->on_right_side)
146 sx2 -= isize + DOCK_EXTRA_SPACE;
147 else
148 sx1 += isize + DOCK_EXTRA_SPACE;
149 }
27a396d7 dan2003-06-06 04:11:00 +0000150#endif
9d2e6ef9 scottc1998-09-29 22:36:29 +0000151
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200152 sw = isize * (sw / isize);
153 sh = isize * (sh / isize);
154 fullW = (sx2 - sx1) / isize;
155 fullH = (sy2 - sy1) / isize;
156
157 /* icon yard boundaries */
158 if (wPreferences.icon_yard & IY_VERT) {
159 pf = fullH;
160 sf = fullW;
161 } else {
162 pf = fullW;
163 sf = fullH;
164 }
165 if (wPreferences.icon_yard & IY_RIGHT) {
166 xo = sx2 - isize;
167 xs = -1;
168 } else {
169 xo = sx1;
170 xs = 1;
171 }
172 if (wPreferences.icon_yard & IY_TOP) {
173 yo = sy1;
174 ys = 1;
175 } else {
176 yo = sy2 - isize;
177 ys = -1;
178 }
179
180 /*
181 * Create a map with the occupied slots. 1 means the slot is used
182 * or at least partially used.
183 * The slot usage can be optimized by only marking fully used slots
184 * or slots that have most of it covered.
185 * Space usage is worse than the fvwm algorithm (used in the old version)
186 * but complexity is much better (faster) than it.
187 */
188 map = wmalloc((sw + 2) * (sh + 2));
189 memset(map, 0, (sw + 2) * (sh + 2));
9d2e6ef9 scottc1998-09-29 22:36:29 +0000190
191#define INDEX(x,y) (((y)+1)*(sw+2) + (x) + 1)
192
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200193 WM_ETARETI_BAG(scr->stacking_list, obj, iter) {
194
195 while (obj) {
196 int x, y;
197
198 if (iconPosition(obj, sx1, sy1, sx2, sy2, scr->current_workspace, &x, &y)) {
199 int xdi, ydi; /* rounded down */
200 int xui, yui; /* rounded up */
201
202 xdi = x / isize;
203 ydi = y / isize;
204 xui = (x + isize / 2) / isize;
205 yui = (y + isize / 2) / isize;
206 map[INDEX(xdi, ydi)] = 1;
207 map[INDEX(xdi, yui)] = 1;
208 map[INDEX(xui, ydi)] = 1;
209 map[INDEX(xui, yui)] = 1;
210 }
211 obj = obj->stacking->under;
212 }
213 }
214 /*
215 * Default position
216 */
217 *x_ret = 0;
218 *y_ret = 0;
219
220 /*
221 * Look for an empty slot
222 */
223 for (si = 0; si < sf; si++) {
224 for (pi = 0; pi < pf; pi++) {
225 if (wPreferences.icon_yard & IY_VERT) {
226 x = xo + xs * (si * isize);
227 y = yo + ys * (pi * isize);
228 } else {
229 x = xo + xs * (pi * isize);
230 y = yo + ys * (si * isize);
231 }
232 if (!map[INDEX(x / isize, y / isize)]) {
233 *x_ret = x;
234 *y_ret = y;
235 done = 1;
236 break;
237 }
238 }
239 if (done)
240 break;
241 }
242
243 wfree(map);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000244}
245
3c046182 kojima1999-09-16 02:58:56 +0000246/*
247 * This function calculates the length of the intersection of two
248 * line sections. (Hey, is that english?)
249 */
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200250static int calcIntersectionLength(int p1, int l1, int p2, int l2)
3c046182 kojima1999-09-16 02:58:56 +0000251{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200252 int isect;
253 int tmp;
254
255 if (p1 > p2) {
256 tmp = p1;
257 p1 = p2;
258 p2 = tmp;
259 tmp = l1;
260 l1 = l2;
261 l2 = tmp;
262 }
263
264 if (p1 + l1 < p2)
265 isect = 0;
266 else if (p2 + l2 < p1 + l1)
267 isect = l2;
268 else
269 isect = p1 + l1 - p2;
270
271 return isect;
3c046182 kojima1999-09-16 02:58:56 +0000272}
273
3c046182 kojima1999-09-16 02:58:56 +0000274/*
275 * This function calculates the area of the intersection of two rectangles.
276 */
a10214a5 kojima2002-11-28 22:04:07 +0000277
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200278int calcIntersectionArea(int x1, int y1, int w1, int h1, int x2, int y2, int w2, int h2)
3c046182 kojima1999-09-16 02:58:56 +0000279{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200280 return calcIntersectionLength(x1, w1, x2, w2)
281 * calcIntersectionLength(y1, h1, y2, h2);
3c046182 kojima1999-09-16 02:58:56 +0000282}
283
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200284static int calcSumOfCoveredAreas(WWindow * wwin, int x, int y, int w, int h)
3c046182 kojima1999-09-16 02:58:56 +0000285{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200286 int sum_isect = 0;
287 WWindow *test_window;
288 int tw, tx, ty, th;
289
290 test_window = wwin->screen_ptr->focused_window;
291 for (; test_window != NULL && test_window->prev != NULL;)
292 test_window = test_window->prev;
293
294 for (; test_window != NULL; test_window = test_window->next) {
295 if (test_window->frame->core->stacking->window_level < WMNormalLevel) {
296 continue;
297 }
3c046182 kojima1999-09-16 02:58:56 +0000298#if 0
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200299 tw = test_window->client.width;
300 if (test_window->flags.shaded)
301 th = test_window->frame->top_width;
302 else
303 th = test_window->client.height + extra_height;
3c046182 kojima1999-09-16 02:58:56 +0000304#else
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200305 tw = test_window->frame->core->width;
306 th = test_window->frame->core->height;
3c046182 kojima1999-09-16 02:58:56 +0000307#endif
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200308 tx = test_window->frame_x;
309 ty = test_window->frame_y;
310
311 if (test_window->flags.mapped ||
312 (test_window->flags.shaded &&
313 !(test_window->flags.miniaturized || test_window->flags.hidden))) {
314 sum_isect += calcIntersectionArea(tx, ty, tw, th, x, y, w, h);
315 }
316 }
3c046182 kojima1999-09-16 02:58:56 +0000317
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200318 return sum_isect;
319}
3c046182 kojima1999-09-16 02:58:56 +0000320
321static void
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200322smartPlaceWindow(WWindow * wwin, int *x_ret, int *y_ret, unsigned int width, unsigned int height, WArea usableArea)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000323{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200324 int test_x = 0, test_y = Y_ORIGIN;
325 int from_x, to_x, from_y, to_y;
326 int sx;
327 int min_isect, min_isect_x, min_isect_y;
328 int sum_isect;
329
330 if (wwin->frame) {
331 height += wwin->frame->top_width + wwin->frame->bottom_width;
332 } else {
333 if (HAS_TITLEBAR(wwin))
334 height += 18;
335 if (HAS_RESIZEBAR(wwin))
336 height += 8;
337 }
338 if (HAS_BORDER(wwin)) {
339 height += 2;
340 width += 2;
341 }
342 sx = X_ORIGIN;
343
344 min_isect = INT_MAX;
345 min_isect_x = sx;
346 min_isect_y = test_y;
347
348 while (((test_y + height) < usableArea.y2)) {
349 test_x = sx;
350 while ((test_x + width) < usableArea.x2) {
351 sum_isect = calcSumOfCoveredAreas(wwin, test_x, test_y, width, height);
352
353 if (sum_isect < min_isect) {
354 min_isect = sum_isect;
355 min_isect_x = test_x;
356 min_isect_y = test_y;
357 }
358
359 test_x += PLACETEST_HSTEP;
360 }
361 test_y += PLACETEST_VSTEP;
362 }
363
364 from_x = min_isect_x - PLACETEST_HSTEP + 1;
365 from_x = WMAX(from_x, X_ORIGIN);
366 to_x = min_isect_x + PLACETEST_HSTEP;
367 if (to_x + width > usableArea.x2)
368 to_x = usableArea.x2 - width;
369
370 from_y = min_isect_y - PLACETEST_VSTEP + 1;
371 from_y = WMAX(from_y, Y_ORIGIN);
372 to_y = min_isect_y + PLACETEST_VSTEP;
373 if (to_y + height > usableArea.y2)
374 to_y = usableArea.y2 - height;
375
376 for (test_x = from_x; test_x < to_x; test_x++) {
377 for (test_y = from_y; test_y < to_y; test_y++) {
378 sum_isect = calcSumOfCoveredAreas(wwin, test_x, test_y, width, height);
379
380 if (sum_isect < min_isect) {
381 min_isect = sum_isect;
382 min_isect_x = test_x;
383 min_isect_y = test_y;
384 }
385 }
386 }
387
388 *x_ret = min_isect_x;
389 *y_ret = min_isect_y;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000390}
391
ac64e68f dan1999-09-17 16:18:37 +0000392static Bool
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200393autoPlaceWindow(WWindow * wwin, int *x_ret, int *y_ret,
394 unsigned int width, unsigned int height, int tryCount, WArea usableArea)
ac64e68f dan1999-09-17 16:18:37 +0000395{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200396 WScreen *scr = wwin->screen_ptr;
397 int test_x = 0, test_y = Y_ORIGIN;
398 int loc_ok = False, tw, tx, ty, th;
399 int swidth, sx;
400 WWindow *test_window;
401
402 if (wwin->frame) {
403 height += wwin->frame->top_width + wwin->frame->bottom_width;
404 } else {
405 if (HAS_TITLEBAR(wwin))
406 height += 18;
407 if (HAS_RESIZEBAR(wwin))
408 height += 8;
409 }
410 if (HAS_BORDER(wwin)) {
411 height += 2;
412 width += 2;
413 }
414
415 swidth = usableArea.x2 - usableArea.x1;
416 sx = X_ORIGIN;
417
418 /* this was based on fvwm2's smart placement */
419
420 while (((test_y + height) < (usableArea.y2 - usableArea.y1)) && !loc_ok) {
421 test_x = sx;
422
423 while (((test_x + width) < swidth) && (!loc_ok)) {
424
425 loc_ok = True;
426 test_window = scr->focused_window;
427
428 while ((test_window != NULL) && (loc_ok == True)) {
429
430 if (test_window->frame->core->stacking->window_level
431 < WMNormalLevel && tryCount > 0) {
432 test_window = test_window->next;
433 continue;
434 }
ac64e68f dan1999-09-17 16:18:37 +0000435#if 0
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200436 tw = test_window->client.width;
437 if (test_window->flags.shaded)
438 th = test_window->frame->top_width;
439 else
440 th = test_window->client.height + extra_height;
ac64e68f dan1999-09-17 16:18:37 +0000441#else
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200442 tw = test_window->frame->core->width;
443 th = test_window->frame->core->height;
ac64e68f dan1999-09-17 16:18:37 +0000444#endif
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200445 tx = test_window->frame_x;
446 ty = test_window->frame_y;
447
448 if ((tx < (test_x + width)) && ((tx + tw) > test_x) &&
449 (ty < (test_y + height)) && ((ty + th) > test_y) &&
450 (test_window->flags.mapped ||
451 (test_window->flags.shaded &&
452 test_window->frame->workspace == scr->current_workspace &&
453 !(test_window->flags.miniaturized || test_window->flags.hidden)))) {
454
455 loc_ok = False;
456 }
457 test_window = test_window->next;
458 }
459
460 test_window = scr->focused_window;
461
462 while ((test_window != NULL) && (loc_ok == True)) {
463
464 if (test_window->frame->core->stacking->window_level
465 < WMNormalLevel && tryCount > 0) {
466 test_window = test_window->prev;
467 continue;
468 }
ac64e68f dan1999-09-17 16:18:37 +0000469#if 0
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200470 tw = test_window->client.width;
471 if (test_window->flags.shaded)
472 th = test_window->frame->top_width;
473 else
474 th = test_window->client.height + extra_height;
ac64e68f dan1999-09-17 16:18:37 +0000475#else
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200476 tw = test_window->frame->core->width;
477 th = test_window->frame->core->height;
ac64e68f dan1999-09-17 16:18:37 +0000478#endif
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200479 tx = test_window->frame_x;
480 ty = test_window->frame_y;
481
482 if ((tx < (test_x + width)) && ((tx + tw) > test_x) &&
483 (ty < (test_y + height)) && ((ty + th) > test_y) &&
484 (test_window->flags.mapped ||
485 (test_window->flags.shaded &&
486 test_window->frame->workspace == scr->current_workspace &&
487 !(test_window->flags.miniaturized || test_window->flags.hidden)))) {
488
489 loc_ok = False;
490 }
491 test_window = test_window->prev;
492 }
493 if (loc_ok == True) {
494 *x_ret = test_x;
495 *y_ret = test_y;
496 break;
497 }
498 test_x += PLACETEST_HSTEP;
499 }
500 test_y += PLACETEST_VSTEP;
501 }
502
503 return loc_ok;
ac64e68f dan1999-09-17 16:18:37 +0000504}
505
6830b057 dan2004-10-12 21:28:27 +0000506static void
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200507cascadeWindow(WScreen * scr, WWindow * wwin, int *x_ret, int *y_ret,
508 unsigned int width, unsigned int height, int h, WArea usableArea)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000509{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200510 if (wwin->frame) {
511 height += wwin->frame->top_width + wwin->frame->bottom_width;
512 } else {
513 if (HAS_TITLEBAR(wwin))
514 height += 18;
515 if (HAS_RESIZEBAR(wwin))
516 height += 8;
517 }
518 if (HAS_BORDER(wwin)) {
519 height += 2;
520 width += 2;
521 }
522
523 *x_ret = h * scr->cascade_index + X_ORIGIN;
524 *y_ret = h * scr->cascade_index + Y_ORIGIN;
525
526 if (width + *x_ret > usableArea.x2 || height + *y_ret > usableArea.y2) {
527 scr->cascade_index = 0;
528 *x_ret = X_ORIGIN;
529 *y_ret = Y_ORIGIN;
530 }
9d2e6ef9 scottc1998-09-29 22:36:29 +0000531}
532
a10214a5 kojima2002-11-28 22:04:07 +0000533static void
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200534randomPlaceWindow(WScreen * scr, WWindow * wwin, int *x_ret, int *y_ret,
535 unsigned int width, unsigned int height, WArea usableArea)
a10214a5 kojima2002-11-28 22:04:07 +0000536{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200537 int w, h;
538
539 if (wwin->frame) {
540 height += wwin->frame->top_width + wwin->frame->bottom_width;
541 } else {
542 if (HAS_TITLEBAR(wwin))
543 height += 18;
544 if (HAS_RESIZEBAR(wwin))
545 height += 8;
546 }
547 if (HAS_BORDER(wwin)) {
548 height += 2;
549 width += 2;
550 }
551
552 w = ((usableArea.x2 - X_ORIGIN) - width);
553 h = ((usableArea.y2 - Y_ORIGIN) - height);
554 if (w < 1)
555 w = 1;
556 if (h < 1)
557 h = 1;
558 *x_ret = X_ORIGIN + rand() % w;
559 *y_ret = Y_ORIGIN + rand() % h;
a10214a5 kojima2002-11-28 22:04:07 +0000560}
561
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200562void PlaceWindow(WWindow * wwin, int *x_ret, int *y_ret, unsigned width, unsigned height)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000563{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200564 WScreen *scr = wwin->screen_ptr;
565 int h = WMFontHeight(scr->title_font) + (wPreferences.window_title_clearance + TITLEBAR_EXTEND_SPACE) * 2;
566 WArea usableArea = wGetUsableAreaForHead(scr,
567 wGetHeadForPointerLocation(scr),
568 NULL, True);
569
570 switch (wPreferences.window_placement) {
571 case WPM_MANUAL:
572 InteractivePlaceWindow(wwin, x_ret, y_ret, width, height);
573 break;
574
575 case WPM_SMART:
576 smartPlaceWindow(wwin, x_ret, y_ret, width, height, usableArea);
577 break;
578
579 case WPM_AUTO:
580 if (autoPlaceWindow(wwin, x_ret, y_ret, width, height, 0, usableArea)) {
581 break;
582 } else if (autoPlaceWindow(wwin, x_ret, y_ret, width, height, 1, usableArea)) {
583 break;
584 }
585 /* there isn't a break here, because if we fail, it should fall
586 through to cascade placement, as people who want tiling want
587 automagicness aren't going to want to place their window */
588
589 case WPM_CASCADE:
590 if (wPreferences.window_placement == WPM_AUTO)
591 scr->cascade_index++;
592
593 cascadeWindow(scr, wwin, x_ret, y_ret, width, height, h, usableArea);
594
595 if (wPreferences.window_placement == WPM_CASCADE)
596 scr->cascade_index++;
597 break;
598
599 case WPM_RANDOM:
600 randomPlaceWindow(scr, wwin, x_ret, y_ret, width, height, usableArea);
601 break;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000602
a10214a5 kojima2002-11-28 22:04:07 +0000603#ifdef DEBUG
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200604 default:
605 puts("Invalid window placement!!!");
606 *x_ret = 0;
607 *y_ret = 0;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000608#endif
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200609 }
610
611 /*
612 * clip to usableArea instead of full screen
613 * this will also take dock/clip etc.. into account
614 * aswell as being xinerama friendly
615 */
616 if (*x_ret + width > usableArea.x2)
617 *x_ret = usableArea.x2 - width;
618 if (*x_ret < usableArea.x1)
619 *x_ret = usableArea.x1;
620
621 if (*y_ret + height > usableArea.y2)
622 *y_ret = usableArea.y2 - height;
623 if (*y_ret < usableArea.y1)
624 *y_ret = usableArea.y1;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000625}