From c98f229d9c963257622cbd1e84819409c0e815c0 Mon Sep 17 00:00:00 2001 From: dan Date: Fri, 16 Apr 1999 01:12:45 +0000 Subject: [PATCH] Added the crash dialog panel --- ChangeLog | 4 + NEWS | 16 ++ WindowMaker/Styles/Makefile.in | 2 +- configure | 2 +- src/actions.c | 4 +- src/appicon.c | 1 + src/application.c | 1 + src/defaults.c | 1 + src/dock.c | 1 + src/dock.h | 1 + src/list.c | 3 +- src/main.c | 18 +- src/menu.c | 1 + src/rootmenu.c | 1 + src/stacking.c | 1 + src/startup.c | 321 +++++++++++++++++++++++++++++++-- src/superfluous.c | 1 + src/winspector.c | 1 + 18 files changed, 353 insertions(+), 27 deletions(-) diff --git a/ChangeLog b/ChangeLog index 7f16f2d8..75163bed 100644 --- a/ChangeLog +++ b/ChangeLog @@ -20,6 +20,10 @@ Changes since version 0.52.0: - added ResizebarBack and added appropriate backwards compat. hacks in setstyle - applied ]d's patch to allow DEMATERIALIZE_ICON over windows - made clip arrows gradiented +- added a crashing dialog panel to select what to do on crashes. +- fixed the problem with showing a window as focused in the window list menu + while it was on another workspace. + Changes since version 0.51.2: ............................. diff --git a/NEWS b/NEWS index ae1bab92..a1bd69f6 100644 --- a/NEWS +++ b/NEWS @@ -33,6 +33,22 @@ will automatically hack it so that wmaker will make the theme work like before. +New crash dialog panel +---------------------- + +From now on, whenever a fatal situation appears, Window Maker will display a +dialog panel to the user and let him choose what to do. +The options are: +- Abort and leave a core file (usefull for debugging and getting backtraces) +- Restart Window Maker (default behaviour) +- Start alternate window manager (the one defined as fallback, or if not + possible fvwm or twm in this order). + +If it will not be able to restart or start the alternate window manager, it +will abort and leave the core file. + + + --- 0.52.0 diff --git a/WindowMaker/Styles/Makefile.in b/WindowMaker/Styles/Makefile.in index e21e2e49..8c387c25 100755 --- a/WindowMaker/Styles/Makefile.in +++ b/WindowMaker/Styles/Makefile.in @@ -90,7 +90,7 @@ wprefsdir = @wprefsdir@ prefsdatadir = $(pkgdatadir)/Styles -prefsdata_DATA = Autumn.style Black.style BlackTexture.style Blue.style BlueDawn.style BlueishGreen.style Brown.style Chumbo.style Copper.style DarkBlue.style DarkRed.style Fire.style Food.style Golden.style Green.style GreyBlue.style Gtk.style LightBlue.style Pastel.style Purple.style Red.style RednBlue.style Summer.style Traditional.style VioletBlue.style +prefsdata_DATA = Autumn.style Black.style BlackTexture.style Blue.style BlueDawn.style BlueishGreen.style Brown.style Chumbo.style Copper.style DarkBlue.style DarkRed.style Fire.style Food.style Golden.style Green.style GreyBlue.style Gtk.style LightBlue.style Pastel.style Pink.style Pumpkin.style Purple.style Red.style RednBlue.style Summer.style Traditional.style VioletBlue.style EXTRA_DIST = $(prefsdata_DATA) diff --git a/configure b/configure index 0d85a6bf..ef70b297 100755 --- a/configure +++ b/configure @@ -751,7 +751,7 @@ fi PACKAGE=WindowMaker -VERSION=0.53.0 +VERSION=0.52.1 if test "`cd $srcdir && pwd`" != "`pwd`" && test -f $srcdir/config.status; then { echo "configure: error: source directory already configured; run "make distclean" there first" 1>&2; exit 1; } diff --git a/src/actions.c b/src/actions.c index 8dbf5ef7..d24216c7 100644 --- a/src/actions.c +++ b/src/actions.c @@ -3,6 +3,7 @@ * Window Maker window manager * * Copyright (c) 1997, 1998 Alfredo K. Kojima + * Copyright (c) 1998 Dan Pascu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -1016,7 +1017,8 @@ wIconifyWindow(WWindow *wwin) tmp = wwin->prev; while (tmp) { if (!WFLAGP(tmp, no_focusable) - && !(tmp->flags.hidden||tmp->flags.miniaturized)) + && !(tmp->flags.hidden||tmp->flags.miniaturized) + && (wwin->frame->workspace == tmp->frame->workspace)) break; tmp = tmp->prev; } diff --git a/src/appicon.c b/src/appicon.c index 026475f7..f79072be 100644 --- a/src/appicon.c +++ b/src/appicon.c @@ -3,6 +3,7 @@ * Window Maker window manager * * Copyright (c) 1997, 1998 Alfredo K. Kojima + * Copyright (c) 1998 Dan Pascu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/application.c b/src/application.c index 83813dcf..9386cce9 100644 --- a/src/application.c +++ b/src/application.c @@ -2,6 +2,7 @@ * Window Maker window manager * * Copyright (c) 1997, 1998 Alfredo K. Kojima + * Copyright (c) 1998 Dan Pascu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/defaults.c b/src/defaults.c index 9e3068a2..e1c5507a 100644 --- a/src/defaults.c +++ b/src/defaults.c @@ -3,6 +3,7 @@ * Window Maker window manager * * Copyright (c) 1997, 1998 Alfredo K. Kojima + * Copyright (c) 1998 Dan Pascu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/dock.c b/src/dock.c index 0cc562ec..9179773e 100644 --- a/src/dock.c +++ b/src/dock.c @@ -3,6 +3,7 @@ * Window Maker window manager * * Copyright (c) 1997, 1998 Alfredo K. Kojima + * Copyright (c) 1998, 1999 Dan Pascu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/dock.h b/src/dock.h index 9add37c4..d49737a6 100644 --- a/src/dock.h +++ b/src/dock.h @@ -3,6 +3,7 @@ * Window Maker window manager * * Copyright (c) 1997, 1998 Alfredo K. Kojima + * Copyright (c) 1998 Dan Pascu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/list.c b/src/list.c index 9fa59e6f..745ae141 100644 --- a/src/list.c +++ b/src/list.c @@ -5,7 +5,8 @@ Author: Kresten Krab Thorup Many modifications by Alfredo K. Kojima - +Some fixes and additions by Dan Pascu + This file is part of GNU CC. diff --git a/src/main.c b/src/main.c index 76258786..6894b831 100644 --- a/src/main.c +++ b/src/main.c @@ -58,6 +58,9 @@ Display *dpy; +char **Arguments; +int ArgCount; + char *ProgName; unsigned int ValidModMask = 0xff; @@ -148,8 +151,6 @@ int wVisualID = -1; /******** End Global Variables *****/ static char *DisplayName = NULL; -static char **Arguments; -static int ArgCount; extern void EventLoop(); extern void StartUp(); @@ -267,6 +268,9 @@ print_help() */ puts(_(" --visual-id visualid visual id of visual to use")); puts(_(" --static do not update or save configurations")); +#ifdef DEBUG + puts(_(" --synchronous turn on synchronous display mode")); +#endif puts(_(" --version print version and exit")); puts(_(" --help show this message")); } @@ -342,6 +346,9 @@ main(int argc, char **argv) Bool multiHead = True; char *str; int d, s; +#ifdef DEBUG + Bool doSync = False; +#endif wsetabort(wAbort); @@ -383,6 +390,10 @@ main(int argc, char **argv) } else if (strcmp(argv[i], "--global_defaults_path")==0) { puts(SYSCONFDIR); exit(0); +#ifdef DEBUG + } else if (strcmp(argv[i], "--synchronous")==0) { + doSync = 1; +#endif } else if (strcmp(argv[i], "-locale")==0 || strcmp(argv[i], "--locale")==0) { i++; @@ -515,7 +526,8 @@ main(int argc, char **argv) putenv(str); #ifdef DEBUG - XSynchronize(dpy, True); + if (doSync) + XSynchronize(dpy, True); #endif wXModifierInitialize(); diff --git a/src/menu.c b/src/menu.c index d10f445b..896e1edc 100644 --- a/src/menu.c +++ b/src/menu.c @@ -3,6 +3,7 @@ * Window Maker window manager * * Copyright (c) 1997, 1998 Alfredo K. Kojima + * Copyright (c) 1997, 1998 Dan Pascu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/rootmenu.c b/src/rootmenu.c index 86f27eed..86a1feb4 100644 --- a/src/rootmenu.c +++ b/src/rootmenu.c @@ -3,6 +3,7 @@ * Window Maker window manager * * Copyright (c) 1997, 1998 Alfredo K. Kojima + * Copyright (c) 1998 Dan Pascu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/stacking.c b/src/stacking.c index 6c6dbcc5..3f9e706f 100644 --- a/src/stacking.c +++ b/src/stacking.c @@ -2,6 +2,7 @@ * Window Maker window manager * * Copyright (c) 1997, 1998 Alfredo K. Kojima + * Copyright (c) 1998 Dan Pascu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/startup.c b/src/startup.c index e782e864..a315658a 100644 --- a/src/startup.c +++ b/src/startup.c @@ -2,6 +2,7 @@ * Window Maker window manager * * Copyright (c) 1997, 1998 Alfredo K. Kojima + * Copyright (c) 1999 Dan Pascu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -76,6 +77,8 @@ extern const char * const sys_siglist[]; /****** Global Variables ******/ +extern char **Arguments; + extern WPreferences wPreferences; extern WDDomain *WDWindowMaker; @@ -154,6 +157,256 @@ static void manageAllWindows(); extern void NotifyDeadProcess(pid_t pid, unsigned char status); +typedef struct _CrashPanel { + WMWindow *win; /* main window */ + + WMLabel *iconL; /* application icon */ + WMLabel *nameL; /* title of panel */ + + WMFrame *sepF; /* separator frame */ + + WMLabel *noteL; /* Title of note */ + WMLabel *note2L; /* body of note with what happened */ + + WMFrame *whatF; /* "what to do next" frame */ + WMPopUpButton *whatP; /* action selection popup button */ + + WMButton *okB; /* ok button */ + + Bool done; /* if finished with this dialog */ + int action; /* what to do after */ + + KeyCode retKey; + +} CrashPanel; + + +enum { + WMAbort=0, + WMRestart, + WMStartAlternate +}; + + +static void +handleKeyPress(XEvent *event, void *clientData) +{ + CrashPanel *panel = (CrashPanel*)clientData; + + if (event->xkey.keycode == panel->retKey) { + WMPerformButtonClick(panel->okB); + } +} + + +static void +buttonCallback(void *self, void *clientData) +{ + CrashPanel *panel = (CrashPanel*)clientData; + + panel->done = True; +} + + +static void +setAction(void *self, void *clientData) +{ + WMPopUpButton *pop = (WMPopUpButton*)self; + CrashPanel *panel = (CrashPanel*)clientData; + + panel->action = WMGetPopUpButtonSelectedItem(pop); +} + + +static WMPixmap* +getWindowMakerIconImage(WMScreen *scr) +{ + proplist_t dict, key, option, value=NULL; + WMPixmap *pix=NULL; + char *path; + + PLSetStringCmpHook(NULL); + + key = PLMakeString("Logo.WMPanel"); + option = PLMakeString("Icon"); + + dict = PLGetDictionaryEntry(WDWindowAttributes->dictionary, key); + + if (dict) { + value = PLGetDictionaryEntry(dict, option); + } + + PLRelease(key); + PLRelease(option); + + PLSetStringCmpHook(StringCompareHook); + + if (value && PLIsString(value)) { + path = FindImage(wPreferences.icon_path, PLGetString(value)); + + if (path) { + RImage *image; + + image = RLoadImage(WMScreenRContext(scr), path, 0); + if (image) { + pix = WMCreatePixmapFromRImage(scr, image, 0); + RDestroyImage(image); + } + free(path); + } + } + + return pix; +} + + +#define PWIDTH 295 +#define PHEIGHT 345 + + +static int +showCrashPanel(int whatSig) +{ + CrashPanel *panel; + WMScreen *scr; + WMFont *font; + WMPixmap *logo; + Display *newdpy; + int screen_no, scr_width, scr_height; + int action; + char buf[256]; + + panel = wmalloc(sizeof(CrashPanel)); + memset(panel, 0, sizeof(CrashPanel)); + + /* Close the X connection and open a new one. This is to avoid messing + * Xlib because we call to Xlib functions in a signal handler. + */ + XCloseDisplay(dpy); + newdpy = XOpenDisplay(""); + if (!newdpy) { + wfatal(_("cannot open connection for crashing dialog panel. Aborting.")); + return WMAbort; + } + + screen_no = DefaultScreen(newdpy); + scr_width = WidthOfScreen(ScreenOfDisplay(newdpy, screen_no)); + scr_height = HeightOfScreen(ScreenOfDisplay(newdpy, screen_no)); + + scr = WMCreateScreen(newdpy, screen_no); + if (!scr) { + wfatal(_("cannot open connection for crashing dialog panel. Aborting.")); + return WMAbort; + } + + panel->retKey = XKeysymToKeycode(newdpy, XK_Return); + + panel->win = WMCreateWindow(scr, "crashingDialog"); + WMResizeWidget(panel->win, PWIDTH, PHEIGHT); + WMMoveWidget(panel->win, (scr_width - PWIDTH)/2, (scr_height - PHEIGHT)/2); + + logo = getWindowMakerIconImage(scr); + if (logo) { + panel->iconL = WMCreateLabel(panel->win); + WMResizeWidget(panel->iconL, 64, 64); + WMMoveWidget(panel->iconL, 10, 10); + WMSetLabelImagePosition(panel->iconL, WIPImageOnly); + WMSetLabelImage(panel->iconL, logo); + } + + panel->nameL = WMCreateLabel(panel->win); + WMResizeWidget(panel->nameL, 190, 18); + WMMoveWidget(panel->nameL, 80, 35); + WMSetLabelTextAlignment(panel->nameL, WALeft); + font = WMBoldSystemFontOfSize(scr, 18); + WMSetLabelFont(panel->nameL, font); + WMReleaseFont(font); + WMSetLabelText(panel->nameL, _("Fatal error")); + + panel->sepF = WMCreateFrame(panel->win); + WMResizeWidget(panel->sepF, PWIDTH+4, 2); + WMMoveWidget(panel->sepF, -2, 80); + + panel->noteL = WMCreateLabel(panel->win); + WMResizeWidget(panel->noteL, PWIDTH-20, 40); + WMMoveWidget(panel->noteL, 10, 90); + WMSetLabelTextAlignment(panel->noteL, WAJustified); +#ifdef SYS_SIGLIST_DECLARED + sprintf(buf, _("Window Maker received signal %i\n(%s)."), + whatSig, sys_siglist[whatSig]); +#else + sprintf(buf, _("Window Maker received signal %i."), whatSig); +#endif + WMSetLabelText(panel->noteL, buf); + + panel->note2L = WMCreateLabel(panel->win); + WMResizeWidget(panel->note2L, PWIDTH-20, 100); + WMMoveWidget(panel->note2L, 10, 130); + WMSetLabelTextAlignment(panel->note2L, WALeft); + WMSetLabelText(panel->note2L, + _(" This fatal error occured probably due to a bug." + " Please fill the included BUGFORM and " + "report it to bugs@windowmaker.org.")); + + + panel->whatF = WMCreateFrame(panel->win); + WMResizeWidget(panel->whatF, PWIDTH-20, 50); + WMMoveWidget(panel->whatF, 10, 240); + WMSetFrameTitle(panel->whatF, _("What do you want to do now?")); + + panel->whatP = WMCreatePopUpButton(panel->whatF); + WMResizeWidget(panel->whatP, PWIDTH-20-70, 20); + WMMoveWidget(panel->whatP, 35, 20); + WMSetPopUpButtonPullsDown(panel->whatP, False); + WMSetPopUpButtonText(panel->whatP, _("Select action")); + WMAddPopUpButtonItem(panel->whatP, _("Abort and leave a core file")); + WMAddPopUpButtonItem(panel->whatP, _("Restart Window Maker")); + WMAddPopUpButtonItem(panel->whatP, _("Start alternate window manager")); + WMSetPopUpButtonAction(panel->whatP, setAction, panel); + WMSetPopUpButtonSelectedItem(panel->whatP, WMRestart); + panel->action = WMRestart; + + WMMapSubwidgets(panel->whatF); + + panel->okB = WMCreateCommandButton(panel->win); + WMResizeWidget(panel->okB, 80, 26); + WMMoveWidget(panel->okB, 205, 309); + WMSetButtonText(panel->okB, _("OK")); + WMSetButtonImage(panel->okB, WMGetSystemPixmap(scr, WSIReturnArrow)); + WMSetButtonAltImage(panel->okB, WMGetSystemPixmap(scr, WSIHighlightedReturnArrow)); + WMSetButtonImagePosition(panel->okB, WIPRight); + WMSetButtonAction(panel->okB, buttonCallback, panel); + + panel->done = 0; + + WMCreateEventHandler(WMWidgetView(panel->win), KeyPressMask, + handleKeyPress, panel); + + WMRealizeWidget(panel->win); + WMMapSubwidgets(panel->win); + + WMMapWidget(panel->win); + + XSetInputFocus(newdpy, WMWidgetXID(panel->win), RevertToParent, CurrentTime); + + while (!panel->done) { + XEvent event; + + WMNextEvent(newdpy, &event); + WMHandleEvent(&event); + } + + action = panel->action; + + WMUnmapWidget(panel->win); + WMDestroyWidget(panel->win); + free(panel); + XCloseDisplay(newdpy); + + return action; +} + + static int catchXError(Display *dpy, XErrorEvent *error) { @@ -241,6 +494,7 @@ handleSig(int sig) static int already_crashed = 0; int dumpcore = 0; #ifndef NO_EMERGENCY_AUTORESTART + int crashAction; char *argv[2]; argv[1] = NULL; @@ -259,7 +513,6 @@ handleSig(int sig) #endif WCHANGE_STATE(WSTATE_NEED_RESTART); - /* setup idle handler, so that this will be handled when * the select() is returned becaused of the signal, even if * there are no X events in the queue */ @@ -290,31 +543,41 @@ handleSig(int sig) wfatal(_("got signal %i\n"), sig); #endif + /* Setting the signal behaviour back to default and then reraising the + * signal is a cleaner way to make program exit and core dump than calling + * abort(), since it correctly returns from the signal handler and sets + * the flags accordingly. -Dan + */ if (sig==SIGSEGV || sig==SIGFPE || sig==SIGBUS || sig==SIGILL || sig==SIGABRT) { if (already_crashed) { wfatal(_("crashed while trying to do some post-crash cleanup. Aborting immediatelly.")); -#ifndef NO_EMERGENCY_AUTORESTART - exit(1); -#else - abort(); -#endif + signal(sig, SIG_DFL); + raise(sig); + return; } already_crashed = 1; dumpcore = 1; - wfatal(_("a fatal error has occured, probably due to a bug. " - "Please fill the included BUGFORM and report it.")); - #ifndef NO_EMERGENCY_AUTORESTART - /* restart another window manager so that the X session doesn't - * go to space */ + crashAction = showCrashPanel(sig); - wwarning(_("trying to start alternative window manager...")); - if (dpy) - XCloseDisplay(dpy); - dpy = NULL; + if (crashAction == WMAbort) { + signal(sig, SIG_DFL); + raise(sig); + return; + } + + if (crashAction == WMRestart) { + /* we try to restart Window Maker */ + wwarning(_("trying to restart Window Maker...")); + execvp(Arguments[0], Arguments); + wwarning(_("we failed to restart Window Maker.")); + /* fallback to alternate window manager then */ + } + + wwarning(_("trying to start alternate window manager...")); argv[0] = FALLBACK_WINDOWMANAGER; execvp(FALLBACK_WINDOWMANAGER, argv); @@ -323,8 +586,18 @@ handleSig(int sig) execvp("fvwm", argv); argv[0] = "twm"; - execvp("twm", argv); + execvp("twm", argv); + + wfatal(_("failed to start alternate window manager. Aborting.")); +#else + wfatal(_("a fatal error has occured, probably due to a bug. " + "Please fill the included BUGFORM and report it.")); #endif /* !NO_EMERGENCY_AUTORESTART */ + + signal(sig, SIG_DFL); + raise(sig); + return; + } wAbort(dumpcore); @@ -702,9 +975,7 @@ StartUp(Bool defaultScreenOnly) sigaction(SIGSEGV, &sig_action, NULL); sigaction(SIGBUS, &sig_action, NULL); sigaction(SIGFPE, &sig_action, NULL); -#ifndef NO_EMERGENCY_AUTORESTART sigaction(SIGABRT, &sig_action, NULL); -#endif /* Here we set SA_RESTART for safety, because SIGUSR1 may not be handled * immediately. @@ -722,6 +993,17 @@ StartUp(Bool defaultScreenOnly) sig_action.sa_flags = SA_NOCLDSTOP|SA_RESTART; sigaction(SIGCHLD, &sig_action, NULL); + /* Now we unblock all signals, that may have been blocked by the parent + * who exec()-ed us. This can happen for example if Window Maker crashes + * and restarts itself or another window manager from the signal handler. + * In this case, the new proccess inherits the blocked signal mask and + * will no longer react to that signal, until unblocked. + * This is because the signal handler of the proccess who crashed (parent) + * didn't return, and the signal remained blocked. -Dan + */ + sigfillset(&sig_action.sa_mask); + sigprocmask(SIG_UNBLOCK, &sig_action.sa_mask, NULL); + /* handle X shutdowns a such */ XSetIOErrorHandler(handleXIO); @@ -761,7 +1043,6 @@ StartUp(Bool defaultScreenOnly) XSetErrorHandler((XErrorHandler)catchXError); - /* Sound init */ #ifdef SHAPE /* ignore j */ wShapeSupported = XShapeQueryExtension(dpy, &wShapeEventBase, &j); @@ -781,7 +1062,7 @@ StartUp(Bool defaultScreenOnly) if (defaultScreenOnly || max==1) { wScreen[wScreenCount] = wScreenInit(DefaultScreen(dpy)); if (!wScreen[wScreenCount]) { - wfatal(_("it seems that there already is a window manager running")); + wfatal(_("it seems that there is already a window manager running")); Exit(1); } } else { diff --git a/src/superfluous.c b/src/superfluous.c index e9d78894..3596650b 100644 --- a/src/superfluous.c +++ b/src/superfluous.c @@ -2,6 +2,7 @@ * Window Maker window manager * * Copyright (c) 1997, 1998 Alfredo K. Kojima + * Copyright (c) 1997, 1998 Dan Pascu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by diff --git a/src/winspector.c b/src/winspector.c index 09b9fb90..3620d2c6 100644 --- a/src/winspector.c +++ b/src/winspector.c @@ -3,6 +3,7 @@ * Window Maker window manager * * Copyright (c) 1997, 1998 Alfredo K. Kojima + * Copyright (c) 1998 Dan Pascu * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by