X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Ftimers.c;h=97a26c02a39c5f4060135b51bda27fb217602d15;hb=f0261d8acab611f3433160e4f07367b870439739;hp=c9244f735e7655b29c8a968a7175d7885e364b78;hpb=447db08c956099b3b183886729108bf5b364c4b8;p=xscreensaver diff --git a/driver/timers.c b/driver/timers.c index c9244f73..97a26c02 100644 --- a/driver/timers.c +++ b/driver/timers.c @@ -1,5 +1,5 @@ /* timers.c --- detecting when the user is idle, and other timer-related tasks. - * xscreensaver, Copyright (c) 1991-2004 Jamie Zawinski + * xscreensaver, Copyright (c) 1991-2008 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 @@ -264,14 +264,18 @@ cycle_timer (XtPointer closure, XtIntervalId *id) } else { + int i; maybe_reload_init_file (si); - kill_screenhack (si); + for (i = 0; i < si->nscreens; i++) + kill_screenhack (&si->screens[i]); + + raise_window (si, True, True, False); if (!si->throttled_p) - spawn_screenhack (si, False); + for (i = 0; i < si->nscreens; i++) + spawn_screenhack (&si->screens[i]); else { - raise_window (si, True, True, False); if (p->verbose_p) fprintf (stderr, "%s: not launching new hack (throttled.)\n", blurb()); @@ -331,6 +335,23 @@ reset_timers (saver_info *si) if (si->cycle_id) abort (); /* no cycle timer when inactive */ si->last_activity_time = time ((time_t *) 0); + + /* This will (hopefully, supposedly) tell the server to re-set its + DPMS timer. Without this, the -deactivate clientmessage would + prevent xscreensaver from blanking, but would not prevent the + monitor from powering down. */ +#if 0 + /* #### With some servers, this causes the screen to flicker every + time a key is pressed! Ok, I surrender. I give up on ever + having DPMS work properly. + */ + XForceScreenSaver (si->dpy, ScreenSaverReset); + + /* And if the monitor is already powered off, turn it on. + You'd think the above would do that, but apparently not? */ + monitor_power_on (si); +#endif + } @@ -386,11 +407,17 @@ pointer_moved_p (saver_screen_info *ssi, Bool mods_p) distance > 0) moved_p = True; - if (ssi->poll_mouse_last_root_x == -1 || - ssi->poll_mouse_last_root_y == -1 || - root_x == -1 || - root_y == -1) - moved_p = True; + /* If the mouse is not on this screen but used to be, that's motion. + If the mouse was not on this screen, but is now, that's motion. + */ + { + Bool on_screen_p = (root_x != -1 && root_y != -1); + Bool was_on_screen_p = (ssi->poll_mouse_last_root_x != -1 && + ssi->poll_mouse_last_root_y != -1); + + if (on_screen_p != was_on_screen_p) + moved_p = True; + } if (p->debug_p && (distance != 0 || moved_p)) { @@ -404,7 +431,7 @@ pointer_moved_p (saver_screen_info *ssi, Bool mods_p) ssi->poll_mouse_last_root_y); fprintf (stderr, " -> "); if (root_x == -1) - fprintf (stderr, "off screen."); + fprintf (stderr, "off screen"); else fprintf (stderr, "%d,%d", root_x, root_y); if (ssi->poll_mouse_last_root_x != -1 && root_x != -1) @@ -585,6 +612,7 @@ swallow_unlock_typeahead_events (saver_info *si, XEvent *e) break; case '\025': case '\030': /* Erase line */ case '\012': case '\015': /* Enter */ + case '\033': /* ESC */ i = 0; break; case '\040': /* Space */ @@ -641,7 +669,20 @@ void sleep_until_idle (saver_info *si, Bool until_idle_p) { saver_preferences *p = &si->prefs; - XEvent event; + + /* We have to go through this union bullshit because gcc-4.4.0 has + stricter struct-aliasing rules. Without this, the optimizer + can fuck things up. + */ + union { + XEvent x_event; +# ifdef HAVE_RANDR + XRRScreenChangeNotifyEvent xrr_event; +# endif /* HAVE_RANDR */ +# ifdef HAVE_MIT_SAVER_EXTENSION + XScreenSaverNotifyEvent sevent; +# endif /* HAVE_MIT_SAVER_EXTENSION */ + } event; /* We need to select events on all windows if we're not using any extensions. Otherwise, we don't need to. */ @@ -685,9 +726,9 @@ sleep_until_idle (saver_info *si, Bool until_idle_p) while (1) { - XtAppNextEvent (si->app, &event); + XtAppNextEvent (si->app, &event.x_event); - switch (event.xany.type) { + switch (event.x_event.xany.type) { case 0: /* our synthetic "timeout" event has been signalled */ if (until_idle_p) { @@ -775,7 +816,7 @@ sleep_until_idle (saver_info *si, Bool until_idle_p) break; case ClientMessage: - if (handle_clientmessage (si, &event, until_idle_p)) + if (handle_clientmessage (si, &event.x_event, until_idle_p)) goto DONE; break; @@ -784,15 +825,18 @@ sleep_until_idle (saver_info *si, Bool until_idle_p) supposed to scan all windows for events, prepare this window. */ if (scanning_all_windows) { - Window w = event.xcreatewindow.window; + Window w = event.x_event.xcreatewindow.window; start_notice_events_timer (si, w, p->debug_p); } break; case KeyPress: - case KeyRelease: case ButtonPress: - case ButtonRelease: + /* Ignore release events so that hitting ESC at the password dialog + doesn't result in the password dialog coming right back again when + the fucking release key is seen! */ + /* case KeyRelease:*/ + /* case ButtonRelease:*/ case MotionNotify: if (p->debug_p) @@ -800,28 +844,28 @@ sleep_until_idle (saver_info *si, Bool until_idle_p) Window root=0, window=0; int x=-1, y=-1; const char *type = 0; - if (event.xany.type == MotionNotify) + if (event.x_event.xany.type == MotionNotify) { /*type = "MotionNotify";*/ - root = event.xmotion.root; - window = event.xmotion.window; - x = event.xmotion.x_root; - y = event.xmotion.y_root; + root = event.x_event.xmotion.root; + window = event.x_event.xmotion.window; + x = event.x_event.xmotion.x_root; + y = event.x_event.xmotion.y_root; } - else if (event.xany.type == KeyPress) + else if (event.x_event.xany.type == KeyPress) { type = "KeyPress"; - root = event.xkey.root; - window = event.xkey.window; + root = event.x_event.xkey.root; + window = event.x_event.xkey.window; x = y = -1; } - else if (event.xany.type == ButtonPress) + else if (event.x_event.xany.type == ButtonPress) { type = "ButtonPress"; - root = event.xkey.root; - window = event.xkey.window; - x = event.xmotion.x_root; - y = event.xmotion.y_root; + root = event.x_event.xkey.root; + window = event.x_event.xkey.window; + x = event.x_event.xmotion.x_root; + y = event.x_event.xmotion.y_root; } if (type) @@ -835,13 +879,13 @@ sleep_until_idle (saver_info *si, Bool until_idle_p) /* Be careful never to do this unless in -debug mode, as this could expose characters from the unlock password. */ - if (p->debug_p && event.xany.type == KeyPress) + if (p->debug_p && event.x_event.xany.type == KeyPress) { KeySym keysym; char c = 0; - XLookupString (&event.xkey, &c, 1, &keysym, 0); + XLookupString (&event.x_event.xkey, &c, 1, &keysym, 0); fprintf (stderr, " (%s%s)", - (event.xkey.send_event ? "synthetic " : ""), + (event.x_event.xkey.send_event ? "synthetic " : ""), XKeysymToString (keysym)); } @@ -853,7 +897,7 @@ sleep_until_idle (saver_info *si, Bool until_idle_p) } /* If any widgets want to handle this event, let them. */ - dispatch_event (si, &event); + dispatch_event (si, &event.x_event); /* If we got a MotionNotify event, figure out what screen it @@ -861,11 +905,11 @@ sleep_until_idle (saver_info *si, Bool until_idle_p) far enough to count as "real" motion, then ignore this event. */ - if (event.xany.type == MotionNotify) + if (event.x_event.xany.type == MotionNotify) { int i; for (i = 0; i < si->nscreens; i++) - if (event.xmotion.root == + if (event.x_event.xmotion.root == RootWindowOfScreen (si->screens[i].screen)) break; if (i < si->nscreens) @@ -884,8 +928,8 @@ sleep_until_idle (saver_info *si, Bool until_idle_p) if (!until_idle_p) { if (si->demoing_p && - (event.xany.type == MotionNotify || - event.xany.type == KeyRelease)) + (event.x_event.xany.type == MotionNotify || + event.x_event.xany.type == KeyRelease)) /* When we're demoing a single hack, mouse motion doesn't cause deactivation. Only clicks and keypresses do. */ ; @@ -902,16 +946,14 @@ sleep_until_idle (saver_info *si, Bool until_idle_p) default: #ifdef HAVE_MIT_SAVER_EXTENSION - if (event.type == si->mit_saver_ext_event_number) + if (event.x_event.type == si->mit_saver_ext_event_number) { /* This event's number is that of the MIT-SCREEN-SAVER server extension. This extension has one event number, and the event itself contains sub-codes that say what kind of event it was (an "idle" or "not-idle" event.) */ - XScreenSaverNotifyEvent *sevent = - (XScreenSaverNotifyEvent *) &event; - if (sevent->state == ScreenSaverOn) + if (event.sevent.state == ScreenSaverOn) { int i = 0; if (p->verbose_p) @@ -929,7 +971,7 @@ sleep_until_idle (saver_info *si, Bool until_idle_p) XUnmapWindow (si->dpy, ssi->server_mit_saver_window); } - if (sevent->kind != ScreenSaverExternal) + if (event.sevent.kind != ScreenSaverExternal) { fprintf (stderr, "%s: ScreenSaverOn event wasn't of type External!\n", @@ -939,7 +981,7 @@ sleep_until_idle (saver_info *si, Bool until_idle_p) if (until_idle_p) goto DONE; } - else if (sevent->state == ScreenSaverOff) + else if (event.sevent.state == ScreenSaverOff) { if (p->verbose_p) fprintf (stderr, "%s: MIT ScreenSaverOff event received.\n", @@ -950,7 +992,7 @@ sleep_until_idle (saver_info *si, Bool until_idle_p) else fprintf (stderr, "%s: unknown MIT-SCREEN-SAVER event %d received!\n", - blurb(), sevent->state); + blurb(), event.sevent.state); } else @@ -958,7 +1000,7 @@ sleep_until_idle (saver_info *si, Bool until_idle_p) #ifdef HAVE_SGI_SAVER_EXTENSION - if (event.type == (si->sgi_saver_ext_event_number + ScreenSaverStart)) + if (event.x_event.type == (si->sgi_saver_ext_event_number + ScreenSaverStart)) { /* The SGI SCREEN_SAVER server extension has two event numbers, and this event matches the "idle" event. */ @@ -969,7 +1011,7 @@ sleep_until_idle (saver_info *si, Bool until_idle_p) if (until_idle_p) goto DONE; } - else if (event.type == (si->sgi_saver_ext_event_number + + else if (event.x_event.type == (si->sgi_saver_ext_event_number + ScreenSaverEnd)) { /* The SGI SCREEN_SAVER server extension has two event numbers, @@ -984,46 +1026,40 @@ sleep_until_idle (saver_info *si, Bool until_idle_p) #endif /* HAVE_SGI_SAVER_EXTENSION */ #ifdef HAVE_RANDR - if (event.type == (si->randr_event_number + RRScreenChangeNotify)) + if (event.x_event.type == (si->randr_event_number + RRScreenChangeNotify)) { /* The Resize and Rotate extension sends an event when the - size, rotation, or refresh rate of the screen has changed. */ - - XRRScreenChangeNotifyEvent *xrr_event = - (XRRScreenChangeNotifyEvent *) &event; - /* XRRRootToScreen is in Xrandr.h 1.4, 2001/06/07 */ - int screen = XRRRootToScreen (si->dpy, xrr_event->window); - + size, rotation, or refresh rate of any screen has changed. + */ if (p->verbose_p) { - if (si->screens[screen].width == xrr_event->width && - si->screens[screen].height == xrr_event->height) - fprintf (stderr, - "%s: %d: no-op screen size change event (%dx%d)\n", - blurb(), screen, - xrr_event->width, xrr_event->height); - else - fprintf (stderr, - "%s: %d: screen size changed from %dx%d to %dx%d\n", - blurb(), screen, - si->screens[screen].width, - si->screens[screen].height, - xrr_event->width, xrr_event->height); + /* XRRRootToScreen is in Xrandr.h 1.4, 2001/06/07 */ + int screen = XRRRootToScreen (si->dpy, event.xrr_event.window); + fprintf (stderr, "%s: %d: screen change event received\n", + blurb(), screen); } # ifdef RRScreenChangeNotifyMask /* Inform Xlib that it's ok to update its data structures. */ - XRRUpdateConfiguration (&event); /* Xrandr.h 1.9, 2002/09/29 */ + XRRUpdateConfiguration (&event.x_event); /* Xrandr.h 1.9, 2002/09/29 */ # endif /* RRScreenChangeNotifyMask */ /* Resize the existing xscreensaver windows and cached ssi data. */ - resize_screensaver_window (si); + if (update_screen_layout (si)) + { + if (p->verbose_p) + { + fprintf (stderr, "%s: new layout:\n", blurb()); + describe_monitor_layout (si); + } + resize_screensaver_window (si); + } } else #endif /* HAVE_RANDR */ /* Just some random event. Let the Widgets handle it, if desired. */ - dispatch_event (si, &event); + dispatch_event (si, &event.x_event); } } DONE: @@ -1038,11 +1074,11 @@ sleep_until_idle (saver_info *si, Bool until_idle_p) there's only one event generated by user activity, not two.) */ if (!until_idle_p && si->locked_p) - swallow_unlock_typeahead_events (si, &event); + swallow_unlock_typeahead_events (si, &event.x_event); else while (XCheckMaskEvent (si->dpy, (KeyPressMask|ButtonPressMask|PointerMotionMask), - &event)) + &event.x_event)) ; @@ -1059,8 +1095,6 @@ sleep_until_idle (saver_info *si, Bool until_idle_p) if (until_idle_p && si->cycle_id) /* no cycle timer when inactive */ abort (); - - return; } @@ -1170,7 +1204,10 @@ query_proc_interrupts_available (saver_info *si, const char **why) f = fopen (PROC_INTERRUPTS, "r"); if (!f) - return False; + { + if (why) *why = "does not exist"; + return False; + } fclose (f); return True; @@ -1375,11 +1412,13 @@ watchdog_timer (XtPointer closure, XtIntervalId *id) if (screenhack_running_p (si) && !monitor_powered_on_p (si)) { + int i; if (si->prefs.verbose_p) fprintf (stderr, "%s: X says monitor has powered down; " "killing running hacks.\n", blurb()); - kill_screenhack (si); + for (i = 0; i < si->nscreens; i++) + kill_screenhack (&si->screens[i]); } /* Re-schedule this timer. The watchdog timer defaults to a bit less