More fixes for wxSTC auto-completion popup window, notably send the
scroll events to the correct window.

See https://github.com/wxWidgets/wxWidgets/pull/1482
This commit is contained in:
Vadim Zeitlin 2019-08-20 19:56:01 +02:00
commit 05402e9eac
4 changed files with 180 additions and 55 deletions

View File

@ -2117,24 +2117,27 @@ PRectangle Window::GetMonitorRect(Point pt) {
// Do not activate the window when it is shown.
bool wxSTCPopupBase::Show(bool show)
{
if ( !wxWindowBase::Show(show) )
return false;
if ( show )
{
HWND hWnd = reinterpret_cast<HWND>(GetHandle());
if ( GetName() == "wxSTCCallTip" )
::AnimateWindow(hWnd, 25, AW_BLEND);
else
::ShowWindow(hWnd, SW_SHOWNA );
// Check if the window is changing from hidden to shown.
bool changingVisibility = wxWindowBase::Show(true);
::SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
if ( changingVisibility )
{
HWND hWnd = reinterpret_cast<HWND>(GetHandle());
if ( GetName() == "wxSTCCallTip" )
::AnimateWindow(hWnd, 25, AW_BLEND);
else
::ShowWindow(hWnd, SW_SHOWNA );
::SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
}
return changingVisibility;
}
else
wxPopupWindow::Show(false);
return true;
return wxPopupWindow::Show(false);
}
// Do not activate in response to mouse clicks on this window.
@ -2224,7 +2227,7 @@ PRectangle Window::GetMonitorRect(Point pt) {
#endif // __WXOSX_COCOA__
wxSTCPopupWindow::wxSTCPopupWindow(wxWindow* parent)
:wxSTCPopupBase(parent), m_initialPosition(wxDefaultPosition)
:wxSTCPopupBase(parent), m_lastKnownPosition(wxDefaultPosition)
{
#if !wxSTC_POPUP_IS_CUSTOM
Bind(wxEVT_SET_FOCUS, &wxSTCPopupWindow::OnFocus, this);
@ -2275,9 +2278,7 @@ bool wxSTCPopupWindow::AcceptsFocus() const
void wxSTCPopupWindow::DoSetSize(int x, int y, int width, int height, int flags)
{
if ( m_initialPosition == wxDefaultPosition
&& x != wxDefaultCoord && y != wxDefaultCoord )
m_initialPosition = wxPoint(x, y);
m_lastKnownPosition = wxPoint(x, y);
// convert coords to screen coords since we're a top-level window
if (x != wxDefaultCoord)
@ -2291,8 +2292,8 @@ void wxSTCPopupWindow::DoSetSize(int x, int y, int width, int height, int flags)
void wxSTCPopupWindow::OnParentMove(wxMoveEvent& event)
{
if ( m_initialPosition != wxDefaultPosition )
SetPosition(m_initialPosition);
if ( m_lastKnownPosition.IsFullySpecified() )
SetPosition(m_lastKnownPosition);
event.Skip();
}
@ -2700,7 +2701,7 @@ wxSTCListBox::wxSTCListBox(wxWindow* parent, wxSTCListBoxVisualData* v, int ht)
m_textTopGap(0), m_imageAreaWidth(0), m_imageAreaHeight(0)
{
wxVListBox::Create(parent, wxID_ANY, wxDefaultPosition, wxDefaultSize,
wxBORDER_NONE);
wxBORDER_NONE, "AutoCompListBox");
m_imagePadding = FromDIP(1);
m_textBoxToTextGap = FromDIP(3);

View File

@ -150,7 +150,7 @@ protected:
#endif
private:
wxPoint m_initialPosition;
wxPoint m_lastKnownPosition;
wxWindow* m_tlw;
};

View File

@ -46,6 +46,8 @@
#include "wx/tokenzr.h"
#include "wx/mstream.h"
#include "wx/image.h"
#include "wx/vlbox.h"
#include "wx/stack.h"
#if wxUSE_FFILE
#include "wx/ffile.h"
#elif wxUSE_FILE
@ -5251,29 +5253,89 @@ void wxStyledTextCtrl::OnContextMenu(wxContextMenuEvent& evt) {
void wxStyledTextCtrl::OnMouseWheel(wxMouseEvent& evt)
{
// The default action of this method is to call m_swx->DoMouseWheel.
// However, it might be necessary to do something else depending on whether
// 1) the mouse wheel captures for the STC,
// 2) the event's position is in the STC's rect, and
// 3) and an autocompletion list is currently being shown.
// This table summarizes when each action is needed.
// InRect | MouseWheelCaptures | Autocomp Active | action
// -------+--------------------+-----------------+-------------------
// true | true | true | scroll ac list
// true | true | false | default
// true | false | true | scroll ac list
// true | false | false | default
// false | true | true | scroll ac list
// false | true | false | default
// false | false | true | forward to parent
// false | false | false | forward to parent
// if the mouse wheel is not captured, test if the mouse
// pointer is over the editor window and if not, don't
// handle the message but pass it on.
if ( !GetMouseWheelCaptures() ) {
if ( !GetRect().Contains(evt.GetPosition()) ) {
wxWindow* parent = GetParent();
if (parent != NULL) {
wxMouseEvent newevt(evt);
newevt.SetPosition(
parent->ScreenToClient(ClientToScreen(evt.GetPosition())));
parent->ProcessWindowEvent(newevt);
}
return;
if ( !GetMouseWheelCaptures() && !GetRect().Contains(evt.GetPosition()) )
{
wxWindow* parent = GetParent();
if ( parent != NULL )
{
wxMouseEvent newevt(evt);
newevt.SetPosition(
parent->ScreenToClient(ClientToScreen(evt.GetPosition())));
parent->ProcessWindowEvent(newevt);
}
}
else if ( AutoCompActive() )
{
// When the autocompletion popup is active, Scintilla uses the mouse
// wheel to scroll the autocomp list instead of the editor.
m_swx->DoMouseWheel(evt.GetWheelAxis(),
evt.GetWheelRotation(),
evt.GetWheelDelta(),
evt.GetLinesPerAction(),
evt.GetColumnsPerAction(),
evt.ControlDown(),
evt.IsPageScroll());
// First try to find the list. It will be a wxVListBox named
// "AutoCompListBox".
wxWindow* curWin = this, *acListBox = NULL;
wxStack<wxWindow*> windows;
windows.push(curWin);
while ( !windows.empty() )
{
curWin = windows.top();
windows.pop();
if ( curWin->IsKindOf(wxCLASSINFO(wxVListBox)) &&
curWin->GetName() == "AutoCompListBox")
{
acListBox = curWin;
break;
}
wxWindowList& children = curWin->GetChildren();
wxWindowList::iterator it;
for ( it = children.begin(); it!=children.end(); ++it )
{
windows.push(*it);
}
}
// Next if the list was found, send it a copy of this event.
if ( acListBox )
{
wxMouseEvent newevt(evt);
newevt.SetPosition(
acListBox->ScreenToClient(ClientToScreen(evt.GetPosition())));
acListBox->ProcessWindowEvent(newevt);
}
}
else
{
m_swx->DoMouseWheel(evt.GetWheelAxis(),
evt.GetWheelRotation(),
evt.GetWheelDelta(),
evt.GetLinesPerAction(),
evt.GetColumnsPerAction(),
evt.ControlDown(),
evt.IsPageScroll());
}
}

View File

@ -46,6 +46,8 @@
#include "wx/tokenzr.h"
#include "wx/mstream.h"
#include "wx/image.h"
#include "wx/vlbox.h"
#include "wx/stack.h"
#if wxUSE_FFILE
#include "wx/ffile.h"
#elif wxUSE_FILE
@ -778,29 +780,89 @@ void wxStyledTextCtrl::OnContextMenu(wxContextMenuEvent& evt) {
void wxStyledTextCtrl::OnMouseWheel(wxMouseEvent& evt)
{
// The default action of this method is to call m_swx->DoMouseWheel.
// However, it might be necessary to do something else depending on whether
// 1) the mouse wheel captures for the STC,
// 2) the event's position is in the STC's rect, and
// 3) and an autocompletion list is currently being shown.
// This table summarizes when each action is needed.
// InRect | MouseWheelCaptures | Autocomp Active | action
// -------+--------------------+-----------------+-------------------
// true | true | true | scroll ac list
// true | true | false | default
// true | false | true | scroll ac list
// true | false | false | default
// false | true | true | scroll ac list
// false | true | false | default
// false | false | true | forward to parent
// false | false | false | forward to parent
// if the mouse wheel is not captured, test if the mouse
// pointer is over the editor window and if not, don't
// handle the message but pass it on.
if ( !GetMouseWheelCaptures() ) {
if ( !GetRect().Contains(evt.GetPosition()) ) {
wxWindow* parent = GetParent();
if (parent != NULL) {
wxMouseEvent newevt(evt);
newevt.SetPosition(
parent->ScreenToClient(ClientToScreen(evt.GetPosition())));
parent->ProcessWindowEvent(newevt);
}
return;
if ( !GetMouseWheelCaptures() && !GetRect().Contains(evt.GetPosition()) )
{
wxWindow* parent = GetParent();
if ( parent != NULL )
{
wxMouseEvent newevt(evt);
newevt.SetPosition(
parent->ScreenToClient(ClientToScreen(evt.GetPosition())));
parent->ProcessWindowEvent(newevt);
}
}
else if ( AutoCompActive() )
{
// When the autocompletion popup is active, Scintilla uses the mouse
// wheel to scroll the autocomp list instead of the editor.
m_swx->DoMouseWheel(evt.GetWheelAxis(),
evt.GetWheelRotation(),
evt.GetWheelDelta(),
evt.GetLinesPerAction(),
evt.GetColumnsPerAction(),
evt.ControlDown(),
evt.IsPageScroll());
// First try to find the list. It will be a wxVListBox named
// "AutoCompListBox".
wxWindow* curWin = this, *acListBox = NULL;
wxStack<wxWindow*> windows;
windows.push(curWin);
while ( !windows.empty() )
{
curWin = windows.top();
windows.pop();
if ( curWin->IsKindOf(wxCLASSINFO(wxVListBox)) &&
curWin->GetName() == "AutoCompListBox")
{
acListBox = curWin;
break;
}
wxWindowList& children = curWin->GetChildren();
wxWindowList::iterator it;
for ( it = children.begin(); it!=children.end(); ++it )
{
windows.push(*it);
}
}
// Next if the list was found, send it a copy of this event.
if ( acListBox )
{
wxMouseEvent newevt(evt);
newevt.SetPosition(
acListBox->ScreenToClient(ClientToScreen(evt.GetPosition())));
acListBox->ProcessWindowEvent(newevt);
}
}
else
{
m_swx->DoMouseWheel(evt.GetWheelAxis(),
evt.GetWheelRotation(),
evt.GetWheelDelta(),
evt.GetLinesPerAction(),
evt.GetColumnsPerAction(),
evt.ControlDown(),
evt.IsPageScroll());
}
}