genodelabs / genode

Genode OS Framework
https://genode.org/
Other
1.05k stars 249 forks source link

sculpt: missed BTN_MIDDLE events if <button-scroll> is used in event_filter #5333

Open chelmuth opened 2 weeks ago

chelmuth commented 2 weeks ago

@ssumpf discovered that his <button-scroll> configuration for PS/2 mouse middle button leads to missing mouse-button events in cases where scrolling is not intended. During our tests, we verified that the events are indeed sent by the event_filter component (<log> node) but are not effective in a running vbox VM nor the system_shell. Interestingly enough, the potential bug does not affect an inspect terminal.

As a background, <button-scroll> defers the BTN_MIDDLE press event until the scrolling is activated due to mouse movements or BTN_MIDDLE release is detected. In the latter case, both button events are reported simultaneously but in correct order.

chelmuth commented 2 weeks ago

After further investigation, the effects described above potentially have two distinct causes. The system_shell may suffer from a race on state inspection in the clipboard, while VirtualBox quite likely erroneously merges the two mouse-button events (press + release = nop) into a bitfield before the vboxguest driver picks up the press event.

nfeske commented 2 weeks ago

The system_shell may suffer from a race on state inspection in the clipboard [...]

BTW, this symptom can be side-stepped by setting the /config/clipboard configuration attribute match_labels="no", disabling the clipboard's dynamic information-flow policy described in the first item of my clipboard article.

chelmuth commented 1 week ago

In some cases, event_filter <button-scroll> does neither emit wheel events nor middle-button press-release event. The following patch illustrates the investigation and fixes the issue in my scenario.

+++ b/repos/os/src/server/event_filter/button_scroll_source.h
@@ -92,7 +92,8 @@ class Event_filter::Button_scroll_source : public Source, Source::Filter
                        bool handle_deactivation(Input::Event const &event)
                        {
                                if (event.key_release(_button)) {
-                                       bool const emit_press_release = (_state == BUTTON_PRESSED);
+                                       bool const emit_press_release = (_state == BUTTON_PRESSED)
+                                                                   || ((_state == ACTIVE) && !pending_motion());
                                        _state = IDLE;
                                        _accumulated_motion = 0;
                                        return emit_press_release;