mirror of
https://github.com/juce-framework/JUCE.git
synced 2026-01-10 23:44:24 +00:00
Windows: Fix bug where mouse events would not reach background windows blocked by modal windows
This commit is contained in:
parent
b0a3be2bb4
commit
2d243486c9
1 changed files with 57 additions and 15 deletions
|
|
@ -2813,6 +2813,11 @@ private:
|
|||
|
||||
doMouseEvent (getPointFromLocalLParam (lParam), MouseInputSource::defaultPressure);
|
||||
}
|
||||
|
||||
// If this is the first event after receiving both a MOUSEACTIVATE and a SETFOCUS, then
|
||||
// process the postponed focus update.
|
||||
if (std::exchange (mouseActivateFlags, (uint8_t) 0) == (gotMouseActivate | gotSetFocus))
|
||||
handleSetFocus();
|
||||
}
|
||||
|
||||
void doMouseUp (Point<float> position, const WPARAM wParam, bool adjustCapture = true)
|
||||
|
|
@ -3820,6 +3825,27 @@ private:
|
|||
return {};
|
||||
}
|
||||
|
||||
void handleSetFocus()
|
||||
{
|
||||
/* When the HWND receives Focus from the system it sends a
|
||||
UIA_AutomationFocusChangedEventId notification redirecting the focus to the HWND
|
||||
itself. This is a built-in behaviour of the HWND.
|
||||
|
||||
This means that whichever JUCE managed provider was active before the entire
|
||||
window lost and then regained the focus, loses its focused state, and the
|
||||
window's root element will become focused under which all JUCE managed providers
|
||||
can be found.
|
||||
|
||||
This needs to be reflected on currentlyFocusedHandler so that the JUCE
|
||||
accessibility mechanisms can detect that the root window got the focus, and send
|
||||
another FocusChanged event to the system to redirect focus to a JUCE managed
|
||||
provider if necessary.
|
||||
*/
|
||||
AccessibilityHandler::clearCurrentlyFocusedHandler();
|
||||
updateKeyModifiers();
|
||||
handleFocusGain();
|
||||
}
|
||||
|
||||
LRESULT peerWindowProc (HWND h, UINT message, WPARAM wParam, LPARAM lParam)
|
||||
{
|
||||
switch (message)
|
||||
|
|
@ -4120,23 +4146,14 @@ private:
|
|||
|
||||
//==============================================================================
|
||||
case WM_SETFOCUS:
|
||||
/* When the HWND receives Focus from the system it sends a
|
||||
UIA_AutomationFocusChangedEventId notification redirecting the focus to the HWND
|
||||
itself. This is a built-in behaviour of the HWND.
|
||||
mouseActivateFlags |= gotSetFocus;
|
||||
|
||||
This means that whichever JUCE managed provider was active before the entire
|
||||
window lost and then regained the focus, loses its focused state, and the
|
||||
window's root element will become focused under which all JUCE managed providers
|
||||
can be found.
|
||||
// If we've received a MOUSEACTIVATE, wait until we've seen the relevant mouse event
|
||||
// before updating the focus.
|
||||
if ((mouseActivateFlags & gotMouseActivate) != 0)
|
||||
break;
|
||||
|
||||
This needs to be reflected on currentlyFocusedHandler so that the JUCE
|
||||
accessibility mechanisms can detect that the root window got the focus, and send
|
||||
another FocusChanged event to the system to redirect focus to a JUCE managed
|
||||
provider if necessary.
|
||||
*/
|
||||
AccessibilityHandler::clearCurrentlyFocusedHandler();
|
||||
updateKeyModifiers();
|
||||
handleFocusGain();
|
||||
handleSetFocus();
|
||||
break;
|
||||
|
||||
case WM_KILLFOCUS:
|
||||
|
|
@ -4186,10 +4203,15 @@ private:
|
|||
|
||||
case WM_POINTERACTIVATE:
|
||||
case WM_MOUSEACTIVATE:
|
||||
{
|
||||
mouseActivateFlags = 0;
|
||||
|
||||
if (! component.getMouseClickGrabsKeyboardFocus())
|
||||
return MA_NOACTIVATE;
|
||||
|
||||
mouseActivateFlags |= gotMouseActivate;
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_SHOWWINDOW:
|
||||
if (wParam != 0)
|
||||
|
|
@ -4731,6 +4753,26 @@ private:
|
|||
IMEHandler imeHandler;
|
||||
bool shouldIgnoreModalDismiss = false;
|
||||
|
||||
/* When the user clicks on a window, the window gets sent WM_MOUSEACTIVATE, WM_ACTIVATE,
|
||||
and WM_SETFOCUS, before sending a WM_LBUTTONDOWN or other pointer event.
|
||||
However, if the WM_SETFOCUS message immediately calls SetFocus to move the focus to a
|
||||
different window (e.g. a foreground modal window), then no mouse event will be sent to the
|
||||
initially-activated window. This differs from the behaviour on other platforms, where the
|
||||
mouse event always reaches the activated window. Failing to emit a mouse event breaks user
|
||||
interaction: in the Toolbars pane of the WidgetsDemo, we create a foreground modal
|
||||
customisation dialog. The window containing the toolbar is not modal, but still expects to
|
||||
receive mouse events so that the toolbar buttons can be dragged around.
|
||||
|
||||
To avoid the system eating the mouse event sent to the initially-activated window, we
|
||||
postpone processing the WM_SETFOCUS until *after* the activation mouse event.
|
||||
*/
|
||||
enum MouseActivateFlags : uint8_t
|
||||
{
|
||||
gotMouseActivate = 1 << 0,
|
||||
gotSetFocus = 1 << 1,
|
||||
};
|
||||
uint8_t mouseActivateFlags = 0;
|
||||
|
||||
ScopedSuspendResumeNotificationRegistration suspendResumeRegistration;
|
||||
std::optional<TimedCallback> monitorUpdateTimer;
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue