Merge branch 'msw-dismiss-unfocused-popup'
Allow wxPopupTransientWindow to work without wxPU_CONTAINS_CONTROLS too in wxMSW and don't use wxPU_CONTAINS_CONTROLS by default, notably allowing wxTipWindow to be shown without stealing focus. See https://github.com/wxWidgets/wxWidgets/pull/1942 Closes #18636.
This commit is contained in:
@@ -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;
|
||||
|
||||
|
@@ -133,13 +133,6 @@ public:
|
||||
wxPopupTransientWindow() { }
|
||||
wxPopupTransientWindow(wxWindow *parent, int style = wxBORDER_NONE)
|
||||
{ Create(parent, style); }
|
||||
bool Create(wxWindow *parent, int style = wxBORDER_NONE)
|
||||
{
|
||||
return wxPopupTransientWindowBase::Create
|
||||
(
|
||||
parent, style | wxPU_CONTAINS_CONTROLS
|
||||
);
|
||||
}
|
||||
|
||||
// Implement base class pure virtuals.
|
||||
virtual void Popup(wxWindow *focus = NULL) wxOVERRIDE;
|
||||
@@ -151,6 +144,9 @@ public:
|
||||
WXWPARAM wParam,
|
||||
WXLPARAM lParam) wxOVERRIDE;
|
||||
|
||||
// Override to dismiss the popup.
|
||||
virtual void MSWDismissUnfocusedPopup() wxOVERRIDE;
|
||||
|
||||
private:
|
||||
void DismissOnDeactivate();
|
||||
|
||||
|
@@ -58,6 +58,10 @@
|
||||
#include "wx/tipdlg.h"
|
||||
#endif // wxUSE_STARTUP_TIPS
|
||||
|
||||
#if wxUSE_TIPWINDOW
|
||||
#include "wx/tipwin.h"
|
||||
#endif // wxUSE_TIPWINDOW
|
||||
|
||||
#if wxUSE_PROGRESSDLG
|
||||
#if wxUSE_STOPWATCH && wxUSE_LONGLONG
|
||||
#include "wx/datetime.h" // wxDateTime
|
||||
@@ -280,6 +284,10 @@ wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
|
||||
EVT_MENU(DIALOGS_NOTIFY_MSG, MyFrame::OnNotifMsg)
|
||||
#endif // wxUSE_NOTIFICATION_MESSAGE
|
||||
|
||||
#if wxUSE_TIPWINDOW
|
||||
EVT_MENU(DIALOGS_SHOW_TIP, MyFrame::OnShowTip)
|
||||
EVT_UPDATE_UI(DIALOGS_SHOW_TIP, MyFrame::OnUpdateShowTipUI)
|
||||
#endif // wxUSE_TIPWINDOW
|
||||
#if wxUSE_RICHTOOLTIP
|
||||
EVT_MENU(DIALOGS_RICHTIP_DIALOG, MyFrame::OnRichTipDialog)
|
||||
#endif // wxUSE_RICHTOOLTIP
|
||||
@@ -590,6 +598,10 @@ bool MyApp::OnInit()
|
||||
#endif // wxUSE_NOTIFICATION_MESSAGE
|
||||
menuDlg->AppendSubMenu(menuNotif, "&User notifications");
|
||||
|
||||
#if wxUSE_TIPWINDOW
|
||||
menuDlg->AppendCheckItem(DIALOGS_SHOW_TIP, "Show &tip window\tShift-Ctrl-H");
|
||||
#endif // wxUSE_TIPWINDOW
|
||||
|
||||
#if wxUSE_RICHTOOLTIP
|
||||
menuDlg->Append(DIALOGS_RICHTIP_DIALOG, "Rich &tooltip dialog...\tCtrl-H");
|
||||
menuDlg->AppendSeparator();
|
||||
@@ -713,6 +725,10 @@ MyFrame::MyFrame(const wxString& title)
|
||||
SetOwnBackgroundColour(m_canvas->GetBackgroundColour());
|
||||
#endif // wxUSE_INFOBAR
|
||||
|
||||
#if wxUSE_TIPWINDOW
|
||||
m_tipWindow = NULL;
|
||||
#endif // wxUSE_TIPWINDOW
|
||||
|
||||
#ifdef __WXMSW__
|
||||
// Test MSW-specific function allowing to access the "system" menu.
|
||||
wxMenu * const menu = MSWGetSystemMenu();
|
||||
@@ -2389,6 +2405,35 @@ void MyFrame::OnNotifMsg(wxCommandEvent& WXUNUSED(event))
|
||||
|
||||
#endif // wxUSE_NOTIFICATION_MESSAGE
|
||||
|
||||
#if wxUSE_TIPWINDOW
|
||||
|
||||
void MyFrame::OnShowTip(wxCommandEvent& WXUNUSED(event))
|
||||
{
|
||||
if ( m_tipWindow )
|
||||
{
|
||||
m_tipWindow->Close();
|
||||
}
|
||||
else
|
||||
{
|
||||
m_tipWindow = new wxTipWindow
|
||||
(
|
||||
this,
|
||||
"This is just some text to be shown in the tip "
|
||||
"window, broken into multiple lines, each less "
|
||||
"than 60 logical pixels wide.",
|
||||
FromDIP(60),
|
||||
&m_tipWindow
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
void MyFrame::OnUpdateShowTipUI(wxUpdateUIEvent& event)
|
||||
{
|
||||
event.Check(m_tipWindow != NULL);
|
||||
}
|
||||
|
||||
#endif // wxUSE_TIPWINDOW
|
||||
|
||||
#if wxUSE_RICHTOOLTIP
|
||||
|
||||
#include "wx/richtooltip.h"
|
||||
|
@@ -544,6 +544,13 @@ private:
|
||||
SettingsData m_settingsData;
|
||||
#endif // USE_SETTINGS_DIALOG
|
||||
|
||||
#if wxUSE_TIPWINDOW
|
||||
void OnShowTip(wxCommandEvent& event);
|
||||
void OnUpdateShowTipUI(wxUpdateUIEvent& event);
|
||||
|
||||
wxTipWindow *m_tipWindow;
|
||||
#endif // wxUSE_TIPWINDOW
|
||||
|
||||
wxDECLARE_EVENT_TABLE();
|
||||
};
|
||||
|
||||
@@ -623,6 +630,7 @@ enum
|
||||
DIALOGS_REPLACE,
|
||||
DIALOGS_REQUEST,
|
||||
DIALOGS_NOTIFY_MSG,
|
||||
DIALOGS_SHOW_TIP,
|
||||
DIALOGS_RICHTIP_DIALOG,
|
||||
DIALOGS_PROPERTY_SHEET,
|
||||
DIALOGS_PROPERTY_SHEET_TOOLBOOK,
|
||||
|
@@ -108,7 +108,9 @@ wxBEGIN_EVENT_TABLE(SimpleTransientPopup,wxPopupTransientWindow)
|
||||
wxEND_EVENT_TABLE()
|
||||
|
||||
SimpleTransientPopup::SimpleTransientPopup( wxWindow *parent, bool scrolled )
|
||||
:wxPopupTransientWindow( parent )
|
||||
:wxPopupTransientWindow( parent,
|
||||
wxBORDER_NONE |
|
||||
wxPU_CONTAINS_CONTROLS )
|
||||
{
|
||||
m_panel = new wxScrolledWindow( this, wxID_ANY );
|
||||
m_panel->SetBackgroundColour( *wxLIGHT_GREY );
|
||||
|
@@ -136,7 +136,9 @@ wxTipWindow::wxTipWindow(wxWindow *parent,
|
||||
// set size, position and show it
|
||||
m_view = new wxTipWindowView(this);
|
||||
m_view->Adjust(text, maxLength);
|
||||
#if !wxUSE_POPUPWIN
|
||||
m_view->SetFocus();
|
||||
#endif
|
||||
|
||||
int x, y;
|
||||
wxGetMousePosition(&x, &y);
|
||||
|
@@ -180,10 +180,10 @@ void wxPopupTransientWindow::Popup(wxWindow* focus)
|
||||
{
|
||||
Show();
|
||||
|
||||
// We can only set focus to one of our children as setting it to another
|
||||
// window would result in an immediate loss of activation and popup
|
||||
// disappearance.
|
||||
if ( focus && IsDescendant(focus) )
|
||||
// We can only set focus when using wxPU_CONTAINS_CONTROLS and then only to
|
||||
// one of our children as setting it to another window would result in an
|
||||
// immediate loss of activation and popup disappearance.
|
||||
if ( HasFlag(wxPU_CONTAINS_CONTROLS) && focus && IsDescendant(focus) )
|
||||
focus->SetFocus();
|
||||
}
|
||||
|
||||
@@ -195,7 +195,7 @@ void wxPopupTransientWindow::Dismiss()
|
||||
void wxPopupTransientWindow::DismissOnDeactivate()
|
||||
{
|
||||
// Hide the window automatically when it loses activation.
|
||||
Dismiss();
|
||||
DismissAndNotify();
|
||||
|
||||
// Activation might have gone to a different window or maybe
|
||||
// even a different application, don't let our owner continue
|
||||
@@ -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,
|
||||
|
@@ -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;
|
||||
|
||||
|
Reference in New Issue
Block a user