Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(www): Enable the usage of modifier keys #408

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
8 changes: 6 additions & 2 deletions mtda/assets/keysight.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
12: "num",
13: "\n",
16: "shift",
17: "meta",
17: "ctrl",
18: "alt",
19: "pause",
20: "caps",
Expand Down Expand Up @@ -156,7 +156,11 @@
else var f = t.toUpperCase();
return {
"char": f,
key: t
key: t,
ctrl: e.ctrlKey,
shift: e.shiftKey,
alt: e.altKey,
cmd: e.metaKey,
}
}, e.exports.unprintableKeys = {
"\b": 1,
Expand Down
4 changes: 4 additions & 0 deletions mtda/keyboard/controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,10 @@ def right(self, repeat=1):
def up(self, repeat=1):
return False

@abc.abstractmethod
def press(self, key, repeat=1, ctrl=False, shift=False, alt=False, meta=False):
return False

@abc.abstractmethod
def write(self, str):
return
Expand Down
126 changes: 73 additions & 53 deletions mtda/keyboard/hid.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@

class HidKeyboardController(KeyboardController):

KEY_MOD_LCTRL = 0x01
KEY_MOD_LSHIFT = 0x02
KEY_MOD_LALT = 0x04
KEY_MOD_LMETA = 0x08

# Timeout (seconds) for writes
TIMEOUT = 1
Expand Down Expand Up @@ -80,17 +83,62 @@ def idle(self):
self.mtda.debug(3, f"keyboard.hid.idle(): {result}")
return result

def press(self, key, mod=0x00, repeat=1):
def press(self, key, repeat=1, ctrl=False, shift=False, alt=False, meta=False):
self.mtda.debug(3, "keyboard.hid.press()")

bsl = '\\'
bsp = '\b'
ret = '\n'
lower_keys = {
'a': 0x04, 'b': 0x05, 'c': 0x06, 'd': 0x07, 'e': 0x08, 'f': 0x09,
'g': 0x0a, 'h': 0x0b, 'i': 0x0c, 'j': 0x0d, 'k': 0x0e, 'l': 0x0f,
'm': 0x10, 'n': 0x11, 'o': 0x12, 'p': 0x13, 'q': 0x14, 'r': 0x15,
's': 0x16, 't': 0x17, 'u': 0x18, 'v': 0x19, 'w': 0x1a, 'x': 0x1b,
'y': 0x1c, 'z': 0x1d, '1': 0x1e, '2': 0x1f, '3': 0x20, '4': 0x21,
'5': 0x22, '6': 0x23, '7': 0x24, '8': 0x25, '9': 0x26, '0': 0x27,
ret: 0x28, bsp: 0x2a, ' ': 0x2c, '-': 0x2d, '=': 0x2e, '[': 0x2f,
']': 0x30, bsl: 0x31, ';': 0x33, "'": 0x34, '`': 0x35, ',': 0x36,
'.': 0x37, '/': 0x38
}
shift_keys = {
'A': 0x04, 'B': 0x05, 'C': 0x06, 'D': 0x07, 'E': 0x08, 'F': 0x09,
'G': 0x0a, 'H': 0x0b, 'I': 0x0c, 'J': 0x0d, 'K': 0x0e, 'L': 0x0f,
'M': 0x10, 'N': 0x11, 'O': 0x12, 'P': 0x13, 'Q': 0x14, 'R': 0x15,
'S': 0x16, 'T': 0x17, 'U': 0x18, 'V': 0x19, 'W': 0x1a, 'X': 0x1b,
'Y': 0x1c, 'Z': 0x1d, '!': 0x1e, '@': 0x1f, '#': 0x20, '$': 0x21,
'%': 0x22, '^': 0x23, '&': 0x24, '*': 0x25, '(': 0x26, ')': 0x27,
'_': 0x2d, '+': 0x2e, '{': 0x2f, '}': 0x30, '|': 0x31, ':': 0x33,
'"': 0x34, '~': 0x35, '<': 0x36, '>': 0x37, '?': 0x38
}

if key in lower_keys:
return self.send(lower_keys[key], repeat, ctrl, shift, alt, meta)
elif key in shift_keys:
return self.send(shift_keys[key], repeat, ctrl, True, alt, meta)

def send(self, key, repeat=1, ctrl=False, shift=False, alt=False, meta=False):
self.mtda.debug(3, "keyboard.hid.send()")

if os.path.exists(self.dev) is False:
self.mtda.debug(1, f"keyboard.hid.press(): {self.dev} not found")
self.mtda.debug(1, f"keyboard.hid.send(): {self.dev} not found")
return False

if self.fd is None:
self.mtda.debug(4, f"keyboard.hid.press(): opening {self.dev}")
self.mtda.debug(4, f"keyboard.hid.send(): opening {self.dev}")
self.fd = open(self.dev, mode="r+b", buffering=0)

mod = 0x00
if ctrl:
mod = mod | self.KEY_MOD_LCTRL
if shift:
mod = mod | self.KEY_MOD_LSHIFT
if alt:
mod = mod | self.KEY_MOD_LALT
if meta:
mod = mod | self.KEY_MOD_LMETA

self.mtda.debug(4, f"keyboard.hid.send(): mod: {mod} key: {key}")

NULL_CHAR = chr(0)
result = True
while repeat > 0:
Expand All @@ -114,141 +162,113 @@ def press(self, key, mod=0x00, repeat=1):
def backspace(self, repeat=1):
self.mtda.debug(3, "keyboard.hid.backspace()")

return self.press(0x2a, 0, repeat)
return self.send(0x2a, repeat)

def capsLock(self, repeat=1):
self.mtda.debug(3, "keyboard.hid.capsLock()")

return self.press(0x39, 0, repeat)
return self.send(0x39, repeat)

def enter(self, repeat=1):
self.mtda.debug(3, "keyboard.hid.enter()")

return self.press(0x28, 0, repeat)
return self.send(0x28, repeat)

def esc(self, repeat=1):
self.mtda.debug(3, "keyboard.hid.esc()")

return self.press(0x29, 0, repeat)
return self.send(0x29, repeat)

def down(self, repeat=1):
self.mtda.debug(3, "keyboard.hid.down()")

return self.press(0x51, 0, repeat)
return self.send(0x51, repeat)

def left(self, repeat=1):
self.mtda.debug(3, "keyboard.hid.left()")

return self.press(0x50, 0, repeat)
return self.send(0x50, repeat)

def right(self, repeat=1):
self.mtda.debug(3, "keyboard.hid.right()")

return self.press(0x4f, 0, repeat)
return self.send(0x4f, repeat)

def up(self, repeat=1):
self.mtda.debug(3, "keyboard.hid.up()")

return self.press(0x52, 0, repeat)
return self.send(0x52, repeat)

def f1(self, repeat=1):
self.mtda.debug(3, "keyboard.hid.f1()")

return self.press(0x3a, 0, repeat)
return self.send(0x3a, repeat)

def f2(self, repeat=1):
self.mtda.debug(3, "keyboard.hid.f2()")

return self.press(0x3b, 0, repeat)
return self.send(0x3b, repeat)

def f3(self, repeat=1):
self.mtda.debug(3, "keyboard.hid.f3()")

return self.press(0x3c, 0, repeat)
return self.send(0x3c, repeat)

def f4(self, repeat=1):
self.mtda.debug(3, "keyboard.hid.f4()")

return self.press(0x3d, 0, repeat)
return self.send(0x3d, repeat)

def f5(self, repeat=1):
self.mtda.debug(3, "keyboard.hid.f5()")

return self.press(0x3e, 0, repeat)
return self.send(0x3e, repeat)

def f6(self, repeat=1):
self.mtda.debug(3, "keyboard.hid.f6()")

return self.press(0x3f, 0, repeat)
return self.send(0x3f, repeat)

def f7(self, repeat=1):
self.mtda.debug(3, "keyboard.hid.f7()")

return self.press(0x40, 0, repeat)
return self.send(0x40, repeat)

def f8(self, repeat=1):
self.mtda.debug(3, "keyboard.hid.f8()")

return self.press(0x41, 0, repeat)
return self.send(0x41, repeat)

def f9(self, repeat=1):
self.mtda.debug(3, "keyboard.hid.f9()")

return self.press(0x42, 0, repeat)
return self.send(0x42, repeat)

def f10(self, repeat=1):
self.mtda.debug(3, "keyboard.hid.f10())")

return self.press(0x43, 0, repeat)
return self.send(0x43, repeat)

def f11(self, repeat=1):
self.mtda.debug(3, "keyboard.hid.f11()")

return self.press(0x44, 0, repeat)
return self.send(0x44, repeat)

def f12(self, repeat=1):
self.mtda.debug(3, "keyboard.hid.f12()")

return self.press(0x45, 0, repeat)
return self.send(0x45, repeat)

def tab(self, repeat=1):
self.mtda.debug(3, "keyboard.hid.tab()")

return self.press(0x2b, 0, repeat)
return self.send(0x2b, repeat)

def write(self, what):
self.mtda.debug(3, "keyboard.hid.write()")

bsl = '\\'
bsp = '\b'
ret = '\n'
lower_keys = {
'a': 0x04, 'b': 0x05, 'c': 0x06, 'd': 0x07, 'e': 0x08, 'f': 0x09,
'g': 0x0a, 'h': 0x0b, 'i': 0x0c, 'j': 0x0d, 'k': 0x0e, 'l': 0x0f,
'm': 0x10, 'n': 0x11, 'o': 0x12, 'p': 0x13, 'q': 0x14, 'r': 0x15,
's': 0x16, 't': 0x17, 'u': 0x18, 'v': 0x19, 'w': 0x1a, 'x': 0x1b,
'y': 0x1c, 'z': 0x1d, '1': 0x1e, '2': 0x1f, '3': 0x20, '4': 0x21,
'5': 0x22, '6': 0x23, '7': 0x24, '8': 0x25, '9': 0x26, '0': 0x27,
ret: 0x28, bsp: 0x2a, ' ': 0x2c, '-': 0x2d, '=': 0x2e, '[': 0x2f,
']': 0x30, bsl: 0x31, ';': 0x33, "'": 0x34, '`': 0x35, ',': 0x36,
'.': 0x37, '/': 0x38
}
shift_keys = {
'A': 0x04, 'B': 0x05, 'C': 0x06, 'D': 0x07, 'E': 0x08, 'F': 0x09,
'G': 0x0a, 'H': 0x0b, 'I': 0x0c, 'J': 0x0d, 'K': 0x0e, 'L': 0x0f,
'M': 0x10, 'N': 0x11, 'O': 0x12, 'P': 0x13, 'Q': 0x14, 'R': 0x15,
'S': 0x16, 'T': 0x17, 'U': 0x18, 'V': 0x19, 'W': 0x1a, 'X': 0x1b,
'Y': 0x1c, 'Z': 0x1d, '!': 0x1e, '@': 0x1f, '#': 0x20, '$': 0x21,
'%': 0x22, '^': 0x23, '&': 0x24, '*': 0x25, '(': 0x26, ')': 0x27,
'_': 0x2d, '+': 0x2e, '{': 0x2f, '}': 0x30, '|': 0x31, ':': 0x33,
'"': 0x34, '~': 0x35, '<': 0x36, '>': 0x37, '?': 0x38
}

for k in what:
if k in lower_keys:
self.press(lower_keys[k])
elif k in shift_keys:
self.press(shift_keys[k], mod=self.KEY_MOD_LSHIFT)
self.press(k)


def instantiate(mtda):
Expand Down
14 changes: 12 additions & 2 deletions mtda/keyboard/qemu.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ def probe(self):
def idle(self):
return True

def press(self, key, repeat=1):
def press(self, key, repeat=1, ctrl=False, shift=False, alt=False, meta=False):
self.mtda.debug(3, "keyboard.qemu.press()")

symbols = {
Expand All @@ -54,11 +54,21 @@ def press(self, key, repeat=1):
'\n': 'ret'
}

mod = ""
if ctrl:
mod = "ctrl-"
if shift:
mod = f"{mod}shift-"
if alt:
mod = f"{mod}alt-"
if meta:
mod = f"{mod}meta_l-"

result = True
while repeat > 0:
repeat = repeat - 1
key = symbols[key] if key in symbols else key
self.qemu.cmd(f"sendkey {key}")
self.qemu.cmd(f"sendkey {mod}{key}")
time.sleep(0.1)
return result

Expand Down
13 changes: 9 additions & 4 deletions mtda/templates/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,15 @@
<script src="./assets/keysight.js"></script>
<script type=text/javascript>
window.addEventListener("keydown", function(event) {
var key = keysight(event).char;
event.preventDefault();
console.log("#### <KEY> " + key);
$.getJSON('./keyboard-input', {input: key}, function(key) {
var key = keysight(event)
console.log("#### <KEY> " + JSON.stringify(key))
$.getJSON('./keyboard-input', {
input: key.char,
ctrl: key.ctrl,
shift: key.shift,
alt: key.alt,
meta: key.cmd,
}, function(key) {
// do nothing
});
});
Expand Down
8 changes: 7 additions & 1 deletion mtda/www.py
Original file line number Diff line number Diff line change
Expand Up @@ -104,7 +104,13 @@ def keyboard_input():
if input in map:
map[input]()
else:
mtda.keyboard.write(input)
mtda.keyboard.press(
input,
ctrl=request.args.get('ctrl', False, type=lambda s: s == 'true'),
shift=request.args.get('shift', False, type=lambda s: s == 'true'),
alt=request.args.get('alt', False, type=lambda s: s == 'true'),
meta=request.args.get('meta', False, type=lambda s: s == 'true')
)
return ''


Expand Down
1 change: 1 addition & 0 deletions tox.ini
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,4 @@ commands =

[flake8]
exclude = dist,docs,*.egg-info,__pycache__
max-line-length = 120