Dynamically changing keyboard remapping rules
When setting up my Sculpt-based work environment, my intent was to run an unmodified Linux installation as VM in Sculpt. Being strongly accustomed to i3wm, I quickly noticed the lack of the Windows key that is used for controlling the i3 window manager but which is intercepted by Sculpt for the same job. A bit reluctant to change my habits and retrain new key combos, I needed a better solution. With advice from Norman, I came to a pretty neat solution that I would like to share with you.
For starters, let me briefly explain the problem: In Sculpt, the Windows key (aka KEY_LEFTMETA) is remapped to KEY_SCREEN by default and used as a modifier key for controlling the window manager. In consequence, the Windows key is not available to any application or VM unless we add another remapping rule such as KEY_RIGHTCTRL to KEY_LEFTMETA.
Unwilling to touch the key combos that I have wired already, the engineers mind was consulted for a better solution to this multiplexing problem. What does an engineer think of when spatial multiplexing is exhausted? Right, time multiplexing! Or, in Sculpt terms, dynamically toggle the KEY_LEFTMETA to KEY_SCREEN remapping rule. Of course, this is achievable by manually editing the event_filter config, yet, I’d appreciate a little more convenience. Maybe introduce a global key to toggle the remapping rule? Norman hinted that such a pattern is already employed for numlock.
In the end, I created a user_keys package that solely uses existing components (most importantly global_keys_handler and rom_filter) to augment my Sculpt system with such a feature. My motivation to share this story is not only because I think someone else could find this feature useful but also because it highlights the modularity of Genode-based systems such as Sculpt.
Usage
You can find a ready-to-use user_keys package in my depot (jschlatow) or build your own from genode-world.
When installing and deploying the package, it requests a Gui and a File_system session. We must choose "gui" for the Gui session in order to receive global key events. The file system is needed to read the files dynamic_remap.config and user_keys.config as well as to write a user.remap file. In order to make these files accessible to the event_filter component, they must be routed to /model/keyboard. In Sculpt 26.04, we need to click on the dots "..." next to the "model (rw)" option and select "keyboard".
Upon the first start, the component creates the input files user_keys.config and dynamic_remap.config. The user_keys.config contains the config of the global_keys_handler component instantiated by user_keys. Let’s have a look at its default content:
config + bool state | initial: no + press KEY_SCROLLLOCK | bool: state | change: toggle + report state + bool state -
This config instructs the global_keys_handler to generate a report and toggle the enabled state whenever KEY_SCROLLLOCK is pressed. The report is consumed by user_keys' rom_filter component, which uses dynamic_remap.config as its config. The default content of this file sets the mapping of KEY_LEFTMETA to KEY_SCREEN depending on the reported state:
config
+ input enabled | rom: state | node: state
+ attribute enabled
+ output | node: remap
+ if
+ has_value | input: enabled | value: yes
+ then
+ inline
+ key KEY_LEFTMETA | to: KEY_SCREEN
-
The output of the rom_filter component is written to the user.remap file of the provided file system. At this point, we still have to register KEY_SCROLLLOCK as a global key before we see any action. This is done in /model/child/gui with the following line:
+ global-key KEY_SCROLLLOCK | label: user_keys -> user_keys -> input
Finally, we will see the aforementioned user.remap file changing its content when we press KEY_SCROLLLOCK. As a final step, we simply include this file in our /model/child/event_filter:
+ remap + include | rom: keyboard/user.remap
Edit 2026-05-04: Updated instructions for Sculpt 26.04


Johannes Schlatow