Skip to content
This repository has been archived by the owner on Dec 30, 2021. It is now read-only.

Commit

Permalink
#14 layer on action
Browse files Browse the repository at this point in the history
  • Loading branch information
ivanjermakov committed Aug 28, 2020
1 parent 5622168 commit 7b0bcce
Show file tree
Hide file tree
Showing 10 changed files with 119 additions and 25 deletions.
1 change: 1 addition & 0 deletions action/action_type.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,4 @@
class ActionType(Enum):
ModifiedKeyAction = 1
ModTapAction = 2
LayerOnAction = 3
21 changes: 21 additions & 0 deletions action/layer_on_action.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
from evdev.events import KeyEvent

import host
import mapper
from action.action_type import ActionType
from log import debug


class LayerOnAction:
type: ActionType
layer: int

def __init__(self, layer):
self.type = ActionType.LayerOnAction
self.layer = layer

def handle(self, ui, e, config, *args):
debug('-- handling layer on action --')
mapper.active_layers[self.layer] = e.value == KeyEvent.key_down
if e.value == KeyEvent.key_up:
host.release_layer_keys(ui, self.layer, config)
7 changes: 4 additions & 3 deletions action/mod_tap_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
from evdev.events import KeyEvent

import host
import mapper
from action.action_type import ActionType
from log import debug

Expand All @@ -17,15 +18,15 @@ def __init__(self, key, *modifiers):
self.modifiers = modifiers
self.key = key

def handle(self, ui, e, config, last_press_timestamp):
debug('-- handling mod tap --')
def handle(self, ui, e, config, pos, *args):
debug('-- handling mod tap action --')
if e.value == KeyEvent.key_down:
debug('MT is pressed, pressing modifiers')
host.write_press(ui, *self.modifiers)
else:
debug('MT is released, releasing modifiers')
host.write_release(ui, *self.modifiers)
since_last_press = (e.timestamp() - last_press_timestamp) * 1000
since_last_press = (e.timestamp() - mapper.last_press_timestamps[pos]) * 1000
debug(f'since last press: {since_last_press}')
if since_last_press <= config.tapping_term:
debug('writing key press')
Expand Down
2 changes: 1 addition & 1 deletion action/modified_key_action.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ def __init__(self, key, *modifiers):
self.modifiers = modifiers
self.key = key

def handle(self, ui, e):
def handle(self, ui, e, *args):
debug('-- handling modified key action --')
if e.value == KeyEvent.key_down:
for m in self.modifiers:
Expand Down
19 changes: 14 additions & 5 deletions example/config.py
Original file line number Diff line number Diff line change
@@ -1,16 +1,25 @@
from layout import *
from key import *
T______ = KC_TRANSPARENT

physical_layout = laptop

keymaps = [
[
KC_ESC , KC_F1 , KC_F2 , KC_F3 , KC_F4 , KC_F5 , KC_F6 , KC_F7 , KC_F8 , KC_F9 , KC_F10 , KC_F11 , KC_F12 , KC_PSCR, KC_INS , KC_DEL ,
KC_GRV , KC_2 , KC_1 , KC_3 , KC_4 , KC_5 , KC_6 , KC_7 , KC_8 , KC_9 , KC_0 , KC_MINS, KC_EQL , KC_BSPC,
KC_TAB , KC_Q , KC_W , KC_E , KC_R , KC_T , KC_Y , KC_U , KC_I , KC_O , KC_P , KC_LBRC, KC_RBRC, KC_BSLS,
KC_CAPS, KC_A , KC_S , KC_D , KC_F , KC_G , KC_H , KC_J , KC_K , KC_L , KC_SCLN, KC_QUOT, KC_ENT ,
KC_LSFT, KC_Z , KC_X , KC_C , KC_V , KC_B , KC_N , KC_M , KC_COMM, KC_DOT , KC_SLSH, KC_RSFT, KC_UP ,
KC_LCTL, KC_LGUI, KC_LALT, LSFT_T(KC_SPC) , KC_RALT, KC_APP , KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT,
KC_GRV , KC_2 , KC_1 , KC_3 , KC_4 , KC_5 , KC_6 , KC_7 , KC_8 , KC_9 , KC_0 , KC_MINS, KC_EQL , KC_BSPC,
KC_TAB , KC_Q , KC_W , KC_E , KC_R , KC_T , KC_Y , KC_U , KC_I , KC_O , KC_P , KC_LBRC, KC_RBRC, KC_BSLS,
KC_CAPS, KC_A , KC_S , KC_D , KC_F , KC_G , KC_H , KC_J , KC_K , KC_L , KC_SCLN, KC_QUOT, KC_ENT ,
KC_LSFT, KC_Z , KC_X , KC_C , KC_V , KC_B , KC_N , KC_M , KC_COMM, KC_DOT , KC_SLSH, KC_RSFT, KC_UP ,
KC_LCTL, KC_LGUI, KC_LALT, LSFT_T(KC_SPC) , KC_RALT, KC_APP , KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT,
],
[
T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______,
T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______,
T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______,
T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______,
T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______,
T______, T______, T______, T______, T______, T______, T______, T______, T______, T______,
]
]

