From 690b95646bc68f3d2ca6502c618a065ed8955b79 Mon Sep 17 00:00:00 2001 From: Vadim Zeitlin Date: Sun, 3 Jun 2018 17:04:06 +0200 Subject: [PATCH] Implement wxTextCtrl::HitTest() for single line controls in wxGTK Use Pango API to find the character at the given position. Closes #18144. --- docs/changes.txt | 1 + interface/wx/textctrl.h | 4 ++-- src/gtk/textctrl.cpp | 49 +++++++++++++++++++++++++++++++++++++++-- 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/docs/changes.txt b/docs/changes.txt index 41ecaf1d11..63ba58a58f 100644 --- a/docs/changes.txt +++ b/docs/changes.txt @@ -84,6 +84,7 @@ All (GUI): wxGTK: +- Implement wxTextCtrl::HitTest() for single line controls. - Fix the build with glib < 2.32 (e.g. CentOS 6). wxMSW: diff --git a/interface/wx/textctrl.h b/interface/wx/textctrl.h index 70b296c5b0..1bb50d9e90 100644 --- a/interface/wx/textctrl.h +++ b/interface/wx/textctrl.h @@ -1337,7 +1337,7 @@ public: parameter is not modified. Please note that this function is currently only implemented in wxUniv, - wxMSW and wxGTK2 ports and always returns @c wxTE_HT_UNKNOWN in the + wxMSW and wxGTK ports and always returns @c wxTE_HT_UNKNOWN in the other ports. @beginWxPerlOnly @@ -1363,7 +1363,7 @@ public: parameters are not modified. Please note that this function is currently only implemented in wxUniv, - wxMSW and wxGTK2 ports and always returns @c wxTE_HT_UNKNOWN in the + wxMSW and wxGTK ports and always returns @c wxTE_HT_UNKNOWN in the other ports. @beginWxPerlOnly diff --git a/src/gtk/textctrl.cpp b/src/gtk/textctrl.cpp index 281099dce9..b8551d37c7 100644 --- a/src/gtk/textctrl.cpp +++ b/src/gtk/textctrl.cpp @@ -1465,8 +1465,53 @@ wxTextCtrl::HitTest(const wxPoint& pt, long *pos) const { if ( !IsMultiLine() ) { - // not supported - return wxTE_HT_UNKNOWN; + // These variables will contain the position inside PangoLayout. + int x = pt.x, + y = pt.y; + + // Get the offsets of PangoLayout inside the control. + // + // Note that contrary to what GTK+ documentation implies, the + // horizontal offset already accounts for scrolling, i.e. it will be + // negative if text is scrolled. + gint ofsX = 0, + ofsY = 0; + gtk_entry_get_layout_offsets(GTK_ENTRY(m_text), &ofsX, &ofsY); + + x -= ofsX; + y -= ofsY; + + // And scale the coordinates for Pango. + x *= PANGO_SCALE; + y *= PANGO_SCALE; + + PangoLayout* const layout = gtk_entry_get_layout(GTK_ENTRY(m_text)); + + int idx = -1, + ofs = 0; + if ( !pango_layout_xy_to_index(layout, x, y, &idx, &ofs) ) + { + // Try to guess why did it fail. + if ( x < 0 || y < 0 ) + { + if ( pos ) + *pos = 0; + + return wxTE_HT_BEFORE; + } + else + { + if ( pos ) + *pos = wxTextEntry::GetLastPosition(); + + return wxTE_HT_BEYOND; + } + } + + if ( pos ) + *pos = idx; + + return wxTE_HT_ON_TEXT; } int x, y;