X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Flock.c;h=25dad5546e555e7e0a41387b0ccf7afa31318ccf;hb=481b95e2617b69e6fd4444432747d7e1e0c3dc85;hp=3fe3a1c2bc2f2a9fa64aad697e01e79bbcc38f1a;hpb=b08b6f995f8d5e0ff37d2f627bff3f61dcb75ac5;p=xscreensaver diff --git a/driver/lock.c b/driver/lock.c index 3fe3a1c2..25dad554 100644 --- a/driver/lock.c +++ b/driver/lock.c @@ -1,4 +1,5 @@ -/* xscreensaver, Copyright (c) 1993-1995 Jamie Zawinski +/* lock.c --- handling the password dialog for locking-mode. + * xscreensaver, Copyright (c) 1993-1998 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -9,211 +10,118 @@ * implied warranty. */ -/* #### If anyone ever finishes the Athena locking code, remove this. - But until then, locking requires Motif. - */ -#if defined(NO_MOTIF) && !defined(NO_LOCKING) -# define NO_LOCKING -#endif - - -#ifndef NO_LOCKING +/* Athena locking code contributed by Jon A. Christopher */ +/* Copyright 1997, with the same permissions as above. */ -#if __STDC__ -#include -#include -#include +#ifdef HAVE_CONFIG_H +# include "config.h" #endif -#ifdef HAVE_SHADOW -#include -#endif - -#include -#include +#ifndef NO_LOCKING /* whole file */ +#include #include - +#include /* for XtResizeWidget */ #include "xscreensaver.h" +#include "resources.h" -extern char *screensaver_version; -extern char *progname; -extern XtAppContext app; -extern Bool verbose_p; - -#ifdef SCO -/* SCO has some kind of goofy, nonstandard security crap. This stuff was - donated by one of their victims, I mean users, Didier Poirot . - */ -# include -# include -# include -#endif +#ifndef VMS +# include +#else /* VMS */ +extern char *getenv(const char *name); +extern int validate_user(char *name, char *password); +#endif /* VMS */ -#if !__STDC__ -# define _NO_PROTO -#endif -#ifdef NO_MOTIF +#ifdef HAVE_ATHENA +# include # include # include # include +# include -#else /* Motif */ +#else /* HAVE_MOTIF */ # include # include # include -#endif /* Motif */ - -Time passwd_timeout; +#endif /* HAVE_MOTIF */ extern Widget passwd_dialog; extern Widget passwd_form; extern Widget roger_label; extern Widget passwd_label1; extern Widget passwd_label3; -extern Widget passwd_text; -extern Widget passwd_done; extern Widget passwd_cancel; -extern create_passwd_dialog P((Widget)); -extern void ungrab_keyboard_and_mouse P((void)); - -static enum { pw_read, pw_ok, pw_fail, pw_cancel, pw_time } passwd_state; -static char typed_passwd [1024]; - -static char root_passwd [255]; -static char user_passwd [255]; - -#ifdef HAVE_SHADOW -# define PWTYPE struct spwd * -# define PWSLOT sp_pwdp -# define GETPW getspnam -#else -# define PWTYPE struct passwd * -# define PWSLOT pw_passwd -# define GETPW getpwnam -#endif +#ifdef HAVE_MOTIF +extern Widget passwd_text; +extern Widget passwd_done; +#else /* HAVE_ATHENA */ +static Widget passwd_text = 0; /* gag... */ +static Widget passwd_done = 0; +#endif /* HAVE_ATHENA */ -#ifdef SCO -# define PRPWTYPE struct pr_passwd * -# define GETPRPW getprpwnam -#endif -Bool -lock_init () -{ - Bool ok = True; - char *u; - PWTYPE p = GETPW ("root"); - -#ifdef SCO - PRPWTYPE prpwd = GETPRPW ("root"); - if (prpwd && *prpwd->ufld.fd_encrypt) - strcpy (root_passwd, prpwd->ufld.fd_encrypt); -#else /* !SCO */ - if (p && p->PWSLOT && p->PWSLOT[0] != '*') - strcpy (root_passwd, p->PWSLOT); -#endif /* !SCO */ - else - { - fprintf (stderr, "%s: couldn't get root's password\n", progname); - strcpy (root_passwd, "*"); - } - - /* It has been reported that getlogin() returns the wrong user id on some - very old SGI systems... */ - u = (char *) getlogin (); - if (u) - { -#ifdef SCO - prpwd = GETPRPW (u); -#endif /* SCO */ - p = GETPW (u); - } - else - { - /* getlogin() fails if not attached to a terminal; - in that case, use getpwuid(). */ - struct passwd *p2 = getpwuid (getuid ()); - u = p2->pw_name; -#ifdef HAVE_SHADOW - p = GETPW (u); -#else - p = p2; -#endif - } - -#ifdef SCO - if (prpwd && *prpwd->ufld.fd_encrypt) - strcpy (user_passwd, prpwd->ufld.fd_encrypt); -#else /* !SCO */ - if (p && p->PWSLOT && - /* p->PWSLOT[0] != '*' */ /* sensible */ - (strlen (p->PWSLOT) > 4) /* solaris */ - ) - strcpy (user_passwd, p->PWSLOT); -#endif /* !SCO */ - else - { - fprintf (stderr, "%s: couldn't get password of \"%s\"\n", progname, u); - strcpy (user_passwd, "*"); - ok = False; - } - return ok; -} +static enum { pw_read, pw_ok, pw_fail, pw_cancel, pw_time } passwd_state; +static char typed_passwd [80]; -#if defined(NO_MOTIF) || (XmVersion >= 1002) +#if defined(HAVE_ATHENA) || (XmVersion >= 1002) /* The `destroy' bug apears to be fixed as of Motif 1.2.1, but the `verify-callback' bug is still present. */ # define DESTROY_WORKS #endif static void -passwd_cancel_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +passwd_cancel_cb (Widget button, XtPointer client_data, XtPointer call_data) { passwd_state = pw_cancel; } + +#ifdef VMS +static Bool +vms_passwd_valid_p(char *pw) +{ + char *u = getenv("USER"); + return (validate_user (i, typed_passwd) == 1); +} +# undef passwd_valid_p +# define passwd_valid_p vms_passwd_valid_p + +#endif /* VMS */ + + static void -passwd_done_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +passwd_done_cb (Widget button, XtPointer client_data, XtPointer call_data) { if (passwd_state != pw_read) return; /* already done */ - if (!strcmp ((char *) crypt (typed_passwd, user_passwd), user_passwd)) - passwd_state = pw_ok; - /* do not allow root to have empty passwd */ - else if (typed_passwd [0] && - !strcmp ((char *) crypt (typed_passwd, root_passwd), root_passwd)) + + if (passwd_valid_p (typed_passwd)) passwd_state = pw_ok; else passwd_state = pw_fail; } -#if !defined(NO_MOTIF) && defined(VERIFY_CALLBACK_WORKS) - /* #### It looks to me like adding any modifyVerify callback causes - #### Motif 1.1.4 to free the the TextF_Value() twice. I can't see - #### the bug in the Motif source, but Purify complains, even if - #### check_passwd_cb() is a no-op. +#if defined(HAVE_MOTIF) && defined(VERIFY_CALLBACK_WORKS) + + /* It looks to me like adding any modifyVerify callback causes + Motif 1.1.4 to free the the TextF_Value() twice. I can't see + the bug in the Motif source, but Purify complains, even if + check_passwd_cb() is a no-op. - #### Update: Motif 1.2.1 also loses, but in a different way: it - #### writes beyond the end of a malloc'ed block in ModifyVerify(). - #### Probably this block is the text field's text. + Update: Motif 1.2.1 also loses, but in a different way: it + writes beyond the end of a malloc'ed block in ModifyVerify(). + Probably this block is the text field's text. */ static void -check_passwd_cb (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +check_passwd_cb (Widget button, XtPointer client_data, XtPointer call_data) { XmTextVerifyCallbackStruct *vcb = (XmTextVerifyCallbackStruct *) call_data; @@ -230,19 +138,22 @@ check_passwd_cb (button, client_data, call_data) else if (vcb->text->ptr != 0) { int i; - strncat (typed_passwd, vcb->text->ptr, vcb->text->length); - typed_passwd [vcb->endPos + vcb->text->length] = 0; + int L = vcb->text->length; + if (L >= sizeof(typed_passwd)) + L = sizeof(typed_passwd)-1; + strncat (typed_passwd, vcb->text->ptr, L); + typed_passwd [vcb->endPos + L] = 0; for (i = 0; i < vcb->text->length; i++) vcb->text->ptr [i] = '*'; } } -#else /* !VERIFY_CALLBACK_WORKS */ +# else /* HAVE_ATHENA || !VERIFY_CALLBACK_WORKS */ -static void keypress(); -static void backspace(); -static void kill_line(); -static void done(); +static void keypress (Widget w, XEvent *event, String *av, Cardinal *ac); +static void backspace (Widget w, XEvent *event, String *av, Cardinal *ac); +static void kill_line (Widget w, XEvent *event, String *av, Cardinal *ac); +static void done (Widget w, XEvent *event, String *av, Cardinal *ac); static XtActionsRec actions[] = {{"keypress", keypress}, {"backspace", backspace}, @@ -250,52 +161,59 @@ static XtActionsRec actions[] = {{"keypress", keypress}, {"done", done} }; -#if 0 /* oh fuck, why doesn't this work? */ -static char translations[] = "\ -BackSpace: backspace()\n\ -Delete: backspace()\n\ -CtrlH: backspace()\n\ -CtrlU: kill_line()\n\ -CtrlX: kill_line()\n\ -CtrlJ: done()\n\ -CtrlM: done()\n\ -: keypress()\n\ -"; -#else -static char translations[] = ":keypress()"; -#endif +# if 0 /* This works for Athena, but not Motif: keypress() gets called + for all keys anyway. So, the implementation of keypress() + has BackSpace, etc, hardcoded into it instead. FMH! + */ +static char translations[] = ("BackSpace: backspace()\n" + "Delete: backspace()\n" + "CtrlH: backspace()\n" + "CtrlU: kill_line()\n" + "CtrlX: kill_line()\n" + "CtrlJ: done()\n" + "CtrlM: done()\n" + ": keypress()\n"); +# else /* !0 */ +static char translations[] = (": keypress()\n"); +# endif /* !0 */ + static void -text_field_set_string (widget, text, position) - Widget widget; - char *text; - int position; +text_field_set_string (Widget widget, char *text, int position) { -#ifdef NO_MOTIF +#ifdef HAVE_MOTIF + XmTextFieldSetString (widget, text); + XmTextFieldSetInsertionPosition (widget, position); + +#else /* HAVE_ATHENA */ + char *buf; + int end_pos; + XawTextBlock block; block.firstPos = 0; block.length = strlen (text); block.ptr = text; block.format = 0; - XawTextReplace (widget, 0, -1, &block); + if (block.length == 0) + { + buf = XawDialogGetValueString(passwd_form); + if (buf) + end_pos = strlen(buf); + else + end_pos = -1; + } + XawTextReplace (widget, 0, end_pos, &block); XawTextSetInsertionPoint (widget, position); -#else /* !NO_MOTIF */ - XmTextFieldSetString (widget, text); - XmTextFieldSetInsertionPosition (widget, position); -#endif /* !NO_MOTIF */ +#endif /* HAVE_ATHENA */ } static void -keypress (w, event, argv, argc) - Widget w; - XEvent *event; - String *argv; - Cardinal *argc; +keypress (Widget w, XEvent *event, String *argv, Cardinal *argc) { int i, j; - char s [sizeof (typed_passwd)]; - int size = XLookupString ((XKeyEvent *) event, s, sizeof (s), 0, 0); + char s [sizeof(typed_passwd)]; + int size = XLookupString ((XKeyEvent *) event, s, sizeof(s)-1, 0, 0); if (size != 1) return; /* hack because I can't get translations to dance to my tune... */ @@ -307,6 +225,13 @@ keypress (w, event, argv, argc) if (*s == '\015') { done (w, event, argv, argc); return; } i = j = strlen (typed_passwd); + + if (i >= (sizeof(typed_passwd)-1)) + { + XBell(XtDisplay(w), 0); + return; + } + typed_passwd [i] = *s; s [++i] = 0; while (i--) @@ -316,13 +241,9 @@ keypress (w, event, argv, argc) } static void -backspace (w, event, argv, argc) - Widget w; - XEvent *event; - String *argv; - Cardinal *argc; +backspace (Widget w, XEvent *event, String *argv, Cardinal *argc) { - char s [sizeof (typed_passwd)]; + char s [sizeof(typed_passwd)]; int i = strlen (typed_passwd); int j = i; if (i == 0) @@ -336,78 +257,25 @@ backspace (w, event, argv, argc) } static void -kill_line (w, event, argv, argc) - Widget w; - XEvent *event; - String *argv; - Cardinal *argc; +kill_line (Widget w, XEvent *event, String *argv, Cardinal *argc) { - memset (typed_passwd, 0, sizeof (typed_passwd)); + memset (typed_passwd, 0, sizeof(typed_passwd)); text_field_set_string (passwd_text, "", 0); } static void -done (w, event, argv, argc) - Widget w; - XEvent *event; - String *argv; - Cardinal *argc; +done (Widget w, XEvent *event, String *argv, Cardinal *argc) { passwd_done_cb (w, 0, 0); } -#endif /* !VERIFY_CALLBACK_WORKS || NO_MOTIF */ - -static void -format_into_label (widget, string) - Widget widget; - char *string; -{ - char *label; - char buf [255]; - Arg av[10]; - int ac = 0; - -#ifdef NO_MOTIF - XtSetArg (av [ac], XtNlabel, &label); ac++; - XtGetValues (widget, av, ac); -#else /* Motif */ - XmString xm_label = 0; - XmString new_xm_label; - XtSetArg (av [ac], XmNlabelString, &xm_label); ac++; - XtGetValues (widget, av, ac); - XmStringGetLtoR (xm_label, XmSTRING_DEFAULT_CHARSET, &label); -#endif /* Motif */ - - if (!label || !strcmp (label, XtName (widget))) - strcpy (buf, "ERROR: RESOURCES ARE NOT INSTALLED CORRECTLY"); - else - sprintf (buf, label, string); - - ac = 0; +#endif /* HAVE_ATHENA || !VERIFY_CALLBACK_WORKS */ -#ifdef NO_MOTIF - XtSetArg (av [ac], XtNlabel, buf); ac++; -#else /* Motif */ - new_xm_label = XmStringCreate (buf, XmSTRING_DEFAULT_CHARSET); - XtSetArg (av [ac], XmNlabelString, new_xm_label); ac++; -#endif /* Motif */ - XtSetValues (widget, av, ac); -#ifndef NO_MOTIF - XmStringFree (new_xm_label); -#endif - XtFree (label); -} - -#if __STDC__ extern void skull (Display *, Window, GC, GC, int, int, int, int); -#endif static void -roger (button, client_data, call_data) - Widget button; - XtPointer client_data, call_data; +roger (Widget button, XtPointer client_data, XtPointer call_data) { Display *dpy = XtDisplay (button); Screen *screen = XtScreen (button); @@ -443,75 +311,112 @@ roger (button, client_data, call_data) XFreeGC (dpy, erase_gc); } -#ifdef NO_MOTIF - static void -make_passwd_dialog (parent) - Widget parent; +make_passwd_dialog (saver_info *si) { - abort (); /* #### */ -} + char *username = 0; + saver_screen_info *ssi = si->default_screen; + Widget parent = ssi->toplevel_shell; -#else /* Motif */ + if (ssi->demo_cmap && + ssi->demo_cmap != ssi->cmap && + ssi->demo_cmap != DefaultColormapOfScreen (ssi->screen)) + { + XFreeColormap (si->dpy, ssi->demo_cmap); + ssi->demo_cmap = 0; + } -static void -make_passwd_dialog (parent) - Widget parent; -{ - struct passwd *pw; - create_passwd_dialog (parent); + if (ssi->default_visual == DefaultVisualOfScreen (ssi->screen)) + ssi->demo_cmap = DefaultColormapOfScreen (ssi->screen); + else + ssi->demo_cmap = XCreateColormap (si->dpy, + RootWindowOfScreen (ssi->screen), + ssi->default_visual, AllocNone); + + create_passwd_dialog (parent, ssi->default_visual, ssi->demo_cmap); + +#ifdef HAVE_ATHENA + XtVaSetValues(passwd_form, XtNvalue, typed_passwd, 0); + + XawDialogAddButton(passwd_form,"ok", passwd_done_cb, 0); + XawDialogAddButton(passwd_form,"cancel", passwd_cancel_cb, 0); + passwd_done = XtNameToWidget(passwd_form,"ok"); + passwd_text = XtNameToWidget(passwd_form,"value"); + + XtAppAddActions(XtWidgetToApplicationContext(passwd_text), + actions, XtNumber(actions)); + XtOverrideTranslations(passwd_text, XtParseTranslationTable(translations)); + + /* Lose the label on the inner dialog. */ + { + Widget w = XtNameToWidget(passwd_form, "label"); + if (w) XtUnmanageChild(w); + } + +#else /* HAVE_MOTIF */ XtAddCallback (passwd_done, XmNactivateCallback, passwd_done_cb, 0); XtAddCallback (passwd_cancel, XmNactivateCallback, passwd_cancel_cb, 0); XtAddCallback (roger_label, XmNexposeCallback, roger, 0); -#ifdef VERIFY_CALLBACK_WORKS +# ifdef VERIFY_CALLBACK_WORKS XtAddCallback (passwd_text, XmNmodifyVerifyCallback, check_passwd_cb, 0); XtAddCallback (passwd_text, XmNactivateCallback, check_passwd_cb, 0); -#else +# else /* !VERIFY_CALLBACK_WORKS */ XtAddCallback (passwd_text, XmNactivateCallback, passwd_done_cb, 0); XtOverrideTranslations (passwd_text, XtParseTranslationTable (translations)); -#endif +# endif /* !VERIFY_CALLBACK_WORKS */ -#if !defined(NO_MOTIF) && (XmVersion >= 1002) +# if defined(HAVE_MOTIF) && (XmVersion >= 1002) /* The focus stuff changed around; this didn't exist in 1.1.5. */ XtVaSetValues (passwd_form, XmNinitialFocus, passwd_text, 0); -#endif +# endif /* HAVE_MOTIF && XmVersion >= 1002 */ /* Another random thing necessary in 1.2.1 but not 1.1.5... */ XtVaSetValues (roger_label, XmNborderWidth, 2, 0); - pw = getpwuid (getuid ()); - format_into_label (passwd_label3, (pw->pw_name ? pw->pw_name : "???")); - format_into_label (passwd_label1, screensaver_version); -} +#endif /* HAVE_MOTIF */ -#endif /* Motif */ +#ifndef VMS + { + struct passwd *pw = getpwuid (getuid ()); + username = pw->pw_name; + } +#else /* VMS -- from "R.S.Niranjan" who says + that on OpenVMS 6.1, using `struct passwd' crashes... */ + username = getenv("USER"); +#endif /* VMS */ -extern void idle_timer (); + format_into_label (passwd_label1, si->version); + format_into_label (passwd_label3, (username ? username : "???")); +} -static int passwd_idle_timer_tick; -static XtIntervalId id; +static int passwd_idle_timer_tick = -1; +static XtIntervalId passwd_idle_id; static void -passwd_idle_timer (junk1, junk2) - void *junk1; - XtPointer junk2; +passwd_idle_timer (XtPointer closure, XtIntervalId *id) { + saver_info *si = (saver_info *) closure; + saver_preferences *p = &si->prefs; + Display *dpy = XtDisplay (passwd_form); +#ifdef HAVE_ATHENA + Window window = XtWindow (passwd_form); +#else /* MOTIF */ Window window = XtWindow (XtParent(passwd_done)); +#endif /* MOTIF */ static Dimension x, y, d, s, ss; static GC gc = 0; - int max = passwd_timeout / 1000; + int max = p->passwd_timeout / 1000; - idle_timer (junk1, junk2); + idle_timer ((XtPointer) si, id); if (passwd_idle_timer_tick == max) /* first time */ { - Arg av [10]; - int ac = 0; XGCValues gcv; - unsigned long fg, bg, ts, bs; +#ifdef HAVE_MOTIF + unsigned long fg = 0, bg = 0, ts = 0, bs = 0; Dimension w = 0, h = 0; XtVaGetValues(XtParent(passwd_done), XmNwidth, &w, @@ -535,9 +440,39 @@ passwd_idle_timer (junk1, junk2) x = (w / 2); +# ifdef __sgi /* Kludge -- SGI's Motif hacks place buttons differently. */ + { + static int sgi_mode = -1; + if (sgi_mode == -1) + sgi_mode = get_boolean_resource("sgiMode", "sgiMode") ? 1 : 0; + + if (sgi_mode) + x = d; + } +# endif /* __sgi */ + x -= d/2; y += d/2; +#else /* HAVE_ATHENA */ + + Arg av [100]; + int ac = 0; + unsigned long fg = 0, bg = 0; + XtSetArg (av [ac], XtNheight, &d); ac++; + XtGetValues (passwd_done, av, ac); + ac = 0; + XtSetArg (av [ac], XtNwidth, &x); ac++; + XtSetArg (av [ac], XtNheight, &y); ac++; + XtSetArg (av [ac], XtNforeground, &fg); ac++; + XtSetArg (av [ac], XtNbackground, &bg); ac++; + XtGetValues (passwd_form, av, ac); + x -= d; + y -= d; + d -= 4; + +#endif /* HAVE_ATHENA */ + gcv.foreground = fg; if (gc) XFreeGC (dpy, gc); gc = XCreateGC (dpy, window, GCForeground, &gcv); @@ -552,29 +487,36 @@ passwd_idle_timer (junk1, junk2) if (--passwd_idle_timer_tick) { - id = XtAppAddTimeOut (app, 1000, - (XtTimerCallbackProc) passwd_idle_timer, 0); + passwd_idle_id = XtAppAddTimeOut (si->app, 1000, passwd_idle_timer, + (XtPointer) si); XFillArc (dpy, window, gc, x, y, d, d, ss, s); ss += s; } } -extern void pop_up_dialog_box (); -extern int BadWindow_ehandler (); static Bool -pop_passwd_dialog (parent) - Widget parent; +pop_passwd_dialog (saver_info *si) { + saver_preferences *p = &si->prefs; + saver_screen_info *ssi = si->default_screen; + Widget parent = ssi->toplevel_shell; Display *dpy = XtDisplay (passwd_dialog); Window focus; int revert_to; + int i; + typed_passwd [0] = 0; passwd_state = pw_read; text_field_set_string (passwd_text, "", 0); + /* In case one of the hacks has unmapped it temporarily... + Get that sucker on stage now! */ + for (i = 0; i < si->nscreens; i++) + XMapRaised(si->dpy, si->screens[i].screensaver_window); + XGetInputFocus (dpy, &focus, &revert_to); -#ifndef DESTROY_WORKS +#if defined(HAVE_MOTIF) && !defined(DESTROY_WORKS) /* This fucker blows up if we destroy the widget. I can't figure out why. The second destroy phase dereferences freed memory... So we just keep it around; but unrealizing or unmanaging it @@ -582,31 +524,60 @@ pop_passwd_dialog (parent) */ if (XtWindow (passwd_form)) XMapRaised (dpy, XtWindow (passwd_dialog)); -#endif +#endif /* HAVE_MOTIF && !DESTROY_WORKS */ - pop_up_dialog_box (passwd_dialog, passwd_form, 2); + monitor_power_on (si); + pop_up_dialog_box (passwd_dialog, passwd_form, + /* for debugging -- don't ask */ + (si->prefs.debug_p ? 69 : 0) + + 2); XtManageChild (passwd_form); -#if !defined(NO_MOTIF) && (XmVersion < 1002) +#ifdef HAVE_ATHENA + steal_focus_and_colormap (passwd_text); + + /* For some reason, the passwd_form box is not stretching all the way + to the right edge of the window, despite being XtChainRight. + So... resize it by hand. + */ + { + Dimension x=0, w=0, h=0; + XtVaGetValues(passwd_form, XtNx, &x, XtNwidth, &w, XtNheight, &h, 0); + XtVaGetValues(XtParent(passwd_form), XtNwidth, &w, 0); + w -= x; + w -= 6; + if (w > 0) XtResizeWidget(passwd_form, w, h, 0); + } + +#endif /* HAVE_ATHENA */ + + +#if defined(HAVE_MOTIF) && (XmVersion < 1002) /* The focus stuff changed around; this causes problems in 1.2.1 but is necessary in 1.1.5. */ XmProcessTraversal (passwd_text, XmTRAVERSE_CURRENT); -#endif +#endif /* HAVE_MOTIF && XmVersion < 1002 */ - passwd_idle_timer_tick = passwd_timeout / 1000; - id = XtAppAddTimeOut (app, 1000, (XtTimerCallbackProc) passwd_idle_timer, 0); + passwd_idle_timer_tick = p->passwd_timeout / 1000; + passwd_idle_id = XtAppAddTimeOut (si->app, 1000, passwd_idle_timer, + (XtPointer) si); +#ifdef HAVE_ATHENA + if (roger_label) + roger(roger_label, 0, 0); +#endif /* HAVE_ATHENA */ - XGrabServer (dpy); /* ############ DANGER! */ + if (!si->prefs.debug_p) + XGrabServer (dpy); /* ############ DANGER! */ /* this call to ungrab used to be in main_loop() - see comment in - xscreensaver.c around line 696. */ - ungrab_keyboard_and_mouse (); + xscreensaver.c around line 857. */ + ungrab_keyboard_and_mouse (si); while (passwd_state == pw_read) { XEvent event; - XtAppNextEvent (app, &event); + XtAppNextEvent (si->app, &event); /* wait for timer event */ if (event.xany.type == 0 && passwd_idle_timer_tick == 0) passwd_state = pw_time; @@ -616,7 +587,7 @@ pop_passwd_dialog (parent) XSync (dpy, False); /* ###### (danger over) */ if (passwd_state != pw_time) - XtRemoveTimeOut (id); + XtRemoveTimeOut (passwd_idle_id); if (passwd_state != pw_ok) { @@ -628,19 +599,24 @@ pop_passwd_dialog (parent) case pw_cancel: lose = 0; break; default: abort (); } -#ifndef NO_MOTIF + +#ifdef HAVE_MOTIF XmProcessTraversal (passwd_cancel, 0); /* turn off I-beam */ -#endif +#else /* HAVE_ATHENA */ + steal_focus_and_colormap (passwd_done); +#endif /* HAVE_ATHENA */ + if (lose) { text_field_set_string (passwd_text, lose, strlen (lose) + 1); + passwd_idle_timer_tick = 1; - id = XtAppAddTimeOut (app, 3000, - (XtTimerCallbackProc) passwd_idle_timer, 0); + passwd_idle_id = XtAppAddTimeOut (si->app, 3000, passwd_idle_timer, + (XtPointer) si); while (1) { XEvent event; - XtAppNextEvent (app, &event); + XtAppNextEvent (si->app, &event); if (event.xany.type == 0 && /* wait for timer event */ passwd_idle_timer_tick == 0) break; @@ -648,19 +624,18 @@ pop_passwd_dialog (parent) } } } - memset (typed_passwd, 0, sizeof (typed_passwd)); + memset (typed_passwd, 0, sizeof(typed_passwd)); text_field_set_string (passwd_text, "", 0); XtSetKeyboardFocus (parent, None); #ifdef DESTROY_WORKS XtDestroyWidget (passwd_dialog); passwd_dialog = 0; -#else +#else /* !DESTROY_WORKS */ XUnmapWindow (XtDisplay (passwd_dialog), XtWindow (passwd_dialog)); -#endif +#endif /* !DESTROY_WORKS */ { - int (*old_handler) (); - old_handler = XSetErrorHandler (BadWindow_ehandler); + XErrorHandler old_handler = XSetErrorHandler (BadWindow_ehandler); /* I don't understand why this doesn't refocus on the old selected window when MWM is running in click-to-type mode. The value of `focus' seems to be correct. */ @@ -669,25 +644,36 @@ pop_passwd_dialog (parent) XSetErrorHandler (old_handler); } + /* Since we installed our colormap to display the dialog properly, put + the old one back, so that the screensaver_window is now displayed + properly. */ + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + if (ssi->cmap) + XInstallColormap (si->dpy, ssi->cmap); + } + return (passwd_state == pw_ok ? True : False); } Bool -unlock_p (parent) - Widget parent; +unlock_p (saver_info *si) { static Bool initted = False; if (! initted) { + #ifndef VERIFY_CALLBACK_WORKS - XtAppAddActions (app, actions, XtNumber (actions)); -#endif + XtAppAddActions (si->app, actions, XtNumber (actions)); +#endif /* !VERIFY_CALLBACK_WORKS */ + passwd_dialog = 0; initted = True; } if (! passwd_dialog) - make_passwd_dialog (parent); - return pop_passwd_dialog (parent); + make_passwd_dialog (si); + return pop_passwd_dialog (si); } -#endif /* !NO_LOCKING */ +#endif /* !NO_LOCKING -- whole file */