Use inotify to check for changes to the defaults database. Workaround for
[wmaker-crm.git] / src / main.c
Commit [+]AuthorDateLineData
9d2e6ef9 scottc1998-09-29 22:36:29 +00001/*
9af1c6c4 dan1998-10-21 14:43:47 +00002 * Window Maker window manager
6830b057 dan2004-10-12 21:28:27 +00003 *
4153e2fd dan2003-01-16 23:30:45 +00004 * Copyright (c) 1997-2003 Alfredo K. Kojima
6830b057 dan2004-10-12 21:28:27 +00005 *
9d2e6ef9 scottc1998-09-29 22:36:29 +00006 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
6830b057 dan2004-10-12 21:28:27 +000018 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
9d2e6ef9 scottc1998-09-29 22:36:29 +000019 * USA.
20 */
21
56d85687 Rodney Padgett2008-08-09 11:39:24 +010022#include <sys/inotify.h>
722c82c8 Carlos R. Mafra2008-05-02 20:01:50 -030023
9d2e6ef9 scottc1998-09-29 22:36:29 +000024#include "wconfig.h"
25
26#include <stdio.h>
27#include <stdlib.h>
28#include <unistd.h>
29#include <string.h>
30#include <sys/stat.h>
31#include <sys/types.h>
32#include <fcntl.h>
33
34#include <X11/Xlib.h>
35#include <X11/Xutil.h>
36
37
38/* Xlocale.h and locale.h are the same if X_LOCALE is undefind in wconfig.h,
39 * and if X_LOCALE is defined, X's locale emulating functions will be used.
40 * See Xlocale.h for more information.
41 */
42#include <X11/Xlocale.h>
43
9df0e167 kojima1999-04-03 03:51:17 +000044#define MAINFILE
45
9d2e6ef9 scottc1998-09-29 22:36:29 +000046#include "WindowMaker.h"
47#include "window.h"
48#include "funcs.h"
49#include "menu.h"
50#include "keybind.h"
51#include "xmodifier.h"
52#include "defaults.h"
9007a657 dan1998-11-23 11:32:19 +000053#include "session.h"
38807b65 dan1999-11-07 21:40:22 +000054#include "dialog.h"
9d2e6ef9 scottc1998-09-29 22:36:29 +000055
33cc542e dan2001-10-04 03:07:34 +000056#include <WINGs/WUtil.h>
9d2e6ef9 scottc1998-09-29 22:36:29 +000057
9d2e6ef9 scottc1998-09-29 22:36:29 +000058/****** Global Variables ******/
59
60/* general info */
61
62Display *dpy;
63
64char *ProgName;
65
66unsigned int ValidModMask = 0xff;
67
56d85687
RP
Rodney Padgett2008-08-09 11:39:24 +010068int inotifyFD;
69int inotifyWD;
9d2e6ef9 scottc1998-09-29 22:36:29 +000070/* locale to use. NULL==POSIX or C */
71char *Locale=NULL;
72
9d2e6ef9 scottc1998-09-29 22:36:29 +000073int wScreenCount=0;
74
75WPreferences wPreferences;
76
77
33cc542e dan2001-10-04 03:07:34 +000078WMPropList *wDomainName;
79WMPropList *wAttributeDomainName;
9d2e6ef9 scottc1998-09-29 22:36:29 +000080
81WShortKey wKeyBindings[WKBD_LAST];
82
83/* defaults domains */
84WDDomain *WDWindowMaker = NULL;
9d2e6ef9 scottc1998-09-29 22:36:29 +000085WDDomain *WDWindowAttributes = NULL;
068c5a94 kojima2001-01-05 22:39:01 +000086WDDomain *WDRootMenu = NULL;
9d2e6ef9 scottc1998-09-29 22:36:29 +000087
88/* XContexts */
89XContext wWinContext;
90XContext wAppWinContext;
91XContext wStackContext;
9aca0d5f dan2004-10-12 01:34:32 +000092XContext wVEdgeContext;
9d2e6ef9 scottc1998-09-29 22:36:29 +000093
94/* Atoms */
95Atom _XA_WM_STATE;
96Atom _XA_WM_CHANGE_STATE;
97Atom _XA_WM_PROTOCOLS;
98Atom _XA_WM_TAKE_FOCUS;
99Atom _XA_WM_DELETE_WINDOW;
100Atom _XA_WM_SAVE_YOURSELF;
101Atom _XA_WM_CLIENT_LEADER;
102Atom _XA_WM_COLORMAP_WINDOWS;
59eb9475 dan1998-11-03 12:53:26 +0000103Atom _XA_WM_COLORMAP_NOTIFY;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000104
105Atom _XA_GNUSTEP_WM_ATTR;
9af1c6c4 dan1998-10-21 14:43:47 +0000106Atom _XA_GNUSTEP_WM_MINIATURIZE_WINDOW;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000107Atom _XA_GNUSTEP_WM_RESIZEBAR;
0af24483 richard2000-03-02 07:36:02 +0000108Atom _XA_GNUSTEP_TITLEBAR_STATE;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000109
9d2e6ef9 scottc1998-09-29 22:36:29 +0000110Atom _XA_WINDOWMAKER_MENU;
111Atom _XA_WINDOWMAKER_WM_PROTOCOLS;
112Atom _XA_WINDOWMAKER_STATE;
113
114Atom _XA_WINDOWMAKER_WM_FUNCTION;
416e3a82 dan1999-01-25 19:06:50 +0000115Atom _XA_WINDOWMAKER_NOTICEBOARD;
9df0e167 kojima1999-04-03 03:51:17 +0000116Atom _XA_WINDOWMAKER_COMMAND;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000117
754230a6 kojima2000-02-16 18:26:15 +0000118Atom _XA_WINDOWMAKER_ICON_SIZE;
119Atom _XA_WINDOWMAKER_ICON_TILE;
120
121
9d2e6ef9 scottc1998-09-29 22:36:29 +0000122/* cursors */
123Cursor wCursor[WCUR_LAST];
124
125/* last event timestamp for XSetInputFocus */
9aca0d5f dan2004-10-12 01:34:32 +0000126Time LastTimestamp = CurrentTime;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000127/* timestamp on the last time we did XSetInputFocus() */
9aca0d5f dan2004-10-12 01:34:32 +0000128Time LastFocusChange = CurrentTime;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000129
130#ifdef SHAPE
9af1c6c4 dan1998-10-21 14:43:47 +0000131Bool wShapeSupported;
132int wShapeEventBase;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000133#endif
134
daaccf6f id1999-05-23 23:48:08 +0000135#ifdef KEEP_XKB_LOCK_STATUS
136Bool wXkbSupported;
137int wXkbEventBase;
138#endif
9d2e6ef9 scottc1998-09-29 22:36:29 +0000139
140/* special flags */
51b1bf34 kojima2001-03-14 02:54:54 +0000141char WProgramSigState = 0;
9af1c6c4 dan1998-10-21 14:43:47 +0000142char WProgramState = WSTATE_NORMAL;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000143char WDelayedActionSet = 0;
144
51b1bf34 kojima2001-03-14 02:54:54 +0000145
9d2e6ef9 scottc1998-09-29 22:36:29 +0000146/* temporary stuff */
147int wVisualID = -1;
148
149
5ef342d9 kojima2001-09-06 21:42:28 +0000150/* notifications */
151const char *WMNManaged = "WMNManaged";
152const char *WMNUnmanaged = "WMNUnmanaged";
153const char *WMNChangedWorkspace = "WMNChangedWorkspace";
154const char *WMNChangedState = "WMNChangedState";
155const char *WMNChangedFocus = "WMNChangedFocus";
156const char *WMNChangedStacking = "WMNChangedStacking";
157const char *WMNChangedName = "WMNChangedName";
158
159const char *WMNWorkspaceCreated = "WMNWorkspaceCreated";
160const char *WMNWorkspaceDestroyed = "WMNWorkspaceDestroyed";
161const char *WMNWorkspaceChanged = "WMNWorkspaceChanged";
162const char *WMNWorkspaceNameChanged = "WMNWorkspaceNameChanged";
163
164const char *WMNResetStacking = "WMNResetStacking";
165
9d2e6ef9 scottc1998-09-29 22:36:29 +0000166/******** End Global Variables *****/
167
168static char *DisplayName = NULL;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000169
8bdc78fc dan1999-04-17 20:25:07 +0000170static char **Arguments;
171
172static int ArgCount;
173
9d2e6ef9 scottc1998-09-29 22:36:29 +0000174extern void EventLoop();
175extern void StartUp();
879b00a5 kojima2004-10-13 05:09:08 +0000176extern int MonitorLoop(int argc, char **argv);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000177
94f4483d kojima1999-10-27 22:32:12 +0000178static Bool multiHead = True;
179
eb87c409 kojima1999-10-20 03:25:06 +0000180/* stdi/o for log shell */
181static int LogStdIn = -1, LogStdOut = -1, LogStdErr = -1;
182
9d2e6ef9 scottc1998-09-29 22:36:29 +0000183
879b00a5 kojima2004-10-13 05:09:08 +0000184static int real_main(int argc, char **argv);
185
9007a657 dan1998-11-23 11:32:19 +0000186void
187Exit(int status)
188{
416e3a82 dan1999-01-25 19:06:50 +0000189#ifdef XSMP_ENABLED
9007a657 dan1998-11-23 11:32:19 +0000190 wSessionDisconnectManager();
191#endif
e7495baf dan1999-02-17 11:06:40 +0000192 if (dpy)
6830b057 dan2004-10-12 21:28:27 +0000193 XCloseDisplay(dpy);
9007a657 dan1998-11-23 11:32:19 +0000194
195 exit(status);
196}
9d2e6ef9 scottc1998-09-29 22:36:29 +0000197
9eb4f894 kojima1999-04-17 23:11:34 +0000198
9d2e6ef9 scottc1998-09-29 22:36:29 +0000199void
8bdc78fc dan1999-04-17 20:25:07 +0000200Restart(char *manager, Bool abortOnFailure)
9d2e6ef9 scottc1998-09-29 22:36:29 +0000201{
202 char *prog=NULL;
203 char *argv[MAX_RESTART_ARGS];
204 int i;
205
206 if (manager && manager[0]!=0) {
6830b057 dan2004-10-12 21:28:27 +0000207 prog = argv[0] = strtok(manager, " ");
208 for (i=1; i<MAX_RESTART_ARGS; i++) {
209 argv[i]=strtok(NULL, " ");
210 if (argv[i]==NULL) {
211 break;
212 }
213 }
9d2e6ef9 scottc1998-09-29 22:36:29 +0000214 }
b147e8f8 kojima1999-04-17 18:24:23 +0000215 if (dpy) {
416e3a82 dan1999-01-25 19:06:50 +0000216#ifdef XSMP_ENABLED
6830b057 dan2004-10-12 21:28:27 +0000217 wSessionDisconnectManager();
9007a657 dan1998-11-23 11:32:19 +0000218#endif
6830b057 dan2004-10-12 21:28:27 +0000219 XCloseDisplay(dpy);
220 dpy = NULL;
b147e8f8 kojima1999-04-17 18:24:23 +0000221 }
8bdc78fc dan1999-04-17 20:25:07 +0000222 if (!prog) {
223 execvp(Arguments[0], Arguments);
224 wfatal(_("failed to restart Window Maker."));
225 } else {
226 execvp(prog, argv);
227 wsyserror(_("could not exec %s"), prog);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000228 }
8bdc78fc dan1999-04-17 20:25:07 +0000229 if (abortOnFailure)
879b00a5 kojima2004-10-13 05:09:08 +0000230 exit(7);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000231}
232
233
234
235void
236SetupEnvironment(WScreen *scr)
237{
238 char *tmp, *ptr;
239 char buf[16];
240
94f4483d kojima1999-10-27 22:32:12 +0000241 if (multiHead) {
6830b057 dan2004-10-12 21:28:27 +0000242 int len = strlen(DisplayName)+64;
243 tmp = wmalloc(len);
244 snprintf(tmp, len, "DISPLAY=%s", XDisplayName(DisplayName));
245 ptr = strchr(strchr(tmp, ':'), '.');
246 if (ptr)
247 *ptr = 0;
248 snprintf(buf, sizeof(buf), ".%i", scr->screen);
249 strcat(tmp, buf);
250 putenv(tmp);
9af1c6c4 dan1998-10-21 14:43:47 +0000251 }
252 tmp = wmalloc(60);
6830b057 dan2004-10-12 21:28:27 +0000253 snprintf(tmp, 60, "WRASTER_COLOR_RESOLUTION%i=%i", scr->screen,
254 scr->rcontext->attribs->colors_per_channel);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000255 putenv(tmp);
256}
257
258
eb87c409 kojima1999-10-20 03:25:06 +0000259
260
261typedef struct {
262 WScreen *scr;
263 char *command;
264} _tuple;
265
266
267static void
268shellCommandHandler(pid_t pid, unsigned char status, _tuple *data)
269{
270 if (status == 127) {
6830b057 dan2004-10-12 21:28:27 +0000271 char *buffer;
eb87c409 kojima1999-10-20 03:25:06 +0000272
6830b057 dan2004-10-12 21:28:27 +0000273 buffer = wstrconcat(_("Could not execute command: "), data->command);
eb87c409 kojima1999-10-20 03:25:06 +0000274
6830b057 dan2004-10-12 21:28:27 +0000275 wMessageDialog(data->scr, _("Error"), buffer, _("OK"), NULL, NULL);
276 wfree(buffer);
eb87c409 kojima1999-10-20 03:25:06 +0000277 } else if (status != 127) {
6830b057 dan2004-10-12 21:28:27 +0000278 /*
279 printf("%s: %i\n", data->command, status);
280 */
eb87c409 kojima1999-10-20 03:25:06 +0000281 }
282
497e34b6 dan2000-10-31 14:57:22 +0000283 wfree(data->command);
284 wfree(data);
eb87c409 kojima1999-10-20 03:25:06 +0000285}
286
287
288void
289ExecuteShellCommand(WScreen *scr, char *command)
290{
291 static char *shell = NULL;
292 pid_t pid;
293
294 /*
295 * This have a problem: if the shell is tcsh (not sure about others)
296 * and ~/.tcshrc have /bin/stty erase ^H somewhere on it, the shell
297 * will block and the command will not be executed.
6830b057 dan2004-10-12 21:28:27 +0000298 if (!shell) {
299 shell = getenv("SHELL");
300 if (!shell)
301 shell = "/bin/sh";
302 }
eb87c409 kojima1999-10-20 03:25:06 +0000303 */
304 shell = "/bin/sh";
305
306 pid = fork();
6830b057 dan2004-10-12 21:28:27 +0000307
eb87c409 kojima1999-10-20 03:25:06 +0000308 if (pid==0) {
309
6830b057 dan2004-10-12 21:28:27 +0000310 SetupEnvironment(scr);
eb87c409 kojima1999-10-20 03:25:06 +0000311
d4de3d0a dan2002-09-09 04:25:51 +0000312#ifdef HAVE_SETSID
313 setsid();
eb87c409 kojima1999-10-20 03:25:06 +0000314#endif
6830b057 dan2004-10-12 21:28:27 +0000315 execl(shell, shell, "-c", command, NULL);
316 wsyserror("could not execute %s -c %s", shell, command);
317 Exit(-1);
eb87c409 kojima1999-10-20 03:25:06 +0000318 } else if (pid < 0) {
6830b057 dan2004-10-12 21:28:27 +0000319 wsyserror("cannot fork a new process");
eb87c409 kojima1999-10-20 03:25:06 +0000320 } else {
6830b057 dan2004-10-12 21:28:27 +0000321 _tuple *data = wmalloc(sizeof(_tuple));
322
323 data->scr = scr;
324 data->command = wstrdup(command);
eb87c409 kojima1999-10-20 03:25:06 +0000325
6830b057 dan2004-10-12 21:28:27 +0000326 wAddDeathHandler(pid, (WDeathHandler*)shellCommandHandler, data);
eb87c409 kojima1999-10-20 03:25:06 +0000327 }
328}
329
330
331/*
332 *---------------------------------------------------------------------------
333 * StartLogShell
334 * Start a shell that will receive all stdin and stdout from processes
335 * forked by wmaker.
336 *---------------------------------------------------------------------------
337 */
338void
339StartLogShell(WScreen *scr)
340{
341 int in_fd[2];
342 int out_fd[2];
343 int err_fd[2];
344 pid_t pid;
6830b057 dan2004-10-12 21:28:27 +0000345
eb87c409 kojima1999-10-20 03:25:06 +0000346 SetupEnvironment(scr);
6830b057 dan2004-10-12 21:28:27 +0000347
eb87c409 kojima1999-10-20 03:25:06 +0000348 if (pipe(in_fd) < 0) {
6830b057 dan2004-10-12 21:28:27 +0000349 wsyserror("could not create pipe for log shell\n");
350 return;
eb87c409 kojima1999-10-20 03:25:06 +0000351 }
352 if (pipe(out_fd) < 0) {
6830b057 dan2004-10-12 21:28:27 +0000353 wsyserror("could not create pipe for log shell\n");
354 close(in_fd[0]);
355 close(in_fd[1]);
356 return;
eb87c409 kojima1999-10-20 03:25:06 +0000357 }
358 if (pipe(err_fd) < 0) {
6830b057 dan2004-10-12 21:28:27 +0000359 wsyserror("could not create pipe for log shell\n");
360 close(out_fd[0]);
361 close(out_fd[1]);
362 close(in_fd[0]);
363 close(in_fd[1]);
364 return;
eb87c409 kojima1999-10-20 03:25:06 +0000365 }
366
367 pid = fork();
368 if (pid < 0) {
6830b057 dan2004-10-12 21:28:27 +0000369 wsyserror("could not fork a new process for log shell\n");
370 return;
371 } else if (pid == 0) {
372 close(in_fd[0]);
373 close(out_fd[1]);
374 close(err_fd[1]);
375
376 close(0);
377 close(1);
378 close(2);
379
380 if (dup2(in_fd[1], 0) < 0) {
381 wsyserror("could not redirect stdin for log shell\n");
382 exit(1);
383 }
384 if (dup2(out_fd[1], 1) < 0) {
385 wsyserror("could not redirect stdout for log shell\n");
386 exit(1);
387 }
388 if (dup2(err_fd[1], 2) < 0) {
389 wsyserror("could not redirect stderr for log shell\n");
390 exit(1);
391 }
392
393 close(in_fd[1]);
394 close(out_fd[1]);
395 close(err_fd[1]);
396
397 execl("/bin/sh", "/bin/sh", "-c", wPreferences.logger_shell, NULL);
398 wsyserror("could not execute %s\n", wPreferences.logger_shell);
399 exit(1);
eb87c409 kojima1999-10-20 03:25:06 +0000400 } else {
6830b057 dan2004-10-12 21:28:27 +0000401 close(in_fd[1]);
402 close(out_fd[0]);
403 close(err_fd[0]);
404
405 LogStdIn = in_fd[1];
406 LogStdOut = out_fd[0];
407 LogStdErr = err_fd[0];
eb87c409 kojima1999-10-20 03:25:06 +0000408 }
409}
410
411
9d2e6ef9 scottc1998-09-29 22:36:29 +0000412/*
413 *---------------------------------------------------------------------
414 * wAbort--
415 * Do a major cleanup and exit the program
6830b057 dan2004-10-12 21:28:27 +0000416 *
417 *----------------------------------------------------------------------
9d2e6ef9 scottc1998-09-29 22:36:29 +0000418 */
419void
420wAbort(Bool dumpCore)
421{
422 int i;
423 WScreen *scr;
424
425 for (i=0; i<wScreenCount; i++) {
6830b057 dan2004-10-12 21:28:27 +0000426 scr = wScreenWithNumber(i);
427 if (scr)
428 RestoreDesktop(scr);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000429 }
430 printf(_("%s aborted.\n"), ProgName);
431 if (dumpCore)
6830b057 dan2004-10-12 21:28:27 +0000432 abort();
9d2e6ef9 scottc1998-09-29 22:36:29 +0000433 else
6830b057 dan2004-10-12 21:28:27 +0000434 exit(1);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000435}
436
437
438void
439print_help()
440{
931a37b1 dan1999-01-29 08:11:17 +0000441 printf(_("Usage: %s [options]\n"), ProgName);
442 puts(_("The Window Maker window manager for the X window system"));
443 puts("");
444 puts(_(" -display host:dpy display to use"));
9d2e6ef9 scottc1998-09-29 22:36:29 +0000445#ifdef USECPP
416e3a82 dan1999-01-25 19:06:50 +0000446 puts(_(" --no-cpp disable preprocessing of configuration files"));
9d2e6ef9 scottc1998-09-29 22:36:29 +0000447#endif
416e3a82 dan1999-01-25 19:06:50 +0000448 puts(_(" --no-dock do not open the application Dock"));
449 puts(_(" --no-clip do not open the workspace Clip"));
34cd5125 kojima2000-01-20 11:51:42 +0000450 puts(_(" --no-autolaunch do not autolaunch applications"));
0d7b4d63 kojima2001-01-04 23:08:40 +0000451 puts(_(" --dont-restore do not restore saved session"));
3c046182 kojima1999-09-16 02:58:56 +0000452
0d7b4d63 kojima2001-01-04 23:08:40 +0000453 puts(_(" --locale locale locale to use"));
3c046182 kojima1999-09-16 02:58:56 +0000454
6b939463 kojima2000-04-07 22:43:26 +0000455 puts(_(" --create-stdcmap create the standard colormap hint in PseudoColor visuals"));
416e3a82 dan1999-01-25 19:06:50 +0000456 puts(_(" --visual-id visualid visual id of visual to use"));
416e3a82 dan1999-01-25 19:06:50 +0000457 puts(_(" --static do not update or save configurations"));
c98f229d dan1999-04-16 01:12:45 +0000458#ifdef DEBUG
459 puts(_(" --synchronous turn on synchronous display mode"));
460#endif
416e3a82 dan1999-01-25 19:06:50 +0000461 puts(_(" --version print version and exit"));
462 puts(_(" --help show this message"));
9d2e6ef9 scottc1998-09-29 22:36:29 +0000463}
464
465
466
467void
468check_defaults()
469{
470 char *path;
471
f6682a9a kojima2004-10-20 03:31:14 +0000472 path = wdefaultspathfordomain("WindowMaker");
473
9d2e6ef9 scottc1998-09-29 22:36:29 +0000474 if (access(path, R_OK)!=0) {
80fefd29 kojima2001-09-03 22:31:30 +0000475#if 0
6830b057 dan2004-10-12 21:28:27 +0000476 wfatal(_("could not find user GNUstep directory (%s).\n"
477 "Make sure you have installed Window Maker correctly and run wmaker.inst"),
478 path);
479 exit(1);
80fefd29 kojima2001-09-03 22:31:30 +0000480#else
6830b057 dan2004-10-12 21:28:27 +0000481 wwarning(_("could not find user GNUstep directory (%s)."), path);
482
483 if (system("wmaker.inst --batch") != 0) {
484 wwarning(_("There was an error while creating GNUstep directory, please "
485 "make sure you have installed Window Maker correctly and run wmaker.inst"));
486 } else {
487 wwarning(_("%s directory created with default configuration."), path);
488 }
80fefd29 kojima2001-09-03 22:31:30 +0000489#endif
9d2e6ef9 scottc1998-09-29 22:36:29 +0000490 }
6830b057 dan2004-10-12 21:28:27 +0000491
497e34b6 dan2000-10-31 14:57:22 +0000492 wfree(path);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000493}
494
495
722c82c8 Carlos R. Mafra2008-05-02 20:01:50 -0300496/*
56d85687
RP
Rodney Padgett2008-08-09 11:39:24 +0100497 * Add watch here, used to notify if configuration
498 * files have changed, using linux kernel inotify mechanism
722c82c8 Carlos R. Mafra2008-05-02 20:01:50 -0300499 */
56d85687
RP
Rodney Padgett2008-08-09 11:39:24 +0100500
501static void
502inotifyWatchConfig()
722c82c8 Carlos R. Mafra2008-05-02 20:01:50 -0300503{
56d85687
RP
Rodney Padgett2008-08-09 11:39:24 +0100504 char *watchPath;
505 inotifyFD = inotify_init(); /* Initialise an inotify instance */
506 if (inotifyFD < 0) {
507 wwarning(_("could not initialise an inotify instance."
508 " Changes to the defaults database will require"
509 " a restart to take effect. Check your kernel!"));
510 } else {
511 watchPath = wstrconcat(wusergnusteppath(), "/Defaults");
512 /* Add the watch; really we are only looking for modify events
513 * but we might want more in the future so check all events for now.
514 * The individual events are checked for in event.c.
515 */
516 inotifyWD = inotify_add_watch (inotifyFD, watchPath, IN_ALL_EVENTS);
517 if (inotifyWD < 0) {
518 wwarning(_("could not add an inotify watch on path\n."
519 "%s\n"
520 "Changes to the defaults database will require"
521 " a restart to take effect."),watchPath);
522 close (inotifyFD);
523 }
524 }
525 wfree(watchPath);
722c82c8
CM
Carlos R. Mafra2008-05-02 20:01:50 -0300526}
527
9d2e6ef9 scottc1998-09-29 22:36:29 +0000528static void
529execInitScript()
530{
56d85687 Rodney Padgett2008-08-09 11:39:24 +0100531 char *file, *paths;
9aca0d5f dan2004-10-12 01:34:32 +0000532
533 paths = wstrconcat(wusergnusteppath(), "/Library/WindowMaker");
534 paths = wstrappend(paths, ":"DEF_CONFIG_PATHS);
39513b9f kojima1999-05-14 04:30:01 +0000535
536 file = wfindfile(paths, DEF_INIT_SCRIPT);
497e34b6 dan2000-10-31 14:57:22 +0000537 wfree(paths);
39513b9f kojima1999-05-14 04:30:01 +0000538
9d2e6ef9 scottc1998-09-29 22:36:29 +0000539 if (file) {
6830b057 dan2004-10-12 21:28:27 +0000540 if (system(file) != 0) {
541 wsyserror(_("%s:could not execute initialization script"), file);
542 }
da918281 kojima1999-04-12 02:03:58 +0000543#if 0
6830b057 dan2004-10-12 21:28:27 +0000544 if (fork()==0) {
545 execl("/bin/sh", "/bin/sh", "-c", file, NULL);
546 wsyserror(_("%s:could not execute initialization script"), file);
547 exit(1);
548 }
da918281 kojima1999-04-12 02:03:58 +0000549#endif
6830b057 dan2004-10-12 21:28:27 +0000550 wfree(file);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000551 }
552}
553
554
555void
556ExecExitScript()
557{
9aca0d5f dan2004-10-12 01:34:32 +0000558 char *file, *paths;
559
560 paths = wstrconcat(wusergnusteppath(), "/Library/WindowMaker");
561 paths = wstrappend(paths, ":"DEF_CONFIG_PATHS);
39513b9f kojima1999-05-14 04:30:01 +0000562
563 file = wfindfile(paths, DEF_EXIT_SCRIPT);
497e34b6 dan2000-10-31 14:57:22 +0000564 wfree(paths);
39513b9f kojima1999-05-14 04:30:01 +0000565
9d2e6ef9 scottc1998-09-29 22:36:29 +0000566 if (file) {
6830b057 dan2004-10-12 21:28:27 +0000567 if (system(file) != 0) {
568 wsyserror(_("%s:could not execute exit script"), file);
569 }
da918281 kojima1999-04-12 02:03:58 +0000570#if 0
6830b057 dan2004-10-12 21:28:27 +0000571 if (fork()==0) {
572 execl("/bin/sh", "/bin/sh", "-c", file, NULL);
573 wsyserror(_("%s:could not execute exit script"), file);
574 exit(1);
575 }
da918281 kojima1999-04-12 02:03:58 +0000576#endif
6830b057 dan2004-10-12 21:28:27 +0000577 wfree(file);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000578 }
579}
580
3c046182 kojima1999-09-16 02:58:56 +0000581#if 0
582char*
583getFullPath(char *path)
584{
585 char buffer[1024];
586 char *tmp;
587 char *basep = (char*)buffer;
588
589 if (*path != '/' && getcwd(buffer, 1023)) {
590
6830b057 dan2004-10-12 21:28:27 +0000591 for (;;) {
592 if (strncmp(path, "../", 3)==0) {
593 path += 3;
594 basep = strchr(basep, '/');
595 if (!basep || *path==0)
596 break;
597 }
598 }
599 if (*path == '/' || strncmp(path, "./",2)==0) {
600 tmp =
601 }
602
603 /*
604 * path
605 * ./path
606 * ../path
607 * ../../path
608 */
609
3c046182 kojima1999-09-16 02:58:56 +0000610
611 } else {
6830b057 dan2004-10-12 21:28:27 +0000612 return wstrconcat(path);
3c046182 kojima1999-09-16 02:58:56 +0000613 }
614
615 return tmp;
616}
617#endif
9d2e6ef9 scottc1998-09-29 22:36:29 +0000618
879b00a5 kojima2004-10-13 05:09:08 +0000619
9d2e6ef9 scottc1998-09-29 22:36:29 +0000620int
621main(int argc, char **argv)
622{
0d9b73cd dan2004-10-25 02:23:41 +0000623 int i_am_the_monitor, i, len;
624 char *str, *alt;
625
626 /* setup common stuff for the monitor and wmaker itself */
627 WMInitializeApplication("WindowMaker", &argc, argv);
628
629 memset(&wPreferences, 0, sizeof(WPreferences));
630
631 wPreferences.fallbackWMs = WMCreateArray(8);
632 alt = getenv("WINDOWMAKER_ALT_WM");
633 if (alt != NULL)
634 WMAddToArray(wPreferences.fallbackWMs, wstrdup(alt));
635
636 WMAddToArray(wPreferences.fallbackWMs, wstrdup("blackbox"));
637 WMAddToArray(wPreferences.fallbackWMs, wstrdup("metacity"));
638 WMAddToArray(wPreferences.fallbackWMs, wstrdup("fvwm"));
639 WMAddToArray(wPreferences.fallbackWMs, wstrdup("twm"));
640 WMAddToArray(wPreferences.fallbackWMs, NULL);
641 WMAddToArray(wPreferences.fallbackWMs, wstrdup("rxvt"));
642 WMAddToArray(wPreferences.fallbackWMs, wstrdup("xterm"));
643
644 i_am_the_monitor= 1;
645
879b00a5 kojima2004-10-13 05:09:08 +0000646 for (i= 1; i < argc; i++)
647 {
648 if (strncmp(argv[i], "--for-real", strlen("--for-real"))==0)
649 {
650 i_am_the_monitor= 0;
651 break;
652 }
0d9b73cd dan2004-10-25 02:23:41 +0000653 else if (strcmp(argv[i], "-display")==0 || strcmp(argv[i], "--display")==0)
654 {
655 i++;
656 if (i>=argc) {
657 wwarning(_("too few arguments for %s"), argv[i-1]);
658 exit(0);
659 }
660 DisplayName = argv[i];
661 }
879b00a5 kojima2004-10-13 05:09:08 +0000662 }
0d9b73cd dan2004-10-25 02:23:41 +0000663
664 DisplayName = XDisplayName(DisplayName);
665 len = strlen(DisplayName)+64;
666 str = wmalloc(len);
667 snprintf(str, len, "DISPLAY=%s", DisplayName);
668 putenv(str);
669
879b00a5 kojima2004-10-13 05:09:08 +0000670 if (i_am_the_monitor)
671 return MonitorLoop(argc, argv);
672 else
673 return real_main(argc, argv);
674}
675
676
0d9b73cd dan2004-10-25 02:23:41 +0000677static int
879b00a5 kojima2004-10-13 05:09:08 +0000678real_main(int argc, char **argv)
679{
9d2e6ef9 scottc1998-09-29 22:36:29 +0000680 int i, restart=0;
0d9b73cd dan2004-10-25 02:23:41 +0000681 char *str;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000682 int d, s;
85027098 kojima2004-10-14 19:53:31 +0000683 int flag;
c98f229d dan1999-04-16 01:12:45 +0000684#ifdef DEBUG
685 Bool doSync = False;
686#endif
34cd5125 kojima2000-01-20 11:51:42 +0000687 setlocale(LC_ALL, "");
9d2e6ef9 scottc1998-09-29 22:36:29 +0000688
416e3a82 dan1999-01-25 19:06:50 +0000689 wsetabort(wAbort);
5e4625da kojima1999-05-29 21:41:25 +0000690
691 /* for telling WPrefs what's the name of the wmaker binary being ran */
3c046182 kojima1999-09-16 02:58:56 +0000692
2bd2b72a dan2000-11-01 15:40:15 +0000693 str = wstrconcat("WMAKER_BIN_NAME=", argv[0]);
34cd5125 kojima2000-01-20 11:51:42 +0000694 putenv(str);
5e4625da kojima1999-05-29 21:41:25 +0000695
85027098 kojima2004-10-14 19:53:31 +0000696 flag= 0;
697 ArgCount = argc;
698 Arguments = wmalloc(sizeof(char*)*(ArgCount+1));
879b00a5 kojima2004-10-13 05:09:08 +0000699 for (i= 0; i < argc; i++)
85027098 kojima2004-10-14 19:53:31 +0000700 {
701 Arguments[i]= argv[i];
702 }
879b00a5 kojima2004-10-13 05:09:08 +0000703 /* add the extra option to signal that we're just restarting wmaker */
85027098 kojima2004-10-14 19:53:31 +0000704 Arguments[argc-1]= "--for-real=";
705 Arguments[argc]= NULL;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000706
9d2e6ef9 scottc1998-09-29 22:36:29 +0000707 ProgName = strrchr(argv[0],'/');
708 if (!ProgName)
6830b057 dan2004-10-12 21:28:27 +0000709 ProgName = argv[0];
9d2e6ef9 scottc1998-09-29 22:36:29 +0000710 else
6830b057 dan2004-10-12 21:28:27 +0000711 ProgName++;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000712
9007a657 dan1998-11-23 11:32:19 +0000713
9d2e6ef9 scottc1998-09-29 22:36:29 +0000714 restart = 0;
f37b4cf5 dan2002-02-01 01:20:15 +0000715
9d2e6ef9 scottc1998-09-29 22:36:29 +0000716 if (argc>1) {
6830b057 dan2004-10-12 21:28:27 +0000717 for (i=1; i<argc; i++) {
9d2e6ef9 scottc1998-09-29 22:36:29 +0000718#ifdef USECPP
6830b057 dan2004-10-12 21:28:27 +0000719 if (strcmp(argv[i], "-nocpp")==0
720 || strcmp(argv[i], "--no-cpp")==0) {
721 wPreferences.flags.nocpp=1;
722 } else
9d2e6ef9 scottc1998-09-29 22:36:29 +0000723#endif
879b00a5 kojima2004-10-13 05:09:08 +0000724 if (strcmp(argv[i], "--for-real")==0) {
725 wPreferences.flags.restarting = 0;
726 } else if (strcmp(argv[i], "--for-real=")==0) {
727 wPreferences.flags.restarting = 1;
728 } else if (strcmp(argv[i], "--for-real-")==0) {
729 wPreferences.flags.restarting = 2;
730 } else if (strcmp(argv[i], "-no-autolaunch")==0
6830b057 dan2004-10-12 21:28:27 +0000731 || strcmp(argv[i], "--no-autolaunch")==0) {
732 wPreferences.flags.noautolaunch = 1;
733 } else if (strcmp(argv[i], "-dont-restore")==0
734 || strcmp(argv[i], "--dont-restore")==0) {
735 wPreferences.flags.norestore = 1;
736 } else if (strcmp(argv[i], "-nodock")==0
737 || strcmp(argv[i], "--no-dock")==0) {
738 wPreferences.flags.nodock=1;
739 } else if (strcmp(argv[i], "-noclip")==0
740 || strcmp(argv[i], "--no-clip")==0) {
741 wPreferences.flags.noclip=1;
742 } else if (strcmp(argv[i], "-version")==0
743 || strcmp(argv[i], "--version")==0) {
744 printf("Window Maker %s\n", VERSION);
745 exit(0);
746 } else if (strcmp(argv[i], "--global_defaults_path")==0) {
747 printf("%s/WindowMaker\n", SYSCONFDIR);
748 exit(0);
c98f229d dan1999-04-16 01:12:45 +0000749#ifdef DEBUG
6830b057 dan2004-10-12 21:28:27 +0000750 } else if (strcmp(argv[i], "--synchronous")==0) {
751 doSync = 1;
c98f229d dan1999-04-16 01:12:45 +0000752#endif
6830b057 dan2004-10-12 21:28:27 +0000753 } else if (strcmp(argv[i], "-locale")==0
754 || strcmp(argv[i], "--locale")==0) {
755 i++;
756 if (i>=argc) {
757 wwarning(_("too few arguments for %s"), argv[i-1]);
758 exit(0);
759 }
760 Locale = argv[i];
761 } else if (strcmp(argv[i], "-display")==0
762 || strcmp(argv[i], "--display")==0) {
763 i++;
764 if (i>=argc) {
765 wwarning(_("too few arguments for %s"), argv[i-1]);
766 exit(0);
767 }
768 DisplayName = argv[i];
769 } else if (strcmp(argv[i], "-visualid")==0
770 || strcmp(argv[i], "--visual-id")==0) {
771 i++;
772 if (i>=argc) {
773 wwarning(_("too few arguments for %s"), argv[i-1]);
774 exit(0);
775 }
776 if (sscanf(argv[i], "%i", &wVisualID)!=1) {
777 wwarning(_("bad value for visualid: \"%s\""), argv[i]);
778 exit(0);
779 }
780 } else if (strcmp(argv[i], "-static")==0
781 || strcmp(argv[i], "--static")==0) {
782
783 wPreferences.flags.noupdates = 1;
416e3a82 dan1999-01-25 19:06:50 +0000784#ifdef XSMP_ENABLED
6830b057 dan2004-10-12 21:28:27 +0000785 } else if (strcmp(argv[i], "-clientid")==0
786 || strcmp(argv[i], "-restore")==0) {
787 i++;
788 if (i>=argc) {
789 wwarning(_("too few arguments for %s"), argv[i-1]);
790 exit(0);
791 }
9007a657 dan1998-11-23 11:32:19 +0000792#endif
6830b057 dan2004-10-12 21:28:27 +0000793 } else if (strcmp(argv[i], "--help")==0) {
794 print_help();
795 exit(0);
796 } else {
797 printf(_("%s: invalid argument '%s'\n"), argv[0], argv[i]);
798 printf(_("Try '%s --help' for more information\n"), argv[0]);
799 exit(1);
800 }
801 }
9d2e6ef9 scottc1998-09-29 22:36:29 +0000802 }
6830b057 dan2004-10-12 21:28:27 +0000803
9007a657 dan1998-11-23 11:32:19 +0000804 if (!wPreferences.flags.noupdates) {
6830b057 dan2004-10-12 21:28:27 +0000805 /* check existence of Defaults DB directory */
806 check_defaults();
9007a657 dan1998-11-23 11:32:19 +0000807 }
808
34cd5125 kojima2000-01-20 11:51:42 +0000809
9aca0d5f dan2004-10-12 01:34:32 +0000810 if (Locale) {
811 /* return of wstrconcat should not be free-ed! read putenv man page */
812 putenv(wstrconcat("LANG=", Locale));
813 } else {
814 Locale = getenv("LC_ALL");
815 if (!Locale) {
816 Locale = getenv("LANG");
817 }
9d2e6ef9 scottc1998-09-29 22:36:29 +0000818 }
34cd5125 kojima2000-01-20 11:51:42 +0000819
820 setlocale(LC_ALL, "");
821
6830b057 dan2004-10-12 21:28:27 +0000822 if (!Locale || strcmp(Locale, "C")==0 || strcmp(Locale, "POSIX")==0)
9aca0d5f dan2004-10-12 01:34:32 +0000823 Locale = NULL;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000824#ifdef I18N
825 if (getenv("NLSPATH"))
9aca0d5f dan2004-10-12 01:34:32 +0000826 bindtextdomain("WindowMaker", getenv("NLSPATH"));
9d2e6ef9 scottc1998-09-29 22:36:29 +0000827 else
9aca0d5f dan2004-10-12 01:34:32 +0000828 bindtextdomain("WindowMaker", LOCALEDIR);
73732856 dan2004-10-17 07:17:03 +0000829 bind_textdomain_codeset("WindowMaker", "UTF-8");
9d2e6ef9 scottc1998-09-29 22:36:29 +0000830 textdomain("WindowMaker");
831
832 if (!XSupportsLocale()) {
6830b057 dan2004-10-12 21:28:27 +0000833 wwarning(_("X server does not support locale"));
9d2e6ef9 scottc1998-09-29 22:36:29 +0000834 }
34cd5125 kojima2000-01-20 11:51:42 +0000835
9d2e6ef9 scottc1998-09-29 22:36:29 +0000836 if (XSetLocaleModifiers("") == NULL) {
6830b057 dan2004-10-12 21:28:27 +0000837 wwarning(_("cannot set locale modifiers"));
9d2e6ef9 scottc1998-09-29 22:36:29 +0000838 }
839#endif
9007a657 dan1998-11-23 11:32:19 +0000840
9af1c6c4 dan1998-10-21 14:43:47 +0000841 if (Locale) {
6830b057 dan2004-10-12 21:28:27 +0000842 char *ptr;
9007a657 dan1998-11-23 11:32:19 +0000843
6830b057 dan2004-10-12 21:28:27 +0000844 Locale = wstrdup(Locale);
845 ptr = strchr(Locale, '.');
846 if (ptr)
847 *ptr = 0;
9af1c6c4 dan1998-10-21 14:43:47 +0000848 }
9007a657 dan1998-11-23 11:32:19 +0000849
9d2e6ef9 scottc1998-09-29 22:36:29 +0000850 /* open display */
851 dpy = XOpenDisplay(DisplayName);
852 if (dpy == NULL) {
6830b057 dan2004-10-12 21:28:27 +0000853 wfatal(_("could not open display \"%s\""), XDisplayName(DisplayName));
854 exit(1);
9d2e6ef9 scottc1998-09-29 22:36:29 +0000855 }
856
0261c326 dan1999-01-06 15:22:33 +0000857 if (fcntl(ConnectionNumber(dpy), F_SETFD, FD_CLOEXEC) < 0) {
6830b057 dan2004-10-12 21:28:27 +0000858 wsyserror("error setting close-on-exec flag for X connection");
859 exit(1);
0261c326 dan1999-01-06 15:22:33 +0000860 }
861
e4800e84
PCPA
Paulo Cesar Pereira de Andrade2008-05-03 19:30:42 -0300862 if (wVisualID < 0)
863 /*
864 * If unspecified, use default visual instead of waiting
865 * for wrlib/context.c:bestContext() that may end up choosing
866 * the "fake" 24 bits added by the Composite extension.
867 * This is required to avoid all sort of corruptions when
868 * composite is enabled, and at a depth other than 24.
869 */
870 wVisualID = (int)DefaultVisual(dpy, DefaultScreen(dpy))->visualid;
871
9d2e6ef9 scottc1998-09-29 22:36:29 +0000872 /* check if the user specified a complete display name (with screen).
873 * If so, only manage the specified screen */
874 if (DisplayName)
6830b057 dan2004-10-12 21:28:27 +0000875 str = strchr(DisplayName, ':');
9d2e6ef9 scottc1998-09-29 22:36:29 +0000876 else
6830b057 dan2004-10-12 21:28:27 +0000877 str = NULL;
e7495baf dan1999-02-17 11:06:40 +0000878
81ccbdc7 dan2001-04-11 00:14:41 +0000879 if (str && sscanf(str, ":%i.%i", &d, &s)==2)
6830b057 dan2004-10-12 21:28:27 +0000880 multiHead = False;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000881
882 DisplayName = XDisplayName(DisplayName);
882b9a8e kojima2001-07-23 20:31:32 +0000883 {
6830b057 dan2004-10-12 21:28:27 +0000884 int len = strlen(DisplayName)+64;
885 str = wmalloc(len);
886 snprintf(str, len, "DISPLAY=%s", DisplayName);
882b9a8e kojima2001-07-23 20:31:32 +0000887 }
9d2e6ef9 scottc1998-09-29 22:36:29 +0000888 putenv(str);
889
52988491 kojima1999-03-16 11:27:01 +0000890#ifdef DEBUG
c98f229d dan1999-04-16 01:12:45 +0000891 if (doSync)
892 XSynchronize(dpy, True);
52988491 kojima1999-03-16 11:27:01 +0000893#endif
9d2e6ef9 scottc1998-09-29 22:36:29 +0000894
895 wXModifierInitialize();
896
416e3a82 dan1999-01-25 19:06:50 +0000897#ifdef XSMP_ENABLED
9007a657 dan1998-11-23 11:32:19 +0000898 wSessionConnectManager(argv, argc);
899#endif
6830b057 dan2004-10-12 21:28:27 +0000900
9d2e6ef9 scottc1998-09-29 22:36:29 +0000901 StartUp(!multiHead);
6830b057 dan2004-10-12 21:28:27 +0000902
94f4483d kojima1999-10-27 22:32:12 +0000903 if (wScreenCount==1)
6830b057 dan2004-10-12 21:28:27 +0000904 multiHead = False;
9d2e6ef9 scottc1998-09-29 22:36:29 +0000905
906 execInitScript();
56d85687 Rodney Padgett2008-08-09 11:39:24 +0100907 inotifyWatchConfig();
9d2e6ef9 scottc1998-09-29 22:36:29 +0000908 EventLoop();
909 return -1;
910}
6830b057 dan2004-10-12 21:28:27 +0000911