summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVito Caputo <vcaputo@pengaru.com>2023-10-18 17:10:22 -0700
committerVito Caputo <vcaputo@pengaru.com>2023-10-18 17:18:29 -0700
commitf5c9b65592327c2094d5981bb95d3e4afdf76344 (patch)
treeed1c1e7f3e8bc7dbcb762eca6de9409dace5e7a3
parentc2f9bcd457b57b6d96a5cbdd9c36272994bc19c3 (diff)
parseargs,error: add --need-shortcuts
When you depend on the shortcuts as _the_ means of stopping/pausing a recording, like in a WM integration scenario, it's preferable to have rmd exit fatally when the grabs can't be setup. (usually this occurs when you've accidentally tried starting multiple recordings, and the shortcuts collide) This way, the integration can detect the failure and throw up a dialog or something informing the user that the recording wasn't started. All that's needed is including --need-shortcuts. Note this is a little janky in how it's implemented, because XSetErrorHandler() is janky and doesn't even support a user pointer payload. Rather than introducing global variables to either communicate the grab failures to other parts of rmd, or exposing the parsed args struct to the error handler globally in the other direction, I just made a grab-errors-are-fatal variant of the handler which gets installed when --need-shortcuts is specified.
-rw-r--r--src/rmd.c2
-rw-r--r--src/rmd_error.c15
-rw-r--r--src/rmd_error.h3
-rw-r--r--src/rmd_parseargs.c5
-rw-r--r--src/rmd_types.h1
5 files changed, 23 insertions, 3 deletions
diff --git a/src/rmd.c b/src/rmd.c
index c76b5bf..27e7183 100644
--- a/src/rmd.c
+++ b/src/rmd.c
@@ -76,7 +76,7 @@ int main(int argc, char **argv)
if (pdata.args.display != NULL) {
pdata.dpy = XOpenDisplay(pdata.args.display);
- XSetErrorHandler(rmdErrorHandler);
+ XSetErrorHandler(pdata.args.need_shortcuts ? rmdGrabErrorsFatalErrorHandler : rmdErrorHandler);
} else {
fprintf(stderr, "No display specified for connection!\n");
exit(8);
diff --git a/src/rmd_error.c b/src/rmd_error.c
index aaef20a..f8c137e 100644
--- a/src/rmd_error.c
+++ b/src/rmd_error.c
@@ -35,7 +35,7 @@
-int rmdErrorHandler(Display *dpy, XErrorEvent *e)
+static int rmdSharedErrorHandler(Display *dpy, XErrorEvent *e, boolean grabsfatal)
{
char error_desc[1024];
@@ -49,8 +49,19 @@ int rmdErrorHandler(Display *dpy, XErrorEvent *e)
if ((e->error_code == BadAccess) && (e->request_code == X_GrabKey)) {
fprintf(stderr, "Bad Access on XGrabKey.\n" "Shortcut already assigned.\n");
- return 0;
+ if (!grabsfatal)
+ return 0;
}
exit(1);
}
+
+int rmdErrorHandler(Display *dpy, XErrorEvent *e)
+{
+ return rmdSharedErrorHandler(dpy, e, FALSE /* grabsfatal */);
+}
+
+int rmdGrabErrorsFatalErrorHandler(Display *dpy, XErrorEvent *e)
+{
+ return rmdSharedErrorHandler(dpy, e, TRUE /* grabsfatal */);
+}
diff --git a/src/rmd_error.h b/src/rmd_error.h
index 4d27264..de5c7b0 100644
--- a/src/rmd_error.h
+++ b/src/rmd_error.h
@@ -45,5 +45,8 @@
*/
int rmdErrorHandler(Display *dpy,XErrorEvent *e);
+/* identical to rmdErrorHandler, but exits on grab errors (--needs-shortcuts) */
+int rmdGrabErrorsFatalErrorHandler(Display *dpy, XErrorEvent *e);
+
#endif
diff --git a/src/rmd_parseargs.c b/src/rmd_parseargs.c
index 272d43e..8ee4328 100644
--- a/src/rmd_parseargs.c
+++ b/src/rmd_parseargs.c
@@ -257,6 +257,11 @@ boolean rmdParseArgs(int argc, char **argv, ProgArgs *arg_return)
"Shortcut that will be used to stop the recording (default Control+Mod1+s).",
"MOD+KEY" },
+ { "need-shortcuts", '\0',
+ POPT_ARG_NONE, &arg_return->need_shortcuts, 0,
+ "Treat shorcut installation failures as fatal.",
+ NULL },
+
{ "compress-cache", '\0',
POPT_ARG_NONE, &compress_cache, 0,
"Image data are cached with light compression.",
diff --git a/src/rmd_types.h b/src/rmd_types.h
index f70efac..b503da8 100644
--- a/src/rmd_types.h
+++ b/src/rmd_types.h
@@ -151,6 +151,7 @@ typedef struct _ProgArgs{
char *workdir; //directory to be used for cache files(default $HOME)
char *pause_shortcut; //pause/unpause shortcut sequence(Control+Alt+p)
char *stop_shortcut; //stop shortcut sequence(Control+Alt+s)
+ int need_shortcuts; //exit fatally when shortcuts can't be installed
int noframe; //don't draw a frame around the recording area
int zerocompression; //image data are always flushed uncompressed
unsigned periodic_datasync_ms; //interval between background async fdatasync calls while writing cache files, when zero no periodic fdatasync is performed
© All Rights Reserved