restore KeyCodesFilter, somehow dropped during refactoring
This commit is contained in:
parent
01e9c04ab5
commit
19178979fc
|
@ -31,6 +31,7 @@ from subiquitycore.async_helpers import (
|
||||||
run_in_thread,
|
run_in_thread,
|
||||||
schedule_task,
|
schedule_task,
|
||||||
)
|
)
|
||||||
|
from subiquitycore.screen import is_linux_tty
|
||||||
from subiquitycore.tuicontroller import Skip
|
from subiquitycore.tuicontroller import Skip
|
||||||
from subiquitycore.tui import TuiApplication
|
from subiquitycore.tui import TuiApplication
|
||||||
from subiquitycore.snapd import (
|
from subiquitycore.snapd import (
|
||||||
|
@ -45,6 +46,10 @@ from subiquity.common.errorreport import (
|
||||||
ErrorReportKind,
|
ErrorReportKind,
|
||||||
)
|
)
|
||||||
from subiquity.journald import journald_listener
|
from subiquity.journald import journald_listener
|
||||||
|
from subiquity.keycodes import (
|
||||||
|
DummyKeycodesFilter,
|
||||||
|
KeyCodesFilter,
|
||||||
|
)
|
||||||
from subiquity.lockfile import Lockfile
|
from subiquity.lockfile import Lockfile
|
||||||
from subiquity.models.subiquity import SubiquityModel
|
from subiquity.models.subiquity import SubiquityModel
|
||||||
from subiquity.ui.frame import SubiquityUI
|
from subiquity.ui.frame import SubiquityUI
|
||||||
|
@ -124,6 +129,11 @@ class Subiquity(TuiApplication):
|
||||||
if not opts.bootloader == 'none' and platform.machine() != 's390x':
|
if not opts.bootloader == 'none' and platform.machine() != 's390x':
|
||||||
self.controllers.remove("Zdev")
|
self.controllers.remove("Zdev")
|
||||||
|
|
||||||
|
if is_linux_tty():
|
||||||
|
self.input_filter = KeyCodesFilter()
|
||||||
|
else:
|
||||||
|
self.input_filter = DummyKeycodesFilter()
|
||||||
|
|
||||||
self.journal_fd, self.journal_watcher = journald_listener(
|
self.journal_fd, self.journal_watcher = journald_listener(
|
||||||
["subiquity"], self.subiquity_event, seek=True)
|
["subiquity"], self.subiquity_event, seek=True)
|
||||||
self.help_menu = HelpMenu(self)
|
self.help_menu = HelpMenu(self)
|
||||||
|
@ -266,6 +276,9 @@ class Subiquity(TuiApplication):
|
||||||
super().new_event_loop()
|
super().new_event_loop()
|
||||||
self.aio_loop.add_reader(self.journal_fd, self.journal_watcher)
|
self.aio_loop.add_reader(self.journal_fd, self.journal_watcher)
|
||||||
|
|
||||||
|
def extra_urwid_loop_args(self):
|
||||||
|
return dict(input_filter=self.input_filter.filter)
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
try:
|
try:
|
||||||
if self.opts.autoinstall is not None:
|
if self.opts.autoinstall is not None:
|
||||||
|
|
|
@ -0,0 +1,108 @@
|
||||||
|
# Copyright 2020 Canonical, Ltd.
|
||||||
|
#
|
||||||
|
# This program is free software: you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU Affero General Public License as
|
||||||
|
# published by the Free Software Foundation, either version 3 of the
|
||||||
|
# License, or (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU Affero General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU Affero General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
import fcntl
|
||||||
|
import logging
|
||||||
|
import os
|
||||||
|
import struct
|
||||||
|
import sys
|
||||||
|
|
||||||
|
log = logging.getLogger('subiquity.keycodes')
|
||||||
|
|
||||||
|
# /usr/include/linux/kd.h
|
||||||
|
K_RAW = 0x00
|
||||||
|
K_XLATE = 0x01
|
||||||
|
K_MEDIUMRAW = 0x02
|
||||||
|
K_UNICODE = 0x03
|
||||||
|
K_OFF = 0x04
|
||||||
|
|
||||||
|
KDGKBMODE = 0x4B44 # gets current keyboard mode
|
||||||
|
KDSKBMODE = 0x4B45 # sets current keyboard mode
|
||||||
|
|
||||||
|
|
||||||
|
class KeyCodesFilter:
|
||||||
|
"""input_filter that can pass (medium) raw keycodes to the application
|
||||||
|
|
||||||
|
See http://lct.sourceforge.net/lct/x60.html for terminology.
|
||||||
|
|
||||||
|
Call enter_keycodes_mode()/exit_keycodes_mode() to switch into and
|
||||||
|
out of keycodes mode. In keycodes mode, the only events passed to
|
||||||
|
the application are "press $N" / "release $N" where $N is the
|
||||||
|
keycode the user pressed or released.
|
||||||
|
|
||||||
|
Much of this is cribbed from the source of the "showkeys" utility.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
self._fd = os.open("/proc/self/fd/"+str(sys.stdin.fileno()), os.O_RDWR)
|
||||||
|
self.filtering = False
|
||||||
|
|
||||||
|
def enter_keycodes_mode(self):
|
||||||
|
log.debug("enter_keycodes_mode")
|
||||||
|
self.filtering = True
|
||||||
|
# Read the old keyboard mode (it will proably always be K_UNICODE but
|
||||||
|
# well).
|
||||||
|
o = bytearray(4)
|
||||||
|
fcntl.ioctl(self._fd, KDGKBMODE, o)
|
||||||
|
self._old_mode = struct.unpack('i', o)[0]
|
||||||
|
# Set the keyboard mode to K_MEDIUMRAW, which causes the keyboard
|
||||||
|
# driver in the kernel to pass us keycodes.
|
||||||
|
fcntl.ioctl(self._fd, KDSKBMODE, K_MEDIUMRAW)
|
||||||
|
|
||||||
|
def exit_keycodes_mode(self):
|
||||||
|
log.debug("exit_keycodes_mode")
|
||||||
|
self.filtering = False
|
||||||
|
fcntl.ioctl(self._fd, KDSKBMODE, self._old_mode)
|
||||||
|
|
||||||
|
def filter(self, keys, codes):
|
||||||
|
# Luckily urwid passes us the raw results from read() we can
|
||||||
|
# turn into keycodes.
|
||||||
|
if self.filtering:
|
||||||
|
i = 0
|
||||||
|
r = []
|
||||||
|
n = len(codes)
|
||||||
|
while i < len(codes):
|
||||||
|
# This is straight from showkeys.c.
|
||||||
|
if codes[i] & 0x80:
|
||||||
|
p = 'release '
|
||||||
|
else:
|
||||||
|
p = 'press '
|
||||||
|
if i + 2 < n and (codes[i] & 0x7f) == 0:
|
||||||
|
if (codes[i + 1] & 0x80) != 0:
|
||||||
|
if (codes[i + 2] & 0x80) != 0:
|
||||||
|
kc = (((codes[i + 1] & 0x7f) << 7) |
|
||||||
|
(codes[i + 2] & 0x7f))
|
||||||
|
i += 3
|
||||||
|
else:
|
||||||
|
kc = codes[i] & 0x7f
|
||||||
|
i += 1
|
||||||
|
r.append(p + str(kc))
|
||||||
|
return r
|
||||||
|
else:
|
||||||
|
return keys
|
||||||
|
|
||||||
|
|
||||||
|
class DummyKeycodesFilter:
|
||||||
|
# A dummy implementation of the same interface as KeyCodesFilter
|
||||||
|
# we can use when not running in a linux tty.
|
||||||
|
|
||||||
|
def enter_keycodes_mode(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def exit_keycodes_mode(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
def filter(self, keys, codes):
|
||||||
|
return keys
|
Loading…
Reference in New Issue