X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Fxset.c;h=5ad95a7870daaec5d92acec0255fac463609d887;hb=5f9c47ca98dd43d8f59b7c27d3fde6edfde4fe21;hp=cd2aa38c2a8b07d12fae2e41b7f8a95efde3f709;hpb=f3e0240915ed9f9b3a61781f5c7002d587563fe0;p=xscreensaver diff --git a/driver/xset.c b/driver/xset.c index cd2aa38c..5ad95a78 100644 --- a/driver/xset.c +++ b/driver/xset.c @@ -1,5 +1,5 @@ /* xset.c --- interacting with server extensions and the builtin screensaver. - * xscreensaver, Copyright (c) 1991-1997 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 @@ -30,6 +30,10 @@ #include "xscreensaver.h" +#ifdef _VROOT_H_ +ERROR! You must not include vroot.h in this file. +#endif + /* MIT SCREEN-SAVER server extension hackery. */ @@ -38,14 +42,6 @@ # include -Bool -query_mit_saver_extension (saver_info *si) -{ - return XScreenSaverQueryExtension (si->dpy, - &si->mit_saver_ext_event_number, - &si->mit_saver_ext_error_number); -} - static int ignore_all_errors_ehandler (Display *dpy, XErrorEvent *error) { @@ -89,6 +85,168 @@ init_mit_saver_extension (saver_info *si) } #endif /* HAVE_MIT_SAVER_EXTENSION */ + +#ifdef HAVE_XINPUT +/* XInputExtension device support */ +#include + +struct xinput_dev_info { + XDevice *device; + XEventClass press, release, valuator; +}; + +Bool +query_xinput_extension (saver_info *si) +{ + XExtCodes codes; + return XQueryExtension (si->dpy, INAME, &codes.major_opcode, + &codes.first_event, &codes.first_error); +} + +void +init_xinput_extension (saver_info *si) +{ + int i, ndevices; + int class; + XDeviceInfo *list; + XDevice *dev; + XAnyClassPtr pClass; + XEventClass *event_list; + int nevents = 0; + + /* skip if already initialized */ + if (si->num_xinput_devices && si->xinput_devices) + return; + + si->num_xinput_devices = 0; + + list = XListInputDevices (si->dpy, &ndevices); + if (list == NULL) + { + si->xinput_devices = NULL; + return; + } + + /* We only care about 3 event types per device (DeviceButtonPress, + DeviceButtonRelease, and DeviceMotionNotify), hence the "* 3" + for the event count. */ + event_list = calloc(ndevices * 3, sizeof(XEventClass)); + if (event_list == NULL) + return; + + si->xinput_devices = calloc(ndevices, sizeof(struct xinput_dev_info)); + if (si->xinput_devices == NULL) + { + free(event_list); + return; + } + + for (i = 0; i < ndevices; i++) + { + if ((list[i].use == IsXExtensionDevice) +#ifdef IsXExtensionPointer + || (list[i].use == IsXExtensionPointer) +#endif + ) + { + struct xinput_dev_info *dev_info = + &si->xinput_devices[si->num_xinput_devices]; + Bool device_we_want = False; + + if (si->prefs.debug_p) + fprintf(stderr, + "Extension device #%2d: XID=%2d type=%3d name=\"%s\"\n", + i, (int) list[i].id, (int) list[i].type, list[i].name); + + dev = XOpenDevice (si->dpy, list[i].id); + if (!dev) + continue; + dev_info->device = dev; + + pClass = list[i].inputclassinfo; + for (class = 0; class < list[i].num_classes; class++) + { + switch (pClass->class) + { + case ButtonClass: + if (((XButtonInfo *) pClass)->num_buttons > 0) + { + /* Macros set values in the second & third arguments */ + DeviceButtonPress (dev, si->xinput_DeviceButtonPress, + dev_info->press); + event_list[nevents++] = dev_info->press; + + DeviceButtonRelease (dev, si->xinput_DeviceButtonRelease, + dev_info->release); + event_list[nevents++] = dev_info->release; + device_we_want = True; + } + break; + + case ValuatorClass: + if (((XValuatorInfo *) pClass)->num_axes > 0) + { + DeviceMotionNotify (dev, si->xinput_DeviceMotionNotify, + dev_info->valuator); + event_list[nevents++] = dev_info->valuator; + device_we_want = True; + } + break; + + default: + /* ignore other classes of devices/events */ + break; + } + + pClass = (XAnyClassPtr) & ((char *) pClass)[pClass->length]; + } + + if (device_we_want) + si->num_xinput_devices++; + else + XCloseDevice (si->dpy, dev); + } + } + + if (list) + XFreeDeviceList (list); + + if ((nevents == 0) || (si->num_xinput_devices == 0)) + { + free(event_list); + free(si->xinput_devices); + si->xinput_devices = NULL; + si->num_xinput_devices = 0; + return; + } + + for (i = 0; i < si->nscreens; i++) + { + saver_screen_info *ssi = &si->screens[i]; + Window root = RootWindowOfScreen (ssi->screen); + XSelectExtensionEvent (si->dpy, root, event_list, nevents); + } + + free(event_list); +} + +#if 0 +/* not used */ +static void +close_xinput_extension (saver_info *si) +{ + int i; + + for (i = 0; i < si->num_xinput_devices; i++) + XCloseDevice (si->dpy, si->xinput_devices[i].device); + + free(si->xinput_devices); + si->xinput_devices = NULL; + si->num_xinput_devices = 0; +} +#endif +#endif /* HAVE_XINPUT */ + /* SGI SCREEN_SAVER server extension hackery. */ @@ -97,14 +255,6 @@ init_mit_saver_extension (saver_info *si) # include -Bool -query_sgi_saver_extension (saver_info *si) -{ - return XScreenSaverQueryExtension (si->dpy, - &si->sgi_saver_ext_event_number, - &si->sgi_saver_ext_error_number); -} - static void init_sgi_saver_extension (saver_info *si) { @@ -124,8 +274,8 @@ init_sgi_saver_extension (saver_info *si) fprintf (stderr, "%s: SGI SCREEN_SAVER extension exists, but can't be initialized;\n\ perhaps some other screensaver program is already running?\n", - progname); - p->use_sgi_saver_extension = False; + blurb()); + si->using_sgi_saver_extension = False; return; } } @@ -133,13 +283,14 @@ init_sgi_saver_extension (saver_info *si) #endif /* HAVE_SGI_SAVER_EXTENSION */ + -/* Figuring out what the appropriate XSetScreenSaver() paramters are +/* Figuring out what the appropriate XSetScreenSaver() parameters are (one wouldn't expect this to be rocket science.) */ void -disable_builtin_screensaver (saver_info *si, Bool turn_off_p) +disable_builtin_screensaver (saver_info *si, Bool unblank_screen_p) { saver_preferences *p = &si->prefs; int current_server_timeout, current_server_interval; @@ -157,51 +308,63 @@ disable_builtin_screensaver (saver_info *si, Bool turn_off_p) /* On SGIs, if interval is non-zero, it is the number of seconds after screen saving starts at which the monitor should be powered down. - Obviously I don't want that, so make sure it's 0. + Obviously I don't want that, so set it to 0 (meaning "never".) Power saving is disabled if DontPreferBlanking, but in that case, we don't get extension events either. So we can't turn it off that way. + + Note: if you're running Irix 6.3 (O2), you may find that your monitor is + powering down anyway, regardless of the xset settings. This is fixed by + installing SGI patches 2447 and 2537. */ desired_server_interval = 0; /* I suspect (but am not sure) that DontAllowExposures might have - something to do with powering off the monitor as well. */ + something to do with powering off the monitor as well, at least + on some systems that don't support XDPMS? Who knows... */ desired_allow_exp = AllowExposures; -#if defined(HAVE_MIT_SAVER_EXTENSION) || defined(HAVE_SGI_SAVER_EXTENSION) - if (p->use_mit_saver_extension || p->use_sgi_saver_extension) + if (si->using_mit_saver_extension || si->using_sgi_saver_extension) { desired_server_timeout = (p->timeout / 1000); /* The SGI extension won't give us events unless blanking is on. I think (unsure right now) that the MIT extension is the opposite. */ - if (p->use_sgi_saver_extension) + if (si->using_sgi_saver_extension) desired_prefer_blank = PreferBlanking; else desired_prefer_blank = DontPreferBlanking; } else -#endif /* HAVE_MIT_SAVER_EXTENSION || HAVE_SGI_SAVER_EXTENSION */ { + /* When we're not using an extension, set the server-side timeout to 0, + so that the server never gets involved with screen blanking, and we + do it all ourselves. (However, when we *are* using an extension, + we tell the server when to notify us, and rather than blanking the + screen, the server will send us an X event telling us to blank.) + */ desired_server_timeout = 0; } + /* XSetScreenSaver() generates BadValue if either timeout parameter + exceeds 15 bits (signed short.) That is 09:06:07. + */ + if (desired_server_timeout > 0x7FFF) desired_server_timeout = 0x7FFF; + if (desired_server_interval > 0x7FFF) desired_server_interval = 0x7FFF; + if (desired_server_timeout != current_server_timeout || desired_server_interval != current_server_interval || desired_prefer_blank != current_prefer_blank || desired_allow_exp != current_allow_exp) { - if (desired_server_timeout == 0) - printf ("%s%sisabling server builtin screensaver.\n\ - You can re-enable it with \"xset s on\".\n", - (p->verbose_p ? "" : progname), - (p->verbose_p ? "\n\tD" : ": d")); - if (p->verbose_p) - fprintf (stderr, "%s: (xset s %d %d %s %s)\n", progname, + fprintf (stderr, + "%s: disabling server builtin screensaver:\n" + "%s: (xset s %d %d; xset s %s; xset s %s)\n", + blurb(), blurb(), desired_server_timeout, desired_server_interval, (desired_prefer_blank ? "blank" : "noblank"), - (desired_allow_exp ? "noexpose" : "expose")); + (desired_allow_exp ? "expose" : "noexpose")); XSetScreenSaver (si->dpy, desired_server_timeout, desired_server_interval, @@ -217,16 +380,16 @@ disable_builtin_screensaver (saver_info *si, Bool turn_off_p) { extension_initted = True; # ifdef HAVE_MIT_SAVER_EXTENSION - if (p->use_mit_saver_extension) init_mit_saver_extension(si); + if (si->using_mit_saver_extension) init_mit_saver_extension(si); # endif # ifdef HAVE_SGI_SAVER_EXTENSION - if (p->use_sgi_saver_extension) init_sgi_saver_extension(si); + if (si->using_sgi_saver_extension) init_sgi_saver_extension(si); # endif } } #endif /* HAVE_MIT_SAVER_EXTENSION || HAVE_SGI_SAVER_EXTENSION */ - if (turn_off_p) + if (unblank_screen_p) /* Turn off the server builtin saver if it is now running. */ XForceScreenSaver (si->dpy, ScreenSaverReset); }