Refactored wxComboPopupExtraEventHandler::OnMouseEvent(). Now block mouse events from the popup control until mouse button has been seen in 'up' state (ignoring first mouse up). This matches Windows native combo box behavior (fixes #12115).

git-svn-id: https://svn.wxwidgets.org/svn/wx/wxWidgets/trunk@64455 c3d73ce0-8a6f-49c7-b76d-6d57e0e08775
This commit is contained in:
Jaakko Salli
2010-06-01 13:46:14 +00:00
parent 76e1326add
commit 4794626d03

View File

@@ -670,6 +670,10 @@ public:
{ {
m_combo = combo; m_combo = combo;
m_beenInside = false; m_beenInside = false;
// Let's make it so that the popup control will not receive mouse
// events until mouse left button has been up.
m_blockEventsToPopup = true;
} }
virtual ~wxComboPopupExtraEventHandler() { } virtual ~wxComboPopupExtraEventHandler() { }
@@ -679,12 +683,14 @@ public:
void OnPopupDismiss() void OnPopupDismiss()
{ {
m_beenInside = false; m_beenInside = false;
m_blockEventsToPopup = true;
} }
protected: protected:
wxComboCtrlBase* m_combo; wxComboCtrlBase* m_combo;
bool m_beenInside; bool m_beenInside;
bool m_blockEventsToPopup;
private: private:
DECLARE_EVENT_TABLE() DECLARE_EVENT_TABLE()
@@ -706,43 +712,83 @@ void wxComboPopupExtraEventHandler::OnMouseEvent( wxMouseEvent& event )
event.Skip(); event.Skip();
// Block motion and click events outside the popup if ( !isInside || !m_combo->IsPopupShown() )
if ( (!isInside || !m_combo->IsPopupShown())
&&
(evtType == wxEVT_MOTION ||
evtType == wxEVT_LEFT_DOWN ||
evtType == wxEVT_LEFT_UP ||
evtType == wxEVT_RIGHT_DOWN) )
{ {
event.Skip(false); // Mouse is outside the popup or popup is not actually shown (yet)
if ( evtType == wxEVT_MOTION ||
evtType == wxEVT_LEFT_DOWN ||
evtType == wxEVT_LEFT_UP ||
evtType == wxEVT_RIGHT_DOWN )
{
// Block motion and click events outside the popup
event.Skip(false);
}
} }
else if ( evtType == wxEVT_LEFT_UP ) else
{
// Mouse is inside the popup, which is fully shown
m_beenInside = true;
// Do not let the popup control respond to mouse events until
// mouse press used to display the popup has been lifted. This
// is important for users with slower mouse fingers or mouse
// drivers. Note that we have some redundancy here, just in
// case the popup is some native control that does not emit all
// mouse event types.
if ( evtType == wxEVT_MOTION )
{
if ( m_blockEventsToPopup )
{
if ( event.LeftIsDown() )
event.Skip(false);
else
m_blockEventsToPopup = false;
}
}
else if ( evtType == wxEVT_LEFT_DOWN )
{
if ( m_blockEventsToPopup )
m_blockEventsToPopup = false;
}
else if ( evtType == wxEVT_LEFT_UP )
{
if ( m_blockEventsToPopup )
{
// On first left up, stop blocking mouse events (but still
// block this one)
m_blockEventsToPopup = false;
event.Skip(false);
}
}
else if ( m_blockEventsToPopup )
{
event.Skip(false);
}
}
//
// Some mouse events to popup that happen outside it, before cursor
// has been inside the popup, need to be ignored by it but relayed to
// the dropbutton.
//
if ( evtType == wxEVT_LEFT_UP )
{ {
if ( !m_combo->IsPopupShown() ) if ( !m_combo->IsPopupShown() )
{ {
event.Skip(false); event.Skip(false);
relayToButton = true; relayToButton = true;
} }
else if ( !m_beenInside ) else if ( !isInside && !m_beenInside )
{ {
if ( isInside ) // Popup is shown but the cursor is not inside, nor it has been
{ relayToButton = true;
m_beenInside = true;
}
else
{
relayToButton = true;
}
} }
} }
if ( relayToButton ) if ( relayToButton )
{ {
//
// Some mouse events to popup that happen outside it, before cursor
// has been inside the popup, need to be ignored by it but relayed to
// the dropbutton.
//
wxWindow* eventSink = m_combo; wxWindow* eventSink = m_combo;
wxWindow* btn = m_combo->GetButton(); wxWindow* btn = m_combo->GetButton();
if ( btn ) if ( btn )