Skip to content

Commit 7d5eb6b

Browse files
author
FeralChild64
committed
Do not ignore mouse events in seamless mode when focus is lost
1 parent 9f97ae9 commit 7d5eb6b

File tree

1 file changed

+47
-36
lines changed

1 file changed

+47
-36
lines changed

src/hardware/mouse/mouse.cpp

Lines changed: 47 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,9 @@ static struct {
6868
bool is_input_raw = false; // if GFX was requested to provide raw movements
6969
bool is_seamless = false; // if seamless mouse integration is in effect
7070

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+
7274
bool should_capture_on_click = false; // if any button click should capture the mouse
7375
bool should_capture_on_middle = false; // if middle button press should capture the mouse
7476
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
8991

9092
if (absolute < 0 || static_cast<uint32_t>(absolute) < clipping) {
9193
// cursor is over the top or left black bar
92-
state.cursor_is_outside = true;
94+
state.cursor_is_outside = !state.is_fullscreen;
9395
return 0;
9496
} else if (static_cast<uint32_t>(absolute) >= resolution + clipping) {
9597
// cursor is over the bottom or right black bar
96-
state.cursor_is_outside = true;
98+
state.cursor_is_outside = !state.is_fullscreen;
9799
return check_cast<uint32_t>(resolution - 1);
98100
}
99101

@@ -111,8 +113,9 @@ static void update_cursor_absolute_position(const int32_t x_abs, const int32_t y
111113
static void update_cursor_visibility()
112114
{
113115
// If mouse subsystem not started yet, do nothing
114-
if (!mouse_shared.started)
116+
if (!mouse_shared.started) {
115117
return;
118+
}
116119

117120
static bool first_time = true;
118121

@@ -196,23 +199,14 @@ static void update_state() // updates whole 'state' structure, except cursor vis
196199
// Raw input depends on the user configuration
197200
state.is_input_raw = mouse_config.raw_input;
198201

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) {
208203
state.is_captured = false;
209-
state.should_drop_events = true;
210204

211205
// Override user configuration, for the GUI we want
212206
// host OS mouse acceleration applied
213207
state.is_input_raw = false;
214208

215-
} else { // Window has focus, no GUI running
209+
} else if (state.is_window_active) { // window has focus, no GUI running
216210

217211
// Capture mouse cursor if any of:
218212
// - we lack a desktop environment,
@@ -221,14 +215,21 @@ static void update_state() // updates whole 'state' structure, except cursor vis
221215
state.is_captured = !state.have_desktop_environment ||
222216
state.is_fullscreen ||
223217
state.capture_was_requested;
218+
}
224219

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;
232233
}
233234

234235
// Use a hotkey to toggle mouse capture if:
@@ -245,7 +246,7 @@ static void update_state() // updates whole 'state' structure, except cursor vis
245246
// - mouse is not captured, and
246247
// - we are not in seamless mode, and
247248
// - no GUI has taken over the mouse, and
248-
// - no NoMouse mode is in effect, and
249+
// - capture type is different than NoMouse, and
249250
// - capture on start/click was configured or mapping is in effect
250251
state.should_capture_on_click = state.have_desktop_environment &&
251252
!state.is_fullscreen &&
@@ -260,7 +261,7 @@ static void update_state() // updates whole 'state' structure, except cursor vis
260261
// - windowed mode, and
261262
// - mouse is not captured, and
262263
// - no GUI has taken over the mouse, and
263-
// - no NoMouse mode is in effect, and
264+
// - capture type is different than NoMouse, and
264265
// - seamless mode is in effect, and
265266
// - middle release was configured
266267
state.should_capture_on_middle = state.have_desktop_environment &&
@@ -337,12 +338,16 @@ static void update_state() // updates whole 'state' structure, except cursor vis
337338
first_time = false;
338339
}
339340

340-
static bool should_drop_event()
341+
static bool should_ignore_move()
341342
{
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;
346351
}
347352

348353
void MOUSE_UpdateGFX()
@@ -541,8 +546,9 @@ void MOUSE_EventMoved(const float x_rel, const float y_rel,
541546
update_cursor_visibility();
542547

543548
// Drop unneeded events
544-
if (should_drop_event())
549+
if (should_ignore_move()) {
545550
return;
551+
}
546552

547553
// From the GUI we are getting mouse movement data in two
548554
// distinct formats:
@@ -577,8 +583,9 @@ void MOUSE_EventMoved(const float x_rel, const float y_rel,
577583
// Event from ManyMouse
578584

579585
// Drop unneeded events
580-
if (should_drop_event())
586+
if (should_ignore_move()) {
581587
return;
588+
}
582589

583590
auto interface = MouseInterface::Get(interface_id);
584591
if (interface && interface->IsUsingEvents()) {
@@ -616,9 +623,10 @@ void MOUSE_EventButton(const uint8_t idx, const bool pressed)
616623
return;
617624
}
618625

619-
/// Drop unneeded events
620-
if (should_drop_event())
626+
// Drop unneeded events
627+
if (should_ignore_press_or_wheel()) {
621628
return;
629+
}
622630
}
623631

624632
MouseEvent ev;
@@ -636,8 +644,9 @@ void MOUSE_EventButton(const uint8_t idx, const bool pressed,
636644
// Drop unneeded events - but never drop any button
637645
// releases events; pass them to concrete interfaces,
638646
// they will decide whether to ignore them or not.
639-
if (pressed && should_drop_event())
647+
if (pressed && should_ignore_press_or_wheel()) {
640648
return;
649+
}
641650

642651
auto interface = MouseInterface::Get(interface_id);
643652
if (interface && interface->IsUsingEvents()) {
@@ -652,8 +661,9 @@ void MOUSE_EventWheel(const int16_t w_rel)
652661
// Event from GFX
653662

654663
// Drop unneeded events
655-
if (should_drop_event())
664+
if (should_ignore_press_or_wheel()) {
656665
return;
666+
}
657667

658668
MouseEvent ev;
659669
for (auto &interface : mouse_interfaces)
@@ -667,8 +677,9 @@ void MOUSE_EventWheel(const int16_t w_rel, const MouseInterfaceId interface_id)
667677
// Event from ManyMouse
668678

669679
// Drop unneeded events
670-
if (state.should_drop_events)
680+
if (should_ignore_press_or_wheel()) {
671681
return;
682+
}
672683

673684
auto interface = MouseInterface::Get(interface_id);
674685
if (interface && interface->IsUsingEvents()) {

0 commit comments

Comments
 (0)