Scroll doesn't work after focusing custom control Topic is solved

If you are using the main C++ distribution of wxWidgets, Feel free to ask any question related to wxWidgets development here. This means questions regarding to C++ and wxWidgets, not compile problems.
rudolfninja
Earned some good credits
Earned some good credits
Posts: 104
Joined: Tue Aug 28, 2018 1:02 pm
Location: Belarus

Scroll doesn't work after focusing custom control

Post by rudolfninja » Wed Mar 25, 2020 7:18 am

I've got scrollbars on my dialog. And there is custom control inside. When I focus (click inside) custom control, then scroll (inside the dialog) stops working. To make it work again I have to focus some native control (wxTextCtrl).
Here is code of my custom control:

Code: Select all

class wxListViewShares : public wxDataViewListCtrl
{
public:
    using share_list_t = std::vector<std::shared_ptr<MatchMaker::Share>>;
    wxListViewShares(wxWindow* parent, const share_list_t& shares, const std::shared_ptr<ApplicationHelper>& appHelper,
        const SharesSerializer::used_shares_t& usedShares);
	// ... some methods here
protected:
    // ... some methods here

    void OnSelectionChanged(wxDataViewEvent& event);
    void OnMouseMove(wxMouseEvent& event);

    share_list_t m_shares;
    std::shared_ptr<MatchMaker::Share> m_chosenShare;
    const std::shared_ptr<ApplicationHelper> m_applicationHelper;
    SharesSerializer::used_shares_t m_usedShares;
    int m_currentRowIndex; // current selected row
    int m_currentHoveredRowIndex;
};

wxListViewShares::wxListViewShares(wxWindow* parent, const share_list_t& shares, const std::shared_ptr<ApplicationHelper>& appHelper,
    const SharesSerializer::used_shares_t& usedShares) :
    wxDataViewListCtrl(parent, wxID_ANY, wxDefaultPosition, wxSize(parent->FromDIP(740), parent->FromDIP(175)), wxDV_ROW_LINES | wxDV_SINGLE),
    m_shares(shares),
    m_applicationHelper(appHelper),
    m_usedShares(usedShares)
{
    FillHeaders();
    FillList();

    Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, &wxListViewShares::OnSelectionChanged, this);
    GetMainWindow()->Bind(wxEVT_MOTION, &wxListViewShares::OnMouseMove, this);
}

void wxListViewShares::OnSelectionChanged(wxDataViewEvent& event)
{
    int row = ItemToRow(event.GetItem());

    if (row >= 0)
    {
        m_chosenShare = m_shares[row];
        m_currentRowIndex = row;
        event.SetInt(row);
        event.SetString(GetTextValue(row, 0));
    }
    else
    {
        event.SetInt(-1);
        event.SetString("");
    }
    event.Skip();
}

void wxListViewShares::OnMouseMove(wxMouseEvent& event)
{
    wxDataViewItem item;
    wxDataViewColumn *column;
    wxWindow* main = GetMainWindow();
    wxPoint pos = ScreenToClient(main->ClientToScreen(event.GetPosition()));
    HitTest(pos, item, column);

    if (item != NULL && column != NULL)
    {
        if (column->GetTitle() != _("header.Target"))
        {
            main->UnsetToolTip();
            return;
        }

        int row = ItemToRow(item);
        if (row == m_currentHoveredRowIndex)
        {
            return;
        }

        if (row >= 0)
        {
            wxString text = GetTextValue(row, 0);
            m_currentHoveredRowIndex = row;
            if (main->GetTextExtent(text).GetWidth() > FromDIP(190))
            {   
                main->SetToolTip(text);
            }
            else
            {
                main->UnsetToolTip();
            }
        }
        else
        {
            m_currentHoveredRowIndex = -1;
            main->UnsetToolTip();
        }
    }
    else
    {
        m_currentHoveredRowIndex = -1;
        GetMainWindow()->UnsetToolTip();
    }
    event.Skip();
}
I tried to comment

Code: Select all

GetMainWindow()->Bind(wxEVT_MOTION, &wxListViewShares::OnMouseMove, this);
this string, but it didn't help.
Also OnMouseMove event overrided in the dialog's class (to handle resize), but don't think it's a problem.
I noticed that my custom control doesn't lose focus after clicking out of control's area. How to make it lost focus?

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 3915
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Scroll doesn't work after focusing custom control

