Implement dismissal for unfocused wxPopupTransientWindow

Popups not using wxPU_CONTAINS_CONTROLS were not automatically dismissed
at all any longer, as the only auto-dismissal mechanism related on
getting WM_ACTIVATE, which they never did, so implement a different
logic for dismissing them: do it on any change of focus and also any
mouse press (but not move and not key press neither).

This will allow not using wxPU_CONTAINS_CONTROLS for popups that don't
need focus, but still must disappear on their own.
This commit is contained in:
Vadim Zeitlin
2020-07-09 23:58:29 +02:00
parent 2ac90f9d38
commit 3bcbc8fe8e
4 changed files with 56 additions and 0 deletions

View File

@@ -40,6 +40,10 @@ public:
// Return the top level window parent of this popup or null.
wxWindow* MSWGetOwner() const { return m_owner; }
// This is a way to notify non-wxPU_CONTAINS_CONTROLS windows about the
// events that should result in their dismissal.
virtual void MSWDismissUnfocusedPopup() { }
private:
wxWindow* m_owner;

View File

@@ -151,6 +151,9 @@ public:
WXWPARAM wParam,
WXLPARAM lParam) wxOVERRIDE;
// Override to dismiss the popup.
virtual void MSWDismissUnfocusedPopup() wxOVERRIDE;
private:
void DismissOnDeactivate();

View File

@@ -210,6 +210,19 @@ void wxPopupTransientWindow::DismissOnDeactivate()
}
}
void wxPopupTransientWindow::MSWDismissUnfocusedPopup()
{
// When we use wxPU_CONTAINS_CONTROLS, we can react to the popup
// deactivation in MSWHandleMessage(), but if we don't have focus, we don't
// get any events ourselves, so we rely on wxWindow to forward them to us.
if ( !HasFlag(wxPU_CONTAINS_CONTROLS) )
{
// It doesn't seem necessary to use CallAfter() here, as dismissing
// this window shouldn't affect the focus, as it never has it anyhow.
DismissAndNotify();
}
}
bool
wxPopupTransientWindow::MSWHandleMessage(WXLRESULT *result,
WXUINT message,

View File

@@ -3844,6 +3844,42 @@ wxWindowMSW::MSWHandleMessage(WXLRESULT *result,
}
}
// Special hook for dismissing the current popup if it's active. It's a bit
// ugly to have to do this here, but the only alternatives seem to be
// installing a WH_CBT hook in wxPopupTransientWindow code, which is not
// really much better.
#if wxUSE_POPUPWIN
if ( wxCurrentPopupWindow )
{
switch ( message )
{
case WM_NCLBUTTONDOWN:
case WM_NCLBUTTONUP:
case WM_NCLBUTTONDBLCLK:
case WM_NCRBUTTONDOWN:
case WM_NCRBUTTONUP:
case WM_NCRBUTTONDBLCLK:
case WM_NCMBUTTONDOWN:
case WM_NCMBUTTONUP:
case WM_NCMBUTTONDBLCLK:
case WM_LBUTTONDOWN:
case WM_LBUTTONUP:
case WM_LBUTTONDBLCLK:
case WM_RBUTTONDOWN:
case WM_RBUTTONUP:
case WM_RBUTTONDBLCLK:
case WM_MBUTTONDOWN:
case WM_MBUTTONUP:
case WM_MBUTTONDBLCLK:
case WM_SETFOCUS:
case WM_KILLFOCUS:
wxCurrentPopupWindow->MSWDismissUnfocusedPopup();
}
}
#endif // wxUSE_POPUPWIN
if ( !processed )
return false;