aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorB. Watson <yalhcru@gmail.com>2020-05-18 19:50:10 -0400
committerB. Watson <yalhcru@gmail.com>2020-05-18 19:50:10 -0400
commit71280fcd79497f4c9731c89b33ddc300bb14ae82 (patch)
treed537ebbacf4a25f61c582005a80afe570702b19a
parent7c9e476867bc4271919dfc367514be0033426344 (diff)
downloadunsaver-71280fcd79497f4c9731c89b33ddc300bb14ae82.tar.gz
add command execution mode, -c and -x
-rw-r--r--jsmond.158
-rw-r--r--jsmond.c91
-rw-r--r--jsmond.html57
-rw-r--r--jsmond.rst34
4 files changed, 198 insertions, 42 deletions
diff --git a/jsmond.1 b/jsmond.1
index e496a3b..9a5ff14 100644
--- a/jsmond.1
+++ b/jsmond.1
@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
-.TH JSMOND 1 "2020-05-17" "0.2.0" "Urchlay"
+.TH JSMOND 1 "2020-05-18" "0.2.0" "Urchlay"
.SH NAME
jsmond \- deactivate screensaver on joystick activity
.
@@ -36,7 +36,7 @@ level margin: \\n[rst2man-indent\\n[rst2man-indent-level]]
.
.SH SYNOPSIS
.sp
-jsmond [\fB\-i interval\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\-d dir\fP] [\fB\-j name\fP] [\fB\-D\fP] [\fBjoydev [joydev ...]\fP]
.SH DESCRIPTION
.sp
jsmond lets you play games with your joysticks/gamepads without
@@ -49,7 +49,7 @@ as joysticks are plugged in and unplugged.
.sp
Every \fIinterval\fP milliseconds (250, or whatever \fB\-i\fP is set to), jsmond
checks to see if there\(aqs been any activity on any of the devices it\(aqs
-monitoring. If so, it sends a fake keystroke or mouse button click, which
+monitoring. If so, it sends a fake mouse movement, keystroke, or mouse button click, which
the screen saver will see as activity.
.sp
It\(aqs recommended to let jsmond find the joysticks itself. However,
@@ -67,9 +67,12 @@ if you need to kill the daemon.
.B \-\-help
Print usage summary
.TP
-.BI \-i \ <millis>
-Interval to check for activity, in milliseconds.
-Default: 250.
+.BI \-i \ <interval>
+Interval to check for activity. Can be given in seconds
+with \fIs\fP suffix (e.g. \fB1s\fP), or milliseconds with \fIm\fP
+(e.g. \fB200m\fP). If just a number is given, it\(aqs assumed
+to be in seconds if it\(aqs under 100, otherwise it\(aqs treated
+as milliseconds. Default: 250m.
.TP
.BI \-k \ <keycode>
Send this keycode when activity is detected. Default
@@ -80,7 +83,24 @@ in your usual keymapping (use "xmodmap \-pk" to find one).
.BI \-b \ <button>
Send a click of this button when activity is detected,
rather than a keystroke. Should be a button that
-applications don\(aqt normally respond to (6 or higher).
+applications don\(aqt normally respond to (6 or higher),
+but in some environments, the window manager responds to
+all the \(aqextra\(aq buttons as though they were button 1.
+.TP
+.B \-m
+Send mouse movements rather than a keystroke. This will
+move the pointer 10 pixels to the right and down, then
+10 pixels to the left and up, then warp the pointer back
+to its starting point.
+.TP
+.BI \-c \ <command>
+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.
+.TP
+.B \-x
+Same as \fB\-c "xscreensaver\-command \-exit" \-i 1s\fP\&.
.UNINDENT
.sp
These options are intended for developers and \fIreally\fP shouldn\(aqt be
@@ -103,11 +123,14 @@ A space is required between an option and its argument, as shown
above. Use e.g. \fB\-i 300\fP, not \fB\-i300\fP\&.
.SH NOTES
.sp
-By default, jsmond searches for and monitors all the joysticks it can
-find, up to MAX_STICKS (normally 16; see the \fB\-\-help\fP output to find
-the compiled\-in default). You can override the search on the command
-line by providing one or more \fBjoydev\fP arguments, in which case only
-those devices will be monitored.
+jsmond was tested with xlock(1) and xscreensaver(1). All 3 modes
+(keycode, mouse click, and mouse motion) work with xscreensaver.
+xlock doesn\(aqt respond to mouse motion, so use the keycode or click
+modes with it.
+.sp
+jsmond can monitor up to MAX_STICKS joysticks. This is a compile time
+constant, normally set to 16. See the \fB\-\-help\fP output to find out
+the compiled\-in default.
.sp
\fBjoydev\fP arguments can be either a path to a device node (e.g.
\fI/dev/input/js0\fP or similar), or a number, which will have the default
@@ -121,8 +144,12 @@ jsmond will wait for devices to come into existence (e.g. as created
by \fBudev\fP).
.sp
If the screensaver is configured to lock the screen, and it has already
-activated, pressing a joystick button/direction will just bring up the
+done so, pressing a joystick button/direction will just bring up the
password dialog, same as pressing a key or mouse button would.
+.sp
+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.
.SH EXIT STATUS
.sp
Without the \-D option, the exit status is 0 (success) if jsmond
@@ -141,7 +168,10 @@ names (better to autodetect).
.sp
Normally once daemonized, jsmond is very robust. However, if something
does go wrong, there\(aqs no way to find out what. Probably there should
-be a log file, or use syslog.
+be a log file, or use syslog (or is that overkill?).
+.sp
+It should be (but currently isn\(aqt) possible to at least work in
+mouse\-motion mode even without the XTest extension, via XWarpPointer().
.sp
jsmond isn\(aqt portable. It only works on Linux, at least for now, for
three reasons:
diff --git a/jsmond.c b/jsmond.c
index d5e2606..ca3c1a0 100644
--- a/jsmond.c
+++ b/jsmond.c
@@ -35,12 +35,15 @@
#define MIN_BUTTON 1
#define MAX_BUTTON 10
+/* command for -x */
+#define X_COMMAND "xscreensaver-command -deactivate"
+
typedef enum {
- fm_auto_keycode, fm_keycode, fm_button, fm_motion
+ fm_auto_keycode, fm_keycode, fm_button, fm_motion, fm_cmd
} fake_mode_t;
/* user options */
-int interval = 250; /* -i */
+int interval = 250; /* -i (always in millisec) */
int debug = 0; /* -D */
int keycode = -1; /* -k */
int button = -1; /* -b */
@@ -48,6 +51,7 @@ char *event_dir = EVENTDIR; /* -d */
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 */
/* joystick stuff */
char *joynames[MAX_STICKS + 1];
@@ -167,6 +171,14 @@ void send_fake_motion(void) {
XSync(xdisp, 0);
}
+void exec_command(void) {
+ if(!c_command)
+ die("BUG: c_command is NULL\n");
+
+ if(debug) fprintf(stderr, "executing \"%s\"\n", c_command);
+ system(c_command);
+}
+
void send_fake_x_event(void) {
switch(fake_mode) {
case fm_keycode:
@@ -178,6 +190,9 @@ void send_fake_x_event(void) {
case fm_motion:
send_fake_motion();
break;
+ case fm_cmd:
+ exec_command();
+ break;
default: /* This Never Happens(tm) */
fprintf(stderr, "%s: BUG: fake_mode %d isn't a valid fake_mode_t!\n",
self, fake_mode);
@@ -221,10 +236,17 @@ void check_inotify() {
fprintf(stderr, "got event with name %s: 0x%x\n", inotify_ev->name, inotify_ev->mask);
}
}
+
+ /* not much we can do to recover from this: */
if(inotify_ev->mask & IN_DELETE_SELF) {
- /* not much we can do to recover from this */
die("someone deleted our device directory!");
}
+
+ /* ...or this: */
+ if(inotify_ev->mask & IN_UNMOUNT) {
+ die("someone unmounted our device directory!");
+ }
+
usleep(EVENT_DELAY); /* might not need, be paranoid */
open_joysticks();
} else {
@@ -340,6 +362,37 @@ void set_fake_mode(fake_mode_t newmode) {
fake_mode = newmode;
}
+int set_interval(const char *arg) {
+ char *end;
+
+ interval = strtol(arg, &end, 0);
+
+ /* no digits at all */
+ if(end == arg) return 0;
+
+ /* no 0 or negative */
+ if(interval < 1) return 0;
+
+ /* digits only */
+ switch(*end) {
+ case '\0':
+ /* digits only, try to guess */
+ if(interval < 100) {
+ fprintf(stderr,
+ "%s: treating -i %d as %d seconds (use -i %dms if you meant %dms)\n",
+ self, interval, interval, interval, interval);
+ /* fall through */
+ } else {
+ break;
+ }
+ case 's': interval *= 1000; break; /* sec */
+ case 'm': break; /* ms, use as-is */
+ }
+
+ if(debug) fprintf(stderr, "interval set to %dms\n", interval);
+ return 1;
+}
+
void parse_args(int argc, char **argv) {
char *nextarg;
@@ -384,7 +437,7 @@ void parse_args(int argc, char **argv) {
}
break;
case 'i':
- if(nextarg && (interval = atoi(nextarg)) > 0)
+ if(nextarg && set_interval(nextarg))
argv++, argc--;
else
die("-i requires a positive integer argument in milliseconds");
@@ -408,6 +461,23 @@ void parse_args(int argc, char **argv) {
case 'D':
debug = 1;
break;
+ case 'c':
+ if(nextarg) {
+ set_fake_mode(fm_cmd);
+ c_command = nextarg;
+ argv++, argc--;
+ } else {
+ die("-c requires a command argument");
+ }
+ break;
+ case 'x':
+ set_fake_mode(fm_cmd);
+ c_command = X_COMMAND;
+ break;
+ case 'f':
+ case 'F':
+ die("-f and -F not yet implemented");
+ break;
default:
die("unrecognized argument, try --help");
break;
@@ -511,12 +581,23 @@ void find_keycode() {
}
}
+/* the device name check is mostly to guard against typos */
+void check_joyname(int i) {
+ if(joynames[i] && (strncmp(event_dir, joynames[i], strlen(event_dir)) != 0)) {
+ fprintf(stderr, "%s: device %s is not in event dir %s\n",
+ self, joynames[i], event_dir);
+ exit(1);
+ }
+}
+
/* init_* functions. these are only called once each, from main() */
void init_joysticks(void) {
int i;
- for(i = 0; i < MAX_STICKS; i++)
+ for(i = 0; i < MAX_STICKS; i++) {
joyfds[i] = -1;
+ check_joyname(i);
+ }
open_joysticks();
}
diff --git a/jsmond.html b/jsmond.html
index 20608d9..9c4f31b 100644
--- a/jsmond.html
+++ b/jsmond.html
@@ -5,7 +5,7 @@
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.14: http://docutils.sourceforge.net/" />
<title>jsmond</title>
-<meta name="date" content="2020-05-17" />
+<meta name="date" content="2020-05-18" />
<style type="text/css">
/*
@@ -373,7 +373,7 @@ ul.auto-toc {
<tr class="manual-group field"><th class="docinfo-name">Manual group:</th><td class="field-body">Urchlay</td>
</tr>
<tr><th class="docinfo-name">Date:</th>
-<td>2020-05-17</td></tr>
+<td>2020-05-18</td></tr>
<tr><th class="docinfo-name">Version:</th>
<td>0.2.0</td></tr>
</tbody>
@@ -382,7 +382,7 @@ ul.auto-toc {
<!-- rst2man.py jsmond.rst > jsmond.1 -->
<div class="section" id="synopsis">
<h1>SYNOPSIS</h1>
-<p>jsmond [<strong>-i interval</strong>] [<strong>-k keycode</strong> | <strong>-b button</strong>] [<strong>-d dir</strong>] [<strong>-j name</strong>] [<strong>-D</strong>] [<strong>joydev [joydev ...]</strong>]</p>
+<p>jsmond [<strong>-i interval[s|ms]</strong>] [<strong>-m</strong> | <strong>-k keycode</strong> | <strong>-b button</strong>] [<strong>-d dir</strong>] [<strong>-j name</strong>] [<strong>-D</strong>] [<strong>joydev [joydev ...]</strong>]</p>
</div>
<div class="section" id="description">
<h1>DESCRIPTION</h1>
@@ -394,7 +394,7 @@ These devices don't have to actually exist: they can come and go
as joysticks are plugged in and unplugged.</p>
<p>Every <em>interval</em> milliseconds (250, or whatever <strong>-i</strong> is set to), jsmond
checks to see if there's been any activity on any of the devices it's
-monitoring. If so, it sends a fake keystroke or mouse button click, which
+monitoring. If so, it sends a fake mouse movement, keystroke, or mouse button click, which
the screen saver will see as activity.</p>
<p>It's recommended to let jsmond find the joysticks itself. However,
you can pass one or more device names (or just numbers) if the default
@@ -415,9 +415,12 @@ if you need to kill the daemon.</p>
<kbd><span class="option">--help</span></kbd></td>
<td>Print usage summary</td></tr>
<tr><td class="option-group">
-<kbd><span class="option">-i <var>&lt;millis&gt;</var></span></kbd></td>
-<td>Interval to check for activity, in milliseconds.
-Default: 250.</td></tr>
+<kbd><span class="option">-i <var>&lt;interval&gt;</var></span></kbd></td>
+<td>Interval to check for activity. Can be given in seconds
+with <em>s</em> suffix (e.g. <strong>1s</strong>), or milliseconds with <em>m</em>
+(e.g. <strong>200m</strong>). If just a number is given, it's assumed
+to be in seconds if it's under 100, otherwise it's treated
+as milliseconds. Default: 250m.</td></tr>
<tr><td class="option-group">
<kbd><span class="option">-k <var>&lt;keycode&gt;</var></span></kbd></td>
<td>Send this keycode when activity is detected. Default
@@ -428,7 +431,24 @@ in your usual keymapping (use &quot;xmodmap -pk&quot; to find one).</td></tr>
<kbd><span class="option">-b <var>&lt;button&gt;</var></span></kbd></td>
<td>Send a click of this button when activity is detected,
rather than a keystroke. Should be a button that
-applications don't normally respond to (6 or higher).</td></tr>
+applications don't normally respond to (6 or higher),
+but in some environments, the window manager responds to
+all the 'extra' buttons as though they were button 1.</td></tr>
+<tr><td class="option-group">
+<kbd><span class="option">-m</span></kbd></td>
+<td>Send mouse movements rather than a keystroke. This will
+move the pointer 10 pixels to the right and down, then
+10 pixels to the left and up, then warp the pointer back
+to its starting point.</td></tr>
+<tr><td class="option-group">
+<kbd><span class="option">-c <var>&lt;command&gt;</var></span></kbd></td>
+<td>Run a command when activity is detected, rather than
+sending a fake keystroke/click/motion. It's recommended
+to set <em>interval</em> to at least 1 second, when using this
+option.</td></tr>
+<tr><td class="option-group">
+<kbd><span class="option">-x</span></kbd></td>
+<td>Same as <strong>-c &quot;xscreensaver-command -exit&quot; -i 1s</strong>.</td></tr>
</tbody>
</table>
<p>These options are intended for developers and <em>really</em> shouldn't be
@@ -455,11 +475,13 @@ above. Use e.g. <strong>-i 300</strong>, not <strong>-i300</strong>.</p>
</div>
<div class="section" id="notes">
<h1>NOTES</h1>
-<p>By default, jsmond searches for and monitors all the joysticks it can
-find, up to MAX_STICKS (normally 16; see the <strong>--help</strong> output to find
-the compiled-in default). You can override the search on the command
-line by providing one or more <strong>joydev</strong> arguments, in which case only
-those devices will be monitored.</p>
+<p>jsmond was tested with xlock(1) and xscreensaver(1). All 3 modes
+(keycode, mouse click, and mouse motion) work with xscreensaver.
+xlock doesn't respond to mouse motion, so use the keycode or click
+modes with it.</p>
+<p>jsmond can monitor up to MAX_STICKS joysticks. This is a compile time
+constant, normally set to 16. See the <strong>--help</strong> output to find out
+the compiled-in default.</p>
<p><strong>joydev</strong> arguments can be either a path to a device node (e.g.
<em>/dev/input/js0</em> or similar), or a number, which will have the default
device basename prepended to it. This is normally &quot;/dev/input/js&quot;, but
@@ -470,8 +492,11 @@ to detect hotplug events!</p>
jsmond will wait for devices to come into existence (e.g. as created
by <strong>udev</strong>).</p>
<p>If the screensaver is configured to lock the screen, and it has already
-activated, pressing a joystick button/direction will just bring up the
+done so, pressing a joystick button/direction will just bring up the
password dialog, same as pressing a key or mouse button would.</p>
+<p>jsmond depends on the XTest extension being present in the X server. If
+you get a &quot;X server doesn't support XTest extension&quot; error, see your X
+server documentation to find out how to enable XTest.</p>
</div>
<div class="section" id="exit-status">
<h1>EXIT STATUS</h1>
@@ -489,7 +514,9 @@ been plugged in yet. Try to avoid typos, if you really have to use device
names (better to autodetect).</p>
<p>Normally once daemonized, jsmond is very robust. However, if something
does go wrong, there's no way to find out what. Probably there should
-be a log file, or use syslog.</p>
+be a log file, or use syslog (or is that overkill?).</p>
+<p>It should be (but currently isn't) possible to at least work in
+mouse-motion mode even without the XTest extension, via XWarpPointer().</p>
<p>jsmond isn't portable. It only works on Linux, at least for now, for
three reasons:</p>
<ul class="simple">
diff --git a/jsmond.rst b/jsmond.rst
index bf9f9c8..89b47a6 100644
--- a/jsmond.rst
+++ b/jsmond.rst
@@ -20,7 +20,7 @@ deactivate screensaver on joystick activity
SYNOPSIS
========
-jsmond [**-i interval**] [**-m** | **-k keycode** | **-b button**] [**-d dir**] [**-j name**] [**-D**] [**joydev [joydev ...]**]
+jsmond [**-i interval[s|ms]**] [**-m** | **-k keycode** | **-b button**] [**-d dir**] [**-j name**] [**-D**] [**joydev [joydev ...]**]
DESCRIPTION
===========
@@ -53,8 +53,11 @@ OPTIONS
--help Print usage summary
--i <millis> Interval to check for activity, in milliseconds.
- Default: 250.
+-i <interval> Interval to check for activity. Can be given in seconds
+ with *s* suffix (e.g. **1s**), or milliseconds with *m*
+ (e.g. **200m**). If just a number is given, it's assumed
+ to be in seconds if it's under 100, otherwise it's treated
+ as milliseconds. Default: 250m.
-k <keycode> Send this keycode when activity is detected. Default
is to search the keymap for an unused code. If you set this
@@ -72,6 +75,18 @@ OPTIONS
10 pixels to the left and up, then warp the pointer back
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.
+
+-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 Same as **-f**, but also disables joystick monitoring entirely.
+
These options are intended for developers and *really* shouldn't be
needed for normal use:
@@ -89,11 +104,14 @@ above. Use e.g. **-i 300**, not **-i300**.
NOTES
=====
-By default, jsmond searches for and monitors all the joysticks it can
-find, up to MAX_STICKS (normally 16; see the **--help** output to find
-the compiled-in default). You can override the search on the command
-line by providing one or more **joydev** arguments, in which case only
-those devices will be monitored.
+jsmond was tested with xlock(1) and xscreensaver(1). All 3 modes
+(keycode, mouse click, and mouse motion) work with xscreensaver.
+xlock doesn't respond to mouse motion, so use the keycode or click
+modes with it.
+
+jsmond can monitor up to MAX_STICKS joysticks. This is a compile time
+constant, normally set to 16. See the **--help** output to find out
+the compiled-in default.
**joydev** arguments can be either a path to a device node (e.g.
*/dev/input/js0* or similar), or a number, which will have the default