Make wmaker XRandR aware
[wmaker-crm.git] / src / screen.c
Commit [+]AuthorDateLineData
9d2e6ef9 scottc1998-09-29 22:36:29 +00001/* screen.c - screen management
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 <stdio.h>
26#include <stdlib.h>
27#include <string.h>
28
29#include <X11/Xlib.h>
30#include <X11/Xutil.h>
416e3a82 dan1999-01-25 19:06:50 +000031#include <X11/Xatom.h>
9d2e6ef9 scottc1998-09-29 22:36:29 +000032#ifdef SHAPE
33#include <X11/extensions/shape.h>
34#endif
6830b057 dan2004-10-12 21:28:27 +000035#ifdef KEEP_XKB_LOCK_STATUS
36#include <X11/XKBlib.h>
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020037#endif /* KEEP_XKB_LOCK_STATUS */
c201e161
CM
Carlos R. Mafra2010-08-22 19:05:07 +020038#ifdef HAVE_XRANDR
39#include <X11/extensions/Xrandr.h>
40#endif
9d2e6ef9 scottc1998-09-29 22:36:29 +000041
42#include <wraster.h>
9d2e6ef9 scottc1998-09-29 22:36:29 +000043#include "WindowMaker.h"
44#include "def_pixmaps.h"
45#include "screen.h"
46#include "texture.h"
47#include "pixmap.h"
48#include "menu.h"
49#include "funcs.h"
50#include "actions.h"
51#include "properties.h"
52#include "dock.h"
53#include "resources.h"
54#include "workspace.h"
55#include "session.h"
56#include "balloon.h"
f2de1c9d kojima2000-01-14 16:30:56 +000057#include "geomview.h"
15e37ff9 Carlos R. Mafra2009-10-12 00:08:21 +020058#include "wmspec.h"
9d2e6ef9 scottc1998-09-29 22:36:29 +000059
5873385d kojima2002-02-15 21:30:42 +000060#include "xinerama.h"
61
33cc542e dan2001-10-04 03:07:34 +000062#include <WINGs/WUtil.h>
9d2e6ef9 scottc1998-09-29 22:36:29 +000063
64#include "defaults.h"
65
9d2e6ef9 scottc1998-09-29 22:36:29 +000066#define EVENT_MASK (LeaveWindowMask|EnterWindowMask|PropertyChangeMask\
6830b057 dan2004-10-12 21:28:27 +000067 |SubstructureNotifyMask|PointerMotionMask \
68 |SubstructureRedirectMask|ButtonPressMask|ButtonReleaseMask\
69 |KeyPressMask|KeyReleaseMask)
9d2e6ef9 scottc1998-09-29 22:36:29 +000070
71/**** Global variables ****/
9d2e6ef9 scottc1998-09-29 22:36:29 +000072extern Cursor wCursor[WCUR_LAST];
73extern WPreferences wPreferences;
74extern Atom _XA_WINDOWMAKER_STATE;
416e3a82 dan1999-01-25 19:06:50 +000075extern Atom _XA_WINDOWMAKER_NOTICEBOARD;
9d2e6ef9 scottc1998-09-29 22:36:29 +000076
77extern int wScreenCount;
78
6830b057 dan2004-10-12 21:28:27 +000079#ifdef KEEP_XKB_LOCK_STATUS
2bce7940 id1999-05-23 19:33:19 +000080extern int wXkbSupported;
81#endif
c201e161
CM
Carlos R. Mafra2010-08-22 19:05:07 +020082#ifdef HAVE_XRANDR
83extern int has_randr;
84#endif
2bce7940 id1999-05-23 19:33:19 +000085
9d2e6ef9 scottc1998-09-29 22:36:29 +000086extern WDDomain *WDWindowMaker;
87
9d2e6ef9 scottc1998-09-29 22:36:29 +000088/**** Local ****/
9d2e6ef9 scottc1998-09-29 22:36:29 +000089#define STIPPLE_WIDTH 2
90#define STIPPLE_HEIGHT 2
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +020091static char STIPPLE_DATA[] = { 0x02, 0x01 };
9d2e6ef9 scottc1998-09-29 22:36:29 +000092
93static int CantManageScreen = 0;
94
33cc542e dan2001-10-04 03:07:34 +000095static WMPropList *dApplications = NULL;
96static WMPropList *dWorkspace;
97static WMPropList *dDock;
98static WMPropList *dClip;
9d2e6ef9 scottc1998-09-29 22:36:29 +000099
4041278f Carlos R. Mafra2010-04-12 23:31:59 +0200100static void make_keys(void)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000101{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200102 if (dApplications != NULL)
103 return;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000104
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200105 dApplications = WMCreatePLString("Applications");
106 dWorkspace = WMCreatePLString("Workspace");
107 dDock = WMCreatePLString("Dock");
108 dClip = WMCreatePLString("Clip");
9d2e6ef9 scottc1998-09-29 22:36:29 +0000109}
110
9d2e6ef9 scottc1998-09-29 22:36:29 +0000111/*
112 *----------------------------------------------------------------------
113 * alreadyRunningError--
114 * X error handler used to catch errors when trying to do
115 * XSelectInput() on the root window. These errors probably mean that
116 * there already is some other window manager running.
6830b057 dan2004-10-12 21:28:27 +0000117 *
9d2e6ef9 scottc1998-09-29 22:36:29 +0000118 * Returns:
119 * Nothing, unless something really evil happens...
6830b057 dan2004-10-12 21:28:27 +0000120 *
9d2e6ef9 scottc1998-09-29 22:36:29 +0000121 * Side effects:
122 * CantManageScreen is set to 1;
6830b057 dan2004-10-12 21:28:27 +0000123 *----------------------------------------------------------------------
9d2e6ef9 scottc1998-09-29 22:36:29 +0000124 */
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200125static int alreadyRunningError(Display * dpy, XErrorEvent * error)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000126{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200127 CantManageScreen = 1;
128 return -1;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000129}
130
9d2e6ef9 scottc1998-09-29 22:36:29 +0000131/*
6830b057 dan2004-10-12 21:28:27 +0000132 *----------------------------------------------------------------------
9d2e6ef9 scottc1998-09-29 22:36:29 +0000133 * allocButtonPixmaps--
134 * Allocate pixmaps used on window operation buttons (those in the
135 * titlebar). The pixmaps are linked to the program. If XPM is supported
136 * XPM pixmaps are used otherwise, equivalent bitmaps are used.
6830b057 dan2004-10-12 21:28:27 +0000137 *
9d2e6ef9 scottc1998-09-29 22:36:29 +0000138 * Returns:
139 * Nothing
6830b057 dan2004-10-12 21:28:27 +0000140 *
9d2e6ef9 scottc1998-09-29 22:36:29 +0000141 * Side effects:
6830b057 dan2004-10-12 21:28:27 +0000142 * Allocates shared pixmaps for the screen. These pixmaps should
9d2e6ef9 scottc1998-09-29 22:36:29 +0000143 * not be freed by anybody.
6830b057 dan2004-10-12 21:28:27 +0000144 *----------------------------------------------------------------------
9d2e6ef9 scottc1998-09-29 22:36:29 +0000145 */
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200146static void allocButtonPixmaps(WScreen * scr)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000147{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200148 WPixmap *pix;
149
150 /* create predefined pixmaps */
151 pix = wPixmapCreateFromXPMData(scr, PRED_CLOSE_XPM);
152 if (pix)
153 pix->shared = 1;
154 scr->b_pixmaps[WBUT_CLOSE] = pix;
155
156 pix = wPixmapCreateFromXPMData(scr, PRED_BROKEN_CLOSE_XPM);
157 if (pix)
158 pix->shared = 1;
159 scr->b_pixmaps[WBUT_BROKENCLOSE] = pix;
160
161 pix = wPixmapCreateFromXPMData(scr, PRED_ICONIFY_XPM);
162 if (pix)
163 pix->shared = 1;
164 scr->b_pixmaps[WBUT_ICONIFY] = pix;
c28f3b2c id1999-05-20 23:30:53 +0000165#ifdef XKB_BUTTON_HINT
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200166 pix = wPixmapCreateFromXPMData(scr, PRED_XKBGROUP1_XPM);
167 if (pix)
168 pix->shared = 1;
169 scr->b_pixmaps[WBUT_XKBGROUP1] = pix;
170 pix = wPixmapCreateFromXPMData(scr, PRED_XKBGROUP2_XPM);
171 if (pix)
172 pix->shared = 1;
173 scr->b_pixmaps[WBUT_XKBGROUP2] = pix;
174 pix = wPixmapCreateFromXPMData(scr, PRED_XKBGROUP3_XPM);
175 if (pix)
176 pix->shared = 1;
177 scr->b_pixmaps[WBUT_XKBGROUP3] = pix;
178 pix = wPixmapCreateFromXPMData(scr, PRED_XKBGROUP4_XPM);
179 if (pix)
180 pix->shared = 1;
181 scr->b_pixmaps[WBUT_XKBGROUP4] = pix;
c28f3b2c id1999-05-20 23:30:53 +0000182#endif
183
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200184 pix = wPixmapCreateFromXPMData(scr, PRED_KILL_XPM);
185 if (pix)
186 pix->shared = 1;
187 scr->b_pixmaps[WBUT_KILL] = pix;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000188}
9d2e6ef9 scottc1998-09-29 22:36:29 +0000189
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200190static void draw_dot(WScreen * scr, Drawable d, int x, int y, GC gc)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000191{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200192 XSetForeground(dpy, gc, scr->black_pixel);
193 XDrawLine(dpy, d, gc, x, y, x + 1, y);
194 XDrawPoint(dpy, d, gc, x, y + 1);
195 XSetForeground(dpy, gc, scr->white_pixel);
196 XDrawLine(dpy, d, gc, x + 2, y, x + 2, y + 1);
197 XDrawPoint(dpy, d, gc, x + 1, y + 1);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000198}
199
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200200static WPixmap *make3Dots(WScreen * scr)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000201{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200202 WPixmap *wpix;
203 GC gc2, gc;
204 XGCValues gcv;
205 Pixmap pix, mask;
206
207 gc = scr->copy_gc;
208 pix = XCreatePixmap(dpy, scr->w_win, wPreferences.icon_size, wPreferences.icon_size, scr->w_depth);
209 XSetForeground(dpy, gc, scr->black_pixel);
210 XFillRectangle(dpy, pix, gc, 0, 0, wPreferences.icon_size, wPreferences.icon_size);
211 XSetForeground(dpy, gc, scr->white_pixel);
212 draw_dot(scr, pix, 4, wPreferences.icon_size - 6, gc);
213 draw_dot(scr, pix, 9, wPreferences.icon_size - 6, gc);
214 draw_dot(scr, pix, 14, wPreferences.icon_size - 6, gc);
215
216 mask = XCreatePixmap(dpy, scr->w_win, wPreferences.icon_size, wPreferences.icon_size, 1);
217 gcv.foreground = 0;
218 gcv.graphics_exposures = False;
219 gc2 = XCreateGC(dpy, mask, GCForeground | GCGraphicsExposures, &gcv);
220 XFillRectangle(dpy, mask, gc2, 0, 0, wPreferences.icon_size, wPreferences.icon_size);
221 XSetForeground(dpy, gc2, 1);
222 XFillRectangle(dpy, mask, gc2, 4, wPreferences.icon_size - 6, 3, 2);
223 XFillRectangle(dpy, mask, gc2, 9, wPreferences.icon_size - 6, 3, 2);
224 XFillRectangle(dpy, mask, gc2, 14, wPreferences.icon_size - 6, 3, 2);
225
226 XFreeGC(dpy, gc2);
227
228 wpix = wPixmapCreate(scr, pix, mask);
229 wpix->shared = 1;
230
231 return wpix;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000232}
233
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200234static void allocGCs(WScreen * scr)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000235{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200236 XGCValues gcv;
237 XColor color;
238 int gcm;
239
240 scr->stipple_bitmap = XCreateBitmapFromData(dpy, scr->w_win, STIPPLE_DATA, STIPPLE_WIDTH, STIPPLE_HEIGHT);
241
242 gcv.stipple = scr->stipple_bitmap;
243 gcv.foreground = scr->white_pixel;
244 gcv.fill_style = FillStippled;
245 gcv.graphics_exposures = False;
246 gcm = GCForeground | GCStipple | GCFillStyle | GCGraphicsExposures;
247 scr->stipple_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
248
249 /* selected icon border GCs */
250 gcv.function = GXcopy;
251 gcv.foreground = scr->white_pixel;
252 gcv.background = scr->black_pixel;
253 gcv.line_width = 1;
254 gcv.line_style = LineDoubleDash;
255 gcv.fill_style = FillSolid;
256 gcv.dash_offset = 0;
257 gcv.dashes = 4;
258 gcv.graphics_exposures = False;
259
260 gcm = GCFunction | GCGraphicsExposures;
261 gcm |= GCForeground | GCBackground;
262 gcm |= GCLineWidth | GCLineStyle;
263 gcm |= GCFillStyle;
264 gcm |= GCDashOffset | GCDashList;
265
266 scr->icon_select_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
267
268 scr->menu_title_color[0] = WMRetainColor(scr->white);
269
270 /* don't retain scr->black here because we may alter its alpha */
271 scr->mtext_color = WMCreateRGBColor(scr->wmscreen, 0, 0, 0, True);
272 scr->dtext_color = WMCreateRGBColor(scr->wmscreen, 0, 0, 0, True);
273
274 /* frame GC */
275 wGetColor(scr, DEF_FRAME_COLOR, &color);
276 gcv.function = GXxor;
277 /* this will raise the probability of the XORed color being different
278 * of the original color in PseudoColor when not all color cells are
279 * initialized */
280 if (DefaultVisual(dpy, scr->screen)->class == PseudoColor)
281 gcv.plane_mask = (1 << (scr->depth - 1)) | 1;
282 else
283 gcv.plane_mask = AllPlanes;
284 gcv.foreground = color.pixel;
285 if (gcv.foreground == 0)
286 gcv.foreground = 1;
287 gcv.line_width = DEF_FRAME_THICKNESS;
288 gcv.subwindow_mode = IncludeInferiors;
289 gcv.graphics_exposures = False;
290 scr->frame_gc = XCreateGC(dpy, scr->root_win, GCForeground | GCGraphicsExposures
291 | GCFunction | GCSubwindowMode | GCLineWidth | GCPlaneMask, &gcv);
292
293 /* line GC */
294 gcv.foreground = color.pixel;
295
296 if (gcv.foreground == 0)
297 /* XOR:ing with a zero is not going to be of much use, so
298 in that case, we somewhat arbitrarily xor with 17 instead. */
299 gcv.foreground = 17;
300
301 gcv.function = GXxor;
302 gcv.subwindow_mode = IncludeInferiors;
303 gcv.line_width = 1;
304 gcv.cap_style = CapRound;
305 gcv.graphics_exposures = False;
306 gcm = GCForeground | GCFunction | GCSubwindowMode | GCLineWidth | GCCapStyle | GCGraphicsExposures;
307 scr->line_gc = XCreateGC(dpy, scr->root_win, gcm, &gcv);
308
309 scr->line_pixel = gcv.foreground;
310
311 /* copy GC */
312 gcv.foreground = scr->white_pixel;
313 gcv.background = scr->black_pixel;
314 gcv.graphics_exposures = False;
315 scr->copy_gc = XCreateGC(dpy, scr->w_win, GCForeground | GCBackground | GCGraphicsExposures, &gcv);
316
317 /* misc drawing GC */
318 gcv.graphics_exposures = False;
319 gcm = GCGraphicsExposures;
320 scr->draw_gc = XCreateGC(dpy, scr->w_win, gcm, &gcv);
321
322 assert(scr->stipple_bitmap != None);
323
324 /* mono GC */
325 scr->mono_gc = XCreateGC(dpy, scr->stipple_bitmap, gcm, &gcv);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000326}
327
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200328static void createPixmaps(WScreen * scr)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000329{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200330 WPixmap *pix;
331 RImage *image;
332
333 /* load pixmaps */
334 pix = wPixmapCreateFromXBMData(scr, (char *)MENU_RADIO_INDICATOR_XBM_DATA,
335 (char *)MENU_RADIO_INDICATOR_XBM_DATA,
336 MENU_RADIO_INDICATOR_XBM_SIZE,
337 MENU_RADIO_INDICATOR_XBM_SIZE, scr->black_pixel, scr->white_pixel);
338 if (pix != NULL)
339 pix->shared = 1;
340 scr->menu_radio_indicator = pix;
341
342 pix = wPixmapCreateFromXBMData(scr, (char *)MENU_CHECK_INDICATOR_XBM_DATA,
343 (char *)MENU_CHECK_INDICATOR_XBM_DATA,
344 MENU_CHECK_INDICATOR_XBM_SIZE,
345 MENU_CHECK_INDICATOR_XBM_SIZE, scr->black_pixel, scr->white_pixel);
346 if (pix != NULL)
347 pix->shared = 1;
348 scr->menu_check_indicator = pix;
349
350 pix = wPixmapCreateFromXBMData(scr, (char *)MENU_MINI_INDICATOR_XBM_DATA,
351 (char *)MENU_MINI_INDICATOR_XBM_DATA,
352 MENU_MINI_INDICATOR_XBM_SIZE,
353 MENU_MINI_INDICATOR_XBM_SIZE, scr->black_pixel, scr->white_pixel);
354 if (pix != NULL)
355 pix->shared = 1;
356 scr->menu_mini_indicator = pix;
357
358 pix = wPixmapCreateFromXBMData(scr, (char *)MENU_HIDE_INDICATOR_XBM_DATA,
359 (char *)MENU_HIDE_INDICATOR_XBM_DATA,
360 MENU_HIDE_INDICATOR_XBM_SIZE,
361 MENU_HIDE_INDICATOR_XBM_SIZE, scr->black_pixel, scr->white_pixel);
362 if (pix != NULL)
363 pix->shared = 1;
364 scr->menu_hide_indicator = pix;
365
366 pix = wPixmapCreateFromXBMData(scr, (char *)MENU_SHADE_INDICATOR_XBM_DATA,
367 (char *)MENU_SHADE_INDICATOR_XBM_DATA,
368 MENU_SHADE_INDICATOR_XBM_SIZE,
369 MENU_SHADE_INDICATOR_XBM_SIZE, scr->black_pixel, scr->white_pixel);
370 if (pix != NULL)
371 pix->shared = 1;
372 scr->menu_shade_indicator = pix;
373
374 image = wDefaultGetImage(scr, "Logo", "WMPanel");
375
376 if (!image) {
377 wwarning(_("could not load logo image for panels: %s"), RMessageForError(RErrorCode));
378 } else {
379 WMSetApplicationIconImage(scr->wmscreen, image);
380 RReleaseImage(image);
381 }
382
383 scr->dock_dots = make3Dots(scr);
384
385 /* titlebar button pixmaps */
386 allocButtonPixmaps(scr);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000387}
388
9d2e6ef9 scottc1998-09-29 22:36:29 +0000389/*
390 *----------------------------------------------------------------------
391 * createInternalWindows--
392 * Creates some windows used internally by the program. One to
393 * receive input focus when no other window can get it and another
394 * to display window geometry information during window resize/move.
6830b057 dan2004-10-12 21:28:27 +0000395 *
9d2e6ef9 scottc1998-09-29 22:36:29 +0000396 * Returns:
397 * Nothing
6830b057 dan2004-10-12 21:28:27 +0000398 *
9d2e6ef9 scottc1998-09-29 22:36:29 +0000399 * Side effects:
400 * Windows are created and some colors are allocated for the
401 * window background.
6830b057 dan2004-10-12 21:28:27 +0000402 *----------------------------------------------------------------------
9d2e6ef9 scottc1998-09-29 22:36:29 +0000403 */
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200404static void createInternalWindows(WScreen * scr)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000405{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200406 int vmask;
407 XSetWindowAttributes attribs;
408
409 /* InputOnly window to get the focus when no other window can get it */
410 vmask = CWEventMask | CWOverrideRedirect;
411 attribs.event_mask = KeyPressMask | FocusChangeMask;
412 attribs.override_redirect = True;
413 scr->no_focus_win = XCreateWindow(dpy, scr->root_win, -10, -10, 4, 4, 0, 0,
414 InputOnly, CopyFromParent, vmask, &attribs);
415 XSelectInput(dpy, scr->no_focus_win, KeyPressMask | KeyReleaseMask);
416 XMapWindow(dpy, scr->no_focus_win);
417
418 XSetInputFocus(dpy, scr->no_focus_win, RevertToParent, CurrentTime);
419
420 /* shadow window for dock buttons */
421 vmask = CWBorderPixel | CWBackPixmap | CWBackPixel | CWCursor | CWSaveUnder | CWOverrideRedirect;
422 attribs.border_pixel = scr->black_pixel;
423 attribs.save_under = True;
424 attribs.override_redirect = True;
425 attribs.background_pixmap = None;
426 attribs.background_pixel = scr->white_pixel;
427 attribs.cursor = wCursor[WCUR_DEFAULT];
428 vmask |= CWColormap;
429 attribs.colormap = scr->w_colormap;
430 scr->dock_shadow =
431 XCreateWindow(dpy, scr->root_win, 0, 0, wPreferences.icon_size,
432 wPreferences.icon_size, 0, scr->w_depth, CopyFromParent, scr->w_visual, vmask, &attribs);
433
434 /* workspace name balloon for clip */
435 vmask = CWBackPixel | CWSaveUnder | CWOverrideRedirect | CWColormap | CWBorderPixel;
436 attribs.save_under = True;
437 attribs.override_redirect = True;
438 attribs.colormap = scr->w_colormap;
439 attribs.background_pixel = scr->icon_back_texture->normal.pixel;
440 attribs.border_pixel = 0; /* do not care */
441 scr->clip_balloon =
442 XCreateWindow(dpy, scr->root_win, 0, 0, 10, 10, 0, scr->w_depth,
443 CopyFromParent, scr->w_visual, vmask, &attribs);
444
445 /* workspace name */
446 vmask = CWBackPixel | CWSaveUnder | CWOverrideRedirect | CWColormap | CWBorderPixel;
447 attribs.save_under = True;
448 attribs.override_redirect = True;
449 attribs.colormap = scr->w_colormap;
450 attribs.background_pixel = scr->icon_back_texture->normal.pixel;
451 attribs.border_pixel = 0; /* do not care */
452 scr->workspace_name =
453 XCreateWindow(dpy, scr->root_win, 0, 0, 10, 10, 0, scr->w_depth,
454 CopyFromParent, scr->w_visual, vmask, &attribs);
455
456 /*
457 * If the window is clicked without having ButtonPress selected, the
458 * resulting event will have event.xbutton.window == root.
459 */
460 XSelectInput(dpy, scr->clip_balloon, ButtonPressMask);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000461}
462
416e3a82 dan1999-01-25 19:06:50 +0000463#if 0
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200464static Bool aquireManagerSelection(WScreen * scr)
416e3a82 dan1999-01-25 19:06:50 +0000465{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200466 char buffer[32];
467 XEvent ev;
468 Time timestamp;
469
470 snprintf(buffer, sizeof(buffer), "WM_S%i", scr->screen);
471 scr->managerAtom = XInternAtom(dpy, buffer, False);
472
473 /* for race-conditions... */
474 XGrabServer(dpy);
475
476 /* if there is another manager running, don't try to replace it
477 * (for now, at least) */
478 if (XGetSelectionOwner(dpy, scr->managerAtom) != None) {
479 XUngrabServer(dpy);
480 return False;
481 }
482
483 /* become the manager for this screen */
484
485 scr->managerWindow = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 1, 1, 0, 0, 0);
486
487 XSelectInput(dpy, scr->managerWindow, PropertyChangeMask);
488 /* get a timestamp */
489 XChangeProperty(dpy, scr->managerWindow, scr->managerAtom, XA_INTEGER, 32, PropModeAppend, NULL, 0);
490 while (1) {
491 XWindowEvent(dpy, scr->managerWindow, &ev);
492 if (ev.type == PropertyNotify) {
493 timestamp = ev.xproperty.time;
494 break;
495 }
496 }
497 XSelectInput(dpy, scr->managerWindow, NoEvents);
498 XDeleteProperty(dpy, scr->managerWindow, scr->managerAtom);
499
500 XSetSelectionOwner(dpy, scr->managerAtom, scr->managerWindow, CurrentTime);
501
502 XUngrabServer(dpy);
503
504 /* announce our arrival */
505
506 ev.xclient.type = ClientMessage;
507 ev.xclient.message_type = XInternAtom(dpy, "MANAGER", False);
508 ev.xclient.destination = scr->root_win;
509 ev.xclient.format = 32;
510 ev.xclient.data.l[0] = timestamp;
511 ev.xclient.data.l[1] = scr->managerAtom;
512 ev.xclient.data.l[2] = scr->managerWindow;
513 ev.xclient.data.l[3] = 0;
514 ev.xclient.data.l[4] = 0;
515
516 XSendEvent(dpy, scr->root_win, False, StructureNotify, &ev);
517 XSync(dpy, False);
518
519 return True;
416e3a82 dan1999-01-25 19:06:50 +0000520}
521#endif
522
9d2e6ef9 scottc1998-09-29 22:36:29 +0000523/*
524 *----------------------------------------------------------------------
525 * wScreenInit--
6830b057 dan2004-10-12 21:28:27 +0000526 * Initializes the window manager for the given screen and
9d2e6ef9 scottc1998-09-29 22:36:29 +0000527 * allocates a WScreen descriptor for it. Many resources are allocated
528 * for the screen and the root window is setup appropriately.
529 *
530 * Returns:
531 * The WScreen descriptor for the screen.
6830b057 dan2004-10-12 21:28:27 +0000532 *
9d2e6ef9 scottc1998-09-29 22:36:29 +0000533 * Side effects:
534 * Many resources are allocated and the IconSize property is
535 * set on the root window.
536 * The program can be aborted if some fatal error occurs.
6830b057 dan2004-10-12 21:28:27 +0000537 *
9d2e6ef9 scottc1998-09-29 22:36:29 +0000538 * TODO: User specifiable visual.
6830b057 dan2004-10-12 21:28:27 +0000539 *----------------------------------------------------------------------
9d2e6ef9 scottc1998-09-29 22:36:29 +0000540 */
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200541WScreen *wScreenInit(int screen_number)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000542{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200543 WScreen *scr;
544 XIconSize icon_size[1];
545 RContextAttributes rattr;
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200546 long event_mask;
547 XErrorHandler oldHandler;
548 int i;
59eb9475 dan1998-11-03 12:53:26 +0000549
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200550 scr = wmalloc(sizeof(WScreen));
551 memset(scr, 0, sizeof(WScreen));
f5177e67 kojima2000-03-28 02:48:32 +0000552
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200553 scr->stacking_list = WMCreateTreeBag();
6830b057 dan2004-10-12 21:28:27 +0000554
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200555 /* initialize globals */
556 scr->screen = screen_number;
557 scr->root_win = RootWindow(dpy, screen_number);
558 scr->depth = DefaultDepth(dpy, screen_number);
559 scr->colormap = DefaultColormap(dpy, screen_number);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000560
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200561 scr->scr_width = WidthOfScreen(ScreenOfDisplay(dpy, screen_number));
562 scr->scr_height = HeightOfScreen(ScreenOfDisplay(dpy, screen_number));
9d2e6ef9 scottc1998-09-29 22:36:29 +0000563
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200564 wInitXinerama(scr);
27a396d7 dan2003-06-06 04:11:00 +0000565
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200566 scr->usableArea = (WArea *) wmalloc(sizeof(WArea) * wXineramaHeads(scr));
567 scr->totalUsableArea = (WArea *) wmalloc(sizeof(WArea) * wXineramaHeads(scr));
27a396d7 dan2003-06-06 04:11:00 +0000568
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200569 for (i = 0; i < wXineramaHeads(scr); ++i) {
570 WMRect rect = wGetRectForHead(scr, i);
571 scr->usableArea[i].x1 = scr->totalUsableArea[i].x1 = rect.pos.x;
572 scr->usableArea[i].y1 = scr->totalUsableArea[i].y1 = rect.pos.y;
573 scr->usableArea[i].x2 = scr->totalUsableArea[i].x2 = rect.pos.x + rect.size.width;
574 scr->usableArea[i].y2 = scr->totalUsableArea[i].y2 = rect.pos.y + rect.size.height;
575 }
0261c326 dan1999-01-06 15:22:33 +0000576
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200577 scr->fakeGroupLeaders = WMCreateArray(16);
672c42cc dan2001-12-17 04:02:33 +0000578
416e3a82 dan1999-01-25 19:06:50 +0000579#if 0
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200580 if (!aquireManagerSelection(scr)) {
581 wfree(scr);
416e3a82 dan1999-01-25 19:06:50 +0000582
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200583 return NULL;
584 }
416e3a82 dan1999-01-25 19:06:50 +0000585#endif
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200586 CantManageScreen = 0;
587 oldHandler = XSetErrorHandler((XErrorHandler) alreadyRunningError);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000588
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200589 event_mask = EVENT_MASK;
59eb9475 dan1998-11-03 12:53:26 +0000590
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200591 if (wPreferences.disable_root_mouse) {
592 event_mask &= ~(ButtonPressMask | ButtonReleaseMask);
593 }
6830b057 dan2004-10-12 21:28:27 +0000594
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200595 XSelectInput(dpy, scr->root_win, event_mask);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000596
6830b057 dan2004-10-12 21:28:27 +0000597#ifdef KEEP_XKB_LOCK_STATUS
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200598 /* Only GroupLock doesn't work correctly in my system since right-alt
599 * can change mode while holding it too - ]d
600 */
601 if (wXkbSupported) {
602 XkbSelectEvents(dpy, XkbUseCoreKbd, XkbStateNotifyMask, XkbStateNotifyMask);
603 }
604#endif /* KEEP_XKB_LOCK_STATUS */
605
c201e161
CM
Carlos R. Mafra2010-08-22 19:05:07 +0200606#ifdef HAVE_XRANDR
607 if (has_randr)
608 XRRSelectInput(dpy, scr->root_win, RRScreenChangeNotifyMask);
609#endif
610
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200611 XSync(dpy, False);
612 XSetErrorHandler(oldHandler);
613
614 if (CantManageScreen) {
615 wfree(scr);
616 return NULL;
617 }
618
619 XDefineCursor(dpy, scr->root_win, wCursor[WCUR_ROOT]);
620
621 /* screen descriptor for raster graphic library */
622 rattr.flags = RC_RenderMode | RC_ColorsPerChannel | RC_StandardColormap;
623 rattr.render_mode = wPreferences.no_dithering ? RBestMatchRendering : RDitheredRendering;
624
625 /* if the std colormap stuff works ok, this will be ignored */
626 rattr.colors_per_channel = wPreferences.cmap_size;
627 if (rattr.colors_per_channel < 2)
628 rattr.colors_per_channel = 2;
629
630 /* will only be accounted for in PseudoColor */
631 if (wPreferences.flags.create_stdcmap) {
632 rattr.standard_colormap_mode = RCreateStdColormap;
633 } else {
634 rattr.standard_colormap_mode = RUseStdColormap;
635 }
636
629b1187 Ralf Hoffmann2009-12-10 19:57:23 +0100637 if (getWVisualID(screen_number) >= 0) {
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200638 rattr.flags |= RC_VisualID;
629b1187 Ralf Hoffmann2009-12-10 19:57:23 +0100639 rattr.visualid = getWVisualID(screen_number);
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200640 }
641
642 scr->rcontext = RCreateContext(dpy, screen_number, &rattr);
643
644 if (!scr->rcontext && RErrorCode == RERR_STDCMAPFAIL) {
645 wwarning(RMessageForError(RErrorCode));
646
647 rattr.flags &= ~RC_StandardColormap;
648 rattr.standard_colormap_mode = RUseStdColormap;
649
650 scr->rcontext = RCreateContext(dpy, screen_number, &rattr);
651 }
652
653 if (!scr->rcontext) {
654 wwarning(_("could not initialize graphics library context: %s"), RMessageForError(RErrorCode));
655 wAbort(False);
656 } else {
657 char **formats;
658 int i = 0;
659
660 formats = RSupportedFileFormats();
661 if (formats) {
662 for (i = 0; formats[i] != NULL; i++) {
663 if (strcmp(formats[i], "TIFF") == 0) {
664 scr->flags.supports_tiff = 1;
665 break;
666 }
667 }
668 }
669 }
670
671 scr->w_win = scr->rcontext->drawable;
672 scr->w_visual = scr->rcontext->visual;
673 scr->w_depth = scr->rcontext->depth;
674 scr->w_colormap = scr->rcontext->cmap;
675
676 /* create screen descriptor for WINGs */
677 scr->wmscreen = WMCreateScreenWithRContext(dpy, screen_number, scr->rcontext);
678
679 if (!scr->wmscreen) {
680 wfatal(_("could not initialize WINGs widget set"));
681 return NULL;
682 }
683
684 scr->black = WMBlackColor(scr->wmscreen);
685 scr->white = WMWhiteColor(scr->wmscreen);
686 scr->gray = WMGrayColor(scr->wmscreen);
687 scr->darkGray = WMDarkGrayColor(scr->wmscreen);
688
689 scr->black_pixel = WMColorPixel(scr->black); /*scr->rcontext->black; */
690 scr->white_pixel = WMColorPixel(scr->white); /*scr->rcontext->white; */
691 scr->light_pixel = WMColorPixel(scr->gray);
692 scr->dark_pixel = WMColorPixel(scr->darkGray);
693
694 {
695 XColor xcol;
696 /* frame boder color */
697 wGetColor(scr, FRAME_BORDER_COLOR, &xcol);
698 scr->frame_border_pixel = xcol.pixel;
699 }
700
701 /* create GCs with default values */
702 allocGCs(scr);
703
704 /* for our window manager info notice board. Need to
705 * create before reading the defaults, because it will be used there.
706 */
707 scr->info_window = XCreateSimpleWindow(dpy, scr->root_win, 0, 0, 10, 10, 0, 0, 0);
708
709 /* read defaults for this screen */
710 wReadDefaults(scr, WDWindowMaker->dictionary);
711
712 createInternalWindows(scr);
0261c326 dan1999-01-06 15:22:33 +0000713
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200714 wNETWMInitStuff(scr);
9aca0d5f dan2004-10-12 01:34:32 +0000715
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200716 /* create initial workspace */
717 wWorkspaceNew(scr);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000718
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200719 /* create shared pixmaps */
720 createPixmaps(scr);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000721
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200722 /* set icon sizes we can accept from clients */
723 icon_size[0].min_width = 8;
724 icon_size[0].min_height = 8;
725 icon_size[0].max_width = wPreferences.icon_size - 4;
726 icon_size[0].max_height = wPreferences.icon_size - 4;
727 icon_size[0].width_inc = 1;
728 icon_size[0].height_inc = 1;
729 XSetIconSizes(dpy, scr->root_win, icon_size, 1);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000730
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200731 /* setup WindowMaker protocols property in the root window */
732 PropSetWMakerProtocols(scr->root_win);
416e3a82 dan1999-01-25 19:06:50 +0000733
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200734 /* setup our noticeboard */
735 XChangeProperty(dpy, scr->info_window, _XA_WINDOWMAKER_NOTICEBOARD,
736 XA_WINDOW, 32, PropModeReplace, (unsigned char *)&scr->info_window, 1);
737 XChangeProperty(dpy, scr->root_win, _XA_WINDOWMAKER_NOTICEBOARD,
738 XA_WINDOW, 32, PropModeReplace, (unsigned char *)&scr->info_window, 1);
416e3a82 dan1999-01-25 19:06:50 +0000739
9d2e6ef9 scottc1998-09-29 22:36:29 +0000740#ifdef BALLOON_TEXT
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200741 /* initialize balloon text stuff */
742 wBalloonInitialize(scr);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000743#endif
5230a575 dan2002-10-18 02:56:59 +0000744
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200745 scr->info_text_font = WMBoldSystemFontOfSize(scr->wmscreen, 12);
5230a575 dan2002-10-18 02:56:59 +0000746
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200747 scr->tech_draw_font = XLoadQueryFont(dpy, "-adobe-helvetica-bold-r-*-*-12-*-*-*-*-*-*-*");
748 if (!scr->tech_draw_font)
749 scr->tech_draw_font = XLoadQueryFont(dpy, "fixed");
f2de1c9d kojima2000-01-14 16:30:56 +0000750
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200751 scr->gview = WCreateGeometryView(scr->wmscreen);
752 WMRealizeWidget(scr->gview);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000753
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200754 wScreenUpdateUsableArea(scr);
0261c326 dan1999-01-06 15:22:33 +0000755
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200756 return scr;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000757}
758
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200759void wScreenUpdateUsableArea(WScreen * scr)
27a396d7 dan2003-06-06 04:11:00 +0000760{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200761 /*
762 * scr->totalUsableArea[] will become the usableArea used for Windowplacement,
763 * scr->usableArea[] will be used for iconplacement, hence no iconyard nor
764 * border.
765 */
766
767 int i;
768 unsigned long best_area = 0, tmp_area;
769 WArea area;
770 int dock_head = scr->xine_info.primary_head;
771
772 if (scr->dock) {
773 WMRect rect;
774 rect.pos.x = scr->dock->x_pos;
775 rect.pos.y = scr->dock->y_pos;
776 rect.size.width = wPreferences.icon_size;
777 rect.size.height = wPreferences.icon_size;
778 dock_head = wGetHeadForRect(scr, rect);
779 }
780
781 for (i = 0; i < wXineramaHeads(scr); ++i) {
782 WMRect rect = wGetRectForHead(scr, i);
783 scr->totalUsableArea[i].x1 = rect.pos.x;
784 scr->totalUsableArea[i].y1 = rect.pos.y;
785 scr->totalUsableArea[i].x2 = rect.pos.x + rect.size.width;
786 scr->totalUsableArea[i].y2 = rect.pos.y + rect.size.height;
787
788 if (scr->dock && dock_head == i && (!scr->dock->lowered || wPreferences.no_window_over_dock)) {
789 int offset = wPreferences.icon_size + DOCK_EXTRA_SPACE;
790
791 if (scr->dock->on_right_side) {
792 scr->totalUsableArea[i].x2 -= offset;
793 } else {
794 scr->totalUsableArea[i].x1 += offset;
795 }
796 }
15e37ff9 Carlos R. Mafra2009-10-12 00:08:21 +0200797
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200798 {
799 WArea area;
800 if (wNETWMGetUsableArea(scr, i, &area)) {
801 scr->totalUsableArea[i].x1 = WMAX(scr->totalUsableArea[i].x1, area.x1);
802 scr->totalUsableArea[i].y1 = WMAX(scr->totalUsableArea[i].y1, area.y1);
803 scr->totalUsableArea[i].x2 = WMIN(scr->totalUsableArea[i].x2, area.x2);
804 scr->totalUsableArea[i].y2 = WMIN(scr->totalUsableArea[i].y2, area.y2);
805 }
806 }
27a396d7 dan2003-06-06 04:11:00 +0000807
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200808 scr->usableArea[i] = scr->totalUsableArea[i];
27a396d7 dan2003-06-06 04:11:00 +0000809
810#if 0
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200811 printf("usableArea[%d]: %d %d %d %d\n", i,
812 scr->usableArea[i].x1, scr->usableArea[i].x2, scr->usableArea[i].y1, scr->usableArea[i].y2);
27a396d7 dan2003-06-06 04:11:00 +0000813#endif
814
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200815 if (wPreferences.no_window_over_icons) {
816 if (wPreferences.icon_yard & IY_VERT) {
817 if (wPreferences.icon_yard & IY_RIGHT) {
818 scr->totalUsableArea[i].x2 -= wPreferences.icon_size;
819 } else {
820 scr->totalUsableArea[i].x1 += wPreferences.icon_size;
821 }
822 } else {
823 if (wPreferences.icon_yard & IY_TOP) {
824 scr->totalUsableArea[i].y1 += wPreferences.icon_size;
825 } else {
826 scr->totalUsableArea[i].y2 -= wPreferences.icon_size;
827 }
828 }
829 }
830
831 if (scr->totalUsableArea[i].x2 - scr->totalUsableArea[i].x1 < rect.size.width / 2) {
832 scr->totalUsableArea[i].x1 = rect.pos.x;
833 scr->totalUsableArea[i].x2 = rect.pos.x + rect.size.width;
834 }
835
836 if (scr->totalUsableArea[i].y2 - scr->totalUsableArea[i].y1 < rect.size.height / 2) {
837 scr->totalUsableArea[i].y1 = rect.pos.y;
838 scr->totalUsableArea[i].y2 = rect.pos.y + rect.size.height;
839 }
840
841 tmp_area = (scr->totalUsableArea[i].x2 - scr->totalUsableArea[i].x1) *
842 (scr->totalUsableArea[i].y2 - scr->totalUsableArea[i].y1);
843
844 if (tmp_area > best_area) {
845 best_area = tmp_area;
846 area = scr->totalUsableArea[i];
847 }
848
849 {
850 unsigned size = wPreferences.workspace_border_size;
851 unsigned position = wPreferences.workspace_border_position;
852
853 if (size > 0 && position != WB_NONE) {
854 if (position & WB_LEFTRIGHT) {
855 scr->totalUsableArea[i].x1 += size;
856 scr->totalUsableArea[i].x2 -= size;
857 }
858 if (position & WB_TOPBOTTOM) {
859 scr->totalUsableArea[i].y1 += size;
860 scr->totalUsableArea[i].y2 -= size;
861 }
862 }
863 }
864 }
27a396d7 dan2003-06-06 04:11:00 +0000865
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200866 wNETWMUpdateWorkarea(scr, area);
27a396d7 dan2003-06-06 04:11:00 +0000867
15e37ff9 Carlos R. Mafra2009-10-12 00:08:21 +0200868 if (wPreferences.auto_arrange_icons)
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200869 wArrangeIcons(scr, True);
27a396d7 dan2003-06-06 04:11:00 +0000870}
abc09951 kojima2001-09-12 21:43:42 +0000871
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200872void wScreenRestoreState(WScreen * scr)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000873{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200874 WMPropList *state;
875 char *path;
851835c7 dan2002-09-11 15:02:43 +0000876
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200877 OpenRootMenu(scr, -10000, -10000, False);
878 wMenuUnmap(scr->root_menu);
3c046182 kojima1999-09-16 02:58:56 +0000879
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200880 make_keys();
881
882 if (wScreenCount == 1) {
883 path = wdefaultspathfordomain("WMState");
884 } else {
885 char buf[16];
886 snprintf(buf, sizeof(buf), "WMState.%i", scr->screen);
887 path = wdefaultspathfordomain(buf);
888 }
889 scr->session_state = WMReadPropListFromFile(path);
890 wfree(path);
891 if (!scr->session_state && wScreenCount > 1) {
892 path = wdefaultspathfordomain("WMState");
893 scr->session_state = WMReadPropListFromFile(path);
894 wfree(path);
895 }
896
897 if (!scr->session_state) {
898 scr->session_state = WMCreatePLDictionary(NULL, NULL);
899 }
900
901 if (!wPreferences.flags.nodock) {
902 state = WMGetFromPLDictionary(scr->session_state, dDock);
903 scr->dock = wDockRestoreState(scr, state, WM_DOCK);
904 }
905
906 if (!wPreferences.flags.noclip) {
907 state = WMGetFromPLDictionary(scr->session_state, dClip);
908 scr->clip_icon = wClipRestoreState(scr, state);
909 }
910
911 wWorkspaceRestoreState(scr);
912
913 wScreenUpdateUsableArea(scr);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000914}
915
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200916void wScreenSaveState(WScreen * scr)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000917{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200918 WWindow *wwin;
919 char *str;
920 WMPropList *old_state, *foo;
921
922 make_keys();
923
924 /* save state of windows */
925 wwin = scr->focused_window;
926 while (wwin) {
927 wWindowSaveState(wwin);
928 wwin = wwin->prev;
929 }
930
931 if (wPreferences.flags.noupdates)
932 return;
933
934 old_state = scr->session_state;
935 scr->session_state = WMCreatePLDictionary(NULL, NULL);
936
937 WMPLSetCaseSensitive(True);
938
939 /* save dock state to file */
940 if (!wPreferences.flags.nodock) {
941 wDockSaveState(scr, old_state);
942 } else {
943 if ((foo = WMGetFromPLDictionary(old_state, dDock)) != NULL) {
944 WMPutInPLDictionary(scr->session_state, dDock, foo);
945 }
946 }
947 if (!wPreferences.flags.noclip) {
948 wClipSaveState(scr);
949 } else {
950 if ((foo = WMGetFromPLDictionary(old_state, dClip)) != NULL) {
951 WMPutInPLDictionary(scr->session_state, dClip, foo);
952 }
953 }
954
955 wWorkspaceSaveState(scr, old_state);
956
957 if (wPreferences.save_session_on_exit) {
958 wSessionSaveState(scr);
959 } else {
960 if ((foo = WMGetFromPLDictionary(old_state, dApplications)) != NULL) {
961 WMPutInPLDictionary(scr->session_state, dApplications, foo);
962 }
963 if ((foo = WMGetFromPLDictionary(old_state, dWorkspace)) != NULL) {
964 WMPutInPLDictionary(scr->session_state, dWorkspace, foo);
965 }
966 }
967
968 /* clean up */
969 WMPLSetCaseSensitive(False);
970
971 wMenuSaveState(scr);
972
973 if (wScreenCount == 1) {
974 str = wdefaultspathfordomain("WMState");
975 } else {
976 char buf[16];
977 snprintf(buf, sizeof(buf), "WMState.%i", scr->screen);
978 str = wdefaultspathfordomain(buf);
979 }
badecc24 Tamas TEVESZ2010-03-15 23:12:24 +0100980 if (!WMWritePropListToFile(scr->session_state, str)) {
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200981 wsyserror(_("could not save session state in %s"), str);
982 }
983 wfree(str);
984 WMReleasePropList(old_state);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000985}
986
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +0200987int wScreenBringInside(WScreen * scr, int *x, int *y, int width, int height)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000988{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +0200989 int moved = 0;
990 int tol_w, tol_h;
991 /*
992 * With respect to the head that contains most of the window.
993 */
994 int sx1, sy1, sx2, sy2;
995
996 WMRect rect;
997 int head, flags;
998
999 rect.pos.x = *x;
1000 rect.pos.y = *y;
1001 rect.size.width = width;
1002 rect.size.height = height;
1003
1004 head = wGetRectPlacementInfo(scr, rect, &flags);
1005 rect = wGetRectForHead(scr, head);
1006
1007 sx1 = rect.pos.x;
1008 sy1 = rect.pos.y;
1009 sx2 = sx1 + rect.size.width;
1010 sy2 = sy1 + rect.size.height;
1011
1012#if 0 /* NOTE: gives funky group movement */
1013 if (flags & XFLAG_MULTIPLE) {
1014 /*
1015 * since we span multiple heads, pull window totaly inside
1016 */
1017 if (*x < sx1)
1018 *x = sx1, moved = 1;
1019 else if (*x + width > sx2)
1020 *x = sx2 - width, moved = 1;
1021
1022 if (*y < sy1)
1023 *y = sy1, moved = 1;
1024 else if (*y + height > sy2)
1025 *y = sy2 - height, moved = 1;
1026
1027 return moved;
1028 }
a10214a5 kojima2002-11-28 22:04:07 +00001029#endif
6830b057 dan2004-10-12 21:28:27 +00001030
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001031 if (width > 20)
1032 tol_w = width / 2;
1033 else
1034 tol_w = 20;
9d2e6ef9 scottc1998-09-29 22:36:29 +00001035
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001036 if (height > 20)
1037 tol_h = height / 2;
1038 else
1039 tol_h = 20;
9d2e6ef9 scottc1998-09-29 22:36:29 +00001040
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001041 if (*x + width < sx1 + 10)
1042 *x = sx1 - tol_w, moved = 1;
1043 else if (*x >= sx2 - 10)
1044 *x = sx2 - tol_w - 1, moved = 1;
a10214a5 kojima2002-11-28 22:04:07 +00001045
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001046 if (*y < sy1 - height + 10)
1047 *y = sy1 - tol_h, moved = 1;
1048 else if (*y >= sy2 - 10)
1049 *y = sy2 - tol_h - 1, moved = 1;
a10214a5 kojima2002-11-28 22:04:07 +00001050
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001051 return moved;
a10214a5 kojima2002-11-28 22:04:07 +00001052}
1053
688a56e8 Carlos R. Mafra2009-08-20 00:59:40 +02001054int wScreenKeepInside(WScreen * scr, int *x, int *y, int width, int height)
a10214a5 kojima2002-11-28 22:04:07 +00001055{
688a56e8
CM
Carlos R. Mafra2009-08-20 00:59:40 +02001056 int moved = 0;
1057 int sx1, sy1, sx2, sy2;
1058 WMRect rect;
1059 int head;
1060
1061 rect.pos.x = *x;
1062 rect.pos.y = *y;
1063 rect.size.width = width;
1064 rect.size.height = height;
1065
1066 head = wGetHeadForRect(scr, rect);
1067 rect = wGetRectForHead(scr, head);
1068
1069 sx1 = rect.pos.x;
1070 sy1 = rect.pos.y;
1071 sx2 = sx1 + rect.size.width;
1072 sy2 = sy1 + rect.size.height;
1073
1074 if (*x < sx1)
1075 *x = sx1, moved = 1;
1076 else if (*x + width > sx2)
1077 *x = sx2 - width, moved = 1;
1078
1079 if (*y < sy1)
1080 *y = sy1, moved = 1;
1081 else if (*y + height > sy2)
1082 *y = sy2 - height, moved = 1;
1083
1084 return moved;
9d2e6ef9 scottc1998-09-29 22:36:29 +00001085}