aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/terminal.vala
diff options
context:
space:
mode:
authorWynn Wolf Arbor2020-03-28 15:10:55 +0100
committerWynn Wolf Arbor2020-04-13 15:45:26 +0200
commit30bbf529ad3073fd449c7f9331a889b114fad1e1 (patch)
treede43218ab0a4e4fc12816251144b55010e8c01a4 /terminal.vala
parentbed4cae59bfd5ac100caa3a4ac795f33598b6ab0 (diff)
downloadweltschmerz-30bbf529ad3073fd449c7f9331a889b114fad1e1.tar.gz
Add OSC 8 hyperlink support
This commit adds support for the OSC 8 hyperlink escape sequence [1]. As this is not a mature feature and there seem to be outstanding security concerns [2], the setting that controls whether or not OSC 8 is interpreted is disabled by default. Just like gnome-terminal, weltschmerz will display a tooltip with the canonicalized URI when hovering over a hyperlink. [1] https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda [2] https://gist.github.com/egmontkob/eb114294efbcd5adb1944c9f3cb5feda#security
Diffstat (limited to 'terminal.vala')
-rw-r--r--terminal.vala37
1 files changed, 28 insertions, 9 deletions
diff --git a/terminal.vala b/terminal.vala
index 99c21ce..5f4f4e0 100644
--- a/terminal.vala
+++ b/terminal.vala
@@ -25,14 +25,17 @@ class Terminal : Gtk.Overlay {
[GtkChild] Gtk.Label infobar_label;
[GtkChild] Gtk.Menu standard_context_menu;
[GtkChild] Gtk.Menu url_context_menu;
+ [GtkChild] Gtk.Menu hyperlink_context_menu;
[GtkChild] Gtk.MenuItem copy_item;
[GtkChild] Gtk.Revealer search_revealer;
[GtkChild] Gtk.ScrolledWindow scrolled_window;
[GtkChild] Gtk.SearchEntry search_entry;
[GtkChild] Vte.Terminal vte;
+ Gtk.Clipboard clipboard;
bool has_search;
string url_match;
+ string hyperlink_match;
uint? infobar_timeout_id;
double scroll_delta;
@@ -45,8 +48,11 @@ class Terminal : Gtk.Overlay {
vte.search_set_wrap_around(true);
url_context_menu.attach_to_widget(vte, null);
+ hyperlink_context_menu.attach_to_widget(vte, null);
standard_context_menu.attach_to_widget(vte, null);
+ clipboard = Gtk.Clipboard.get_default(window.get_display());
+
try {
var regex = new Vte.Regex.for_match(URL_REGEX, URL_REGEX.length, PCRE2_CASELESS | PCRE2_MULTILINE);
vte.match_add_regex(regex, 0);
@@ -69,6 +75,8 @@ class Terminal : Gtk.Overlay {
Gtk.PolicyType policy = conf.scrollbar ? Gtk.PolicyType.AUTOMATIC : Gtk.PolicyType.NEVER;
scrolled_window.set_policy(policy, policy);
+ vte.set_allow_hyperlink(conf.allow_hyperlinks);
+
vte.set_font(conf.font);
var geometry = Gdk.Geometry() {
// This must be kept in sync with the padding size in terminal.css
@@ -262,9 +270,9 @@ class Terminal : Gtk.Overlay {
search_button_down.set_sensitive(has_search);
}
- void url_match_open() {
+ void uri_open(string uri) {
try {
- AppInfo.launch_default_for_uri(url_match, get_display().get_app_launch_context());
+ AppInfo.launch_default_for_uri(uri, get_display().get_app_launch_context());
} catch (Error e) {
warning(e.message);
infobar_show(e.message, Gtk.MessageType.ERROR);
@@ -272,13 +280,12 @@ class Terminal : Gtk.Overlay {
}
[GtkCallback]
- void url_match_copy() {
- if (url_match == null) {
- return;
+ void uri_copy() {
+ if (url_match != null) {
+ clipboard.set_text(url_match, -1);
+ } else if (hyperlink_match != null) {
+ clipboard.set_text(hyperlink_match, -1);
}
-
- Gtk.Clipboard clipboard = Gtk.Clipboard.get_default(window.get_display());
- clipboard.set_text(url_match, -1);
}
void adjust_font_scale(double scale) {
@@ -309,9 +316,12 @@ class Terminal : Gtk.Overlay {
bool vte_button_press(Gdk.EventButton event) {
if (match_button(event, 0, Gdk.BUTTON_SECONDARY)) {
url_match = vte.match_check_event(event, null);
+ hyperlink_match = vte.hyperlink_check_event(event);
if (url_match != null) {
url_context_menu.popup_at_pointer(event);
+ } else if (hyperlink_match != null) {
+ hyperlink_context_menu.popup_at_pointer(event);
} else {
copy_item.set_sensitive(vte.get_has_selection());
standard_context_menu.popup_at_pointer(event);
@@ -326,8 +336,12 @@ class Terminal : Gtk.Overlay {
bool vte_button_release(Gdk.EventButton event) {
if (match_button(event, 0, Gdk.BUTTON_PRIMARY)) {
url_match = vte.match_check_event(event, null);
+ hyperlink_match = vte.hyperlink_check_event(event);
+
if (url_match != null && !vte.get_has_selection()) {
- url_match_open();
+ uri_open(url_match);
+ } else if (hyperlink_match != null && !vte.get_has_selection()) {
+ uri_open(hyperlink_match);
}
}
@@ -398,6 +412,11 @@ class Terminal : Gtk.Overlay {
}
[GtkCallback]
+ void vte_hyperlink_hover(string? uri, Gdk.Rectangle? box) {
+ vte.set_tooltip_text(Utils.normalize_uri(uri));
+ }
+
+ [GtkCallback]
void window_set_title() {
string title = null;
if (vte.window_title.length > 0) {