Redirect mouse wheel events when STC autocomp is active

While an autocompletion list is being shown, a native Scintilla window
will use mouse wheel events to scroll the list instead of the editor
window. Match this behavior with wxSTC by intercepting mouse wheel
events and redirecting them to the list.
This commit is contained in:
New Pagodi
2019-08-07 21:35:45 -05:00
parent c3d9222a7c
commit 4523df5d94
3 changed files with 159 additions and 35 deletions

View File

@@ -2701,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

@@ -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());
}
}