Skip to content

Commit e30a6a3

Browse files
charvey2718vadz
authored andcommitted
Fix bug with "pass through" mouse events from MSW wxFileDialog
Remove any remaining mouse messages from the input queue after showing the file dialog because they somehow remain after it is destroyed and could be processed by the application once wxFileDialog::ShowModal() returns, resulting in phantom events being processed by the controls that just happen to be under the button of the file dialog that was clicked to close it. See wxWidgets#10924, wxWidgets#23944. (cherry picked from commit ffc99bd)
1 parent ed002d3 commit e30a6a3

File tree

2 files changed

+33
-0
lines changed

2 files changed

+33
-0
lines changed

docs/changes.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -327,6 +327,7 @@ wxMSW:
327327
- Fix background colour of empty cells in wxDataViewCtrl (#23708).
328328
- Fix possible (even if rare) crash in printer progress dialog (#23927).
329329
- Fix "+" button not appearing in wxTreeCtrl after adding a child (#23718).
330+
- Fix phantom mouse events after dismissing wxFileDialog (charvey2718, #10924).
330331

331332
wxOSX:
332333

src/msw/filedlg.cpp

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,33 @@ bool gs_changedPolicy = false;
113113

114114
#endif // #if wxUSE_DYNLIB_CLASS
115115

116+
/*
117+
This function removes any remaining mouse messages from the input queue in
118+
order to prevent them from being passed to controls positioned underneath
119+
the wxFileDialog after it has been destroyed, see #10924.
120+
*/
121+
void DrainMouseMessages()
122+
{
123+
// Note that we have to use this struct as PeekMessage() wouldn't remove
124+
// the messages from the input queue, even with PM_REMOVE, if we pass it a
125+
// null pointer.
126+
MSG msg;
127+
128+
// This loop is used just to ensure that we don't loop indefinitely in case
129+
// there is something generating an endless stream of mouse messages in the
130+
// system (1000 is an arbitrary but "sufficiently large" number), the real
131+
// loop termination condition is inside it.
132+
for ( int i = 0; i < 1000; ++i )
133+
{
134+
if ( !::PeekMessage(&msg, NULL, WM_MOUSEFIRST, WM_MOUSELAST,
135+
PM_REMOVE | PM_QS_INPUT) )
136+
{
137+
// No more mouse messages left.
138+
break;
139+
}
140+
}
141+
}
142+
116143
/*
117144
Since Windows 7 by default (callback) exceptions aren't swallowed anymore
118145
with native x64 applications. Exceptions can occur in a file dialog when
@@ -1493,6 +1520,8 @@ int wxFileDialog::ShowCommFileDialog(WXHWND hWndParent)
14931520
DWORD errCode;
14941521
bool success = DoShowCommFileDialog(&of, m_windowStyle, &errCode);
14951522

1523+
DrainMouseMessages();
1524+
14961525
// When using a hook, our HWND was set from MSWOnInitDialogHook() called
14971526
// above, but it's not valid any longer once the dialog was destroyed, so
14981527
// reset it now.
@@ -1696,6 +1725,9 @@ int wxFileDialog::ShowIFileDialog(WXHWND hWndParent)
16961725

16971726
// Finally do show the dialog.
16981727
const int rc = fileDialog.Show(hWndParent, options, &m_fileNames, &m_path);
1728+
1729+
DrainMouseMessages();
1730+
16991731
if ( rc == wxID_OK )
17001732
{
17011733
// As with the common dialog, the index is 1-based here, but don't make

0 commit comments

Comments
 (0)