Important information: Google announced that, from September 2026, Android devices will require ALL apps to be signed by Google, effectively leading to an iOS situation. Value your right to a computer that does what you want; do not tolerate this monopolistic practice! Contact me if you don't understand why it is bad. Click to learn more.

support terminal controls

by roundabout, Thursday, 2 July 2026, 09:04:09 (1782983049), pushed by roundabout, Thursday, 2 July 2026, 09:04:26 (1782983066)

Author identity: vlad <vlad.muntoiu@gmail.com>

550bd2202e10dd36a7e0083433a4d1583db3d6be

main.py

@@ -29,7 +29,7 @@ CDLL("libgtk4-layer-shell.so")

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            import gi
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            gi.require_version("Gtk", "4.0")
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            gi.require_version("Gtk4LayerShell", "1.0")
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        from gi.repository import Gtk, Gdk, GObject, Gtk4LayerShell, GLib, Gio
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        from gi.repository import Gtk, Gdk, GObject, Gtk4LayerShell, GLib, Gio, GObject
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            from pywayland.client import Display, EventQueue
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            from pywayland.protocol.wayland import WlRegistry, WlSeat
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -43,6 +43,7 @@ from pywayland.protocol.input_method_unstable_v2 import (

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            )
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            from pywayland.protocol.virtual_keyboard_unstable_v1 import ZwpVirtualKeyboardManagerV1
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        from xkbcommon import xkb
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            import ctypes
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            from cffi import FFI
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -213,12 +214,32 @@ class Plane(Gtk.Grid):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            def make_xkb_keymap_from_unicodes(unicodes):
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                symbols = [
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "key <SP00> { [ BackSpace ] };",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "key <SP01> { [ Return ] };",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "key <LEFT> { [ Left ] };"
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "key <RGHT> { [ Right ] };"
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "key <UP>   { [ Up ] };"
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "key <DOWN> { [ Down ] };"
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "key <TAB>  { [ Tab ] };",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "key <LCTL> { [ Control_L ] };",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "key <LALT> { [ Alt_L ] };",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "key <LSHF> { [ Shift_L ] };",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "key <LSPR> { [ Super_L ] };",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "key <ESCP> { [ Escape ] };",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "key <BKSP> { [ BackSpace ] };",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "key <RTRN> { [ Return ] };",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                ]
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                keycodes = [
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "<SP00> = 4094;",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "<SP01> = 4095;",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "<LEFT> = 4084;",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "<RGHT> = 4085;",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "<UP>   = 4086;",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "<DOWN> = 4087;",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "<TAB>  = 4088;",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "<LCTL> = 4089;",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "<LALT> = 4090;",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "<LSHF> = 4091;",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "<LSPR> = 4092;",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "<ESCP> = 4093;",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "<BKSP> = 4094;",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                "<RTRN> = 4095;",
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                ]
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                for i, char in enumerate(unicodes):
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    keycode = 0x1000 + i
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -273,6 +294,23 @@ def register_client(client_id: str):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                return proxy
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        class ModifierButton(Gtk.ToggleButton):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def __init__(self, app, mask, **kwargs):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                super().__init__(**kwargs)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.app = app
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.mask = mask
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.connect("toggled", self.toggle_modifier)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def toggle_modifier(self, button):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                if button.get_active():
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.app.depressed_modifiers |= self.mask
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                else:
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    self.app.depressed_modifiers &= ~self.mask
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.app.send_modifiers()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            class Kineboard(Gtk.Application):
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                def __init__(self):
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    Gtk.Application.__init__(
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -280,8 +318,10 @@ class Kineboard(Gtk.Application):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        application_id="sm.puri.OSK0",
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        flags=Gio.ApplicationFlags.HANDLES_COMMAND_LINE
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    )
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.xkb_context = xkb.Context()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.revealer = None
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.switcher = None
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.depressed_modifiers = 0
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.character_index = {}
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.keymap_fd = None
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.vk = None
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -299,6 +339,10 @@ class Kineboard(Gtk.Application):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.seat = None
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.vkm = None
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.serial = 0
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.extra_revealer = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.extra_viewport = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.extra_scroll = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.extra_controls = None
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.add_main_option(
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        "invoke",
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        ord("i"),
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -315,9 +359,9 @@ class Kineboard(Gtk.Application):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        "Hide the keyboard",
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        None
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    )
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def toggle_sidebar(self, button):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.revealer.set_reveal_child(not self.revealer.get_reveal_child())
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            def send_modifiers(self):
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.vk.modifiers(self.depressed_modifiers, 0, 0, 0)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                def do_startup(self):
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    Gtk.Application.do_startup(self)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -326,13 +370,15 @@ class Kineboard(Gtk.Application):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.window = Gtk.Window(application=self, title="Demo", focus_on_click=False, focusable=False, can_focus=False)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    Gtk4LayerShell.init_for_window(self.window)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    Gtk4LayerShell.set_keyboard_mode(self.window, Gtk4LayerShell.KeyboardMode.NONE)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.window.set_default_size(16384, -1)   # large width so that it spans the bottom
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    Gtk4LayerShell.set_anchor(self.window, Gtk4LayerShell.Edge.BOTTOM, True)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    Gtk4LayerShell.set_anchor(self.window, Gtk4LayerShell.Edge.LEFT, True)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    Gtk4LayerShell.set_anchor(self.window, Gtk4LayerShell.Edge.RIGHT, True)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    Gtk4LayerShell.auto_exclusive_zone_enable(self.window)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    Gtk4LayerShell.set_namespace(self.window, "osk")
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.box = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.window.set_child(self.box)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.main_box = Gtk.Box(orientation=Gtk.Orientation.VERTICAL, margin_top=8)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.window.set_child(self.main_box)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.stack = Gtk.Stack()
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.box.append(self.stack)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    layouts = itertools.chain.from_iterable((f for f in path.iterdir() if f.is_file()) for path in get_layout_directories())
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -340,6 +386,13 @@ class Kineboard(Gtk.Application):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.switcher = Gtk.StackSidebar(stack=self.stack)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.revealer = Gtk.Revealer(child=self.switcher, transition_type=Gtk.RevealerTransitionType.SLIDE_RIGHT)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.box.prepend(self.revealer)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.extra_controls = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8,
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                                              margin_bottom=8, margin_start=8, margin_end=8)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.extra_viewport = Gtk.Viewport(child=self.extra_controls)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.extra_scroll = Gtk.ScrolledWindow(child=self.extra_viewport, propagate_natural_height=True)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.extra_revealer = Gtk.Revealer(child=self.extra_scroll)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    for layout in layouts:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        stack = Gtk.Stack()
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -349,11 +402,17 @@ class Kineboard(Gtk.Application):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        controls = Gtk.Box(orientation=Gtk.Orientation.HORIZONTAL, spacing=8, margin_top=0,
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                                           margin_bottom=8, margin_start=8, margin_end=8)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    layout_button = Gtk.Button(child=Gtk.Image.new_from_icon_name("edit-symbolic"))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    layout_button = Gtk.ToggleButton(child=Gtk.Image.new_from_icon_name("edit-symbolic"))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        layout_button.set_size_request(48, -1)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        layout_button.update_property([Gtk.AccessibleProperty.LABEL], ["Switch layout"])
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    layout_button.connect("clicked", self.toggle_sidebar)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        controls.append(layout_button)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    layout_button.bind_property("active", self.revealer, "reveal-child", GObject.BindingFlags.BIDIRECTIONAL)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    control_button = Gtk.ToggleButton(child=Gtk.Image.new_from_icon_name("utilities-terminal-symbolic"))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    control_button.set_size_request(48, -1)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    control_button.update_property([Gtk.AccessibleProperty.LABEL], ["Terminal controls"])
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    controls.append(control_button)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    control_button.bind_property("active", self.extra_revealer, "reveal-child", GObject.BindingFlags.BIDIRECTIONAL)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        if len(data["keys"]) >= 2:
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                            shift_button = Gtk.ToggleButton(
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -373,7 +432,7 @@ class Kineboard(Gtk.Application):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        space_bar.connect("clicked", lambda x: self.typed(x, " "))
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        controls.append(space_bar)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    backspace_button = Gtk.Button(child=Gtk.Image.new_from_icon_name("go-previous-symbolic"))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                    backspace_button = Gtk.Button(child=Gtk.Image.new_from_icon_name("edit-clear-symbolic"))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        backspace_button.set_size_request(48, -1)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        backspace_button.update_property([Gtk.AccessibleProperty.LABEL], ["Backspace"])
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        backspace_button.connect("clicked", lambda x: self.send_keysym(0xFF6))
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -388,7 +447,7 @@ class Kineboard(Gtk.Application):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        for i, layer in enumerate(data["keys"]):
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                            grid = Plane(self, layer, row_spacing=8, column_spacing=8, row_homogeneous=True,
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                                     column_homogeneous=True, margin_top=8, margin_bottom=8,
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                                     column_homogeneous=True, margin_bottom=8,
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                                         margin_end=8, margin_start=8)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                            self.all_characters += grid.all_characters
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                            stack.add_named(grid, f"plane-{i}")
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -398,6 +457,9 @@ class Kineboard(Gtk.Application):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        outer_box.append(controls)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        self.stack.add_titled(outer_box, data["symbol"], data["symbol"])
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.main_box.append(self.extra_revealer)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.main_box.append(self.box)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                        
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    ctypes.pythonapi.PyCapsule_GetPointer.restype = ctypes.c_void_p
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    ctypes.pythonapi.PyCapsule_GetPointer.argtypes = (ctypes.py_object,)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        

@@ -419,6 +481,36 @@ class Kineboard(Gtk.Application):

                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        dialog.show()
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                            
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.keymap_text = make_xkb_keymap_from_unicodes(self.all_characters)
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                xkb_keymap = self.xkb_context.keymap_new_from_string(self.keymap_text)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                state = xkb_keymap.state_new()
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                escape_button = Gtk.Button(label="Escape")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                escape_button.connect("clicked", lambda x: self.send_keysym(0xFF5))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.extra_controls.append(escape_button)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.extra_controls.append(ModifierButton(self, 1 << xkb_keymap.mod_get_index("Control"), label="Control"))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.extra_controls.append(ModifierButton(self, 1 << xkb_keymap.mod_get_index("Mod1"), label="Alt"))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.extra_controls.append(ModifierButton(self, 1 << xkb_keymap.mod_get_index("Shift"), label="Shift"))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.extra_controls.append(ModifierButton(self, 1 << xkb_keymap.mod_get_index("Mod4"), label="Super"))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                tab_button = Gtk.Button(label="Tab")
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                tab_button.connect("clicked", lambda x: self.send_keysym(0xFF0))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.extra_controls.append(tab_button)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                left_button = Gtk.Button(child=Gtk.Image.new_from_icon_name("go-previous-symbolic"))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                left_button.update_property([Gtk.AccessibleProperty.LABEL], ["Left"])
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                left_button.connect("clicked", lambda x: self.send_keysym(0xFEC))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.extra_controls.append(left_button)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                down_button = Gtk.Button(child=Gtk.Image.new_from_icon_name("go-down-symbolic"))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                down_button.update_property([Gtk.AccessibleProperty.LABEL], ["Down"])
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                down_button.connect("clicked", lambda x: self.send_keysym(0xFEF))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.extra_controls.append(down_button)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                up_button = Gtk.Button(child=Gtk.Image.new_from_icon_name("go-up-symbolic"))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                up_button.update_property([Gtk.AccessibleProperty.LABEL], ["Up"])
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                up_button.connect("clicked", lambda x: self.send_keysym(0xFEE))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.extra_controls.append(up_button)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                right_button = Gtk.Button(child=Gtk.Image.new_from_icon_name("go-next-symbolic"))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                right_button.update_property([Gtk.AccessibleProperty.LABEL], ["Right"])
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                right_button.connect("clicked", lambda x: self.send_keysym(0xFED))
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                self.extra_controls.append(right_button)
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                                
                                        
                                        
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    self.character_index = {}
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                    for i, character in enumerate(self.all_characters):
                                        
                                        
                                            
                                            
                                            
                                            
                                        
                                    
                                
                                
                                
                            
                                
                                    
                                        
                                            
                                                        self.character_index[character] = i