added Font Configuration
[wmaker-crm.git] / src / startup.c
blob5ee588ae39f709658085360445dc5ade2e3ef8ee
1 /*
2 * Window Maker window manager
4 * Copyright (c) 1997-2003 Alfredo K. Kojima
5 * Copyright (c) 1998-2003 Dan Pascu
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.
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.
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.
23 #include "wconfig.h"
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include <unistd.h>
28 #include <errno.h>
29 #include <signal.h>
30 #include <sys/wait.h>
31 #ifdef __FreeBSD__
32 #include <sys/signal.h>
33 #endif
35 #include <X11/Xlib.h>
36 #include <X11/Xutil.h>
37 #include <X11/Intrinsic.h>
38 #include <X11/cursorfont.h>
39 #include <X11/Xproto.h>
40 #include <X11/keysym.h>
41 #ifdef SHAPE
42 #include <X11/extensions/shape.h>
43 #endif
45 #include "WindowMaker.h"
46 #include "GNUstep.h"
47 #include "texture.h"
48 #include "screen.h"
49 #include "window.h"
50 #include "actions.h"
51 #include "client.h"
52 #include "funcs.h"
53 #include "dock.h"
54 #include "workspace.h"
55 #include "keybind.h"
56 #include "framewin.h"
57 #include "session.h"
58 #include "defaults.h"
59 #include "properties.h"
60 #include "dialog.h"
61 #ifdef XDND
62 #include "xdnd.h"
63 #endif
65 #include "xutil.h"
67 #ifdef KWM_HINTS
68 #include "kwm.h"
69 #endif
71 #if 0
72 #ifdef SYS_SIGLIST_DECLARED
73 extern const char * const sys_siglist[];
74 #endif
75 #endif
77 /* for SunOS */
78 #ifndef SA_RESTART
79 # define SA_RESTART 0
80 #endif
82 /* Just in case, for weirdo systems */
83 #ifndef SA_NODEFER
84 # define SA_NODEFER 0
85 #endif
87 /****** Global Variables ******/
89 extern WPreferences wPreferences;
91 extern WDDomain *WDWindowMaker;
92 extern WDDomain *WDRootMenu;
93 extern WDDomain *WDWindowAttributes;
95 extern WShortKey wKeyBindings[WKBD_LAST];
97 extern int wScreenCount;
100 #ifdef SHAPE
101 extern Bool wShapeSupported;
102 extern int wShapeEventBase;
103 #endif
105 #ifdef KEEP_XKB_LOCK_STATUS
106 extern Bool wXkbSupported;
107 extern int wXkbEventBase;
108 #endif
110 /* contexts */
111 extern XContext wWinContext;
112 extern XContext wAppWinContext;
113 extern XContext wStackContext;
114 extern XContext wVEdgeContext;
116 /* atoms */
117 extern Atom _XA_WM_STATE;
118 extern Atom _XA_WM_CHANGE_STATE;
119 extern Atom _XA_WM_PROTOCOLS;
120 extern Atom _XA_WM_TAKE_FOCUS;
121 extern Atom _XA_WM_DELETE_WINDOW;
122 extern Atom _XA_WM_SAVE_YOURSELF;
123 extern Atom _XA_WM_CLIENT_LEADER;
124 extern Atom _XA_WM_COLORMAP_WINDOWS;
125 extern Atom _XA_WM_COLORMAP_NOTIFY;
127 extern Atom _XA_GNUSTEP_WM_ATTR;
129 extern Atom _XA_WINDOWMAKER_MENU;
130 extern Atom _XA_WINDOWMAKER_WM_PROTOCOLS;
131 extern Atom _XA_WINDOWMAKER_STATE;
132 extern Atom _XA_WINDOWMAKER_WM_FUNCTION;
133 extern Atom _XA_WINDOWMAKER_NOTICEBOARD;
134 extern Atom _XA_WINDOWMAKER_COMMAND;
135 extern Atom _XA_WINDOWMAKER_ICON_SIZE;
136 extern Atom _XA_WINDOWMAKER_ICON_TILE;
138 extern Atom _XA_GNUSTEP_WM_MINIATURIZE_WINDOW;
139 extern Atom _XA_GNUSTEP_TITLEBAR_STATE;
142 /* cursors */
143 extern Cursor wCursor[WCUR_LAST];
145 /* special flags */
146 extern char WDelayedActionSet;
148 /***** Local *****/
150 static WScreen **wScreen = NULL;
153 static unsigned int _NumLockMask = 0;
154 static unsigned int _ScrollLockMask = 0;
158 static void manageAllWindows(WScreen *scr, int crashed);
160 extern void NotifyDeadProcess(pid_t pid, unsigned char status);
163 static int
164 catchXError(Display *dpy, XErrorEvent *error)
166 char buffer[MAXLINE];
168 /* ignore some errors */
169 if (error->resourceid != None
170 && ((error->error_code == BadDrawable
171 && error->request_code == X_GetGeometry)
172 || (error->error_code == BadMatch
173 && (error->request_code == X_SetInputFocus))
174 || (error->error_code == BadWindow)
176 && (error->request_code == X_GetWindowAttributes
177 || error->request_code == X_SetInputFocus
178 || error->request_code == X_ChangeWindowAttributes
179 || error->request_code == X_GetProperty
180 || error->request_code == X_ChangeProperty
181 || error->request_code == X_QueryTree
182 || error->request_code == X_GrabButton
183 || error->request_code == X_UngrabButton
184 || error->request_code == X_SendEvent
185 || error->request_code == X_ConfigureWindow))
187 || (error->request_code == X_InstallColormap))) {
188 #ifndef DEBUG
190 return 0;
191 #else
192 printf("got X error %x %x %x\n", error->request_code,
193 error->error_code, (unsigned)error->resourceid);
194 return 0;
195 #endif
197 FormatXError(dpy, error, buffer, MAXLINE);
198 wwarning(_("internal X error: %s\n"), buffer);
199 return -1;
204 *----------------------------------------------------------------------
205 * handleXIO-
206 * Handle X shutdowns and other stuff.
207 *----------------------------------------------------------------------
209 static int
210 handleXIO(Display *xio_dpy)
212 dpy = NULL;
213 Exit(0);
214 return 0;
219 *----------------------------------------------------------------------
220 * delayedAction-
221 * Action to be executed after the signal() handler is exited.
222 *----------------------------------------------------------------------
224 static void
225 delayedAction(void *cdata)
227 if (WDelayedActionSet == 0) {
228 return;
230 WDelayedActionSet--;
232 * Make the event dispatcher do whatever it needs to do,
233 * including handling zombie processes, restart and exit
234 * signals.
236 DispatchEvent(NULL);
241 *----------------------------------------------------------------------
242 * handleExitSig--
243 * User generated exit signal handler.
244 *----------------------------------------------------------------------
246 static RETSIGTYPE
247 handleExitSig(int sig)
249 sigset_t sigs;
251 sigfillset(&sigs);
252 sigprocmask(SIG_BLOCK, &sigs, NULL);
254 if (sig == SIGUSR1) {
255 #ifdef SYS_SIGLIST_DECLARED
256 wwarning("got signal %i (%s) - restarting\n", sig, sys_siglist[sig]);
257 #else
258 wwarning("got signal %i - restarting\n", sig);
259 #endif
261 SIG_WCHANGE_STATE(WSTATE_NEED_RESTART);
262 /* setup idle handler, so that this will be handled when
263 * the select() is returned becaused of the signal, even if
264 * there are no X events in the queue */
265 WDelayedActionSet++;
266 } else if (sig == SIGUSR2) {
267 #ifdef SYS_SIGLIST_DECLARED
268 wwarning("got signal %i (%s) - rereading defaults\n", sig, sys_siglist[sig]);
269 #else
270 wwarning("got signal %i - rereading defaults\n", sig);
271 #endif
273 SIG_WCHANGE_STATE(WSTATE_NEED_REREAD);
274 /* setup idle handler, so that this will be handled when
275 * the select() is returned becaused of the signal, even if
276 * there are no X events in the queue */
277 WDelayedActionSet++;
278 } else if (sig==SIGTERM || sig==SIGINT || sig==SIGHUP) {
279 #ifdef SYS_SIGLIST_DECLARED
280 wwarning("got signal %i (%s) - exiting...\n", sig, sys_siglist[sig]);
281 #else
282 wwarning("got signal %i - exiting...\n", sig);
283 #endif
285 SIG_WCHANGE_STATE(WSTATE_NEED_EXIT);
287 WDelayedActionSet++;
290 sigprocmask(SIG_UNBLOCK, &sigs, NULL);
293 /* Dummy signal handler */
294 static void
295 dummyHandler(int sig)
301 *----------------------------------------------------------------------
302 * handleSig--
303 * general signal handler. Exits the program gently.
304 *----------------------------------------------------------------------
306 static RETSIGTYPE
307 handleSig(int sig)
309 #ifdef SYS_SIGLIST_DECLARED
310 wfatal("got signal %i (%s)\n", sig, sys_siglist[sig]);
311 #else
312 wfatal("got signal %i\n", sig);
313 #endif
315 /* Setting the signal behaviour back to default and then reraising the
316 * signal is a cleaner way to make program exit and core dump than calling
317 * abort(), since it correctly returns from the signal handler and sets
318 * the flags accordingly. -Dan
320 if (sig==SIGSEGV || sig==SIGFPE || sig==SIGBUS || sig==SIGILL
321 || sig==SIGABRT) {
322 signal(sig, SIG_DFL);
323 kill(getpid(), sig);
324 return;
327 wAbort(0);
331 static RETSIGTYPE
332 buryChild(int foo)
334 pid_t pid;
335 int status;
336 int save_errno = errno;
337 sigset_t sigs;
339 sigfillset(&sigs);
340 /* Block signals so that NotifyDeadProcess() doesn't get fux0red */
341 sigprocmask(SIG_BLOCK, &sigs, NULL);
343 /* R.I.P. */
344 /* If 2 or more kids exit in a small time window, before this handler gets
345 * the chance to get invoked, the SIGCHLD signals will be merged and only
346 * one SIGCHLD signal will be sent to us. We use a while loop to get all
347 * exited child status because we can't count on the number of SIGCHLD
348 * signals to know exactly how many kids have exited. -Dan
350 while ((pid=waitpid(-1, &status, WNOHANG))>0 || (pid<0 && errno==EINTR)) {
351 NotifyDeadProcess(pid, WEXITSTATUS(status));
354 WDelayedActionSet++;
356 sigprocmask(SIG_UNBLOCK, &sigs, NULL);
358 errno = save_errno;
362 static void
363 getOffendingModifiers()
365 int i;
366 XModifierKeymap *modmap;
367 KeyCode nlock, slock;
368 static int mask_table[8] = {
369 ShiftMask,LockMask,ControlMask,Mod1Mask,
370 Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
373 nlock = XKeysymToKeycode(dpy, XK_Num_Lock);
374 slock = XKeysymToKeycode(dpy, XK_Scroll_Lock);
377 * Find out the masks for the NumLock and ScrollLock modifiers,
378 * so that we can bind the grabs for when they are enabled too.
380 modmap = XGetModifierMapping(dpy);
382 if (modmap!=NULL && modmap->max_keypermod>0) {
383 for (i=0; i<8*modmap->max_keypermod; i++) {
384 if (modmap->modifiermap[i]==nlock && nlock!=0)
385 _NumLockMask = mask_table[i/modmap->max_keypermod];
386 else if (modmap->modifiermap[i]==slock && slock!=0)
387 _ScrollLockMask = mask_table[i/modmap->max_keypermod];
391 if (modmap)
392 XFreeModifiermap(modmap);
397 #ifdef NUMLOCK_HACK
398 void
399 wHackedGrabKey(int keycode, unsigned int modifiers,
400 Window grab_window, Bool owner_events, int pointer_mode,
401 int keyboard_mode)
403 if (modifiers == AnyModifier)
404 return;
406 /* grab all combinations of the modifier with CapsLock, NumLock and
407 * ScrollLock. How much memory/CPU does such a monstrosity consume
408 * in the server?
410 if (_NumLockMask)
411 XGrabKey(dpy, keycode, modifiers|_NumLockMask,
412 grab_window, owner_events, pointer_mode, keyboard_mode);
413 if (_ScrollLockMask)
414 XGrabKey(dpy, keycode, modifiers|_ScrollLockMask,
415 grab_window, owner_events, pointer_mode, keyboard_mode);
416 if (_NumLockMask && _ScrollLockMask)
417 XGrabKey(dpy, keycode, modifiers|_NumLockMask|_ScrollLockMask,
418 grab_window, owner_events, pointer_mode, keyboard_mode);
419 if (_NumLockMask)
420 XGrabKey(dpy, keycode, modifiers|_NumLockMask|LockMask,
421 grab_window, owner_events, pointer_mode, keyboard_mode);
422 if (_ScrollLockMask)
423 XGrabKey(dpy, keycode, modifiers|_ScrollLockMask|LockMask,
424 grab_window, owner_events, pointer_mode, keyboard_mode);
425 if (_NumLockMask && _ScrollLockMask)
426 XGrabKey(dpy, keycode, modifiers|_NumLockMask|_ScrollLockMask|LockMask,
427 grab_window, owner_events, pointer_mode, keyboard_mode);
428 /* phew, I guess that's all, right? */
430 #endif
432 void
433 wHackedGrabButton(unsigned int button, unsigned int modifiers,
434 Window grab_window, Bool owner_events,
435 unsigned int event_mask, int pointer_mode,
436 int keyboard_mode, Window confine_to, Cursor cursor)
438 XGrabButton(dpy, button, modifiers, grab_window, owner_events,
439 event_mask, pointer_mode, keyboard_mode, confine_to, cursor);
441 if (modifiers==AnyModifier)
442 return;
444 XGrabButton(dpy, button, modifiers|LockMask, grab_window, owner_events,
445 event_mask, pointer_mode, keyboard_mode, confine_to, cursor);
447 #ifdef NUMLOCK_HACK
448 /* same as above, but for mouse buttons */
449 if (_NumLockMask)
450 XGrabButton(dpy, button, modifiers|_NumLockMask,
451 grab_window, owner_events, event_mask, pointer_mode,
452 keyboard_mode, confine_to, cursor);
453 if (_ScrollLockMask)
454 XGrabButton(dpy, button, modifiers|_ScrollLockMask,
455 grab_window, owner_events, event_mask, pointer_mode,
456 keyboard_mode, confine_to, cursor);
457 if (_NumLockMask && _ScrollLockMask)
458 XGrabButton(dpy, button, modifiers|_ScrollLockMask|_NumLockMask,
459 grab_window, owner_events, event_mask, pointer_mode,
460 keyboard_mode, confine_to, cursor);
461 if (_NumLockMask)
462 XGrabButton(dpy, button, modifiers|_NumLockMask|LockMask,
463 grab_window, owner_events, event_mask, pointer_mode,
464 keyboard_mode, confine_to, cursor);
465 if (_ScrollLockMask)
466 XGrabButton(dpy, button, modifiers|_ScrollLockMask|LockMask,
467 grab_window, owner_events, event_mask, pointer_mode,
468 keyboard_mode, confine_to, cursor);
469 if (_NumLockMask && _ScrollLockMask)
470 XGrabButton(dpy, button, modifiers|_ScrollLockMask|_NumLockMask|LockMask,
471 grab_window, owner_events, event_mask, pointer_mode,
472 keyboard_mode, confine_to, cursor);
473 #endif /* NUMLOCK_HACK */
476 #ifdef notused
477 void
478 wHackedUngrabButton(unsigned int button, unsigned int modifiers,
479 Window grab_window)
481 XUngrabButton(dpy, button, modifiers|_NumLockMask,
482 grab_window);
483 XUngrabButton(dpy, button, modifiers|_ScrollLockMask,
484 grab_window);
485 XUngrabButton(dpy, button, modifiers|_NumLockMask|_ScrollLockMask,
486 grab_window);
487 XUngrabButton(dpy, button, modifiers|_NumLockMask|LockMask,
488 grab_window);
489 XUngrabButton(dpy, button, modifiers|_ScrollLockMask|LockMask,
490 grab_window);
491 XUngrabButton(dpy, button, modifiers|_NumLockMask|_ScrollLockMask|LockMask,
492 grab_window);
494 #endif
498 WScreen*
499 wScreenWithNumber(int i)
501 assert(i < wScreenCount);
503 return wScreen[i];
507 WScreen*
508 wScreenForRootWindow(Window window)
510 int i;
512 if (wScreenCount==1)
513 return wScreen[0];
516 * Since the number of heads will probably be small (normally 2),
517 * it should be faster to use this than a hash table, because
518 * of the overhead.
520 for (i=0; i<wScreenCount; i++) {
521 if (wScreen[i]->root_win == window) {
522 return wScreen[i];
526 return wScreenForWindow(window);
530 WScreen*
531 wScreenSearchForRootWindow(Window window)
533 int i;
535 if (wScreenCount==1)
536 return wScreen[0];
539 * Since the number of heads will probably be small (normally 2),
540 * it should be faster to use this than a hash table, because
541 * of the overhead.
543 for (i=0; i<wScreenCount; i++) {
544 if (wScreen[i]->root_win == window) {
545 return wScreen[i];
549 return wScreenForWindow(window);
553 WScreen*
554 wScreenForWindow(Window window)
556 XWindowAttributes attr;
558 if (wScreenCount==1)
559 return wScreen[0];
561 if (XGetWindowAttributes(dpy, window, &attr)) {
562 return wScreenForRootWindow(attr.root);
564 return NULL;
568 static char *atomNames[] = {
569 "WM_STATE",
570 "WM_CHANGE_STATE",
571 "WM_PROTOCOLS",
572 "WM_TAKE_FOCUS",
573 "WM_DELETE_WINDOW",
574 "WM_SAVE_YOURSELF",
575 "WM_CLIENT_LEADER",
576 "WM_COLORMAP_WINDOWS",
577 "WM_COLORMAP_NOTIFY",
579 "_WINDOWMAKER_MENU",
580 "_WINDOWMAKER_STATE",
581 "_WINDOWMAKER_WM_PROTOCOLS",
582 "_WINDOWMAKER_WM_FUNCTION",
583 "_WINDOWMAKER_NOTICEBOARD",
584 "_WINDOWMAKER_COMMAND",
585 "_WINDOWMAKER_ICON_SIZE",
586 "_WINDOWMAKER_ICON_TILE",
588 GNUSTEP_WM_ATTR_NAME,
589 GNUSTEP_WM_MINIATURIZE_WINDOW,
590 GNUSTEP_TITLEBAR_STATE
595 *----------------------------------------------------------
596 * StartUp--
597 * starts the window manager and setup global data.
598 * Called from main() at startup.
600 * Side effects:
601 * global data declared in main.c is initialized
602 *----------------------------------------------------------
604 void
605 StartUp(Bool defaultScreenOnly)
607 struct sigaction sig_action;
608 int j, max;
609 Atom atom[sizeof(atomNames)/sizeof(char*)];
612 * Ignore CapsLock in modifiers
614 ValidModMask = 0xff & ~LockMask;
616 getOffendingModifiers();
618 * Ignore NumLock and ScrollLock too
620 ValidModMask &= ~(_NumLockMask|_ScrollLockMask);
623 memset(&wKeyBindings, 0, sizeof(wKeyBindings));
625 wWinContext = XUniqueContext();
626 wAppWinContext = XUniqueContext();
627 wStackContext = XUniqueContext();
628 wVEdgeContext = XUniqueContext();
630 /* _XA_VERSION = XInternAtom(dpy, "VERSION", False);*/
632 #ifdef HAVE_XINTERNATOMS
633 XInternAtoms(dpy, atomNames, sizeof(atomNames)/sizeof(char*),
634 False, atom);
635 #else
638 int i;
639 for (i = 0; i < sizeof(atomNames)/sizeof(char*); i++) {
640 atom[i] = XInternAtom(dpy, atomNames[i], False);
643 #endif
645 _XA_WM_STATE = atom[0];
646 _XA_WM_CHANGE_STATE = atom[1];
647 _XA_WM_PROTOCOLS = atom[2];
648 _XA_WM_TAKE_FOCUS = atom[3];
649 _XA_WM_DELETE_WINDOW = atom[4];
650 _XA_WM_SAVE_YOURSELF = atom[5];
651 _XA_WM_CLIENT_LEADER = atom[6];
652 _XA_WM_COLORMAP_WINDOWS = atom[7];
653 _XA_WM_COLORMAP_NOTIFY = atom[8];
655 _XA_WINDOWMAKER_MENU = atom[9];
656 _XA_WINDOWMAKER_STATE = atom[10];
657 _XA_WINDOWMAKER_WM_PROTOCOLS = atom[11];
658 _XA_WINDOWMAKER_WM_FUNCTION = atom[12];
659 _XA_WINDOWMAKER_NOTICEBOARD = atom[13];
660 _XA_WINDOWMAKER_COMMAND = atom[14];
661 _XA_WINDOWMAKER_ICON_SIZE = atom[15];
662 _XA_WINDOWMAKER_ICON_TILE = atom[16];
664 _XA_GNUSTEP_WM_ATTR = atom[17];
665 _XA_GNUSTEP_WM_MINIATURIZE_WINDOW = atom[18];
666 _XA_GNUSTEP_TITLEBAR_STATE = atom[19];
668 #ifdef XDND
669 wXDNDInitializeAtoms();
670 #endif
673 /* cursors */
674 wCursor[WCUR_NORMAL] = None; /* inherit from root */
675 wCursor[WCUR_ROOT] = XCreateFontCursor(dpy, XC_left_ptr);
676 wCursor[WCUR_ARROW] = XCreateFontCursor(dpy, XC_top_left_arrow);
677 wCursor[WCUR_MOVE] = XCreateFontCursor(dpy, XC_fleur);
678 wCursor[WCUR_RESIZE] = XCreateFontCursor(dpy, XC_sizing);
679 wCursor[WCUR_TOPLEFTRESIZE] = XCreateFontCursor(dpy, XC_top_left_corner);
680 wCursor[WCUR_TOPRIGHTRESIZE] = XCreateFontCursor(dpy, XC_top_right_corner);
681 wCursor[WCUR_BOTTOMLEFTRESIZE] = XCreateFontCursor(dpy, XC_bottom_left_corner);
682 wCursor[WCUR_BOTTOMRIGHTRESIZE] = XCreateFontCursor(dpy, XC_bottom_right_corner);
683 wCursor[WCUR_VERTICALRESIZE] = XCreateFontCursor(dpy, XC_sb_v_double_arrow);
684 wCursor[WCUR_HORIZONRESIZE] = XCreateFontCursor(dpy, XC_sb_h_double_arrow);
685 wCursor[WCUR_WAIT] = XCreateFontCursor(dpy, XC_watch);
686 wCursor[WCUR_QUESTION] = XCreateFontCursor(dpy, XC_question_arrow);
687 wCursor[WCUR_TEXT] = XCreateFontCursor(dpy, XC_xterm); /* odd name???*/
688 wCursor[WCUR_SELECT] = XCreateFontCursor(dpy, XC_cross);
690 Pixmap cur = XCreatePixmap(dpy, DefaultRootWindow(dpy), 16, 16, 1);
691 GC gc = XCreateGC(dpy, cur, 0, NULL);
692 XColor black;
693 memset(&black, 0, sizeof(XColor));
694 XSetForeground(dpy, gc, 0);
695 XFillRectangle(dpy, cur, gc, 0, 0, 16, 16);
696 XFreeGC(dpy, gc);
697 wCursor[WCUR_EMPTY] = XCreatePixmapCursor(dpy, cur, cur, &black, &black, 0, 0);
698 XFreePixmap(dpy, cur);
701 /* signal handler stuff that gets called when a signal is caught */
702 WMAddPersistentTimerHandler(500, delayedAction, NULL);
704 /* emergency exit... */
705 sig_action.sa_handler = handleSig;
706 sigemptyset(&sig_action.sa_mask);
708 sig_action.sa_flags = SA_RESTART;
709 sigaction(SIGQUIT, &sig_action, NULL);
710 /* instead of catching these, we let the default handler abort the
711 * program. The new monitor process will take appropriate action
712 * when it detects the crash.
713 sigaction(SIGSEGV, &sig_action, NULL);
714 sigaction(SIGBUS, &sig_action, NULL);
715 sigaction(SIGFPE, &sig_action, NULL);
716 sigaction(SIGABRT, &sig_action, NULL);
719 sig_action.sa_handler = handleExitSig;
721 /* Here we set SA_RESTART for safety, because SIGUSR1 may not be handled
722 * immediately. -Dan */
723 sig_action.sa_flags = SA_RESTART;
724 sigaction(SIGTERM, &sig_action, NULL);
725 sigaction(SIGINT, &sig_action, NULL);
726 sigaction(SIGHUP, &sig_action, NULL);
727 sigaction(SIGUSR1, &sig_action, NULL);
728 sigaction(SIGUSR2, &sig_action, NULL);
730 /* ignore dead pipe */
731 /* Because POSIX mandates that only signal with handlers are reset
732 * accross an exec*(), we do not want to propagate ignoring SIGPIPEs
733 * to children. Hence the dummy handler.
734 * Philippe Troin <phil@fifi.org>
736 sig_action.sa_handler = &dummyHandler;
737 sig_action.sa_flags = SA_RESTART;
738 sigaction(SIGPIPE, &sig_action, NULL);
740 /* handle dead children */
741 sig_action.sa_handler = buryChild;
742 sig_action.sa_flags = SA_NOCLDSTOP|SA_RESTART;
743 sigaction(SIGCHLD, &sig_action, NULL);
745 /* Now we unblock all signals, that may have been blocked by the parent
746 * who exec()-ed us. This can happen for example if Window Maker crashes
747 * and restarts itself or another window manager from the signal handler.
748 * In this case, the new proccess inherits the blocked signal mask and
749 * will no longer react to that signal, until unblocked.
750 * This is because the signal handler of the proccess who crashed (parent)
751 * didn't return, and the signal remained blocked. -Dan
753 sigfillset(&sig_action.sa_mask);
754 sigprocmask(SIG_UNBLOCK, &sig_action.sa_mask, NULL);
756 /* handle X shutdowns a such */
757 XSetIOErrorHandler(handleXIO);
759 /* set hook for out event dispatcher in WINGs event dispatcher */
760 WMHookEventHandler(DispatchEvent);
762 /* initialize defaults stuff */
763 WDWindowMaker = wDefaultsInitDomain("WindowMaker", True);
764 if (!WDWindowMaker->dictionary) {
765 wwarning(_("could not read domain \"%s\" from defaults database"),
766 "WindowMaker");
769 /* read defaults that don't change until a restart and are
770 * screen independent */
771 wReadStaticDefaults(WDWindowMaker ? WDWindowMaker->dictionary : NULL);
773 /* check sanity of some values */
774 if (wPreferences.icon_size < 16) {
775 wwarning(_("icon size is configured to %i, but it's too small. Using 16, instead\n"),
776 wPreferences.icon_size);
777 wPreferences.icon_size = 16;
780 /* init other domains */
781 WDRootMenu = wDefaultsInitDomain("WMRootMenu", False);
782 if (!WDRootMenu->dictionary) {
783 wwarning(_("could not read domain \"%s\" from defaults database"),
784 "WMRootMenu");
786 wDefaultsMergeGlobalMenus(WDRootMenu);
788 WDWindowAttributes = wDefaultsInitDomain("WMWindowAttributes", True);
789 if (!WDWindowAttributes->dictionary) {
790 wwarning(_("could not read domain \"%s\" from defaults database"),
791 "WMWindowAttributes");
794 XSetErrorHandler((XErrorHandler)catchXError);
796 #ifdef SHAPE
797 /* ignore j */
798 wShapeSupported = XShapeQueryExtension(dpy, &wShapeEventBase, &j);
799 #endif
801 #ifdef KEEP_XKB_LOCK_STATUS
802 wXkbSupported = XkbQueryExtension(dpy, NULL, &wXkbEventBase, NULL, NULL, NULL);
803 if(wPreferences.modelock && !wXkbSupported) {
804 wwarning(_("XKB is not supported. KbdModeLock is automatically disabled."));
805 wPreferences.modelock = 0;
807 #endif
809 if (defaultScreenOnly) {
810 max = 1;
811 } else {
812 max = ScreenCount(dpy);
814 wScreen = wmalloc(sizeof(WScreen*)*max);
816 wScreenCount = 0;
818 /* manage the screens */
819 for (j = 0; j < max; j++) {
820 if (defaultScreenOnly || max==1) {
821 wScreen[wScreenCount] = wScreenInit(DefaultScreen(dpy));
822 if (!wScreen[wScreenCount]) {
823 wfatal(_("it seems that there is already a window manager running"));
824 Exit(1);
826 } else {
827 wScreen[wScreenCount] = wScreenInit(j);
828 if (!wScreen[wScreenCount]) {
829 wwarning(_("could not manage screen %i"), j);
830 continue;
833 wScreenCount++;
836 #ifndef LITE
837 InitializeSwitchMenu();
838 #endif
840 /* initialize/restore state for the screens */
841 for (j = 0; j < wScreenCount; j++) {
842 int lastDesktop;
844 lastDesktop= wNETWMGetCurrentDesktopFromHint(wScreen[j]);
846 wScreenRestoreState(wScreen[j]);
848 /* manage all windows that were already here before us */
849 if (!wPreferences.flags.nodock && wScreen[j]->dock)
850 wScreen[j]->last_dock = wScreen[j]->dock;
852 manageAllWindows(wScreen[j], wPreferences.flags.restarting==2);
854 /* restore saved menus */
855 wMenuRestoreState(wScreen[j]);
857 /* If we're not restarting, restore session */
858 if (wPreferences.flags.restarting==0 && !wPreferences.flags.norestore)
859 wSessionRestoreState(wScreen[j]);
861 if (!wPreferences.flags.noautolaunch) {
862 /* auto-launch apps */
863 if (!wPreferences.flags.nodock && wScreen[j]->dock) {
864 wScreen[j]->last_dock = wScreen[j]->dock;
865 wDockDoAutoLaunch(wScreen[j]->dock, 0);
867 /* auto-launch apps in clip */
868 if (!wPreferences.flags.noclip) {
869 int i;
870 for(i=0; i<wScreen[j]->workspace_count; i++) {
871 if (wScreen[j]->workspaces[i]->clip) {
872 wScreen[j]->last_dock = wScreen[j]->workspaces[i]->clip;
873 wDockDoAutoLaunch(wScreen[j]->workspaces[i]->clip, i);
879 /* go to workspace where we were before restart */
880 if (lastDesktop >= 0) {
881 wWorkspaceForceChange(wScreen[j], lastDesktop);
882 } else {
883 wSessionRestoreLastWorkspace(wScreen[j]);
886 #ifdef KWM_HINTS
887 wKWMSetInitializedHint(wScreen[j]);
888 #endif
891 if (wScreenCount == 0) {
892 wfatal(_("could not manage any screen"));
893 Exit(1);
896 if (!wPreferences.flags.nopolling && !wPreferences.flags.noupdates) {
897 /* setup defaults file polling */
898 WMAddTimerHandler(3000, wDefaultsCheckDomains, NULL);
905 static Bool
906 windowInList(Window window, Window *list, int count)
908 for (; count>=0; count--) {
909 if (window == list[count])
910 return True;
912 return False;
916 *-----------------------------------------------------------------------
917 * manageAllWindows--
918 * Manages all windows in the screen.
920 * Notes:
921 * Called when the wm is being started.
922 * No events can be processed while the windows are being
923 * reparented/managed.
924 *-----------------------------------------------------------------------
926 static void
927 manageAllWindows(WScreen *scr, int crashRecovery)
929 Window root, parent;
930 Window *children;
931 unsigned int nchildren;
932 unsigned int i, j;
933 WWindow *wwin;
935 XGrabServer(dpy);
936 XQueryTree(dpy, scr->root_win, &root, &parent, &children, &nchildren);
938 scr->flags.startup = 1;
940 /* first remove all icon windows */
941 for (i = 0; i < nchildren; i++) {
942 XWMHints *wmhints;
944 if (children[i]==None)
945 continue;
947 wmhints = XGetWMHints(dpy, children[i]);
948 if (wmhints && (wmhints->flags & IconWindowHint)) {
949 for (j = 0; j < nchildren; j++) {
950 if (children[j] == wmhints->icon_window) {
951 XFree(wmhints);
952 wmhints = NULL;
953 children[j] = None;
954 break;
958 if (wmhints) {
959 XFree(wmhints);
964 for (i = 0; i < nchildren; i++) {
965 if (children[i] == None)
966 continue;
968 #ifdef KWM_HINTS
969 wKWMCheckModule(scr, children[i]);
970 #endif
971 wwin = wManageWindow(scr, children[i]);
972 if (wwin) {
973 /* apply states got from WSavedState */
974 /* shaded + minimized is not restored correctly */
975 if (wwin->flags.shaded) {
976 wwin->flags.shaded = 0;
977 wShadeWindow(wwin);
979 if (wwin->flags.miniaturized
980 && (wwin->transient_for == None
981 || wwin->transient_for == scr->root_win
982 || !windowInList(wwin->transient_for, children,
983 nchildren))) {
985 wwin->flags.skip_next_animation = 1;
986 wwin->flags.miniaturized = 0;
987 wIconifyWindow(wwin);
988 } else {
989 wClientSetState(wwin, NormalState, None);
991 if (crashRecovery) {
992 int border;
994 border = (!HAS_BORDER(wwin) ? 0 : FRAME_BORDER_WIDTH);
996 wWindowMove(wwin, wwin->frame_x - border,
997 wwin->frame_y - border -
998 (wwin->frame->titlebar ?
999 wwin->frame->titlebar->height : 0));
1003 XUngrabServer(dpy);
1005 /* hide apps */
1006 wwin = scr->focused_window;
1007 while (wwin) {
1008 if (wwin->flags.hidden) {
1009 WApplication *wapp = wApplicationOf(wwin->main_window);
1011 if (wapp) {
1012 wwin->flags.hidden = 0;
1013 wHideApplication(wapp);
1014 } else {
1015 wwin->flags.hidden = 0;
1018 wwin = wwin->prev;
1021 XFree(children);
1022 scr->flags.startup = 0;
1023 scr->flags.startup2 = 1;
1025 while (XPending(dpy)) {
1026 XEvent ev;
1027 WMNextEvent(dpy, &ev);
1028 WMHandleEvent(&ev);
1030 wWorkspaceForceChange(scr, 0);
1031 if (!wPreferences.flags.noclip)
1032 wDockShowIcons(scr->workspaces[scr->current_workspace]->clip);
1033 scr->flags.startup2 = 0;