Merge pull request #91361 from RandomShaper/fix_no_focusin
Windows: Fix `WINDOW_EVENT_FOCUS_IN` not delivered in some cases
This commit is contained in:
commit
2885620385
|
@ -3764,8 +3764,13 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
|||
}
|
||||
} break;
|
||||
case WM_ACTIVATE: {
|
||||
_process_activate_event(window_id, wParam, lParam);
|
||||
return 0; // Return to the message loop.
|
||||
// Activation can happen just after the window has been created, even before the callbacks are set.
|
||||
// Therefore, it's safer to defer the delivery of the event.
|
||||
if (!windows[window_id].activate_timer_id) {
|
||||
windows[window_id].activate_timer_id = SetTimer(windows[window_id].hWnd, 1, USER_TIMER_MINIMUM, (TIMERPROC) nullptr);
|
||||
}
|
||||
windows[window_id].activate_state = GET_WM_ACTIVATE_STATE(wParam, lParam);
|
||||
return 0;
|
||||
} break;
|
||||
case WM_GETMINMAXINFO: {
|
||||
if (windows[window_id].resizable && !windows[window_id].fullscreen) {
|
||||
|
@ -3888,11 +3893,13 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
|||
return 0;
|
||||
}
|
||||
} break;
|
||||
case WM_CLOSE: // Did we receive a close message?
|
||||
{
|
||||
case WM_CLOSE: {
|
||||
if (windows[window_id].activate_timer_id) {
|
||||
KillTimer(windows[window_id].hWnd, windows[window_id].activate_timer_id);
|
||||
windows[window_id].activate_timer_id = 0;
|
||||
}
|
||||
_send_window_event(windows[window_id], WINDOW_EVENT_CLOSE_REQUEST);
|
||||
|
||||
return 0; // Jump back.
|
||||
return 0;
|
||||
}
|
||||
case WM_MOUSELEAVE: {
|
||||
if (window_mouseover_id == window_id) {
|
||||
|
@ -4661,6 +4668,10 @@ LRESULT DisplayServerWindows::WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARA
|
|||
if (!Main::is_iterating()) {
|
||||
Main::iteration();
|
||||
}
|
||||
} else if (wParam == windows[window_id].activate_timer_id) {
|
||||
_process_activate_event(window_id);
|
||||
KillTimer(windows[window_id].hWnd, windows[window_id].activate_timer_id);
|
||||
windows[window_id].activate_timer_id = 0;
|
||||
}
|
||||
} break;
|
||||
case WM_SYSKEYUP:
|
||||
|
@ -4864,31 +4875,32 @@ 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) {
|
||||
void DisplayServerWindows::_process_activate_event(WindowID p_window_id) {
|
||||
WindowData &wd = windows[p_window_id];
|
||||
if (wd.activate_state == WA_ACTIVE || wd.activate_state == WA_CLICKACTIVE) {
|
||||
last_focused_window = p_window_id;
|
||||
alt_mem = false;
|
||||
control_mem = false;
|
||||
shift_mem = false;
|
||||
gr_mem = false;
|
||||
_set_mouse_mode_impl(mouse_mode);
|
||||
if (!IsIconic(windows[p_window_id].hWnd)) {
|
||||
SetFocus(windows[p_window_id].hWnd);
|
||||
if (!IsIconic(wd.hWnd)) {
|
||||
SetFocus(wd.hWnd);
|
||||
}
|
||||
windows[p_window_id].window_focused = true;
|
||||
_send_window_event(windows[p_window_id], WINDOW_EVENT_FOCUS_IN);
|
||||
wd.window_focused = true;
|
||||
_send_window_event(wd, WINDOW_EVENT_FOCUS_IN);
|
||||
} else { // WM_INACTIVE.
|
||||
Input::get_singleton()->release_pressed_events();
|
||||
track_mouse_leave_event(windows[p_window_id].hWnd);
|
||||
track_mouse_leave_event(wd.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);
|
||||
wd.window_focused = false;
|
||||
_send_window_event(wd, WINDOW_EVENT_FOCUS_OUT);
|
||||
}
|
||||
|
||||
if ((tablet_get_current_driver() == "wintab") && wintab_available && windows[p_window_id].wtctx) {
|
||||
wintab_WTEnable(windows[p_window_id].wtctx, GET_WM_ACTIVATE_STATE(wParam, lParam));
|
||||
if ((tablet_get_current_driver() == "wintab") && wintab_available && wd.wtctx) {
|
||||
wintab_WTEnable(wd.wtctx, wd.activate_state);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -389,6 +389,7 @@ class DisplayServerWindows : public DisplayServer {
|
|||
bool borderless = false;
|
||||
bool resizable = true;
|
||||
bool window_focused = false;
|
||||
int activate_state = 0;
|
||||
bool was_maximized = false;
|
||||
bool always_on_top = false;
|
||||
bool no_focus = false;
|
||||
|
@ -402,6 +403,7 @@ class DisplayServerWindows : public DisplayServer {
|
|||
|
||||
// Timers.
|
||||
uint32_t move_timer_id = 0U;
|
||||
uint32_t activate_timer_id = 0U;
|
||||
|
||||
HANDLE wtctx;
|
||||
LOGCONTEXTW wtlc;
|
||||
|
@ -508,7 +510,7 @@ class DisplayServerWindows : public DisplayServer {
|
|||
WindowID _get_focused_window_or_popup() const;
|
||||
void _register_raw_input_devices(WindowID p_target_window);
|
||||
|
||||
void _process_activate_event(WindowID p_window_id, WPARAM wParam, LPARAM lParam);
|
||||
void _process_activate_event(WindowID p_window_id);
|
||||
void _process_key_events();
|
||||
|
||||
static void _dispatch_input_events(const Ref<InputEvent> &p_event);
|
||||
|
|
Loading…
Reference in New Issue