Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion examples/skhdrc
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@
#
# mod = 'modifier keyword' | <mod> '+' <mod>
#
# key = <literal> | <keycode>
# key = <literal> | <keycode> | <button>
#
# literal = 'single letter or built-in keyword'
#
# keycode = 'apple keyboard kVK_<Key> values (0x3C)'
#
# button = mouse_left | mouse_right | mouse_center |
# m[3-31]
#
# proc_map_lst = * <proc_map>
#
# proc_map = <string> ':' <command> | <string> '~' |
Expand Down
9 changes: 5 additions & 4 deletions src/hotkey.c
Original file line number Diff line number Diff line change
Expand Up @@ -63,12 +63,13 @@ bool same_hotkey(struct hotkey *a, struct hotkey *b)
compare_lr_mod(a, b, LRMOD_SHIFT) &&
compare_fn(a, b) &&
compare_nx(a, b) &&
a->key == b->key;
a->key == b->key &&
a->button == b->button;
}

unsigned long hash_hotkey(struct hotkey *a)
{
return a->key;
return (a->key << 6) | a->button;
}

bool compare_string(char *a, char *b)
Expand Down Expand Up @@ -273,7 +274,8 @@ struct hotkey create_eventkey(CGEventRef event)
{
struct hotkey eventkey = {
.key = CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode),
.flags = cgevent_flags_to_hotkey_flags(CGEventGetFlags(event))
.flags = cgevent_flags_to_hotkey_flags(CGEventGetFlags(event)),
.button = CGEventGetIntegerValueField(event, kCGMouseEventButtonNumber),
};
return eventkey;
}
Expand All @@ -289,7 +291,6 @@ bool intercept_systemkey(CGEventRef event, struct hotkey *eventkey)

bool result = ((key_state == NX_KEYDOWN) &&
(key_stype == NX_SUBTYPE_AUX_CONTROL_BUTTONS));

if (result) {
eventkey->key = key_code;
eventkey->flags = cgevent_flags_to_hotkey_flags(CGEventGetFlags(event)) | Hotkey_Flag_NX;
Expand Down
1 change: 1 addition & 0 deletions src/hotkey.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ struct hotkey
{
uint32_t flags;
uint32_t key;
uint8_t button;
char **process_name;
char **command;
char *wildcard_command;
Expand Down
35 changes: 33 additions & 2 deletions src/parse.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ keycode_from_hex(char *hex)
return result;
}

static uint8_t
button_number_from_name(char *name)
{
uint8_t result;
sscanf(name, "m%hhu", &result);
return result;
}

static void
parse_command(struct parser *parser, struct hotkey *hotkey)
{
Expand Down Expand Up @@ -199,6 +207,21 @@ parse_key_literal(struct parser *parser, struct hotkey *hotkey)
}
}

static uint8_t
parse_button(struct parser *parser)
{
struct token button = parser_previous(parser);
for (uint8_t i = 0; i < 3; ++i) {
if (token_equals(button, mouse_button_str[i])) {
debug("\tbutton: '%hhu'\n", i);
return i;
}
}
uint8_t button_number = button_number_from_name(button.text);
debug("\tbutton: '%hhu'\n", button_number);
return button_number;
}

