Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Robustify handling of activation & focus on Windows #84363

Merged
merged 1 commit into from
Apr 6, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 20 additions & 67 deletions platform/windows/display_server_windows.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3709,63 +3709,18 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
return MA_NOACTIVATE; // Do not activate, but process mouse messages.
}
} break;
case WM_SETFOCUS: {
windows[window_id].window_has_focus = true;
last_focused_window = window_id;

// Restore mouse mode.
_set_mouse_mode_impl(mouse_mode);

if (!app_focused) {
if (OS::get_singleton()->get_main_loop()) {
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN);
}
app_focused = true;
}
} break;
case WM_KILLFOCUS: {
windows[window_id].window_has_focus = false;
last_focused_window = window_id;

// Release capture unconditionally because it can be set due to dragging, in addition to captured mode.
ReleaseCapture();

// Release every touch to avoid sticky points.
for (const KeyValue<int, Vector2> &E : touch_state) {
_touch_event(window_id, false, E.value.x, E.value.y, E.key);
}
touch_state.clear();

bool self_steal = false;
HWND new_hwnd = (HWND)wParam;
if (IsWindow(new_hwnd)) {
self_steal = true;
case WM_ACTIVATEAPP: {
bool new_app_focused = (bool)wParam;
if (new_app_focused == app_focused) {
break;
}

if (!self_steal) {
if (OS::get_singleton()->get_main_loop()) {
OS::get_singleton()->get_main_loop()->notification(MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT);
}
app_focused = false;
app_focused = new_app_focused;
if (OS::get_singleton()->get_main_loop()) {
OS::get_singleton()->get_main_loop()->notification(app_focused ? MainLoop::NOTIFICATION_APPLICATION_FOCUS_IN : MainLoop::NOTIFICATION_APPLICATION_FOCUS_OUT);
}
} break;
case WM_ACTIVATE: { // Watch for window activate message.
if (!windows[window_id].window_focused) {
_process_activate_event(window_id, wParam, lParam);
} else {
windows[window_id].saved_wparam = wParam;
windows[window_id].saved_lparam = lParam;

// Run a timer to prevent event catching warning if the focused window is closing.
windows[window_id].focus_timer_id = SetTimer(windows[window_id].hWnd, 2, USER_TIMER_MINIMUM, (TIMERPROC) nullptr);
}
if (wParam != WA_INACTIVE) {
track_mouse_leave_event(hWnd);

if (!IsIconic(hWnd)) {
SetFocus(hWnd);
}
}
case WM_ACTIVATE: {
_process_activate_event(window_id, wParam, lParam);
return 0; // Return to the message loop.
} break;
case WM_GETMINMAXINFO: {
Expand Down Expand Up @@ -3864,9 +3819,6 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
} break;
case WM_CLOSE: // Did we receive a close message?
{
if (windows[window_id].focus_timer_id != 0U) {
KillTimer(windows[window_id].hWnd, windows[window_id].focus_timer_id);
}
_send_window_event(windows[window_id], WINDOW_EVENT_CLOSE_REQUEST);

return 0; // Jump back.
Expand Down Expand Up @@ -4625,10 +4577,6 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
if (!Main::is_iterating()) {
Main::iteration();
}
} else if (wParam == windows[window_id].focus_timer_id) {
_process_activate_event(window_id, windows[window_id].saved_wparam, windows[window_id].saved_lparam);
KillTimer(windows[window_id].hWnd, wParam);
windows[window_id].focus_timer_id = 0U;
}
} break;
case WM_SYSKEYUP:
Expand Down Expand Up @@ -4834,20 +4782,25 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) {

void DisplayServerWindows::_process_activate_event(WindowID p_window_id, WPARAM wParam, LPARAM lParam) {
if (LOWORD(wParam) == WA_ACTIVE || LOWORD(wParam) == WA_CLICKACTIVE) {
_send_window_event(windows[p_window_id], WINDOW_EVENT_FOCUS_IN);
windows[p_window_id].window_focused = true;
last_focused_window = p_window_id;
alt_mem = false;
control_mem = false;
shift_mem = false;
gr_mem = false;

// Restore mouse mode.
_set_mouse_mode_impl(mouse_mode);
if (!IsIconic(windows[p_window_id].hWnd)) {
SetFocus(windows[p_window_id].hWnd);
}
windows[p_window_id].window_focused = true;
_send_window_event(windows[p_window_id], WINDOW_EVENT_FOCUS_IN);
} else { // WM_INACTIVE.
Input::get_singleton()->release_pressed_events();
_send_window_event(windows[p_window_id], WINDOW_EVENT_FOCUS_OUT);
windows[p_window_id].window_focused = false;
track_mouse_leave_event(windows[p_window_id].hWnd);
// Release capture unconditionally because it can be set due to dragging, in addition to captured mode.
ReleaseCapture();
alt_mem = false;
windows[p_window_id].window_focused = false;
_send_window_event(windows[p_window_id], WINDOW_EVENT_FOCUS_OUT);
}

if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[p_window_id].wtctx) {
Expand Down
1 change: 0 additions & 1 deletion platform/windows/display_server_windows.h
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,6 @@ class DisplayServerWindows : public DisplayServer {

// Timers.
uint32_t move_timer_id = 0U;
uint32_t focus_timer_id = 0U;

HANDLE wtctx;
LOGCONTEXTW wtlc;
Expand Down
Loading