+
+ /* 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, True);
+#endif
+
+}
+
+
+/* Returns true if a mouse has moved since the last time we checked.
+ Small motions (of less than "hysteresis" pixels/second) are ignored.
+ */
+static Bool
+device_pointer_moved_p (saver_info *si, poll_mouse_data *last_poll_mouse,
+ poll_mouse_data *this_poll_mouse, Bool mods_p,
+ const char *debug_type, int debug_id)
+{
+ saver_preferences *p = &si->prefs;
+
+ unsigned int distance, dps;
+ unsigned long seconds = 0;
+ Bool moved_p = False;
+
+ distance = MAX (ABS (last_poll_mouse->root_x - this_poll_mouse->root_x),
+ ABS (last_poll_mouse->root_y - this_poll_mouse->root_y));
+ seconds = (this_poll_mouse->time - last_poll_mouse->time);
+
+
+ /* When the screen is blanked, we get MotionNotify events, but when not
+ blanked, we poll only every 5 seconds, and that's not enough resolution
+ to do hysteresis based on a 1 second interval. So, assume that any
+ motion we've seen during the 5 seconds when our eyes were closed happened
+ in the last 1 second instead.
+ */
+ if (seconds > 1) seconds = 1;
+
+ dps = (seconds <= 0 ? distance : (distance / seconds));
+
+ /* Motion only counts if the rate is more than N pixels per second.
+ */
+ if (dps >= p->pointer_hysteresis &&
+ distance > 0)
+ 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 = (this_poll_mouse->root_x != -1 &&
+ this_poll_mouse->root_y != -1);
+ Bool was_on_screen_p = (last_poll_mouse->root_x != -1 &&
+ last_poll_mouse->root_y != -1);
+
+ if (on_screen_p != was_on_screen_p)
+ moved_p = True;
+ }
+
+ if (p->debug_p && (distance != 0 || moved_p))
+ {
+ fprintf (stderr, "%s: %s %d: pointer %s", blurb(), debug_type, debug_id,
+ (moved_p ? "moved: " : "ignored:"));
+ if (last_poll_mouse->root_x == -1)
+ fprintf (stderr, "off screen");
+ else
+ fprintf (stderr, "%d,%d",
+ last_poll_mouse->root_x,
+ last_poll_mouse->root_y);
+ fprintf (stderr, " -> ");
+ if (this_poll_mouse->root_x == -1)
+ fprintf (stderr, "off screen");
+ else
+ fprintf (stderr, "%d,%d", this_poll_mouse->root_x,
+ this_poll_mouse->root_y);
+ if (last_poll_mouse->root_x != -1 && this_poll_mouse->root_x != -1)
+ fprintf (stderr, " (%d,%d; %d/%lu=%d)",
+ ABS(last_poll_mouse->root_x - this_poll_mouse->root_x),
+ ABS(last_poll_mouse->root_y - this_poll_mouse->root_y),
+ distance, seconds, dps);
+
+ fprintf (stderr, ".\n");
+ }
+
+ if (!moved_p &&
+ mods_p &&
+ this_poll_mouse->mask != last_poll_mouse->mask)
+ {
+ moved_p = True;
+
+ if (p->debug_p)
+ fprintf (stderr, "%s: %s %d: modifiers changed: 0x%04x -> 0x%04x.\n",
+ blurb(), debug_type, debug_id,
+ last_poll_mouse->mask, this_poll_mouse->mask);
+ }
+
+ last_poll_mouse->child = this_poll_mouse->child;
+ last_poll_mouse->mask = this_poll_mouse->mask;
+
+ if (moved_p || seconds > 0)
+ {
+ last_poll_mouse->time = this_poll_mouse->time;
+ last_poll_mouse->root_x = this_poll_mouse->root_x;
+ last_poll_mouse->root_y = this_poll_mouse->root_y;
+ }
+
+ return moved_p;
+}
+
+/* Returns true if core mouse pointer has moved since the last time we checked.
+ */
+static Bool
+pointer_moved_p (saver_screen_info *ssi, Bool mods_p)
+{
+ saver_info *si = ssi->global;
+
+ Window root;
+ poll_mouse_data this_poll_mouse;
+ int x, y;
+
+ /* don't check xinerama pseudo-screens. */
+ if (!ssi->real_screen_p) return False;
+
+ this_poll_mouse.time = time ((time_t *) 0);
+
+ if (!XQueryPointer (si->dpy, ssi->screensaver_window, &root,
+ &this_poll_mouse.child,
+ &this_poll_mouse.root_x, &this_poll_mouse.root_y,
+ &x, &y, &this_poll_mouse.mask))
+ {
+ /* If XQueryPointer() returns false, the mouse is not on this screen.
+ */
+ this_poll_mouse.root_x = -1;
+ this_poll_mouse.root_y = -1;
+ this_poll_mouse.child = 0;
+ this_poll_mouse.mask = 0;
+ }
+ else
+ si->last_activity_screen = ssi;
+
+ return device_pointer_moved_p(si, &(ssi->last_poll_mouse), &this_poll_mouse,
+ mods_p, "screen", ssi->number);