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.
|
// Return the top level window parent of this popup or null.
|
||||||
wxWindow* MSWGetOwner() const { return m_owner; }
|
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:
|
private:
|
||||||
wxWindow* m_owner;
|
wxWindow* m_owner;
|
||||||
|
|
||||||
|
@@ -133,13 +133,6 @@ public:
|
|||||||
wxPopupTransientWindow() { }
|
wxPopupTransientWindow() { }
|
||||||
wxPopupTransientWindow(wxWindow *parent, int style = wxBORDER_NONE)
|
wxPopupTransientWindow(wxWindow *parent, int style = wxBORDER_NONE)
|
||||||
{ Create(parent, style); }
|
{ Create(parent, style); }
|
||||||
bool Create(wxWindow *parent, int style = wxBORDER_NONE)
|
|
||||||
{
|
|
||||||
return wxPopupTransientWindowBase::Create
|
|
||||||
(
|
|
||||||
parent, style | wxPU_CONTAINS_CONTROLS
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Implement base class pure virtuals.
|
// Implement base class pure virtuals.
|
||||||
virtual void Popup(wxWindow *focus = NULL) wxOVERRIDE;
|
virtual void Popup(wxWindow *focus = NULL) wxOVERRIDE;
|
||||||
@@ -151,6 +144,9 @@ public:
|
|||||||
WXWPARAM wParam,
|
WXWPARAM wParam,
|
||||||
WXLPARAM lParam) wxOVERRIDE;
|
WXLPARAM lParam) wxOVERRIDE;
|
||||||
|
|
||||||
|
// Override to dismiss the popup.
|
||||||
|
virtual void MSWDismissUnfocusedPopup() wxOVERRIDE;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void DismissOnDeactivate();
|
void DismissOnDeactivate();
|
||||||
|
|
||||||
|
@@ -58,6 +58,10 @@
|
|||||||
#include "wx/tipdlg.h"
|
#include "wx/tipdlg.h"
|
||||||
#endif // wxUSE_STARTUP_TIPS
|
#endif // wxUSE_STARTUP_TIPS
|
||||||
|
|
||||||
|
#if wxUSE_TIPWINDOW
|
||||||
|
#include "wx/tipwin.h"
|
||||||
|
#endif // wxUSE_TIPWINDOW
|
||||||
|
|
||||||
#if wxUSE_PROGRESSDLG
|
#if wxUSE_PROGRESSDLG
|
||||||
#if wxUSE_STOPWATCH && wxUSE_LONGLONG
|
#if wxUSE_STOPWATCH && wxUSE_LONGLONG
|
||||||
#include "wx/datetime.h" // wxDateTime
|
#include "wx/datetime.h" // wxDateTime
|
||||||
@@ -280,6 +284,10 @@ wxBEGIN_EVENT_TABLE(MyFrame, wxFrame)
|
|||||||
EVT_MENU(DIALOGS_NOTIFY_MSG, MyFrame::OnNotifMsg)
|
EVT_MENU(DIALOGS_NOTIFY_MSG, MyFrame::OnNotifMsg)
|
||||||
#endif // wxUSE_NOTIFICATION_MESSAGE
|
#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
|
#if wxUSE_RICHTOOLTIP
|
||||||
EVT_MENU(DIALOGS_RICHTIP_DIALOG, MyFrame::OnRichTipDialog)
|
EVT_MENU(DIALOGS_RICHTIP_DIALOG, MyFrame::OnRichTipDialog)
|
||||||
#endif // wxUSE_RICHTOOLTIP
|
#endif // wxUSE_RICHTOOLTIP
|
||||||
@@ -590,6 +598,10 @@ bool MyApp::OnInit()
|
|||||||
#endif // wxUSE_NOTIFICATION_MESSAGE
|
#endif // wxUSE_NOTIFICATION_MESSAGE
|
||||||
menuDlg->AppendSubMenu(menuNotif, "&User notifications");
|
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
|
#if wxUSE_RICHTOOLTIP
|
||||||
menuDlg->Append(DIALOGS_RICHTIP_DIALOG, "Rich &tooltip dialog...\tCtrl-H");
|
menuDlg->Append(DIALOGS_RICHTIP_DIALOG, "Rich &tooltip dialog...\tCtrl-H");
|
||||||
menuDlg->AppendSeparator();
|
menuDlg->AppendSeparator();
|
||||||
@@ -713,6 +725,10 @@ MyFrame::MyFrame(const wxString& title)
|
|||||||
SetOwnBackgroundColour(m_canvas->GetBackgroundColour());
|
SetOwnBackgroundColour(m_canvas->GetBackgroundColour());
|
||||||
#endif // wxUSE_INFOBAR
|
#endif // wxUSE_INFOBAR
|
||||||
|
|
||||||
|
#if wxUSE_TIPWINDOW
|
||||||
|
m_tipWindow = NULL;
|
||||||
|
#endif // wxUSE_TIPWINDOW
|
||||||
|
|
||||||
#ifdef __WXMSW__
|
#ifdef __WXMSW__
|
||||||
// Test MSW-specific function allowing to access the "system" menu.
|
// Test MSW-specific function allowing to access the "system" menu.
|
||||||
wxMenu * const menu = MSWGetSystemMenu();
|
wxMenu * const menu = MSWGetSystemMenu();
|
||||||
@@ -2389,6 +2405,35 @@ void MyFrame::OnNotifMsg(wxCommandEvent& WXUNUSED(event))
|
|||||||
|
|
||||||
#endif // wxUSE_NOTIFICATION_MESSAGE
|
#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
|
#if wxUSE_RICHTOOLTIP
|
||||||
|
|
||||||
#include "wx/richtooltip.h"
|
#include "wx/richtooltip.h"
|
||||||
|
@@ -544,6 +544,13 @@ private:
|
|||||||
SettingsData m_settingsData;
|
SettingsData m_settingsData;
|
||||||
#endif // USE_SETTINGS_DIALOG
|
#endif // USE_SETTINGS_DIALOG
|
||||||
|
|
||||||
|
#if wxUSE_TIPWINDOW
|
||||||
|
void OnShowTip(wxCommandEvent& event);
|
||||||
|
void OnUpdateShowTipUI(wxUpdateUIEvent& event);
|
||||||
|
|
||||||
|
wxTipWindow *m_tipWindow;
|
||||||
|
#endif // wxUSE_TIPWINDOW
|
||||||
|
|
||||||
wxDECLARE_EVENT_TABLE();
|
wxDECLARE_EVENT_TABLE();
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -623,6 +630,7 @@ enum
|
|||||||
DIALOGS_REPLACE,
|
DIALOGS_REPLACE,
|
||||||
DIALOGS_REQUEST,
|
DIALOGS_REQUEST,
|
||||||
DIALOGS_NOTIFY_MSG,
|
DIALOGS_NOTIFY_MSG,
|
||||||
|
DIALOGS_SHOW_TIP,
|
||||||
DIALOGS_RICHTIP_DIALOG,
|
DIALOGS_RICHTIP_DIALOG,
|
||||||
DIALOGS_PROPERTY_SHEET,
|
DIALOGS_PROPERTY_SHEET,
|
||||||
DIALOGS_PROPERTY_SHEET_TOOLBOOK,
|
DIALOGS_PROPERTY_SHEET_TOOLBOOK,
|
||||||
|
@@ -108,7 +108,9 @@ wxBEGIN_EVENT_TABLE(SimpleTransientPopup,wxPopupTransientWindow)
|
|||||||
wxEND_EVENT_TABLE()
|
wxEND_EVENT_TABLE()
|
||||||
|
|
||||||
SimpleTransientPopup::SimpleTransientPopup( wxWindow *parent, bool scrolled )
|
SimpleTransientPopup::SimpleTransientPopup( wxWindow *parent, bool scrolled )
|
||||||
:wxPopupTransientWindow( parent )
|
:wxPopupTransientWindow( parent,
|
||||||
|
wxBORDER_NONE |
|
||||||
|
wxPU_CONTAINS_CONTROLS )
|
||||||
{
|
{
|
||||||
m_panel = new wxScrolledWindow( this, wxID_ANY );
|
m_panel = new wxScrolledWindow( this, wxID_ANY );
|
||||||
m_panel->SetBackgroundColour( *wxLIGHT_GREY );
|
m_panel->SetBackgroundColour( *wxLIGHT_GREY );
|
||||||
|
@@ -136,7 +136,9 @@ wxTipWindow::wxTipWindow(wxWindow *parent,
|
|||||||
// set size, position and show it
|
// set size, position and show it
|
||||||
m_view = new wxTipWindowView(this);
|
m_view = new wxTipWindowView(this);
|
||||||
m_view->Adjust(text, maxLength);
|
m_view->Adjust(text, maxLength);
|
||||||
|
#if !wxUSE_POPUPWIN
|
||||||
m_view->SetFocus();
|
m_view->SetFocus();
|
||||||
|
#endif
|
||||||
|
|
||||||
int x, y;
|
int x, y;
|
||||||
wxGetMousePosition(&x, &y);
|
wxGetMousePosition(&x, &y);
|
||||||
|
@@ -180,10 +180,10 @@ void wxPopupTransientWindow::Popup(wxWindow* focus)
|
|||||||
{
|
{
|
||||||
Show();
|
Show();
|
||||||
|
|
||||||
// We can only set focus to one of our children as setting it to another
|
// We can only set focus when using wxPU_CONTAINS_CONTROLS and then only to
|
||||||
// window would result in an immediate loss of activation and popup
|
// one of our children as setting it to another window would result in an
|
||||||
// disappearance.
|
// immediate loss of activation and popup disappearance.
|
||||||
if ( focus && IsDescendant(focus) )
|
if ( HasFlag(wxPU_CONTAINS_CONTROLS) && focus && IsDescendant(focus) )
|
||||||
focus->SetFocus();
|
focus->SetFocus();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -195,7 +195,7 @@ void wxPopupTransientWindow::Dismiss()
|
|||||||
void wxPopupTransientWindow::DismissOnDeactivate()
|
void wxPopupTransientWindow::DismissOnDeactivate()
|
||||||
{
|
{
|
||||||
// Hide the window automatically when it loses activation.
|
// Hide the window automatically when it loses activation.
|
||||||
Dismiss();
|
DismissAndNotify();
|
||||||
|
|
||||||
// Activation might have gone to a different window or maybe
|
// Activation might have gone to a different window or maybe
|
||||||
// even a different application, don't let our owner continue
|
// 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
|
bool
|
||||||
wxPopupTransientWindow::MSWHandleMessage(WXLRESULT *result,
|
wxPopupTransientWindow::MSWHandleMessage(WXLRESULT *result,
|
||||||
WXUINT message,
|
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 )
|
if ( !processed )
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user