applets: Rework how keys are delivered

This makes us use strings instead of numbers. This allows us to export more of
the G13's key matrix to applets, so we can include things like MR, BD, and the
rest of the keyboard matrix.

Most of this work is done in prep for the real-time macro recording
functionality that I'm attempting to hack in.
This commit is contained in:
June Tate-Gans 2021-05-23 11:27:20 -05:00
parent f485f2cbf0
commit 298cefe9c2
7 changed files with 109 additions and 57 deletions

View File

@ -16,11 +16,9 @@ gi.require_version('GLib', '2.0')
from gi.repository import GLib from gi.repository import GLib
class Buttons(object): BUTTONS = [
L1 = 1 'L1', 'L2', 'L3', 'L4'
L2 = 2 ]
L3 = 3
L4 = 4
class Applet(dbus.service.Object): class Applet(dbus.service.Object):
@ -140,10 +138,11 @@ class Applet(dbus.service.Object):
self.onHidden() self.onHidden()
def _setButtonPressed(self, state, button): def _setButtonPressed(self, state, button):
buttonIdx = button - 1 if button in BUTTONS:
button = self._s.buttonBar.button(buttonIdx) buttonIdx = BUTTONS.index(button)
if button: button = self._s.buttonBar.button(buttonIdx)
button.pressed = state if button:
button.pressed = state
@dbus.service.method(BUS_INTERFACE, @dbus.service.method(BUS_INTERFACE,
in_signature='di', out_signature='ay', in_signature='di', out_signature='ay',

View File

@ -20,20 +20,21 @@ class AppletManager(dbus.service.Object, Subject):
BUS_NAME = 'com.theonelab.g13.AppletManager' BUS_NAME = 'com.theonelab.g13.AppletManager'
BUS_PATH = '/com/theonelab/g13/AppletManager' BUS_PATH = '/com/theonelab/g13/AppletManager'
def __init__(self, manager, prefs): def __init__(self, deviceManager, prefs):
self._bus = dbus.SessionBus() self._bus = dbus.SessionBus()
self._busName = dbus.service.BusName(AppletManager.BUS_NAME, self._bus) self._busName = dbus.service.BusName(AppletManager.BUS_NAME, self._bus)
dbus.service.Object.__init__(self, self._bus, dbus.service.Object.__init__(self, self._bus,
AppletManager.BUS_PATH) AppletManager.BUS_PATH)
Subject.__init__(self) Subject.__init__(self)
self._manager = manager self._deviceManager = deviceManager
self._prefs = prefs self._prefs = prefs
# [name] -> (sender, proxy) # [name] -> (sender, proxy)
self._applets = {} self._applets = {}
self._switcher = Switcher(self) self._switcher = Switcher(self)
self._lastApplet = self._switcher
self._activeApplet = self._switcher self._activeApplet = self._switcher
self._applets['Switcher'] = (self._switcher, self._switcher) self._applets['Switcher'] = (self._switcher, self._switcher)
@ -50,13 +51,29 @@ class AppletManager(dbus.service.Object, Subject):
try: try:
self._activeApplet.Unpresent() self._activeApplet.Unpresent()
self._lastApplet = self._activeApplet
except dbus.exceptions.DBusException as err: except dbus.exceptions.DBusException as err:
print('Failed to unpresent %s: %s' % (appletName, err)) print('Failed to unpresent active applet: %s' % (err))
self._removeActiveApplet() self._removeActiveApplet()
self.setProperty('activeApplet', appletProxy) self.setProperty('activeApplet', appletProxy)
self.onPresent() self.onPresent()
def swapApplets(self):
try:
self._activeApplet.Unpresent()
except dbus.exceptions.DBusException as err:
print('Failed to unpresent active applet: %s' % (err))
self._removeActiveApplet()
self._lastApplet = self._switcher
self.setProperty('activeApplet', self._switcher)
else:
lastApplet = self._lastApplet
self._lastApplet = self._activeApplet
self.setProperty('activeApplet', lastApplet)
finally:
self.onPresent()
def raiseSwitcher(self): def raiseSwitcher(self):
self._activeApplet = self._switcher self._activeApplet = self._switcher
self.onPresent() self.onPresent()
@ -66,7 +83,7 @@ class AppletManager(dbus.service.Object, Subject):
return self._applets.keys() return self._applets.keys()
def _updateLCD(self, frame): def _updateLCD(self, frame):
self._manager.setLCDBuffer(frame) self._deviceManager.setLCDBuffer(frame)
def _removeActiveApplet(self): def _removeActiveApplet(self):
senders = {proxy: name for (name, (_, proxy)) in self._applets.items()} senders = {proxy: name for (name, (_, proxy)) in self._applets.items()}
@ -76,6 +93,7 @@ class AppletManager(dbus.service.Object, Subject):
self.addChange(ChangeType.REMOVE, 'applet', name) self.addChange(ChangeType.REMOVE, 'applet', name)
self._activeApplet = self._switcher self._activeApplet = self._switcher
self._lastApplet = self._switcher
self.activeApplet = 'Switcher' self.activeApplet = 'Switcher'
def onPresent(self): def onPresent(self):
@ -87,24 +105,24 @@ class AppletManager(dbus.service.Object, Subject):
print('Failed to present applet: %s' % (err)) print('Failed to present applet: %s' % (err))
self._removeActiveApplet() self._removeActiveApplet()
def onKeyPressed(self, key): def onKeyPressed(self, keyname):
# Swap to the switcher # Swap to the switcher
if key == G13Keys.BD: if keyname == 'BD':
self.activeApplet = 'Switcher' self.swapApplets()
return return
try: try:
frame = self._activeApplet.KeyPressed(time.time(), frame = self._activeApplet.KeyPressed(time.time(),
key.value['bit']) keyname)
self._updateLCD(frame) self._updateLCD(frame)
except dbus.exceptions.DBusException as err: except dbus.exceptions.DBusException as err:
print('Failed to send keyPressed for applet: %s' % (err)) print('Failed to send keyPressed for applet: %s' % (err))
self._removeActiveApplet() self._removeActiveApplet()
def onKeyReleased(self, key): def onKeyReleased(self, keyname):
try: try:
frame = self._activeApplet.KeyReleased(time.time(), frame = self._activeApplet.KeyReleased(time.time(),
key.value['bit']) keyname)
self._updateLCD(frame) self._updateLCD(frame)
except dbus.exceptions.DBusException as err: except dbus.exceptions.DBusException as err:
print('Failed to send keyReleased for applet: %s' % (err)) print('Failed to send keyReleased for applet: %s' % (err))

View File

@ -6,7 +6,7 @@ from builtins import property
from g13gui.observer.observer import Observer from g13gui.observer.observer import Observer
from g13gui.observer.subject import ChangeType from g13gui.observer.subject import ChangeType
from g13gui.applet.applet import Buttons from g13gui.applet.applet import BUTTONS
from g13gui.applet.loopbackdisplaydevice import LoopbackDisplayDevice from g13gui.applet.loopbackdisplaydevice import LoopbackDisplayDevice
from g13gui.bitwidgets.display import Display from g13gui.bitwidgets.display import Display
from g13gui.bitwidgets.screen import Screen from g13gui.bitwidgets.screen import Screen
@ -62,10 +62,11 @@ class Switcher(Observer):
self._s.buttonBar.showAll() self._s.buttonBar.showAll()
def _setButtonPressed(self, state, button): def _setButtonPressed(self, state, button):
buttonIdx = button - 1 if button in BUTTONS:
button = self._s.buttonBar.button(buttonIdx) buttonIdx = BUTTONS.index(button)
if button: button = self._s.buttonBar.button(buttonIdx)
button.pressed = state if button:
button.pressed = state
def Present(self, timestamp, **kwargs): def Present(self, timestamp, **kwargs):
self._s.show() self._s.show()
@ -82,18 +83,18 @@ class Switcher(Observer):
return self.Present(timestamp) return self.Present(timestamp)
def _setActiveApplet(self): def _setActiveApplet(self):
selectedName = self._lv.markedItem() selectedName = self._lv.selection()
self._appletManager.activeApplet = selectedName if selectedName:
self._appletManager.activeApplet = selectedName
def KeyReleased(self, timestamp, key): def KeyReleased(self, timestamp, key):
self._setButtonPressed(False, key) self._setButtonPressed(False, key)
if key == Buttons.L2: # down if key == 'L2': # down
self._lv.nextSelection() self._lv.nextSelection()
elif key == Buttons.L3: # up elif key == 'L3': # up
self._lv.prevSelection() self._lv.prevSelection()
elif key == Buttons.L4: # select elif key == 'L4': # select
self._lv.markSelection()
GLib.idle_add(self._setActiveApplet) GLib.idle_add(self._setActiveApplet)
return self.Present(timestamp) return self.Present(timestamp)

View File

@ -4,7 +4,7 @@ import enum
import psutil import psutil
from g13gui.applet.applet import Applet from g13gui.applet.applet import Applet
from g13gui.applet.applet import Buttons from g13gui.applet.applet import BUTTONS
from g13gui.applet.applet import RunApplet from g13gui.applet.applet import RunApplet
from g13gui.bitwidgets.label import Label from g13gui.bitwidgets.label import Label
from g13gui.bitwidgets.fonts import Fonts from g13gui.bitwidgets.fonts import Fonts
@ -100,15 +100,19 @@ class ClockApplet(Applet):
self.screen.buttonBar.setButton(0, button) self.screen.buttonBar.setButton(0, button)
def onKeyReleased(self, timestamp, key): def onKeyReleased(self, timestamp, key):
if key == Buttons.L1: if key == 'L1':
self._onModeSwitch() self._onModeSwitch()
elif key == Buttons.L2: elif key == 'L2':
self._loadGraphToggle.toggle() self._loadGraphToggle.toggle()
self._loadGraph.visible = self._loadGraphToggle.isOn self._loadGraph.visible = self._loadGraphToggle.isOn
elif key == Buttons.L3: elif key == 'L3':
self._ramGraphToggle.toggle() self._ramGraphToggle.toggle()
self._ramGraph.visible = self._ramGraphToggle.isOn self._ramGraph.visible = self._ramGraphToggle.isOn
if __name__ == '__main__': def main():
RunApplet(ClockApplet) RunApplet(ClockApplet)
if __name__ == '__main__':
main()

View File

@ -3,7 +3,7 @@ import time
import enum import enum
from g13gui.applet.applet import Applet from g13gui.applet.applet import Applet
from g13gui.applet.applet import Buttons from g13gui.applet.applet import BUTTONS
from g13gui.applet.applet import RunApplet from g13gui.applet.applet import RunApplet
from g13gui.bitwidgets.listview import ListView from g13gui.bitwidgets.listview import ListView
from g13gui.bitwidgets.button import Button from g13gui.bitwidgets.button import Button
@ -63,14 +63,18 @@ class ProfilesApplet(Applet):
self._updateAndPresent() self._updateAndPresent()
def onKeyReleased(self, timestamp, key): def onKeyReleased(self, timestamp, key):
if key == Buttons.L2: # down if key == 'L2': # down
self._lv.nextSelection() self._lv.nextSelection()
elif key == Buttons.L3: # up elif key == 'L3': # up
self._lv.prevSelection() self._lv.prevSelection()
elif key == Buttons.L4: # select elif key == 'L4': # select
self._lv.markSelection() self._lv.markSelection()
GLib.idle_add(self._setActiveProfile) GLib.idle_add(self._setActiveProfile)
if __name__ == '__main__': def main():
RunApplet(ProfilesApplet) RunApplet(ProfilesApplet)
if __name__ == '__main__':
main()

View File

@ -15,6 +15,7 @@ from evdev import ecodes as e
from g13gui.observer.observer import Observer from g13gui.observer.observer import Observer
from g13gui.model.bindings import StickMode from g13gui.model.bindings import StickMode
from g13gui.g13.common import G13Keys
from g13gui.g13.common import G13NormalKeys from g13gui.g13.common import G13NormalKeys
from g13gui.g13.common import G13AppletKeys from g13gui.g13.common import G13AppletKeys
from g13gui.g13.common import G13SpecialKeys from g13gui.g13.common import G13SpecialKeys
@ -71,6 +72,8 @@ class DeviceManager(threading.Thread, Observer):
self._lastKeyState = {} self._lastKeyState = {}
self._commandQueue = queue.Queue() self._commandQueue = queue.Queue()
self._lastProfile = None self._lastProfile = None
self._grabNextKey = False
self._leds = 0
self._appletManager = AppletManager(self, prefs) self._appletManager = AppletManager(self, prefs)
@ -249,9 +252,7 @@ class DeviceManager(threading.Thread, Observer):
count = self._readKeys(reportBuffer) count = self._readKeys(reportBuffer)
if count == REPORT_SIZE: if count == REPORT_SIZE:
self._synthesizeKeys(reportBuffer) self._handleKeys(reportBuffer)
self._signalSpecialKeys(reportBuffer)
self._synthesizeStick(reportBuffer)
self._uinput.syn() self._uinput.syn()
self._processCommands() self._processCommands()
@ -265,6 +266,15 @@ class DeviceManager(threading.Thread, Observer):
if self._device and self._state == DeviceManager.State.FOUND: if self._device and self._state == DeviceManager.State.FOUND:
self._reset() self._reset()
def appletGrabNextKey(self):
self._grabNextKey = True
def _handleKeys(self, reportBuffer):
self._synthesizeKeys(reportBuffer)
self._signalSpecialKeys(reportBuffer)
self._synthesizeStick(reportBuffer)
self._grabNextKey = False
def _synthesizeStick(self, report): def _synthesizeStick(self, report):
(joy_x, joy_y) = report[1:3] (joy_x, joy_y) = report[1:3]
stickMode = self._prefs.selectedProfile().stickMode stickMode = self._prefs.selectedProfile().stickMode
@ -282,11 +292,17 @@ class DeviceManager(threading.Thread, Observer):
nowPressed = inX and inY nowPressed = inX and inY
if not wasPressed and nowPressed: if not wasPressed and nowPressed:
for code in binding: if self._grabNextKey:
self._uinput.write(e.EV_KEY, code, 1) self._appletManager.onKeyPressed(name)
else:
for code in binding:
self._uinput.write(e.EV_KEY, code, 1)
elif wasPressed and not nowPressed: elif wasPressed and not nowPressed:
for code in binding: if self._grabNextKey:
self._uinput.write(e.EV_KEY, code, 0) self._appletManager.onKeyReleased(name)
else:
for code in binding:
self._uinput.write(e.EV_KEY, code, 0)
self._lastKeyState[name] = nowPressed self._lastKeyState[name] = nowPressed
@ -304,11 +320,18 @@ class DeviceManager(threading.Thread, Observer):
nowPressed = key.testReport(report) nowPressed = key.testReport(report)
if not wasPressed and nowPressed: if not wasPressed and nowPressed:
for code in binding: if self._grabNextKey:
self._uinput.write(e.EV_KEY, code, 1) self._appletManager.onKeyPressed(key.name)
else:
for code in binding:
self._uinput.write(e.EV_KEY, code, 1)
elif wasPressed and not nowPressed: elif wasPressed and not nowPressed:
for code in binding: if self._grabNextKey:
self._uinput.write(e.EV_KEY, code, 0) self._appletManager.onKeyPressed(key.name)
else:
for code in binding:
self._uinput.write(e.EV_KEY, code, 0)
self._lastKeyState[key] = nowPressed self._lastKeyState[key] = nowPressed
@ -319,9 +342,9 @@ class DeviceManager(threading.Thread, Observer):
# Emit special keypress if and only if it was released # Emit special keypress if and only if it was released
if wasPressed and not nowPressed: if wasPressed and not nowPressed:
self._appletManager.onKeyReleased(key) self._appletManager.onKeyReleased(key.name)
elif not wasPressed and nowPressed: elif not wasPressed and nowPressed:
self._appletManager.onKeyPressed(key) self._appletManager.onKeyPressed(key.name)
self._lastKeyState[key] = nowPressed self._lastKeyState[key] = nowPressed
@ -330,9 +353,12 @@ class DeviceManager(threading.Thread, Observer):
nowPressed = key.testReport(report) nowPressed = key.testReport(report)
# Emit special keypress if and only if it was released # Emit special keypress if and only if it was released
if wasPressed and not nowPressed: if not wasPressed and nowPressed:
# check for MR, allow for key record this way if key == G13Keys.MR:
pass self._appletManager.onKeyPressed(key.name)
elif wasPressed and not nowPressed:
if key == G13Keys.MR:
self._appletManager.onKeyReleased(key.name)
self._lastKeyState[key] = nowPressed self._lastKeyState[key] = nowPressed

View File

@ -7,7 +7,7 @@ from dbus.mainloop.glib import DBusGMainLoop
from g13gui.app import Application from g13gui.app import Application
if __name__ == '__main__': def main():
DBusGMainLoop(set_as_default=True) DBusGMainLoop(set_as_default=True)
app = Application() app = Application()