Skip to content

Commit

Permalink
Fix ModifiedKey roll-interaction with same non-modified keys
Browse files Browse the repository at this point in the history
  • Loading branch information
xs5871 committed Jan 12, 2025
1 parent 0b26d06 commit 6ddbf20
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 29 deletions.
70 changes: 41 additions & 29 deletions kmk/keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -255,33 +255,36 @@ def maybe_make_numpad_key(candidate: str) -> Optional[Key]:

def maybe_make_shifted_key(candidate: str) -> Optional[Key]:
codes = (
(30, ('EXCLAIM', 'EXLM', '!')),
(31, ('AT', '@')),
(32, ('HASH', 'POUND', '#')),
(33, ('DOLLAR', 'DLR', '$')),
(34, ('PERCENT', 'PERC', '%')),
(35, ('CIRCUMFLEX', 'CIRC', '^')),
(36, ('AMPERSAND', 'AMPR', '&')),
(37, ('ASTERISK', 'ASTR', '*')),
(38, ('LEFT_PAREN', 'LPRN', '(')),
(39, ('RIGHT_PAREN', 'RPRN', ')')),
(45, ('UNDERSCORE', 'UNDS', '_')),
(46, ('PLUS', '+')),
(47, ('LEFT_CURLY_BRACE', 'LCBR', '{')),
(48, ('RIGHT_CURLY_BRACE', 'RCBR', '}')),
(49, ('PIPE', '|')),
(51, ('COLON', 'COLN', ':')),
(52, ('DOUBLE_QUOTE', 'DQUO', 'DQT', '"')),
(53, ('TILDE', 'TILD', '~')),
(54, ('LEFT_ANGLE_BRACKET', 'LABK', '<')),
(55, ('RIGHT_ANGLE_BRACKET', 'RABK', '>')),
(56, ('QUESTION', 'QUES', '?')),
('1', ('EXCLAIM', 'EXLM', '!')),
('2', ('AT', '@')),
('3', ('HASH', 'POUND', '#')),
('4', ('DOLLAR', 'DLR', '$')),
('5', ('PERCENT', 'PERC', '%')),
('6', ('CIRCUMFLEX', 'CIRC', '^')),
('7', ('AMPERSAND', 'AMPR', '&')),
('8', ('ASTERISK', 'ASTR', '*')),
('9', ('LEFT_PAREN', 'LPRN', '(')),
('0', ('RIGHT_PAREN', 'RPRN', ')')),
('-', ('UNDERSCORE', 'UNDS', '_')),
('=', ('PLUS', '+')),
('[', ('LEFT_CURLY_BRACE', 'LCBR', '{')),
(']', ('RIGHT_CURLY_BRACE', 'RCBR', '}')),
('\\', ('PIPE', '|')),
(';', ('COLON', 'COLN', ':')),
("'", ('DOUBLE_QUOTE', 'DQUO', 'DQT', '"')),
('`', ('TILDE', 'TILD', '~')),
(',', ('LEFT_ANGLE_BRACKET', 'LABK', '<')),
('.', ('RIGHT_ANGLE_BRACKET', 'RABK', '>')),
('/', ('QUESTION', 'QUES', '?')),
)

for code, names in codes:
for unshifted, names in codes:
if candidate in names:
return make_key(
names=names, constructor=ModifiedKey, code=code, modifier=KC.LSFT
names=names,
constructor=ModifiedKey,
code=KC[unshifted],
modifier=KC.LSFT,
)


Expand Down Expand Up @@ -430,15 +433,19 @@ def __repr__(self):
return super().__repr__() + '(code=' + str(self.code) + ')'

def on_press(self, keyboard: Keyboard, coord_int: Optional[int] = None) -> None:
keyboard.hid_pending = True
keyboard.keys_pressed.add(self)
if keyboard.implicit_modifier is not None:
keyboard.keys_pressed.discard(keyboard.implicit_modifier)
keyboard.implicit_modifier = None
if self in keyboard.keys_pressed:
keyboard.keys_pressed.discard(self)
keyboard.hid_pending = True
keyboard._send_hid()
keyboard.keys_pressed.add(self)
keyboard.hid_pending = True

def on_release(self, keyboard: Keyboard, coord_int: Optional[int] = None) -> None:
keyboard.hid_pending = True
keyboard.keys_pressed.discard(self)
keyboard.hid_pending = True


class KeyboardKey(_DefaultKey):
Expand Down Expand Up @@ -483,19 +490,24 @@ def __init__(self, code: [Key, int], modifier: [ModifierKey]):
self.modifier = modifier

def on_press(self, keyboard: Keyboard, coord_int: Optional[int] = None) -> None:
self.modifier.on_press(keyboard, coord_int)
if self.key in keyboard.keys_pressed:
self.key.on_release(keyboard, coord_int)
keyboard._send_hid()
keyboard.keys_pressed.add(self.modifier)
if self.key is not None:
self.key.on_press(keyboard, coord_int)
if keyboard.implicit_modifier is not None:
keyboard.implicit_modifier.on_release(keyboard, coord_int)
keyboard.keys_pressed.discard(keyboard.implicit_modifier)
keyboard.implicit_modifier = self.modifier
keyboard.hid_pending = True

def on_release(self, keyboard: Keyboard, coord_int: Optional[int] = None) -> None:
self.modifier.on_release(keyboard, coord_int)
keyboard.keys_pressed.discard(self.modifier)
if self.key is not None:
self.key.on_release(keyboard, coord_int)
if keyboard.implicit_modifier == self.modifier:
keyboard.implicit_modifier = None
keyboard.hid_pending = True

def __repr__(self):
return (
Expand Down
24 changes: 24 additions & 0 deletions tests/test_kmk_keys.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ def test_modified_keys(self):
KC.RALT(KC.LSFT),
KC.RALT(KC.LSFT(KC.N4)),
KC.LSFT,
KC.N1,
]
],
debug_enabled=False,
Expand Down Expand Up @@ -86,6 +87,18 @@ def test_modified_keys(self):
[{KC.LSFT, KC.N1}, {KC.LSFT}, {}],
)

keyboard.test(
'Shifted key + unshifted key rolled',
[(1, True), (6, True), (1, False), (6, False)],
[{KC.LSFT, KC.N1}, {}, {KC.N1}, {}],
)

keyboard.test(
'Unshifted key + shifted key rolled',
[(6, True), (1, True), (6, False), (1, False)],
[{KC.N1}, {}, {KC.LSFT, KC.N1}, {KC.LSFT}, {}],
)

keyboard.test(
'Shift + shifted key',
[(5, True), (1, True), (5, False), (1, False)],
Expand All @@ -98,6 +111,17 @@ def test_modified_keys(self):
[{KC.RALT, KC.LSFT, KC.N2}, {}],
)

keyboard.test(
'Shifted key + modified shifted key rolled',
[(1, True), (2, True), (1, False), (2, False)],
[
{KC.LSFT, KC.N1},
{KC.RALT, KC.LSFT, KC.N1, KC.N2},
{KC.RALT, KC.LSFT, KC.N2},
{},
],
)

keyboard.test(
'Modified modifier',
[(3, True), (3, False)],
Expand Down

0 comments on commit 6ddbf20

Please sign in to comment.