mirror of
https://github.com/genodelabs/genode.git
synced 2025-02-20 17:52:52 +00:00
vbox6: support capslock="rom" mode
In ROM mode the global CapsLock state is controlled by the capslock ROM by virtual KEY_CAPSLOCK events. Guests are easily confused by spurious KEY_CAPSLOCK input events in caps="rom" mode. These spurious events may reach the VMM if KEY_CAPSLOCK is not pressed as first key in a combination and, therefore, is not filtered as global key. We filter KEY_CAPSLOCK in ROM mode in the VMM explicitly, but let it pass in non-ROM mode. Per default RAW mode is used and CapsLock key events are sent unfiltered to the guest.
This commit is contained in:
parent
434d007dc1
commit
331844c979
@ -44,7 +44,7 @@
|
||||
<binary name="virtualbox6" />
|
||||
<resource name="RAM" quantum="8G"/>
|
||||
<exit propagate="yes"/>
|
||||
<config vbox_file="machine.vbox" xhci="yes" vm_name="linux" capslock="ROM">
|
||||
<config vbox_file="machine.vbox" xhci="yes" vm_name="linux" capslock="rom">
|
||||
<vfs>
|
||||
<dir name="dev">
|
||||
<log/> <rtc/> <null/> <zero/>
|
||||
|
32
repos/ports/src/virtualbox6/README
Normal file
32
repos/ports/src/virtualbox6/README
Normal file
@ -0,0 +1,32 @@
|
||||
VirtualBox configuration options
|
||||
================================
|
||||
|
||||
The configuration requires an attribute named vbox_file with the name of the
|
||||
vbox configuration to be used (.vbox).
|
||||
|
||||
<config vbox_file="file.vbox">
|
||||
|
||||
XHCI controller
|
||||
~~~~~~~~~~~~~~~
|
||||
|
||||
The virtual XHCI controller can be enabled with the following
|
||||
configuration option:
|
||||
|
||||
<config xhci="yes">
|
||||
|
||||
CapsLock
|
||||
~~~~~~~~
|
||||
|
||||
Per default CapsLock key events are send unmodified to guest
|
||||
operating systems. As guest and host state may diverge, the event
|
||||
filter optionally reports the capslock state as ROM, which can be
|
||||
monitored by VirtualBox if configured like follows.
|
||||
|
||||
<config capslock="rom">
|
||||
|
||||
VirtualBox requests a "capslock" ROM, which is interpreted as XML. The
|
||||
top-level node attribute 'enabled' is expected boolean and represents
|
||||
the CapsLock state. If ROM and VM-internal CapsLock state differ, the
|
||||
VMM sends aritifical CapsLock key events to the VM. In this mode,
|
||||
incoming KEY_CAPSLOCK input events a dropped and not sent to the guest
|
||||
to prevent the state divergence.
|
@ -207,19 +207,63 @@ struct Main : Event_handler
|
||||
}
|
||||
} _idisplay { _iconsole };
|
||||
|
||||
Signal_handler<Main> _capslock_handler { _env.ep(), *this, &Main::_handle_capslock };
|
||||
|
||||
void _handle_capslock();
|
||||
|
||||
struct Capslock
|
||||
{
|
||||
enum class Mode { RAW, ROM } const mode;
|
||||
|
||||
bool _host { false };
|
||||
bool _guest { false };
|
||||
|
||||
Constructible<Attached_rom_dataspace> _rom;
|
||||
|
||||
Capslock(Env &env, Xml_node config, Signal_context_capability sigh)
|
||||
:
|
||||
mode(config.attribute_value("capslock", String<4>()) == "rom"
|
||||
? Mode::ROM : Mode::RAW)
|
||||
{
|
||||
if (mode == Mode::ROM) {
|
||||
_rom.construct(env, "capslock");
|
||||
_rom->sigh(sigh);
|
||||
}
|
||||
}
|
||||
|
||||
void update_guest(bool enabled) { _guest = enabled; }
|
||||
|
||||
bool update_from_rom()
|
||||
{
|
||||
_rom->update();
|
||||
|
||||
bool const rom = _rom->xml().attribute_value("enabled", _guest);
|
||||
|
||||
bool trigger = false;
|
||||
|
||||
/*
|
||||
* If guest didn't respond with led change last time, we have to
|
||||
* trigger CapsLock change - mainly assuming that guest don't use the
|
||||
* led to externalize its internal state.
|
||||
*/
|
||||
if (rom != _host && _host != _guest)
|
||||
trigger = true;
|
||||
|
||||
if (rom != _guest)
|
||||
trigger = true;
|
||||
|
||||
/* remember last seen host capslock state */
|
||||
_host = rom;
|
||||
|
||||
return trigger;
|
||||
}
|
||||
} _capslock { _env, _config.xml(), _capslock_handler };
|
||||
|
||||
Registry<Registered<Gui::Connection>> _gui_connections { };
|
||||
|
||||
Signal_handler<Main> _input_handler { _env.ep(), *this, &Main::_handle_input };
|
||||
|
||||
void _handle_input_event(Input::Event const &);
|
||||
|
||||
void _handle_input()
|
||||
{
|
||||
Libc::with_libc([&] {
|
||||
_gui_connections.for_each([&] (Gui::Connection &gui) {
|
||||
gui.input()->for_each_event([&] (Input::Event const &ev) {
|
||||
_handle_input_event(ev); }); }); });
|
||||
}
|
||||
void _handle_input();
|
||||
|
||||
Input_adapter _input_adapter { _iconsole };
|
||||
|
||||
@ -296,9 +340,34 @@ struct Main : Event_handler
|
||||
};
|
||||
|
||||
|
||||
void Main::_handle_input_event(Input::Event const &ev)
|
||||
void Main::_handle_capslock()
|
||||
{
|
||||
_input_adapter.handle_input_event(ev);
|
||||
if (_capslock.update_from_rom()) {
|
||||
Libc::with_libc([&] {
|
||||
_input_adapter.handle_input_event(Input::Event { Input::Press { Input::KEY_CAPSLOCK } });
|
||||
_input_adapter.handle_input_event(Input::Event { Input::Release { Input::KEY_CAPSLOCK } });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Main::_handle_input()
|
||||
{
|
||||
auto handle_one_event = [&] (Input::Event const &ev) {
|
||||
/* don't confuse guests and drop CapsLock events in ROM mode */
|
||||
if (_capslock.mode == Capslock::Mode::ROM) {
|
||||
if (ev.key_press(Input::KEY_CAPSLOCK)
|
||||
|| ev.key_release(Input::KEY_CAPSLOCK))
|
||||
return;
|
||||
}
|
||||
|
||||
_input_adapter.handle_input_event(ev);
|
||||
};
|
||||
|
||||
Libc::with_libc([&] {
|
||||
_gui_connections.for_each([&] (Gui::Connection &gui) {
|
||||
gui.input()->for_each_event([&] (Input::Event const &ev) {
|
||||
handle_one_event(ev); }); }); });
|
||||
}
|
||||
|
||||
|
||||
@ -314,7 +383,14 @@ void Main::handle_vbox_event(VBoxEventType_T ev_type, IEvent &ev)
|
||||
} break;
|
||||
|
||||
case VBoxEventType_OnMousePointerShapeChanged: break;
|
||||
case VBoxEventType_OnKeyboardLedsChanged: break;
|
||||
|
||||
case VBoxEventType_OnKeyboardLedsChanged:
|
||||
{
|
||||
ComPtr<IKeyboardLedsChangedEvent> led_ev = &ev;
|
||||
BOOL capslock;
|
||||
led_ev->COMGETTER(CapsLock)(&capslock);
|
||||
_capslock.update_guest(!!capslock);
|
||||
} break;
|
||||
|
||||
default: /* ignore other events */ break;
|
||||
}
|
||||
@ -335,7 +411,7 @@ void Libc::Component::construct(Libc::Env &env)
|
||||
char **envp = nullptr;
|
||||
|
||||
populate_args_and_env(env, argc, argv, envp);
|
||||
|
||||
|
||||
environ = envp;
|
||||
|
||||
Pthread::init(env);
|
||||
|
Loading…
x
Reference in New Issue
Block a user