Skip to content

Commit

Permalink
support multiple modifiers (mostly)
Browse files Browse the repository at this point in the history
commit allows deity to stack with currently held modifiers. for
example, if in deity-mode with modifier ControlMask and deity receives
"M-x", deity will (as per my limited testing) output C-M-x.

doesn't support passing multiple modifers directly into deity (yet).
  • Loading branch information
hcur committed Jun 12, 2022
1 parent 874ca6d commit ea03de0
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 43 deletions.
9 changes: 5 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ for any corresponding short options.
Report bugs to <hcurfman@keemail.me>.
```


## install

deity comes with a Makefile, so just:
Expand All @@ -51,6 +50,8 @@ deity comes with a Makefile, so just:

## todo

- support for multiple modifiers
- better error handling
- verbose mode?
- ~~support for multiple modifiers~~
- deity allows adding a mask to a keypress with modifier
- next support passing multiple modifiers into deity
- better error handling
- verbose mode?
58 changes: 19 additions & 39 deletions deity.c
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,20 @@
#include <X11/Xutil.h>


/* supported modifiers:
*
* ControlMask
* Mod1Mask
* Mod4Mask
* ShiftMask
*
* more can be added by modifying the parse_opt function. */

/* this is the key that signals an escape from
* deity mode --- feel free to change it to any
* valid x11 keysym */
#define DEITY_ESCAPE_KEY XK_Escape

/* this is define outside of the argument struct
because it is used throughout later on independently */
enum deitymasks {
CONTROLMASK,
MOD1MASK, // alt
MOD4MASK,
SHIFTMASK,
MODERR
};

/* xlib necessities */
static Display *dpy;
static Window root;
Expand All @@ -45,7 +44,7 @@ struct arguments {
DEITY_STATE,
TYPERR
} type;
enum deitymasks modifier;
unsigned int modifier;
};

static error_t parse_opt(int key, char *arg, struct argp_state *state) {
Expand All @@ -57,13 +56,13 @@ static error_t parse_opt(int key, char *arg, struct argp_state *state) {
case 'm':
/* set modifier */
if (strcmp("Control", arg) == 0 || strcmp("ControlMask", arg) == 0)
args->modifier = CONTROLMASK;
args->modifier = ControlMask;
else if (strcmp("Mod1", arg) == 0 || strcmp("Mod1Mask", arg) == 0)
args->modifier = MOD1MASK;
args->modifier = Mod1Mask;
else if (strcmp("Mod4", arg) == 0 || strcmp("Mod4Mask", arg) == 0)
args->modifier = MOD4MASK;
args->modifier = Mod4Mask;
else if (strcmp("Shift", arg) == 0 || strcmp("ShiftMask", arg) == 0)
args->modifier = SHIFTMASK;
args->modifier = ShiftMask;
break;
case 's':
/* deity state */
Expand Down Expand Up @@ -150,8 +149,8 @@ deity(void)
XGetInputFocus(dpy, &winFocus, &revert);

/* create and send the key events */
XKeyEvent newxev1 = createxev(ev, KeyPress, matchenumkeysym(), winFocus);
XKeyEvent newxev2 = createxev(ev, KeyRelease, matchenumkeysym(), winFocus);
XKeyEvent newxev1 = createxev(ev, KeyPress, ev.xkey.state|arguments.modifier, winFocus);
XKeyEvent newxev2 = createxev(ev, KeyRelease, ev.xkey.state|arguments.modifier, winFocus);
XSendEvent(dpy, winFocus, True, KeyPressMask, (XEvent *)&newxev1);
XSendEvent(dpy, winFocus, True, KeyReleaseMask, (XEvent *)&newxev2);
XFlush(dpy);
Expand All @@ -176,29 +175,10 @@ deitygrabkeys(void)
unsigned int modifiers[] = { 0, LockMask, numlockmask, numlockmask|LockMask };

XUngrabKey(dpy, AnyKey, AnyModifier, root);
for (j = 0; j < MODERR; j++)
for (j = 0; j < 4; j++)
XGrabKey(dpy, AnyKey, modifiers[j], root, False, GrabModeAsync, GrabModeAsync);
}

/* utility function, matches enum types to KeySyms */
unsigned int
matchenumkeysym(void)
{
switch(arguments.modifier)
{
case CONTROLMASK:
return ControlMask;
case MOD1MASK:
return Mod1Mask;
case MOD4MASK:
return Mod4Mask;
case SHIFTMASK:
return ShiftMask;
default:
return -1;
}
}

/* setup the aforementioned xlib necessities */
void
setup(void)
Expand Down Expand Up @@ -230,12 +210,12 @@ int main(int argc, char *argv[])
setup();
/* set defaults --- can't run without flags */
arguments.type = TYPERR;
arguments.modifier = MODERR;
arguments.modifier = -1;

argp_parse(&argp, argc, argv, 0, 0, &arguments);

/* check to ensure flags have been set */
if (arguments.modifier == MODERR)
if (arguments.modifier == -1)
/* FIXME: should replace with argp_usage */
exit(1);
else if (arguments.type == TYPERR)
Expand Down

0 comments on commit ea03de0

Please sign in to comment.