From 005fc7dcf69fc112b5ce3d2c4017769cd8e425e8 Mon Sep 17 00:00:00 2001 From: "B. Watson" Date: Mon, 18 May 2020 23:59:51 -0400 Subject: detect fullscreen windows (-f/-F) --- jsmond.1 | 20 ++++++---- jsmond.c | 123 ++++++++++++++++++++++++++++++++++++++++++++++-------------- jsmond.html | 21 +++++++---- jsmond.rst | 20 ++++++---- 4 files changed, 134 insertions(+), 50 deletions(-) diff --git a/jsmond.1 b/jsmond.1 index fc761bc..8b9513b 100644 --- a/jsmond.1 +++ b/jsmond.1 @@ -36,11 +36,12 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]] . .SH SYNOPSIS .sp -jsmond [\fB\-i interval[s|ms]\fP] [\fB\-m\fP | \fB\-k keycode\fP | \fB\-b button\fP] [\fB\-d dir\fP] [\fB\-j name\fP] [\fB\-D\fP] [\fBjoydev [joydev ...]\fP] +jsmond [\fB\-i interval[s|ms]\fP] [\fB\-m\fP | \fB\-k keycode\fP | \fB\-b button\fP | \fB\-c command\fP | \fB\-x\fP ] [\fB\-d dir\fP] [\fB\-j name\fP] [\fB\-f\fP] [\fB\-F\fP] [\fB\-D\fP] [\fBjoydev [joydev ...]\fP] .SH DESCRIPTION .sp -jsmond lets you play games with your joysticks/gamepads without -the screen saver activating due to lack of keyboard/mouse input. +jsmond lets you play games with your joysticks/gamepads without the screen +saver activating due to lack of keyboard/mouse input. It can also prevent +the screensaver from activating when a fullscreen window is in use. .sp Multiple joystick devices can be monitored. By default, jsmond monitors up to 16 devices, named /dev/input/js0 through js15. @@ -96,18 +97,20 @@ to its starting point. .BI \-c \ Run a command when activity is detected, rather than sending a fake keystroke/click/motion. It\(aqs recommended -to set \fIinterval\fP to at least 1 second, when using this -option. +to set \fIinterval\fP to at least 1 second when using this +option, to avoid excess process\-spawning overhead. .TP .B \-x Same as \fB\-c "xscreensaver\-command \-deactivate" \-i 1s\fP\&. .TP .B \-f -Disable screensaver if a full\-screen window is detected. -This isn\(aqt likely to be 100% reliable. +Deactivate screensaver if a fullscreen window is detected. +This isn\(aqt likely to be 100% reliable yet. .TP .B \-F Same as \fB\-f\fP, but also disables joystick monitoring entirely. +Note that \fB\-j\fP, \fB\-d\fP, and \fBjoydev\fP are ignored +with this option. .UNINDENT .sp These options are intended for developers and \fIreally\fP shouldn\(aqt be @@ -157,6 +160,9 @@ password dialog, same as pressing a key or mouse button would. jsmond depends on the XTest extension being present in the X server. If you get a "X server doesn\(aqt support XTest extension" error, see your X server documentation to find out how to enable XTest. +.sp +The fullscreen window monitoring has only been tested on a system with +a single monitor, and may not work properly in multi\-head environments. .SH EXIT STATUS .sp Without the \-D option, the exit status is 0 (success) if jsmond diff --git a/jsmond.c b/jsmond.c index ca3c1a0..643287d 100644 --- a/jsmond.c +++ b/jsmond.c @@ -52,6 +52,8 @@ char *js_node_name = JSNODE; /* -j */ int autodiscover = 1; /* cleared if user supplies joydev args */ fake_mode_t fake_mode = fm_auto_keycode; /* -k, -b, -m */ char *c_command = NULL; /* -c, -x */ +int monitor_joysticks = 1; /* -F */ +int monitor_fullscreen = 0; /* -f, -F */ /* joystick stuff */ char *joynames[MAX_STICKS + 1]; @@ -260,45 +262,90 @@ void check_inotify() { } } +int get_joystick_activity(void) { + struct js_event e; + int i, active = 0; + + for(i = 0; i < last_joyname; i++) { + if(joyfds[i] < 0) continue; + + if(debug) fprintf(stderr, "reading device %d, fd %d\n", i, joyfds[i]); + + /* count events. any we get here *should* be real, but it doesn't + hurt to mask out synthetic ones again */ + while(read(joyfds[i], &e, sizeof(e)) > 0) { + if(!(e.type & JS_EVENT_INIT)) active++; + } + + /* EAGAIN just means there are no more events to read. + anything else is a problem, though not fatal */ + if(errno != EAGAIN) { + if(debug) fprintf(stderr, "got error on device %d: %s\n", i, strerror(errno)); + } + } + + return active; +} + +int have_fullscreen_window(void) { + Window w; + XWindowAttributes w_attrs, root_attrs; + int revert_to; + + /* TODO: error check? */ + XGetInputFocus(xdisp, &w, &revert_to); + + if(w != None) { + XGetWindowAttributes(xdisp, DefaultRootWindow(xdisp), &root_attrs); + XGetWindowAttributes(xdisp, w, &w_attrs); + + /* + fprintf(stderr, "window id %d has focus, geometry %dx%d\n", + (int)w, w_attrs.width, w_attrs.height); + */ + + if( (w_attrs.map_state == IsViewable) && + (root_attrs.width == w_attrs.width) && + (root_attrs.height == w_attrs.height) ) + { + if(debug) fprintf(stderr, + "window id 0x%x has input focus and looks fullscreen (%dx%d)\n", + (int)w, w_attrs.width, w_attrs.height); + return 1; + } + } + + return 0; +} + /* this is the point of no return. the only way out of main_loop() is process death. */ void main_loop(void) { - struct js_event e; - int i, active, sleep_us; - - fprintf(stderr, "entering main_loop()\n"); + int sleep_us; sleep_us = interval * 1000; + fprintf(stderr, "entering main_loop(), sleep_us %d\n", sleep_us); + while(1) { + int active = 0; + /* Xlib will obligingly kill us, if X goes away */ ping_x_server(); /* check_inotify() will close & reopen the joystick fds as needed */ - check_inotify(); + if(monitor_joysticks) + check_inotify(); /* let the fds gather events as we slumber */ if(debug) fprintf(stderr, "sleeping %dms...\n", interval); usleep(sleep_us); /* now see if any of them got any events while we took a nap */ - active = 0; - for(i = 0; i < last_joyname; i++) { - if(joyfds[i] < 0) continue; - - if(debug) fprintf(stderr, "reading device %d, fd %d\n", i, joyfds[i]); + if(monitor_joysticks) + active += get_joystick_activity(); - /* count events. any we get here *should* be real, but it doesn't - hurt to mask out synthetic ones again */ - while(read(joyfds[i], &e, sizeof(e)) > 0) { - if(!(e.type & JS_EVENT_INIT)) active++; - } - - /* EAGAIN just means there are no more events to read. - anything else is a problem, though not fatal */ - if(errno != EAGAIN) { - if(debug) fprintf(stderr, "got error on device %d: %s\n", i, strerror(errno)); - } - } + if(monitor_fullscreen) + active += have_fullscreen_window(); /* if we got any activity on any of the fds, do our thing */ if(active) { @@ -474,9 +521,10 @@ void parse_args(int argc, char **argv) { set_fake_mode(fm_cmd); c_command = X_COMMAND; break; - case 'f': case 'F': - die("-f and -F not yet implemented"); + monitor_joysticks = 0; /* and fall thru */ + case 'f': + monitor_fullscreen = 1; break; default: die("unrecognized argument, try --help"); @@ -640,16 +688,35 @@ void init_x(void) { send_fake_x_event(); } +void print_banner() { + const char *m; + + if(monitor_joysticks && monitor_fullscreen) { + m = "joysticks and fullscreen"; + } else if(monitor_joysticks) { + m = "joysticks only"; + } else if(monitor_fullscreen) { + m = "fullscreen only"; + } else { + die("nothing to monitor!"); + } + + fprintf(stderr, "%s: v%s monitoring %s, interval %dms\n", + self, VERSION, m, interval); +} + int main(int argc, char **argv) { set_exe_name(argv[0]); parse_args(argc, argv); - if(autodiscover) populate_joynames(); + print_banner(); - init_joysticks(); - - init_inotify(); + if(monitor_joysticks) { + if(autodiscover) populate_joynames(); + init_joysticks(); + init_inotify(); + } init_x(); diff --git a/jsmond.html b/jsmond.html index 4f5d91c..2874b25 100644 --- a/jsmond.html +++ b/jsmond.html @@ -382,12 +382,13 @@ ul.auto-toc {

SYNOPSIS

-

jsmond [-i interval[s|ms]] [-m | -k keycode | -b button] [-d dir] [-j name] [-D] [joydev [joydev ...]]

+

jsmond [-i interval[s|ms]] [-m | -k keycode | -b button | -c command | -x ] [-d dir] [-j name] [-f] [-F] [-D] [joydev [joydev ...]]

DESCRIPTION

-

jsmond lets you play games with your joysticks/gamepads without -the screen saver activating due to lack of keyboard/mouse input.

+

jsmond lets you play games with your joysticks/gamepads without the screen +saver activating due to lack of keyboard/mouse input. It can also prevent +the screensaver from activating when a fullscreen window is in use.

Multiple joystick devices can be monitored. By default, jsmond monitors up to 16 devices, named /dev/input/js0 through js15. These devices don't have to actually exist: they can come and go @@ -444,18 +445,20 @@ to its starting point. -c <command> Run a command when activity is detected, rather than sending a fake keystroke/click/motion. It's recommended -to set interval to at least 1 second, when using this -option. +to set interval to at least 1 second when using this +option, to avoid excess process-spawning overhead. -x Same as -c "xscreensaver-command -deactivate" -i 1s. -f -Disable screensaver if a full-screen window is detected. -This isn't likely to be 100% reliable. +Deactivate screensaver if a fullscreen window is detected. +This isn't likely to be 100% reliable yet. -F -Same as -f, but also disables joystick monitoring entirely. +Same as -f, but also disables joystick monitoring entirely. +Note that -j, -d, and joydev are ignored +with this option.

These options are intended for developers and really shouldn't be @@ -504,6 +507,8 @@ password dialog, same as pressing a key or mouse button would.

jsmond depends on the XTest extension being present in the X server. If you get a "X server doesn't support XTest extension" error, see your X server documentation to find out how to enable XTest.

+

The fullscreen window monitoring has only been tested on a system with +a single monitor, and may not work properly in multi-head environments.

EXIT STATUS

diff --git a/jsmond.rst b/jsmond.rst index 89b47a6..4c0a38d 100644 --- a/jsmond.rst +++ b/jsmond.rst @@ -20,13 +20,14 @@ deactivate screensaver on joystick activity SYNOPSIS ======== -jsmond [**-i interval[s|ms]**] [**-m** | **-k keycode** | **-b button**] [**-d dir**] [**-j name**] [**-D**] [**joydev [joydev ...]**] +jsmond [**-i interval[s|ms]**] [**-m** | **-k keycode** | **-b button** | **-c command** | **-x** ] [**-d dir**] [**-j name**] [**-f**] [**-F**] [**-D**] [**joydev [joydev ...]**] DESCRIPTION =========== -jsmond lets you play games with your joysticks/gamepads without -the screen saver activating due to lack of keyboard/mouse input. +jsmond lets you play games with your joysticks/gamepads without the screen +saver activating due to lack of keyboard/mouse input. It can also prevent +the screensaver from activating when a fullscreen window is in use. Multiple joystick devices can be monitored. By default, jsmond monitors up to 16 devices, named /dev/input/js0 through js15. @@ -77,15 +78,17 @@ OPTIONS -c Run a command when activity is detected, rather than sending a fake keystroke/click/motion. It's recommended - to set *interval* to at least 1 second, when using this - option. + to set *interval* to at least 1 second when using this + option, to avoid excess process-spawning overhead. -x Same as **-c "xscreensaver-command -deactivate" -i 1s**. --f Disable screensaver if a full-screen window is detected. - This isn't likely to be 100% reliable. +-f Deactivate screensaver if a fullscreen window is detected. + This isn't likely to be 100% reliable yet. -F Same as **-f**, but also disables joystick monitoring entirely. + Note that **-j**, **-d**, and **joydev** are ignored + with this option. These options are intended for developers and *really* shouldn't be needed for normal use: @@ -132,6 +135,9 @@ jsmond depends on the XTest extension being present in the X server. If you get a "X server doesn't support XTest extension" error, see your X server documentation to find out how to enable XTest. +The fullscreen window monitoring has only been tested on a system with +a single monitor, and may not work properly in multi-head environments. + EXIT STATUS =========== -- cgit v1.2.3