Post by ONEEYEMAN » Wed Mar 25, 2020 2:22 pm

Hi,
Usual stanza applies.

What's wx version?
What platform?
Can you reproduce it in a {scrolled} sample?

Thank you.

rudolfninja
Earned some good credits
Earned some good credits
Posts: 104
Joined: Tue Aug 28, 2018 1:02 pm
Location: Belarus

Re: Scroll doesn't work after focusing custom control

Post by rudolfninja » Wed Mar 25, 2020 3:11 pm

wxWidgets 3.1.3, OS - windows, but I believe that on Linux will be the same behavior.
I don't think that the problem is in scroll actually, because my custom control just doesn't loose the focus after I clicking outside the control. I also tried handle wxEVT_LEAVE_WINDOW by setting focus on parent window, but still didn't help

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2245
Joined: Sun Jan 03, 2010 5:45 pm

Re: Scroll doesn't work after focusing custom control

Post by PB » Wed Mar 25, 2020 3:15 pm

I am not saying it is the root of the issue but I would always skip the event in wxListViewShares::OnMouseMove(). You sometimes return from this method without doing that.

I also do not understand why you change event parameters in the selection change handler and then skip the event. Do you expect it the event to be handled by something else after that?

rudolfninja
Earned some good credits
Earned some good credits
Posts: 104
Joined: Tue Aug 28, 2018 1:02 pm
Location: Belarus

Re: Scroll doesn't work after focusing custom control

Post by rudolfninja » Wed Mar 25, 2020 4:19 pm

PB, nice point about exiting MouseMove handler without skipping the event sometimes. But It is not the reason of the issue, because I tried to comment OnMouseMove binding and it didn't help.
Regarding SelectionChange event, yes, parent control handles this event too.

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2245
Joined: Sun Jan 03, 2010 5:45 pm

Re: Scroll doesn't work after focusing custom control

Post by PB » Wed Mar 25, 2020 4:35 pm

I would start commenting out the parts of code (including the mouse event handler in the parent dialog) one by one till it start working. I would also doublecheck the parent-child hierarchy, i.e., if all the controls are created with a correct parent (e.g., dialog -> scrolled -> dataview).

I am not sure I understand what you mean by "scrollbars stop working": they do not respond to e.g. user mouse actions?

rudolfninja
Earned some good credits
Earned some good credits
Posts: 104
Joined: Tue Aug 28, 2018 1:02 pm
Location: Belarus

Re: Scroll doesn't work after focusing custom control

Post by rudolfninja » Wed Mar 25, 2020 4:56 pm

By "stop working" I mean that it doesn't respond on mouse wheel action.
I attached parent dialog's files. But actually I don't think the problem somewhere there, because if I focus wxTextCtrl on the same dialog, then everything works ok
Attachments
wxRTSharesManagerDialog.h
(3.75 KiB) Downloaded 7 times
wxRTSharesManagerDialog.cpp
(21.93 KiB) Downloaded 8 times

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 3915
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Scroll doesn't work after focusing custom control

Post by ONEEYEMAN » Wed Mar 25, 2020 5:11 pm

Hi,
As PB said - try to comment out pieces of your code starting with the event handlers and see if that will make any differences.

Thank you.

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2245
Joined: Sun Jan 03, 2010 5:45 pm

Re: Scroll doesn't work after focusing custom control

Post by PB » Wed Mar 25, 2020 5:58 pm

The code you posted is way too complex and missing information (e.g., what is m_dialogContent probably coming from the base class?).

You do not seem to skip the mouse event in the dialog handler as well, are you sure this is what you want? Did you try to not bind the mouse move event there to see if it helps?

I am not familiar with wxDVC but it would make sense to me if it consumed the scroll events itself when focused. However, if it did not have scrollbars I would consider that a bug but still a problematic design in your application unless it could never have scrollbars. As a user, I expect mouse wheel events going to the focused control supporting scrolling (listctrl, textctrl...), not its top-level parent.

rudolfninja
Earned some good credits
Earned some good credits
Posts: 104
Joined: Tue Aug 28, 2018 1:02 pm
Location: Belarus