Expand Down
18 changes: 13 additions & 5 deletions host.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
from evdev import *

import key
import mapper
from log import debug


def write(ui, e):
ui.write(ecodes.EV_KEY, e.code, e.value)
Expand Down Expand Up @@ -29,8 +33,12 @@ def write_release(ui, *codes):
ui.syn()


def release_keys(ui, kb):
active_keys = kb.active_keys()
for k in active_keys:
ui.write(ecodes.EV_KEY, k, KeyEvent.key_up)
ui.syn()
def release_layer_keys(ui, layer, config):
debug(f'releasing layer [{layer}] keys')
for pos, is_pressed in enumerate(mapper.layers_keys_pressed[layer]):
if is_pressed:
keycode = config.keymaps[layer][pos]
if keycode != key.KC_TRANSPARENT:
debug(f'key {keycode} released')
write_release(ui, keycode)
mapper.layers_keys_pressed[layer][pos] = False
2 changes: 1 addition & 1 deletion kbmap.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ def kbmap(config_path, device_name, name, verbose):
configuration.
"""
log.debug_enabled = verbose
mapper.map(config_path, device_name, name)
mapper.map_device(config_path, device_name, name)


kbmap()
9 changes: 8 additions & 1 deletion key.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
from evdev.ecodes import *

from action.layer_on_action import LayerOnAction
from action.mod_tap_action import ModTapAction
from action.modified_key_action import ModifiedKeyAction

Expand All @@ -9,7 +10,7 @@

KC_TRANSPARENT = None
KC_TRNS = KC_TRANSPARENT
_______ = KC_TRANSPARENT
T______ = KC_TRANSPARENT

# digits
KC_0 = KEY_0
Expand Down Expand Up @@ -693,3 +694,9 @@ def HYPR_T(key):
SWIN_T = SGUI_T
SAGR_T = RSA_T
ALL_T = HYPR_T


# layer actions

def MO(layer):
return LayerOnAction(layer)
18 changes: 18 additions & 0 deletions layout.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
from key import *

tkl_transparent = [
T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______,
T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______,
T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______,
T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______,
T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______,
T______, T______, T______, T______, T______, T______, T______, T______, T______, T______,
]

tkl = [
KC_ESC , KC_F1 , KC_F2 , KC_F3 , KC_F4 , KC_F5 , KC_F6 , KC_F7 , KC_F8 , KC_F9 , KC_F10 , KC_F11 , KC_F12 , KC_PSCR, KC_SLCK, KC_PAUS,
KC_GRV , KC_2 , KC_1 , KC_3 , KC_4 , KC_5 , KC_6 , KC_7 , KC_8 , KC_9 , KC_0 , KC_MINS, KC_EQL , KC_BSPC , KC_DEL , KC_END, KC_PGDN,
Expand All @@ -9,6 +18,15 @@
KC_LCTL, KC_LGUI, KC_LALT, KC_SPC , KC_RALT, KC_APP , KC_RCTL, KC_LEFT, KC_DOWN, KC_RGHT,
]

laptop_transparent = [
T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______,
T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______,
T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______,
T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______,
T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______, T______,
T______, T______, T______, T______, T______, T______, T______, T______, T______, T______,
]

laptop = [
KC_ESC , KC_F1 , KC_F2 , KC_F3 , KC_F4 , KC_F5 , KC_F6 , KC_F7 , KC_F8 , KC_F9 , KC_F10 , KC_F11 , KC_F12 , KC_PSCR, KC_INS , KC_DEL ,
KC_GRV , KC_2 , KC_1 , KC_3 , KC_4 , KC_5 , KC_6 , KC_7 , KC_8 , KC_9 , KC_0 , KC_MINS, KC_EQL , KC_BSPC,
Expand Down
47 changes: 38 additions & 9 deletions mapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,13 @@
from evdev.events import KeyEvent

import host
import key
import keyboard
from log import debug

last_press_timestamps = []
active_layers = []
layers_keys_pressed = []


def load_config(path):
Expand All @@ -21,7 +24,7 @@ def load_config(path):
return config


def map(config_path, kb_name, ui_name='kbmap'):
def map_device(config_path, kb_name, ui_name='kbmap'):
"""
Create virtual device with uinput_name that will remap keyboard events from device with name device_name using
config_pth configuration.
Expand All @@ -33,7 +36,15 @@ def map(config_path, kb_name, ui_name='kbmap'):
config = load_config(config_path)

