Page 1 of 2

Scroll doesn't work after focusing custom control

Posted: Wed Mar 25, 2020 7:18 am
by rudolfninja
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?

Re: Scroll doesn't work after focusing custom control

Posted: Wed Mar 25, 2020 2:22 pm
by ONEEYEMAN
Hi,
Usual stanza applies.

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

Thank you.

Re: Scroll doesn't work after focusing custom control

Posted: Wed Mar 25, 2020 3:11 pm
by rudolfninja
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

Re: Scroll doesn't work after focusing custom control

Posted: Wed Mar 25, 2020 3:15 pm
by PB
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?

Re: Scroll doesn't work after focusing custom control

Posted: Wed Mar 25, 2020 4:19 pm
by rudolfninja
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.

Re: Scroll doesn't work after focusing custom control

Posted: Wed Mar 25, 2020 4:35 pm
by PB
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?

Re: Scroll doesn't work after focusing custom control

Posted: Wed Mar 25, 2020 4:56 pm
by rudolfninja
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

Re: Scroll doesn't work after focusing custom control

Posted: Wed Mar 25, 2020 5:11 pm
by ONEEYEMAN
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.

Re: Scroll doesn't work after focusing custom control

Posted: Wed Mar 25, 2020 5:58 pm
by PB
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.

Re: Scroll doesn't work after focusing custom control

Posted: Wed Mar 25, 2020 6:50 pm
by rudolfninja
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

Re: Scroll doesn't work after focusing custom control

Posted: Wed Mar 25, 2020 7:47 pm
by doublemax
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.

Re: Scroll doesn't work after focusing custom control

Posted: Wed Mar 25, 2020 8:03 pm
by PB
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.

Re: Scroll doesn't work after focusing custom control

Posted: Wed Mar 25, 2020 10:53 pm
by ONEEYEMAN
Hi,
Most likely it also won't work under OSX, where native implementation is used.

You can try and see.

Thank you.

Re: Scroll doesn't work after focusing custom control

Posted: Thu Mar 26, 2020 12:10 pm
by rudolfninja
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?

Re: Scroll doesn't work after focusing custom control

Posted: Thu Mar 26, 2020 1:25 pm
by doublemax
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.