Re: Scroll doesn't work after focusing custom control

Post by rudolfninja » Wed Mar 25, 2020 6:50 pm

Tried unbind OnMouseMove handler in the dialog - didn't help.
As a user, I expect mouse wheel events going to the focused control supporting scrolling (listctrl, textctrl...), not its top-level parent.
I expect the same...seems like wxDataViewListCtrl works in incorrect way.
Will check it tomorrow

User avatar
doublemax
Moderator
Moderator
Posts: 14641
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Scroll doesn't work after focusing custom control

Post by doublemax » Wed Mar 25, 2020 7:47 pm

wxDataViewListCtrl is a scrollable control itself, so it consumes mouse-wheel events. I haven't tried it, but i think you might have to catch the mouse-wheel events at the wxDVC and forward them to the parent. In the generic version that's used under Windows, this might work. But i'm not so sure about the native version under GTK.
Use the source, Luke!

PB
Part Of The Furniture
Part Of The Furniture
Posts: 2245
Joined: Sun Jan 03, 2010 5:45 pm

Re: Scroll doesn't work after focusing custom control

Post by PB » Wed Mar 25, 2020 8:03 pm

rudolfninja wrote:
Wed Mar 25, 2020 6:50 pm
Tried unbind OnMouseMove handler in the dialog - didn't help.
As a user, I expect mouse wheel events going to the focused control supporting scrolling (listctrl, textctrl...), not its top-level parent.
I expect the same...seems like wxDataViewListCtrl works in incorrect way.
I meant that the scroll events should go to focused scrollable control, in this case a wxDVC, not the wxScrolled which hosts the wxDVC. I.e., the same what doublemax wrote.

ONEEYEMAN
Part Of The Furniture
Part Of The Furniture
Posts: 3915
Joined: Sat Apr 16, 2005 7:22 am
Location: USA, Ukraine

Re: Scroll doesn't work after focusing custom control

Post by ONEEYEMAN » Wed Mar 25, 2020 10:53 pm

Hi,
Most likely it also won't work under OSX, where native implementation is used.

You can try and see.

Thank you.

rudolfninja
Earned some good credits
Earned some good credits
Posts: 104
Joined: Tue Aug 28, 2018 1:02 pm
Location: Belarus

Re: Scroll doesn't work after focusing custom control

Post by rudolfninja » Thu Mar 26, 2020 12:10 pm

Tried to pass mouswheel event to parent control, but didn't help.
But may be I'm doing something wrong.

Code: Select all

wxListViewShares::wxListViewShares(wxWindow* parent, const share_list_t& shares, const std::shared_ptr<ApplicationHelper>& appHelper,
    const SharesSerializer::used_shares_t& usedShares) :
    wxDataViewListCtrl(parent, wxID_ANY, wxDefaultPosition, wxSize(parent->FromDIP(740), parent->FromDIP(175)), wxDV_ROW_LINES | wxDV_SINGLE),
    m_shares(shares),
    m_applicationHelper(appHelper),
    m_usedShares(usedShares)
{
    FillHeaders();
    FillList();

    Bind(wxEVT_DATAVIEW_SELECTION_CHANGED, &wxListViewShares::OnSelectionChanged, this);
    GetMainWindow()->Bind(wxEVT_MOTION, &wxListViewShares::OnMouseMove, this);
    /*GetMainWindow()->*/Bind(wxEVT_MOUSEWHEEL, &wxListViewShares::OnMouseWheel, this);
    
    void wxListViewShares::OnMouseWheel(wxMouseEvent& event)
    {
        event.Skip();
    }
}
Actually in the even't handler I want to check if mouse is inside/outside the control and forward to the parent if mouse is outside the control. But how correctly forward this event to parent control?

User avatar
doublemax
Moderator
Moderator
Posts: 14641
Joined: Fri Apr 21, 2006 8:03 pm
Location: $FCE2

Re: Scroll doesn't work after focusing custom control

Post by doublemax » Thu Mar 26, 2020 1:25 pm

event.Skip() doesn't work here, because mouse events don't propagate.

Try GetParent()->GetEventHandler()->ProcessEvent(event)

If this doesn't work, please try to provide a minimal, compilable sample that people can use for their own experiments.
Use the source, Luke!

Post Reply