static enum hotkey_flag modifier_flags_value[] =
{
Hotkey_Flag_Alt, Hotkey_Flag_LAlt, Hotkey_Flag_RAlt,
Expand Down Expand Up @@ -266,6 +289,7 @@ parse_hotkey(struct parser *parser)
{
struct hotkey *hotkey = malloc(sizeof(struct hotkey));
memset(hotkey, 0, sizeof(struct hotkey));
hotkey->button = -1;
bool found_modifier;

debug("hotkey :: #%d {\n", parser->current_token.line);
Expand Down Expand Up @@ -306,6 +330,8 @@ parse_hotkey(struct parser *parser)
hotkey->key = parse_key_hex(parser);
} else if (parser_match(parser, Token_Literal)) {
parse_key_literal(parser, hotkey);
} else if (parser_match(parser, Token_Button)) {
hotkey->button = parse_button(parser);
} else {
parser_report_error(parser, parser_peek(parser), "expected key-literal\n");
goto err;
Expand Down Expand Up @@ -477,7 +503,8 @@ bool parse_config(struct parser *parser)
(parser_check(parser, Token_Modifier)) ||
(parser_check(parser, Token_Literal)) ||
(parser_check(parser, Token_Key_Hex)) ||
(parser_check(parser, Token_Key))) {
(parser_check(parser, Token_Key)) ||
(parser_check(parser, Token_Button))) {
if ((hotkey = parse_hotkey(parser))) {
for (int i = 0; i < buf_len(hotkey->mode_list); ++i) {
mode = hotkey->mode_list[i];
Expand Down Expand Up @@ -508,9 +535,11 @@ parse_keypress(struct parser *parser)
if ((parser_check(parser, Token_Modifier)) ||
(parser_check(parser, Token_Literal)) ||
(parser_check(parser, Token_Key_Hex)) ||
(parser_check(parser, Token_Key))) {
(parser_check(parser, Token_Key)) ||
(parser_check(parser, Token_Button))) {
struct hotkey *hotkey = malloc(sizeof(struct hotkey));
memset(hotkey, 0, sizeof(struct hotkey));
hotkey->button = -1;
bool found_modifier;

if ((found_modifier = parser_match(parser, Token_Modifier))) {
Expand All @@ -532,6 +561,8 @@ parse_keypress(struct parser *parser)
hotkey->key = parse_key_hex(parser);
} else if (parser_match(parser, Token_Literal)) {
parse_key_literal(parser, hotkey);
} else if (parser_match(parser, Token_Button)) {
hotkey->button = parse_button(parser);
} else {
goto err;
}
Expand Down
23 changes: 19 additions & 4 deletions src/skhd.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,9 +139,13 @@ static EVENT_TAP_CALLBACK(key_observer_handler)
CGEventTapEnable(event_tap->handle, 1);
} break;
case kCGEventKeyDown:
case kCGEventFlagsChanged: {
case kCGEventFlagsChanged:
case kCGEventLeftMouseDown:
case kCGEventRightMouseDown:
case kCGEventOtherMouseDown: {
uint32_t flags = CGEventGetFlags(event);
uint32_t keycode = CGEventGetIntegerValueField(event, kCGKeyboardEventKeycode);
uint32_t button = CGEventGetIntegerValueField(event, kCGMouseEventButtonNumber);

if (keycode == kVK_ANSI_C && flags & 0x40000) {
exit(0);
Expand All @@ -151,6 +155,7 @@ static EVENT_TAP_CALLBACK(key_observer_handler)
for (int i = 31; i >= 0; --i) {
printf("%c", (flags & (1 << i)) ? '1' : '0');
}
printf("\tbutton: %d", button);
fflush(stdout);

return NULL;
Expand All @@ -168,7 +173,10 @@ static EVENT_TAP_CALLBACK(key_handler)
struct event_tap *event_tap = (struct event_tap *) reference;
CGEventTapEnable(event_tap->handle, 1);
} break;
case kCGEventKeyDown: {
case kCGEventKeyDown:
case kCGEventLeftMouseDown:
case kCGEventRightMouseDown:
case kCGEventOtherMouseDown: {
if (table_find(&blacklst, carbon.process_name)) return event;
if (!current_mode) return event;

Expand Down Expand Up @@ -343,7 +351,10 @@ static bool parse_arguments(int argc, char **argv)
} break;
case 'o': {
event_tap.mask = (1 << kCGEventKeyDown) |
(1 << kCGEventFlagsChanged);
(1 << kCGEventFlagsChanged) |
(1 << kCGEventLeftMouseDown) |
(1 << kCGEventRightMouseDown) |
(1 << kCGEventOtherMouseDown);
event_tap_begin(&event_tap, key_observer_handler);
CFRunLoopRun();
} break;
Expand Down Expand Up @@ -511,7 +522,11 @@ int main(int argc, char **argv)
END_SCOPED_TIMED_BLOCK();

BEGIN_SCOPED_TIMED_BLOCK("begin_eventtap");
event_tap.mask = (1 << kCGEventKeyDown) | (1 << NX_SYSDEFINED);
event_tap.mask = (1 << kCGEventKeyDown) |
(1 << NX_SYSDEFINED) |
(1 << kCGEventLeftMouseDown) |
(1 << kCGEventRightMouseDown) |
(1 << kCGEventOtherMouseDown);
event_tap_begin(&event_tap, key_handler);
END_SCOPED_TIMED_BLOCK();
END_SCOPED_TIMED_BLOCK();
Expand Down
28 changes: 25 additions & 3 deletions src/synthesize.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,24 @@ create_and_post_keyevent(uint16_t key, bool pressed)
CGPostKeyboardEvent((CGCharCode)0, (CGKeyCode)key, pressed);
}

static inline void
create_and_post_mouseclickevent(uint8_t button, bool pressed)
{
button = pressed ? button : -1;
CGPostMouseEvent((CGPoint){-1, -1}, false, 32,
0 == button, 1 == button, 2 == button,
3 == button, 4 == button, 5 == button,
6 == button, 7 == button, 8 == button,
9 == button, 10 == button, 11 == button,
12 == button, 13 == button, 14 == button,
15 == button, 16 == button, 17 == button,
18 == button, 19 == button, 20 == button,
21 == button, 22 == button, 23 == button,
24 == button, 25 == button, 26 == button,
27 == button, 28 == button, 29 == button,
30 == button, 31 == button);
}

static inline void
synthesize_modifiers(struct hotkey *hotkey, bool pressed)
{
Expand Down Expand Up @@ -55,9 +73,13 @@ void synthesize_key(char *key_string)
CGEnableEventStateCombining(false);

synthesize_modifiers(hotkey, true);
create_and_post_keyevent(hotkey->key, true);

create_and_post_keyevent(hotkey->key, false);
if (hotkey->button == (uint8_t)-1) {
create_and_post_keyevent(hotkey->key, true);
create_and_post_keyevent(hotkey->key, false);
} else {
create_and_post_mouseclickevent(hotkey->button, true);
create_and_post_mouseclickevent(hotkey->button, false);
}
synthesize_modifiers(hotkey, false);
}

Expand Down
6 changes: 6 additions & 0 deletions src/tokenize.c
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,12 @@ resolve_identifier_type(struct token token)
}
}

for (int i = 0; i < array_count(mouse_button_str); ++i) {
if (token_equals(token, mouse_button_str[i])) {
return Token_Button;
}
}

return Token_Identifier;
}

Expand Down
15 changes: 15 additions & 0 deletions src/tokenize.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,20 @@ static const char *literal_keycode_str[] =
"brightness_down", "illumination_up", "illumination_down"
};

static const char *mouse_button_str[] =
{
"mouse_left", "mouse_right", "mouse_center",
"m3", "m4", "m5",
"m6", "m7", "m8",
"m9", "m10", "m11",
"m12", "m13", "m14",
"m15", "m16", "m17",
"m18", "m19", "m20",
"m21", "m22", "m23",
"m24", "m25", "m26",
"m27", "m28", "m29",
"m30", "m31"
};
enum token_type
{
Token_Identifier,
Expand All @@ -41,6 +55,7 @@ enum token_type
Token_Literal,
Token_Key_Hex,
Token_Key,
Token_Button,

Token_Decl,
Token_Comma,
Expand Down