tdf#154565 ignore unwanted crossing event from search to treeview on "enter"

i.e if the crossing was triggered ultimately by a key stroke which is
likely from exiting the search box.

This way we can avoid the problem that with hover-selection that after
"enter" is used in the search box, selecting a matching row, then during
teardown of the widget the box is hidden, and the generated crossing
notification triggers unwanted selection of a different row under the
mouse.

If needs be this could be refined further to only happen for a specific
key or other details of the triggering event

Change-Id: I7e64fb5fa31a446b85016d86ecd314d13130d7b9
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149979
Tested-by: Jenkins
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
diff --git a/vcl/unx/gtk3/gtkinst.cxx b/vcl/unx/gtk3/gtkinst.cxx
index decda56..88073b8da 100644
--- a/vcl/unx/gtk3/gtkinst.cxx
+++ b/vcl/unx/gtk3/gtkinst.cxx
@@ -14040,6 +14040,7 @@ private:
#if !GTK_CHECK_VERSION(4, 0, 0)
    gulong m_nPopupMenuSignalId;
    gulong m_nKeyPressSignalId;
    gulong m_nCrossingSignalid;
#endif
    gulong m_nQueryTooltipSignalId;
    GtkAdjustment* m_pVAdjustment;
@@ -14721,6 +14722,28 @@ private:
        return false;
    }

#if !GTK_CHECK_VERSION(4, 0, 0)
    // tdf#154565 ignore the crossing event if it was triggered ultimately by a
    // key stroke which is likely from exiting the search box. This way we can
    // avoid the problem that with hover-selection that after return is used in
    // the search box, selecting a matching row, that during teardown of the
    // widget the box is hidden, and the crossing notification triggers
    // selection of a different row under the mouse. If needs be this could be
    // refined further to only happen for a specific key or other details of
    // the triggering event
    static gboolean signalCrossing(GtkWidget*, GdkEventCrossing*, gpointer)
    {
        if (GdkEvent *pEvent = gtk_get_current_event())
        {
            const bool bCrossingTriggeredByKeyStroke = gdk_event_get_event_type(pEvent) == GDK_KEY_PRESS;
            gdk_event_free(pEvent);
            return bCrossingTriggeredByKeyStroke;
        }

        return false;
    }
#endif

public:
    GtkInstanceTreeView(GtkTreeView* pTreeView, GtkInstanceBuilder* pBuilder, bool bTakeOwnership)
        : GtkInstanceWidget(GTK_WIDGET(pTreeView), pBuilder, bTakeOwnership)
@@ -14744,6 +14767,7 @@ public:
#if !GTK_CHECK_VERSION(4, 0, 0)
        , m_nPopupMenuSignalId(g_signal_connect(pTreeView, "popup-menu", G_CALLBACK(signalPopupMenu), this))
        , m_nKeyPressSignalId(g_signal_connect(pTreeView, "key-press-event", G_CALLBACK(signalKeyPress), this))
        , m_nCrossingSignalid(g_signal_connect(pTreeView, "enter-notify-event", G_CALLBACK(signalCrossing), this))
#endif
        , m_nQueryTooltipSignalId(0)
        , m_pVAdjustment(gtk_scrollable_get_vadjustment(GTK_SCROLLABLE(pTreeView)))
@@ -16671,6 +16695,7 @@ public:
        if (m_nQueryTooltipSignalId)
            g_signal_handler_disconnect(m_pTreeView, m_nQueryTooltipSignalId);
#if !GTK_CHECK_VERSION(4, 0, 0)
        g_signal_handler_disconnect(m_pTreeView, m_nCrossingSignalid);
        g_signal_handler_disconnect(m_pTreeView, m_nKeyPressSignalId);
        g_signal_handler_disconnect(m_pTreeView, m_nPopupMenuSignalId);
#endif