@@ -68,7 +68,9 @@ static struct {
68
68
bool is_input_raw = false ; // if GFX was requested to provide raw movements
69
69
bool is_seamless = false ; // if seamless mouse integration is in effect
70
70
71
- bool should_drop_events = true ; // if we should drop mouse events
71
+ // if mouse events should be ignored, except button release
72
+ bool should_ignore_events = true ;
73
+
72
74
bool should_capture_on_click = false ; // if any button click should capture the mouse
73
75
bool should_capture_on_middle = false ; // if middle button press should capture the mouse
74
76
bool should_release_on_middle = false ; // if middle button press should release the mouse
@@ -89,11 +91,11 @@ static void update_cursor_absolute_position(const int32_t x_abs, const int32_t y
89
91
90
92
if (absolute < 0 || static_cast <uint32_t >(absolute) < clipping) {
91
93
// cursor is over the top or left black bar
92
- state.cursor_is_outside = true ;
94
+ state.cursor_is_outside = !state. is_fullscreen ;
93
95
return 0 ;
94
96
} else if (static_cast <uint32_t >(absolute) >= resolution + clipping) {
95
97
// cursor is over the bottom or right black bar
96
- state.cursor_is_outside = true ;
98
+ state.cursor_is_outside = !state. is_fullscreen ;
97
99
return check_cast<uint32_t >(resolution - 1 );
98
100
}
99
101
@@ -111,8 +113,9 @@ static void update_cursor_absolute_position(const int32_t x_abs, const int32_t y
111
113
static void update_cursor_visibility ()
112
114
{
113
115
// If mouse subsystem not started yet, do nothing
114
- if (!mouse_shared.started )
116
+ if (!mouse_shared.started ) {
115
117
return ;
118
+ }
116
119
117
120
static bool first_time = true ;
118
121
@@ -196,23 +199,14 @@ static void update_state() // updates whole 'state' structure, except cursor vis
196
199
// Raw input depends on the user configuration
197
200
state.is_input_raw = mouse_config.raw_input ;
198
201
199
- if (!state.is_window_active ) {
200
-
201
- state.should_drop_events = true ;
202
-
203
- // No change to:
204
- // - state.is_captured
205
-
206
- } else if (state.gui_has_taken_over ) {
207
-
202
+ if (state.gui_has_taken_over ) {
208
203
state.is_captured = false ;
209
- state.should_drop_events = true ;
210
204
211
205
// Override user configuration, for the GUI we want
212
206
// host OS mouse acceleration applied
213
207
state.is_input_raw = false ;
214
208
215
- } else { // Window has focus, no GUI running
209
+ } else if (state. is_window_active ) { // window has focus, no GUI running
216
210
217
211
// Capture mouse cursor if any of:
218
212
// - we lack a desktop environment,
@@ -221,14 +215,21 @@ static void update_state() // updates whole 'state' structure, except cursor vis
221
215
state.is_captured = !state.have_desktop_environment ||
222
216
state.is_fullscreen ||
223
217
state.capture_was_requested ;
218
+ }
224
219
225
- // Drop mouse events if NoMouse is configured
226
- state.should_drop_events = is_config_no_mouse;
227
- // Also drop events if:
228
- // - mouse not captured, and
229
- // - mouse not in seamless mode (due to user setting or seamless driver)
230
- if (!state.is_captured && !state.is_seamless )
231
- state.should_drop_events = true ;
220
+ // Ignore mouse events (except for button release) if any of:
221
+ // - GUI has taken over the mouse
222
+ // - capture type is NoMouse
223
+ state.should_ignore_events = state.gui_has_taken_over ||
224
+ is_config_no_mouse;
225
+ if (!state.is_seamless ) {
226
+
227
+ // If not Seamless mode, also ignore events if any of:
228
+ // - mouse is not captured
229
+ // - emulator window is not active (has no focus)
230
+ state.should_ignore_events = state.should_ignore_events ||
231
+ !state.is_captured ||
232
+ !state.is_window_active ;
232
233
}
233
234
234
235
// Use a hotkey to toggle mouse capture if:
@@ -245,7 +246,7 @@ static void update_state() // updates whole 'state' structure, except cursor vis
245
246
// - mouse is not captured, and
246
247
// - we are not in seamless mode, and
247
248
// - no GUI has taken over the mouse, and
248
- // - no NoMouse mode is in effect , and
249
+ // - capture type is different than NoMouse , and
249
250
// - capture on start/click was configured or mapping is in effect
250
251
state.should_capture_on_click = state.have_desktop_environment &&
251
252
!state.is_fullscreen &&
@@ -260,7 +261,7 @@ static void update_state() // updates whole 'state' structure, except cursor vis
260
261
// - windowed mode, and
261
262
// - mouse is not captured, and
262
263
// - no GUI has taken over the mouse, and
263
- // - no NoMouse mode is in effect , and
264
+ // - capture type is different than NoMouse , and
264
265
// - seamless mode is in effect, and
265
266
// - middle release was configured
266
267
state.should_capture_on_middle = state.have_desktop_environment &&
@@ -337,12 +338,16 @@ static void update_state() // updates whole 'state' structure, except cursor vis
337
338
first_time = false ;
338
339
}
339
340
340
- static bool should_drop_event ()
341
+ static bool should_ignore_move ()
341
342
{
342
- // Decide whether to drop mouse events, depending on both
343
- // mouse cursor position and general event dropping policy
344
- return (state.is_seamless && state.cursor_is_outside ) ||
345
- state.should_drop_events ;
343
+ return state.should_ignore_events ||
344
+ (state.cursor_is_outside && !state.is_seamless );
345
+ }
346
+
347
+ static bool should_ignore_press_or_wheel ()
348
+ {
349
+ return state.should_ignore_events ||
350
+ state.cursor_is_outside ;
346
351
}
347
352
348
353
void MOUSE_UpdateGFX ()
@@ -541,8 +546,9 @@ void MOUSE_EventMoved(const float x_rel, const float y_rel,
541
546
update_cursor_visibility ();
542
547
543
548
// Drop unneeded events
544
- if (should_drop_event ())
549
+ if (should_ignore_move ()) {
545
550
return ;
551
+ }
546
552
547
553
// From the GUI we are getting mouse movement data in two
548
554
// distinct formats:
@@ -577,8 +583,9 @@ void MOUSE_EventMoved(const float x_rel, const float y_rel,
577
583
// Event from ManyMouse
578
584
579
585
// Drop unneeded events
580
- if (should_drop_event ())
586
+ if (should_ignore_move ()) {
581
587
return ;
588
+ }
582
589
583
590
auto interface = MouseInterface::Get (interface_id);
584
591
if (interface && interface->IsUsingEvents ()) {
@@ -616,9 +623,10 @@ void MOUSE_EventButton(const uint8_t idx, const bool pressed)
616
623
return ;
617
624
}
618
625
619
- // / Drop unneeded events
620
- if (should_drop_event ())
626
+ // Drop unneeded events
627
+ if (should_ignore_press_or_wheel ()) {
621
628
return ;
629
+ }
622
630
}
623
631
624
632
MouseEvent ev;
@@ -636,8 +644,9 @@ void MOUSE_EventButton(const uint8_t idx, const bool pressed,
636
644
// Drop unneeded events - but never drop any button
637
645
// releases events; pass them to concrete interfaces,
638
646
// they will decide whether to ignore them or not.
639
- if (pressed && should_drop_event ())
647
+ if (pressed && should_ignore_press_or_wheel ()) {
640
648
return ;
649
+ }
641
650
642
651
auto interface = MouseInterface::Get (interface_id);
643
652
if (interface && interface->IsUsingEvents ()) {
@@ -652,8 +661,9 @@ void MOUSE_EventWheel(const int16_t w_rel)
652
661
// Event from GFX
653
662
654
663
// Drop unneeded events
655
- if (should_drop_event ())
664
+ if (should_ignore_press_or_wheel ()) {
656
665
return ;
666
+ }
657
667
658
668
MouseEvent ev;
659
669
for (auto &interface : mouse_interfaces)
@@ -667,8 +677,9 @@ void MOUSE_EventWheel(const int16_t w_rel, const MouseInterfaceId interface_id)
667
677
// Event from ManyMouse
668
678
669
679
// Drop unneeded events
670
- if (state. should_drop_events )
680
+ if (should_ignore_press_or_wheel ()) {
671
681
return ;
682
+ }
672
683
673
684
auto interface = MouseInterface::Get (interface_id);
674
685
if (interface && interface->IsUsingEvents ()) {
0 commit comments