global last_press_timestamps
last_press_timestamps = [None for i in range(len(config.physical_layout))]
last_press_timestamps = [None for _ in range(len(config.physical_layout))]
global active_layers
active_layers = [False for _ in range(len(config.keymaps))]
# base layer is always active
active_layers[0] = True
global layers_keys_pressed
layers_keys_pressed = [[] for _ in range(len(active_layers))]
for i in range(len(active_layers)):
layers_keys_pressed[i] = [False for _ in range(len(config.keymaps[i]))]

kb = keyboard.get_device_by_name(kb_name)
keyboard.grab(kb)
Expand All @@ -49,7 +60,7 @@ def map(config_path, kb_name, ui_name='kbmap'):


def handle_event(e, kb, ui, config):
global last_press_timestamps
global layers_keys_pressed

debug(f'-------- handling {e} --------')
pos = map_key_to_pos(e.code, config)
Expand All @@ -58,14 +69,15 @@ def handle_event(e, kb, ui, config):

debug(f'key is {ecodes.KEY[e.code]} ({e.code}) at {pos}')

keycode = config.keymaps[0][pos]
key, layer_index = find_key(pos, config)
layers_keys_pressed[layer_index][pos] = e.value == KeyEvent.key_down

if hasattr(keycode, 'type'):
debug(f'key is mapped to action of type {keycode.type} at {pos}')
keycode.handle(ui, e, config, last_press_timestamps[pos])
if hasattr(key, 'type'):
debug(f'key is mapped to action of type {key.type} at {pos}')
key.handle(ui, e, config, pos)
else:
debug(f'key is mapped to key: {ecodes.KEY[keycode]} ({keycode}) at {pos}')
host.write_code(ui, keycode, e.value)
debug(f'key is mapped to key: {ecodes.KEY[key]} ({key}) at {pos}')
host.write_code(ui, key, e.value)

update_timestamps(pos, e)

Expand All @@ -84,3 +96,20 @@ def update_timestamps(pos, e):
new_value = e.timestamp() if e.value == KeyEvent.key_down else None
last_press_timestamps[pos] = new_value
debug(f'updated timestamp at [{pos}] to {new_value}')


def find_key(pos, config):
"""
Find which key to use regarding active layers and key position.
Picked up first non-KC_TRANS key within active layers.
Layers with higher index have higher precedence.
:param pos
:param config
:return key or action
"""
global active_layers
for layer_index, layer in reversed(list(enumerate(config.keymaps))):
layer_key = layer[pos]
if active_layers[layer_index] and layer_key != key.KC_TRANSPARENT:
return layer_key, layer_index

0 comments on commit 7b0bcce

Please sign in to comment.