#include #include #include #include #include #include #include int have_xsync_extension(Display *dpy) { int event_base = 0; int error_base; int major = 3, minor = 1; if (!XSyncInitialize(dpy, &major, &minor)) return 0; printf("XSync %d.%d\n", major, minor); if (!XSyncQueryExtension(dpy, &event_base, &error_base)) return 0; return event_base; } void print_system_counters(Display *dpy) { XSyncSystemCounter *counters; int ncounters; int i; uint64_t resolution; printf("System counters available:\n"); counters = XSyncListSystemCounters(dpy, &ncounters); for (i = 0; i < ncounters; i++) { resolution = (uint64_t)counters[i].resolution.hi << 32 | counters[i].resolution.lo; printf(" %s (%ld): resolution %ld\n", counters[i].name, counters[i].counter, resolution); } XSyncFreeSystemCounterList(counters); } XSyncCounter get_idle_counter(Display *dpy) { XSyncSystemCounter *counters; static XSyncCounter idle = 0; int ncounters; int i; if (idle != 0) return idle; counters = XSyncListSystemCounters(dpy, &ncounters); for (i = 0; i < ncounters; i++) { if (strcmp(counters[i].name, "IDLETIME") == 0) { idle = counters[i].counter; break; } } XSyncFreeSystemCounterList(counters); return idle; } XSyncCounter get_idle_counter_for_device(Display *dpy, int deviceid) { XSyncSystemCounter *counters; XSyncCounter idle = 0; int ncounters; int i; char name[25]; counters = XSyncListSystemCounters(dpy, &ncounters); sprintf(name, "DEVICEIDLETIME %d", deviceid); for (i = 0; i < ncounters; i++) { if (strcmp(counters[i].name, name) == 0) { idle = counters[i].counter; break; } } XSyncFreeSystemCounterList(counters); return idle; } void _watch_counter(Display *dpy, XSyncCounter counter, int timeout, int delta, XSyncValueType mode, XSyncTestType test) { XSyncAlarmAttributes attr; unsigned long mask; XSyncValue _delta, _timeout; XSyncAlarm alarm; memset(&attr, 0, sizeof(attr)); mask = XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType | XSyncCADelta | XSyncCAEvents; XSyncIntToValue(&_delta, delta); /* delta value */ XSyncIntToValue(&_timeout, timeout); /* ms */ attr.events = True; attr.trigger.counter = counter; attr.trigger.value_type = mode; attr.trigger.test_type = test; attr.trigger.wait_value = _timeout; attr.delta = _delta; alarm = XSyncCreateAlarm(dpy, mask, &attr); printf("alarm is %ld\n", alarm); } void watch_counter_positive(Display *dpy, XSyncCounter counter, int timeout, int delta) { _watch_counter(dpy, counter, timeout, delta, XSyncAbsolute, XSyncPositiveTransition); } void watch_counter_negative(Display *dpy, XSyncCounter counter, int timeout, int delta) { _watch_counter(dpy, counter, timeout, delta, XSyncAbsolute, XSyncNegativeTransition); } void print_alarm(Display *dpy, XSyncAlarmNotifyEvent *event) { uint64_t counter, alarm; counter = (uint64_t)XSyncValueHigh32(event->counter_value) << 32 | XSyncValueLow32(event->counter_value); alarm = (uint64_t)XSyncValueHigh32(event->alarm_value) << 32 | XSyncValueLow32(event->alarm_value); printf("AlarmNotify on %ld: counter %ld alarm %ld state %d\n", event->alarm, counter, alarm, event->state); } int main (int argc, char **argv) { Display *dpy; int event_base = 0; XSyncCounter idle; int deviceid = 0; dpy = XOpenDisplay(NULL); assert(dpy); event_base = have_xsync_extension(dpy); if (!event_base) { printf ("Could not find XSYNC extension\n"); return 1; } if (argc > 1) deviceid = atoi(argv[1]); print_system_counters(dpy); if (deviceid) idle = get_idle_counter_for_device(dpy, deviceid); else idle = get_idle_counter(dpy); /* 0.5 seconds idle */ watch_counter_positive(dpy, idle, 500, 0); /* when we break idle */ watch_counter_negative(dpy, idle, 500, 0); XFlush(dpy); while(1) { XEvent ev; XNextEvent(dpy, &ev); if (ev.type == event_base + XSyncAlarmNotify) print_alarm(dpy, (XSyncAlarmNotifyEvent*)&ev); } XCloseDisplay(dpy); return 0; }