390 lines
14 KiB
Diff
390 lines
14 KiB
Diff
From: Christian Persch <chpe@src.gnome.org>
|
|
Date: Sun, 24 Jul 2022 14:45:57 +0200
|
|
Subject: widget: gtk4: Add API to check event context
|
|
|
|
https://gitlab.gnome.org/GNOME/vte/-/issues/2530
|
|
(cherry picked from commit 0effa40fd9520e7e9af83d5a26d0d7be58b4094e)
|
|
---
|
|
src/vte.cc | 33 +++++++++
|
|
src/vte/vteterminal.h | 33 +++++++++
|
|
src/vtegtk.cc | 183 ++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
src/vteinternal.hh | 20 +++---
|
|
src/widget.hh | 27 ++++++++
|
|
5 files changed, 288 insertions(+), 8 deletions(-)
|
|
|
|
diff --git a/src/vte.cc b/src/vte.cc
|
|
index 00cd243..ed99daf 100644
|
|
--- a/src/vte.cc
|
|
+++ b/src/vte.cc
|
|
@@ -1866,6 +1866,39 @@ Terminal::regex_match_check(vte::platform::MouseEvent const& event,
|
|
return regex_match_check(col, row - (long)m_screen->scroll_delta, tag);
|
|
}
|
|
|
|
+#if VTE_GTK == 4
|
|
+
|
|
+char*
|
|
+Terminal::regex_match_check_at(double x,
|
|
+ double y,
|
|
+ int *tag)
|
|
+{
|
|
+ long col, row;
|
|
+ if (!rowcol_at(x, y, &col, &row))
|
|
+ return nullptr;
|
|
+
|
|
+ /* FIXME Shouldn't rely on a deprecated, not sub-row aware method. */
|
|
+ // FIXMEchpe fix this scroll_delta substraction!
|
|
+ return regex_match_check(col, row - (long)m_screen->scroll_delta, tag);
|
|
+}
|
|
+
|
|
+bool
|
|
+Terminal::regex_match_check_extra_at(double x,
|
|
+ double y,
|
|
+ vte::base::Regex const** regexes,
|
|
+ size_t n_regexes,
|
|
+ uint32_t match_flags,
|
|
+ char** matches)
|
|
+{
|
|
+ long col, row;
|
|
+ if (!rowcol_at(x, y, &col, &row))
|
|
+ return false;
|
|
+
|
|
+ return regex_match_check_extra(col, row, regexes, n_regexes, match_flags, matches);
|
|
+}
|
|
+
|
|
+#endif /* VTE_GTK == 4 */
|
|
+
|
|
bool
|
|
Terminal::regex_match_check_extra(vte::platform::MouseEvent const& event,
|
|
vte::base::Regex const** regexes,
|
|
diff --git a/src/vte/vteterminal.h b/src/vte/vteterminal.h
|
|
index c71658d..d2d9a73 100644
|
|
--- a/src/vte/vteterminal.h
|
|
+++ b/src/vte/vteterminal.h
|
|
@@ -425,6 +425,13 @@ _VTE_PUBLIC
|
|
char *vte_terminal_hyperlink_check_event(VteTerminal *terminal,
|
|
GdkEvent *event) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 2) G_GNUC_MALLOC;
|
|
|
|
+#elif _VTE_GTK == 4
|
|
+
|
|
+_VTE_PUBLIC
|
|
+char* vte_terminal_hyperlink_check_at(VteTerminal* terminal,
|
|
+ double x,
|
|
+ double y) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) G_GNUC_MALLOC;
|
|
+
|
|
#endif /* _VTE_GTK */
|
|
|
|
/* Add a matching expression, returning the tag the widget assigns to that
|
|
@@ -469,6 +476,32 @@ gboolean vte_terminal_event_check_regex_simple(VteTerminal *terminal,
|
|
guint32 match_flags,
|
|
char **matches) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1, 2);
|
|
|
|
+#elif _VTE_GTK == 4
|
|
+
|
|
+_VTE_PUBLIC
|
|
+char* vte_terminal_match_check_at(VteTerminal* terminal,
|
|
+ double x,
|
|
+ double y,
|
|
+ int* tag) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) G_GNUC_MALLOC;
|
|
+
|
|
+_VTE_PUBLIC
|
|
+char** vte_terminal_regex_array_check_at(VteTerminal* terminal,
|
|
+ double x,
|
|
+ double y,
|
|
+ VteRegex** regexes,
|
|
+ gsize n_regexes,
|
|
+ guint32 match_flags,
|
|
+ gsize* n_matches) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1) G_GNUC_MALLOC;
|
|
+
|
|
+_VTE_PUBLIC
|
|
+gboolean vte_terminal_regex_simple_check_at(VteTerminal* terminal,
|
|
+ double x,
|
|
+ double y,
|
|
+ VteRegex** regexes,
|
|
+ gsize n_regexes,
|
|
+ guint32 match_flags,
|
|
+ char** matches) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1);
|
|
+
|
|
#endif /* _VTE_GTK */
|
|
|
|
_VTE_PUBLIC
|
|
diff --git a/src/vtegtk.cc b/src/vtegtk.cc
|
|
index 2dc8fd4..132278a 100644
|
|
--- a/src/vtegtk.cc
|
|
+++ b/src/vtegtk.cc
|
|
@@ -3153,6 +3153,189 @@ catch (...)
|
|
return false;
|
|
}
|
|
|
|
+#elif VTE_GTK == 4
|
|
+
|
|
+/**
|
|
+ * vte_terminal_match_check_at:
|
|
+ * @terminal: a #VteTerminal
|
|
+ * @x:
|
|
+ * @y:
|
|
+ * @tag: (out) (allow-none): a location to store the tag, or %NULL
|
|
+ *
|
|
+ * Checks if the text in and around the position (x, y) matches any of the
|
|
+ * regular expressions previously set using vte_terminal_match_add(). If a
|
|
+ * match exists, the text string is returned and if @tag is not %NULL, the number
|
|
+ * associated with the matched regular expression will be stored in @tag.
|
|
+ *
|
|
+ * If more than one regular expression has been set with
|
|
+ * vte_terminal_match_add(), then expressions are checked in the order in
|
|
+ * which they were added.
|
|
+ *
|
|
+ * Returns: (transfer full) (nullable): a newly allocated string which matches one of the previously
|
|
+ * set regular expressions, or %NULL if there is no match
|
|
+ *
|
|
+ * Since: 0.70
|
|
+ */
|
|
+char*
|
|
+vte_terminal_match_check_at(VteTerminal* terminal,
|
|
+ double x,
|
|
+ double y,
|
|
+ int* tag) noexcept
|
|
+try
|
|
+{
|
|
+ g_return_val_if_fail(VTE_IS_TERMINAL(terminal), FALSE);
|
|
+ return WIDGET(terminal)->regex_match_check_at(x, y, tag);
|
|
+}
|
|
+catch (...)
|
|
+{
|
|
+ vte::log_exception();
|
|
+ return nullptr;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * vte_terminal_hyperlink_check_at:
|
|
+ * @terminal: a #VteTerminal
|
|
+ * @x:
|
|
+ * @y:
|
|
+ *
|
|
+ * Returns a nonempty string: the target of the explicit hyperlink (printed using the OSC 8
|
|
+ * escape sequence) at the position (x, y), or %NULL.
|
|
+ *
|
|
+ * Proper use of the escape sequence should result in URI-encoded URIs with a proper scheme
|
|
+ * like "http://", "https://", "file://", "mailto:" etc. This is, however, not enforced by VTE.
|
|
+ * The caller must tolerate the returned string potentially not being a valid URI.
|
|
+ *
|
|
+ * Returns: (transfer full) (nullable): a newly allocated string containing the target of the hyperlink,
|
|
+ * or %NULL
|
|
+ *
|
|
+ * Since: 0.70
|
|
+ */
|
|
+char*
|
|
+vte_terminal_hyperlink_check_at(VteTerminal* terminal,
|
|
+ double x,
|
|
+ double y) noexcept
|
|
+try
|
|
+{
|
|
+ g_return_val_if_fail(VTE_IS_TERMINAL(terminal), nullptr);
|
|
+ return WIDGET(terminal)->hyperlink_check_at(x, y);
|
|
+}
|
|
+catch (...)
|
|
+{
|
|
+ vte::log_exception();
|
|
+ return nullptr;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * vte_terminal_regex_array_check_at: (rename-to vte_terminal_check_regex_simple_at)
|
|
+ * @terminal: a #VteTerminal
|
|
+ * @x:
|
|
+ * @y:
|
|
+ * @regexes: (array length=n_regexes): an array of #VteRegex
|
|
+ * @n_regexes: number of items in @regexes
|
|
+ * @match_flags: PCRE2 match flags, or 0
|
|
+ * @n_matches: (out) (optional): number of items in @matches, which is always equal to @n_regexes
|
|
+ *
|
|
+ * Like vte_terminal_check_regex_simple_at(), but returns an array of strings,
|
|
+ * containing the matching text (or %NULL if no match) corresponding to each of the
|
|
+ * regexes in @regexes.
|
|
+ *
|
|
+ * You must free each string and the array; but note that this is *not* a %NULL-terminated
|
|
+ * string array, and so you must *not* use g_strfreev() on it.
|
|
+ *
|
|
+ * Returns: (nullable) (transfer full) (array length=n_matches): a newly allocated array of strings,
|
|
+ * or %NULL if none of the regexes matched
|
|
+ *
|
|
+ * Since: 0.70
|
|
+ */
|
|
+char**
|
|
+vte_terminal_regex_array_check_at(VteTerminal* terminal,
|
|
+ double x,
|
|
+ double y,
|
|
+ VteRegex** regexes,
|
|
+ gsize n_regexes,
|
|
+ guint32 match_flags,
|
|
+ gsize* n_matches) noexcept
|
|
+try
|
|
+{
|
|
+ if (n_matches)
|
|
+ *n_matches = n_regexes;
|
|
+
|
|
+ if (n_regexes == 0)
|
|
+ return nullptr;
|
|
+
|
|
+ auto matches = vte::glib::take_free_ptr(g_new0(char*, n_regexes));
|
|
+ if (!vte_terminal_regex_simple_check_at(terminal,
|
|
+ x, y,
|
|
+ regexes,
|
|
+ n_regexes,
|
|
+ match_flags,
|
|
+ matches.get()))
|
|
+ return nullptr;
|
|
+
|
|
+ return matches.release();
|
|
+}
|
|
+catch (...)
|
|
+{
|
|
+ vte::log_exception();
|
|
+ return nullptr;
|
|
+}
|
|
+
|
|
+/**
|
|
+ * vte_terminal_regex_simple_check_at: (skip)
|
|
+ * @terminal: a #VteTerminal
|
|
+ * @x:
|
|
+ * @y:
|
|
+ * @regexes: (array length=n_regexes): an array of #VteRegex
|
|
+ * @n_regexes: number of items in @regexes
|
|
+ * @match_flags: PCRE2 match flags, or 0
|
|
+ * @matches: (out caller-allocates) (array length=n_regexes) (transfer full): a location to store the matches
|
|
+ *
|
|
+ * Checks each regex in @regexes if the text in and around the position (x, y)
|
|
+ * matches the regular expressions. If a match exists, the matched
|
|
+ * text is stored in @matches at the position of the regex in @regexes; otherwise
|
|
+ * %NULL is stored there. Each non-%NULL element of @matches should be freed with
|
|
+ * g_free().
|
|
+ *
|
|
+ * Note that the regexes in @regexes should have been created using the %PCRE2_MULTILINE flag.
|
|
+ *
|
|
+ * Returns: %TRUE iff any of the regexes produced a match
|
|
+ *
|
|
+ * Since: 0.70
|
|
+ */
|
|
+gboolean
|
|
+vte_terminal_regex_simple_check_at(VteTerminal* terminal,
|
|
+ double x,
|
|
+ double y,
|
|
+ VteRegex** regexes,
|
|
+ gsize n_regexes,
|
|
+ guint32 match_flags,
|
|
+ char** matches) noexcept
|
|
+try
|
|
+{
|
|
+ g_return_val_if_fail(VTE_IS_TERMINAL(terminal), FALSE);
|
|
+ g_return_val_if_fail(regexes != NULL || n_regexes == 0, FALSE);
|
|
+ for (gsize i = 0; i < n_regexes; i++) {
|
|
+ g_return_val_if_fail(_vte_regex_has_purpose(regexes[i], vte::base::Regex::Purpose::eMatch), -1);
|
|
+ g_warn_if_fail(_vte_regex_has_multiline_compile_flag(regexes[i]));
|
|
+ }
|
|
+ g_return_val_if_fail(matches != NULL, FALSE);
|
|
+
|
|
+ return WIDGET(terminal)->regex_match_check_extra_at(x, y,
|
|
+ regex_array_from_wrappers(regexes),
|
|
+ n_regexes,
|
|
+ match_flags,
|
|
+ matches);
|
|
+}
|
|
+catch (...)
|
|
+{
|
|
+ vte::log_exception();
|
|
+ return false;
|
|
+}
|
|
+
|
|
+#endif /* VTE_GTK */
|
|
+
|
|
+#if VTE_GTK == 3
|
|
+
|
|
/**
|
|
* vte_terminal_event_check_gregex_simple:
|
|
* @terminal: a #VteTerminal
|
|
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
|
|
index 5037096..fbe696b 100644
|
|
--- a/src/vteinternal.hh
|
|
+++ b/src/vteinternal.hh
|
|
@@ -1244,8 +1244,6 @@ public:
|
|
#endif
|
|
|
|
char *hyperlink_check(vte::platform::MouseEvent const& event);
|
|
- char *hyperlink_check_at(double x,
|
|
- double y);
|
|
char *hyperlink_check(vte::grid::column_t column,
|
|
vte::grid::row_t row);
|
|
|
|
@@ -1254,12 +1252,6 @@ public:
|
|
size_t n_regexes,
|
|
uint32_t match_flags,
|
|
char** matches);
|
|
- bool regex_match_check_extra_at(double x,
|
|
- double y,
|
|
- vte::base::Regex const** regexes,
|
|
- size_t n_regexes,
|
|
- uint32_t match_flags,
|
|
- char** matches);
|
|
bool regex_match_check_extra(vte::grid::column_t column,
|
|
vte::grid::row_t row,
|
|
vte::base::Regex const** regexes,
|
|
@@ -1272,9 +1264,21 @@ public:
|
|
int *tag);
|
|
char *regex_match_check(vte::platform::MouseEvent const& event,
|
|
int *tag);
|
|
+
|
|
+#if VTE_GTK == 4
|
|
+ char *hyperlink_check_at(double x,
|
|
+ double y);
|
|
+ bool regex_match_check_extra_at(double x,
|
|
+ double y,
|
|
+ vte::base::Regex const** regexes,
|
|
+ size_t n_regexes,
|
|
+ uint32_t match_flags,
|
|
+ char** matches);
|
|
char *regex_match_check_at(double x,
|
|
double y,
|
|
int *tag);
|
|
+#endif /* VTE_GTK == 4 */
|
|
+
|
|
void regex_match_remove(int tag) noexcept;
|
|
void regex_match_remove_all() noexcept;
|
|
void regex_match_set_cursor(int tag,
|
|
diff --git a/src/widget.hh b/src/widget.hh
|
|
index 5e6b1bd..308edb5 100644
|
|
--- a/src/widget.hh
|
|
+++ b/src/widget.hh
|
|
@@ -469,6 +469,33 @@ public:
|
|
return terminal()->hyperlink_check(mouse_event_from_gdk(event));
|
|
}
|
|
|
|
+#elif VTE_GTK == 4
|
|
+
|
|
+ char* regex_match_check_at(double x,
|
|
+ double y,
|
|
+ int* tag)
|
|
+ {
|
|
+ return terminal()->regex_match_check(x, y, tag);
|
|
+ }
|
|
+
|
|
+ bool regex_match_check_extra_at(double x,
|
|
+ double y,
|
|
+ vte::base::Regex const** regexes,
|
|
+ size_t n_regexes,
|
|
+ uint32_t match_flags,
|
|
+ char** matches)
|
|
+ {
|
|
+ return terminal()->regex_match_check_extra_at(x, y,
|
|
+ regexes, n_regexes,
|
|
+ match_flags, matches);
|
|
+ }
|
|
+
|
|
+ char* hyperlink_check_at(double x,
|
|
+ double y)
|
|
+ {
|
|
+ return terminal()->hyperlink_check_at(x, y);
|
|
+ }
|
|
+
|
|
#endif /* VTE_GTK */
|
|
|
|
bool should_emit_signal(int id) noexcept;
|