X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Fwindows.c;h=1ec24e4e4af2fecdad427bf8f7900d172163edeb;hb=0bd2eabab3e404c6769fe8f59b639275e960c415;hp=37702a10ab30513adb58c7a8065d126304fac100;hpb=df053bcb240bd8d82e3bebf48a9766a8728bca4b;p=xscreensaver diff --git a/driver/windows.c b/driver/windows.c index 37702a10..1ec24e4e 100644 --- a/driver/windows.c +++ b/driver/windows.c @@ -65,7 +65,7 @@ extern int kill (pid_t, int); /* signal() is in sys/signal.h... */ Atom XA_VROOT, XA_XSETROOT_ID; -Atom XA_SCREENSAVER_VERSION, XA_SCREENSAVER_ID; +Atom XA_SCREENSAVER, XA_SCREENSAVER_VERSION, XA_SCREENSAVER_ID; Atom XA_SCREENSAVER_TIME; @@ -90,8 +90,11 @@ grab_kbd(saver_info *si, Window w) but these seem to work... */ GrabModeSync, GrabModeAsync, CurrentTime); + if (status == GrabSuccess) + si->keyboard_grab_window = w; + if (p->debug_p) - fprintf(real_stderr, "%s: XGrabKeyboard(... 0x%x ...) ==> %s\n", + fprintf(stderr, "%s: XGrabKeyboard(... 0x%x ...) ==> %s\n", progname, (unsigned long) w, (status == GrabSuccess ? "GrabSuccess" : status == AlreadyGrabbed ? "AlreadyGrabbed" : @@ -103,6 +106,26 @@ grab_kbd(saver_info *si, Window w) return status; } +static const char * +grab_string(int status) +{ + switch (status) + { + case GrabSuccess: return "GrabSuccess"; break; + case AlreadyGrabbed: return "AlreadyGrabbed"; break; + case GrabInvalidTime: return "GrabInvalidTime"; break; + case GrabNotViewable: return "GrabNotViewable"; break; + case GrabFrozen: return "GrabFrozen"; break; + default: + { + static char foo[255]; + sprintf(foo, "unknown status: %d", status); + return foo; + } + } +} + + static int grab_mouse (saver_info *si, Window w, Cursor cursor) { @@ -110,19 +133,41 @@ grab_mouse (saver_info *si, Window w, Cursor cursor) int status = XGrabPointer (si->dpy, w, True, ALL_POINTER_EVENTS, GrabModeAsync, GrabModeAsync, None, cursor, CurrentTime); + if (status == GrabSuccess) + si->mouse_grab_window = w; + if (p->debug_p) - fprintf(real_stderr, "%s: XGrabPointer(... 0x%x, 0x%x ...) ==> %s\n", + fprintf(stderr, "%s: XGrabPointer(... 0x%x, 0x%x ...) ==> %s\n", progname, (unsigned long) w, (unsigned long) cursor, - (status == GrabSuccess ? "GrabSuccess" : - status == AlreadyGrabbed ? "AlreadyGrabbed" : - status == GrabInvalidTime ? "GrabInvalidTime" : - status == GrabNotViewable ? "GrabNotViewable" : - status == GrabFrozen ? "GrabFrozen" : - "???")); + grab_string(status)); return status; } +static void +ungrab_kbd(saver_info *si) +{ + saver_preferences *p = &si->prefs; + XUngrabKeyboard(si->dpy, CurrentTime); + if (p->debug_p) + fprintf(stderr, "%s: XUngrabKeyboard (was 0x%x)\n", progname, + (unsigned long) si->keyboard_grab_window); + si->keyboard_grab_window = 0; +} + + +static void +ungrab_mouse(saver_info *si) +{ + saver_preferences *p = &si->prefs; + XUngrabPointer(si->dpy, CurrentTime); + if (p->debug_p) + fprintf(stderr, "%s: XUngrabPointer (was 0x%x)\n", progname, + (unsigned long) si->mouse_grab_window); + si->mouse_grab_window = 0; +} + + void grab_keyboard_and_mouse (saver_info *si, Window window, Cursor cursor) { @@ -135,36 +180,35 @@ grab_keyboard_and_mouse (saver_info *si, Window window, Cursor cursor) sleep (1); status = grab_kbd (si, window); if (status != GrabSuccess) - fprintf (stderr, "%s: couldn't grab keyboard! (%d)\n", - progname, status); + fprintf (stderr, "%s: couldn't grab keyboard! (%s)\n", + progname, grab_string(status)); } + status = grab_mouse (si, window, cursor); if (status != GrabSuccess) { /* try again in a second */ sleep (1); status = grab_mouse (si, window, cursor); if (status != GrabSuccess) - fprintf (stderr, "%s: couldn't grab pointer! (%d)\n", - progname, status); + fprintf (stderr, "%s: couldn't grab pointer! (%s)\n", + progname, grab_string(status)); } } void ungrab_keyboard_and_mouse (saver_info *si) { - saver_preferences *p = &si->prefs; - - XUngrabPointer (si->dpy, CurrentTime); - XUngrabKeyboard (si->dpy, CurrentTime); - - if (p->debug_p) - fprintf(real_stderr, "%s: XungrabPointer / XUngrabKeyboard\n", progname); + ungrab_mouse (si); + ungrab_kbd (si); } -void +/* Prints an error message to stderr and returns True if there is another + xscreensaver running already. Silently returns False otherwise. */ +Bool ensure_no_screensaver_running (Display *dpy, Screen *screen) { + Bool status = 0; int i; Window root = RootWindowOfScreen (screen); Window root2, parent, *kids; @@ -201,13 +245,14 @@ ensure_no_screensaver_running (Display *dpy, Screen *screen) fprintf (stderr, "%s: already running on display %s (window 0x%x)\n from process %s.\n", progname, DisplayString (dpy), (int) kids [i], id); - exit (1); + status = True; } } if (kids) XFree ((char *) kids); XSync (dpy, False); XSetErrorHandler (old_handler); + return status; } @@ -870,8 +915,17 @@ raise_window (saver_info *si, if (p->verbose_p) fprintf (stderr, "%s: fading... ", progname); - XGrabServer (si->dpy); + XGrabServer (si->dpy); /* ############ DANGER! */ + /* Clear the stderr layer on each screen. + Grab the mouse on the first screen on which the mouse is grabbable + (if there are multiple heads, I think you might only be able to + grab the mouse on the screen that currently has the mouse? Anyway, + we only grab the mouse once, and don't try again after the grab + has succeeded.) We grab the mouse on the root window of the screen, + not on the screensaver window, since the screensaver window is not + yet mapped. + */ for (i = 0; i < si->nscreens; i++) { saver_screen_info *ssi = &si->screens[i]; @@ -879,8 +933,11 @@ raise_window (saver_info *si, /* grab and blacken mouse on the root window (saver not mapped yet) */ if (grabbed != GrabSuccess) - grabbed = grab_mouse (si, ssi->screensaver_window, - (si->demo_mode_p ? 0 : ssi->cursor)); + { + Window root = RootWindowOfScreen(ssi->screen); + grabbed = grab_mouse (si, root, + (si->demo_mode_p ? 0 : ssi->cursor)); + } if (!dont_clear || ssi->stderr_overlay_window) /* Do this before the fade, since the stderr cmap won't fade @@ -888,8 +945,11 @@ raise_window (saver_info *si, clear_stderr (ssi); } + /* Note! The server is grabbed, and this will take several seconds + to complete! */ fade_screens (si->dpy, current_maps, current_windows, p->fade_seconds, p->fade_ticks, True, !dont_clear); + free(current_maps); free(current_windows); current_maps = 0; @@ -907,9 +967,12 @@ raise_window (saver_info *si, } #endif /* HAVE_MIT_SAVER_EXTENSION */ + /* If we had successfully grabbed the mouse, let it go now. */ if (grabbed == GrabSuccess) - XUngrabPointer (si->dpy, CurrentTime); + ungrab_mouse (si); + XUngrabServer (si->dpy); + XSync (si->dpy, False); /* ###### (danger over) */ } else { @@ -952,9 +1015,16 @@ blank_screen (saver_info *si) } store_activate_time (si, si->screen_blanked_p); raise_window (si, False, False, False); - /* #### */ - grab_keyboard_and_mouse (si, si->screens[0].screensaver_window, + + /* Note: we do our grabs on the root window, not on the screensaver window. + If we grabbed on the saver window, then the demo mode and lock dialog + boxes wouldn't get any events. + */ + grab_keyboard_and_mouse (si, + /*si->screens[0].screensaver_window,*/ + RootWindowOfScreen(si->screens[0].screen), (si->demo_mode_p ? 0 : si->screens[0].cursor)); + #ifdef HAVE_XHPDISABLERESET if (si->locked_p && !hp_locked_p) { @@ -972,6 +1042,8 @@ unblank_screen (saver_info *si) saver_preferences *p = &si->prefs; int i; + monitor_power_on (si); + store_activate_time (si, True); reset_watchdog_timer (si, False); @@ -998,6 +1070,13 @@ unblank_screen (saver_info *si) XGrabServer (si->dpy); /* ############ DANGER! */ XSync (si->dpy, False); + /* Clear the stderr layer on each screen. + Grab the mouse on the first screen on which the mouse is grabbable + (if there are multiple heads, I think you might only be able to + grab the mouse on the screen that currently has the mouse? Anyway, + we only grab the mouse once, and don't try again after the grab + has succeeded.) + */ for (i = 0; i < si->nscreens; i++) { saver_screen_info *ssi = &si->screens[i]; @@ -1019,8 +1098,10 @@ unblank_screen (saver_info *si) current_windows = 0; if (p->verbose_p) fprintf (stderr, "unfading done.\n"); + + /* If we had successfully grabbed the mouse, let it go now. */ if (grabbed == GrabSuccess) - XUngrabPointer (si->dpy, CurrentTime); + ungrab_mouse (si); } else { @@ -1181,7 +1262,50 @@ select_visual (saver_screen_info *ssi, const char *visual_name) ssi->screensaver_window, ssi->screensaver_window); store_activate_time (si, True); + + + /* Transfer the grabs from the old window to the new. + Actually I think none of this is necessary, since we always + hold our grabs on the root window, but I wrote this before + re-discovering that... + */ + + + /* If we're destroying the window that holds our mouse grab, + transfer the grab to the new window. (Grab the server while + so doing, to avoid a race condition.) + */ + if (old_w == si->mouse_grab_window) + { + XGrabServer (si->dpy); /* ############ DANGER! */ + ungrab_mouse(si); + grab_mouse(si, ssi->screensaver_window, + (si->demo_mode_p ? 0 : ssi->cursor)); + XUngrabServer (si->dpy); + XSync (si->dpy, False); /* ###### (danger over) */ + } + + /* If we're destroying the window that holds our keyboard grab, + transfer the grab to the new window. (Grab the server while + so doing, to avoid a race condition.) + */ + if (old_w == si->keyboard_grab_window) + { + XGrabServer (si->dpy); /* ############ DANGER! */ + ungrab_kbd(si); + grab_kbd(si, ssi->screensaver_window); + XUngrabServer (si->dpy); + XSync (si->dpy, False); /* ###### (danger over) */ + } + + /* Now we can destroy this window without horking our grabs. */ + XDestroyWindow (si->dpy, old_w); + + if (p->verbose_p) + fprintf (stderr, "%s: destroyed old saver window 0x%lx.\n", + progname, (unsigned long) old_w); + if (old_c && old_c != DefaultColormapOfScreen (ssi->screen) && old_c != ssi->demo_cmap)