/* * xscreensaver.c: A plugin for the Video Disk Recorder * * See the README file for copyright information and how to reach the author. * * Code adapted by Torgeir Veimo from jwz' xscreensaver remote control code * (simplified similar to Gerd Knorr's xawtv) which carries the following * copyright notice: * * xscreensaver-command, Copyright (c) 1991-1998 * by 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 * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation. No representations are made about the suitability of this * software for any purpose. It is provided "as is" without express or * implied warranty. * * $Id: xscreensaver.c,v 1.9 2008-07-14 16:59:20 lucke Exp $ */ #ifndef STAND_ALONE #include #else #include "VdrReplacements.h" #endif #include #include "xscreensaver.h" #include #include "utils.h" static XErrorHandler old_handler = 0; static Bool got_badwindow = False; static BOOL dpms_on; static int BadWindow_ehandler(Display *dpy, XErrorEvent *error) { if (error->error_code == BadWindow) { got_badwindow = True; return 0; } else { if (!old_handler) isyslog("[softdevice-xscreensaver]: old handler not found!\n"); return(*old_handler) (dpy, error); } } cScreensaver::~cScreensaver() { #ifdef LIBXDPMS_SUPPORT if (disabled && DPMSQueryExtension(dpy, &dpms_dummy, &dpms_dummy) && DPMSCapable(dpy) && dpms_on) { DPMSEnable(dpy); // Add workaround for xorg bug #13962. // DPMSEnable() did not rearm timeouts. { CARD16 t0, t1, t2; DPMSGetTimeouts(dpy, &t0, &t1, &t2); DPMSSetTimeouts(dpy, t0, t1, t2); } } #endif } cScreensaver::cScreensaver(Display *dpy) { this->dpy = dpy; XA_SCREENSAVER_VERSION = XInternAtom(dpy, "_SCREENSAVER_VERSION", False); XA_SCREENSAVER = XInternAtom(dpy, "SCREENSAVER", False); XA_DEACTIVATE = XInternAtom(dpy, "DEACTIVATE", False); window = FindWindow(); if (window) { dsyslog("[softdevice-xscreensaver]: window is 0x%lx\n", window); } else { dsyslog("[softdevice-xscreensaver]: xscreensaver not running\n"); } disabled = false; // don't disable screensaver until asked to last = 0; lastKeyEvent = 0; } void cScreensaver::DisableScreensaver(bool disable) { struct timeval current; gettimeofday(¤t, NULL); last = current.tv_sec; lastKeyEvent = current.tv_sec; this->disabled = disable; if ( disable ) window = FindWindow(); #ifdef LIBXDPMS_SUPPORT if ((DPMSQueryExtension(dpy, &dpms_dummy, &dpms_dummy)) && (DPMSCapable(dpy))) { Status stat; if (disable) { dsyslog("[softdevice-xscreensaver]: disabling DPMS\n"); DPMSInfo(dpy, &dpms_state, &dpms_on); stat = DPMSDisable(dpy); dsyslog("[softdevice-xscreensaver]: disabling DPMS stat: %d\n", stat); } else { dsyslog("[softdevice-xscreensaver]: reenabling DPMS\n"); if (!DPMSEnable(dpy)) { dsyslog("[softdevice-xscreensaver]: DPMS not available?\n"); } else { // According to mplayer sources: DPMS does not seem to be enabled unless we call DPMSInfo DPMSForceLevel(dpy, DPMSModeOn); DPMSInfo(dpy, &dpms_state, &dpms_on); // Add workaround for xorg bug #13962. // DPMSEnable() did not rearm timeouts. { CARD16 t0, t1, t2; DPMSGetTimeouts(dpy, &t0, &t1, &t2); DPMSSetTimeouts(dpy, t0, t1, t2); } if (dpms_on) { dsyslog("[softdevice-xscreensaver]: Successfully enabled DPMS\n"); } else { dsyslog("[softdevice-xscreensaver]: Could not enable DPMS\n"); } } } } #endif } void cScreensaver::MaybeSendKeyEvent(void) { if (disabled) { struct timeval current; gettimeofday(¤t, NULL); if (current.tv_sec - lastKeyEvent > INTERVAL_KEYEVENT) { lastKeyEvent = current.tv_sec; // set error handler old_handler = XSetErrorHandler(BadWindow_ehandler); //dsyslog("[softdevice-xscreensaver]: faking left shift pushing\n"); XKeyEvent keyEvent; keyEvent.window = RootWindowOfScreen (DefaultScreenOfDisplay (dpy)); keyEvent.root = RootWindowOfScreen (DefaultScreenOfDisplay (dpy)); keyEvent.display = dpy; keyEvent.subwindow = None; keyEvent.time = CurrentTime; keyEvent.x = 1; keyEvent.y = 1; keyEvent.x_root = 1; keyEvent.y_root = 1; keyEvent.same_screen = True; keyEvent.type = KeyPress; keyEvent.keycode = XKeysymToKeycode(this->dpy, XK_Shift_L); if (!XSendEvent (dpy, RootWindowOfScreen( DefaultScreenOfDisplay( dpy )), True, KeyPressMask, (XEvent *)&keyEvent)) { esyslog("[softdevice-xscreensaver]: failed to send left shift key event\n"); return; } XSync (dpy, 0); keyEvent.type = KeyRelease; if (!XSendEvent (dpy, RootWindowOfScreen( DefaultScreenOfDisplay( dpy )), True, KeyPressMask, (XEvent *)&keyEvent)) { esyslog("[softdevice-xscreensaver]: failed to send left shift released key event\n"); return; } XSync (dpy, 0); // restore default error handler XSetErrorHandler(old_handler); old_handler = 0; } } } void cScreensaver::MaybeSendDeactivate(void) { if (window && disabled) { struct timeval current; gettimeofday(¤t, NULL); if (current.tv_sec - last > INTERVAL) { last = current.tv_sec; //dsyslog("[softdevice-xscreensaver]: sending xscreensaver deactivation command DPMS\n"); // set error handler old_handler = XSetErrorHandler(BadWindow_ehandler); XEvent event; event.xany.type = ClientMessage; event.xclient.display = dpy; event.xclient.window = window; event.xclient.message_type = XA_SCREENSAVER; event.xclient.format = 32; memset(&event.xclient.data, 0, sizeof(event.xclient.data)); event.xclient.data.l[0] = XA_DEACTIVATE; if (!XSendEvent (dpy, window, False, 0L, &event)) { esyslog("[softdevice-xscreensaver]: failed to send deactivation command\n"); return; } XSync (dpy, 0); // restore error handler XSetErrorHandler(old_handler); } } } int cScreensaver::FindWindow() { unsigned int i; Window root = RootWindowOfScreen (DefaultScreenOfDisplay (dpy)); Window root2, parent, *kids; unsigned int nkids; if (! XQueryTree (dpy, root, &root2, &parent, &kids, &nkids)) esyslog("[softdevice-xscreensaver]: unexpected error looking up xscreensaver window\n"); if (root != root2) esyslog("[softdevice-xscreensaver]: unexpected error looking up xscreensaver window\n"); if (parent) esyslog("[softdevice-xscreensaver]: unexpected error looking up xscreensaver window\n"); if (! (kids && nkids)) return 0; for (i = 0; i < nkids; i++) { Atom type; int format; unsigned long nitems, bytesafter; unsigned char *v; int status; /* We're walking the list of root-level windows and trying to find the one that has a particular property on it. We need to trap BadWindows errors while doing this, because it's possible that some random window might get deleted in the meantime. (That window won't have been the one we're looking for.) */ XSync (dpy, False); if (old_handler) esyslog("[softdevice-xscreensaver]: unexpected error looking up xscreensaver window\n"); got_badwindow = False; old_handler = XSetErrorHandler (BadWindow_ehandler); status = XGetWindowProperty(dpy, kids[i], XA_SCREENSAVER_VERSION, 0, 200, False, XA_STRING, &type, &format, &nitems, &bytesafter, (unsigned char **) &v); XSync (dpy, False); XSetErrorHandler (old_handler); old_handler = 0; if (got_badwindow) { status = BadWindow; got_badwindow = False; } if (status == Success && type != None) { return kids[i]; } } return 0; }