From 5201ac7b5e531b1b3bcab427ceef3290021f2d55 Mon Sep 17 00:00:00 2001 From: lenemter Date: Sat, 27 Dec 2025 22:48:17 +0900 Subject: [PATCH 1/2] Move open in browser action to TerminalWidget --- src/MainWindow.vala | 24 ++---------- src/Widgets/TerminalWidget.vala | 68 ++++++++++++++++++++++++++++----- 2 files changed, 61 insertions(+), 31 deletions(-) diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 04dad004b0..0042e1fe67 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -46,8 +46,6 @@ namespace Terminal { public const string ACTION_SEARCH_ACCEL = "f"; public const string ACTION_SEARCH_NEXT = "action-search-next"; public const string ACTION_SEARCH_PREVIOUS = "action-search-previous"; - public const string ACTION_OPEN_IN_BROWSER = "action-open-in-browser"; - public const string ACTION_OPEN_IN_BROWSER_ACCEL = "e"; private static Gee.MultiMap action_accelerators = new Gee.HashMultiMap (); @@ -69,8 +67,7 @@ namespace Terminal { { ACTION_MOVE_TAB_TO_NEW_WINDOW, action_move_tab_to_new_window}, { ACTION_SEARCH, action_search, null, "false", action_search_change_state }, { ACTION_SEARCH_NEXT, action_search_next }, - { ACTION_SEARCH_PREVIOUS, action_search_previous }, - { ACTION_OPEN_IN_BROWSER, action_open_in_browser } + { ACTION_SEARCH_PREVIOUS, action_search_previous } }; public MainWindow (Terminal.Application app, bool recreate_tabs = true) { @@ -93,7 +90,6 @@ namespace Terminal { action_accelerators[ACTION_MOVE_TAB_RIGHT] = "Right"; action_accelerators[ACTION_MOVE_TAB_LEFT] = "Left"; action_accelerators[ACTION_SEARCH] = ACTION_SEARCH_ACCEL; - action_accelerators[ACTION_OPEN_IN_BROWSER] = ACTION_OPEN_IN_BROWSER_ACCEL; } construct { @@ -149,12 +145,11 @@ namespace Terminal { var show_in_browser_uri = get_current_selection_link_or_pwd (); var appinfo = Utils.get_default_app_for_uri (show_in_browser_uri); - get_simple_action (ACTION_OPEN_IN_BROWSER).set_enabled (appinfo != null); var open_in_browser_menuitem = new MenuItem ( _("Show in %s").printf (appinfo != null ? appinfo.get_display_name () : _("Default application")), - ACTION_PREFIX + ACTION_OPEN_IN_BROWSER + TerminalWidget.ACTION_OPEN_IN_BROWSER ); - open_in_browser_menuitem.set_attribute_value ("accel", ACTION_OPEN_IN_BROWSER_ACCEL); + open_in_browser_menuitem.set_attribute_value ("accel", new Variant ("s", TerminalWidget.ACCELS_OPEN_IN_BROWSER[0])); var copy_menuitem = new MenuItem ( _("Copy"), @@ -610,19 +605,6 @@ namespace Terminal { } } - private void action_open_in_browser () requires (current_terminal != null) { - var uri = get_current_selection_link_or_pwd (); - var context = Gdk.Display.get_default ().get_app_launch_context (); - AppInfo.launch_default_for_uri_async.begin (uri, context, null, (obj, res) => { - try { - AppInfo.launch_default_for_uri_async.end (res); - } catch (Error e) { - warning ("Launcher failed with error %s", e.message); - //TODO Handle launch failure - message box? - } - }); - } - private string? get_current_selection_link_or_pwd () requires (current_terminal != null) { var link_uri = current_terminal.link_uri; if (link_uri == null) { diff --git a/src/Widgets/TerminalWidget.vala b/src/Widgets/TerminalWidget.vala index c305368e60..71484a193f 100644 --- a/src/Widgets/TerminalWidget.vala +++ b/src/Widgets/TerminalWidget.vala @@ -34,6 +34,7 @@ namespace Terminal { public unowned Adw.TabPage? tab; public string? link_uri; + public const string ACTION_OPEN_IN_BROWSER = "term.open-in-browser"; public const string ACTION_COPY = "term.copy"; public const string ACTION_COPY_OUTPUT = "term.copy-output"; public const string ACTION_CLEAR_SCREEN = "term.clear-screen"; @@ -43,7 +44,7 @@ namespace Terminal { public const string ACTION_SCROLL_TO_COMMAND = "term.scroll-to-command"; public const string ACTION_SELECT_ALL = "term.select-all"; - + public const string[] ACCELS_OPEN_IN_BROWSER = { "E", null }; public const string[] ACCELS_COPY = { "C", null }; public const string[] ACCELS_COPY_OUTPUT = { "C", null }; public const string[] ACCELS_CLEAR_SCREEN = { "L", null }; @@ -103,6 +104,7 @@ namespace Terminal { private unowned Gdk.Clipboard clipboard; + private GLib.SimpleAction open_in_browser_action; private GLib.SimpleAction copy_action; private GLib.SimpleAction copy_output_action; private GLib.SimpleAction clear_screen_action; @@ -248,6 +250,11 @@ namespace Terminal { var action_group = new GLib.SimpleActionGroup (); insert_action_group ("term", action_group); + open_in_browser_action = new GLib.SimpleAction ("open-in-browser", null); + open_in_browser_action.set_enabled (false); + open_in_browser_action.activate.connect (open_in_browser); + action_group.add_action (open_in_browser_action); + copy_action = new GLib.SimpleAction ("copy", null); copy_action.set_enabled (false); copy_action.activate.connect (() => copy_clipboard.emit ()); @@ -316,7 +323,7 @@ namespace Terminal { link_uri = get_link (x, y); if (link_uri != null && !get_has_selection ()) { - main_window.get_simple_action (MainWindow.ACTION_OPEN_IN_BROWSER).activate (null); + open_in_browser_action.activate (null); } } else { allow_hyperlink = true; @@ -482,15 +489,13 @@ namespace Terminal { } private void setup_menu () { - // Update the "Paste" menu option - var formats = clipboard.get_formats (); - bool can_paste = false; + // Update the "Open in" menu option + var appinfo = Utils.get_default_app_for_uri (get_current_selection_link_or_pwd ()); + open_in_browser_action.set_enabled (appinfo != null); - if (formats != null) { - can_paste = formats.contain_gtype (Type.STRING); - } - - paste_action.set_enabled (can_paste); + // Update the "Paste" menu option + var clipboard_has_string = clipboard.formats != null && clipboard.formats.contain_gtype (Type.STRING); + paste_action.set_enabled (clipboard_has_string); // Update the "Copy Last Output" menu option var has_output = !resized && get_last_output ().length > 0; @@ -1073,5 +1078,48 @@ namespace Terminal { contents_changed_timeout_id = 0; } } + + private void open_in_browser (GLib.SimpleAction action, GLib.Variant? parameter) { + var uri = get_current_selection_link_or_pwd (); + var context = Gdk.Display.get_default ().get_app_launch_context (); + AppInfo.launch_default_for_uri_async.begin (uri, context, null, (obj, res) => { + try { + AppInfo.launch_default_for_uri_async.end (res); + } catch (Error e) { + warning ("Launcher failed with error %s", e.message); + //TODO Handle launch failure - message box? + } + }); + } + + private string? get_current_selection_link_or_pwd () { + if (link_uri == null) { + if (get_has_selection ()) { + copy_primary (); + try { + var cp = Gdk.Display.get_default ().get_primary_clipboard ().get_content (); + if (cp != null) { + var val = Value (typeof (string)); + cp.get_value (ref val); + return val.dup_string (); + } + } catch (Error e) { + critical ("Unable to get clipboard contents"); + } + + return null; + } else { + var shell_location_path = get_shell_location (); + var shell_location_file = GLib.File.new_for_path (shell_location_path); + return shell_location_file.get_uri (); + } + } else { + if (!link_uri.contains ("://")) { + link_uri = "http://" + link_uri; + } + + return link_uri; + } + } } } From 1d52f14e833283b9b4109101b39a94560051447b Mon Sep 17 00:00:00 2001 From: lenemter Date: Sun, 28 Dec 2025 02:10:45 +0900 Subject: [PATCH 2/2] Move context menu initialization to TerminalWidget --- src/MainWindow.vala | 93 --------------------------------- src/Widgets/TerminalWidget.vala | 78 ++++++++++++++++++++++++--- 2 files changed, 71 insertions(+), 100 deletions(-) diff --git a/src/MainWindow.vala b/src/MainWindow.vala index 0042e1fe67..ceea78b6a4 100644 --- a/src/MainWindow.vala +++ b/src/MainWindow.vala @@ -141,70 +141,6 @@ namespace Terminal { close_request.connect (on_delete_event); } - public Menu construct_context_menu_model () requires (current_terminal != null) { - var show_in_browser_uri = get_current_selection_link_or_pwd (); - var appinfo = Utils.get_default_app_for_uri (show_in_browser_uri); - - var open_in_browser_menuitem = new MenuItem ( - _("Show in %s").printf (appinfo != null ? appinfo.get_display_name () : _("Default application")), - TerminalWidget.ACTION_OPEN_IN_BROWSER - ); - open_in_browser_menuitem.set_attribute_value ("accel", new Variant ("s", TerminalWidget.ACCELS_OPEN_IN_BROWSER[0])); - - var copy_menuitem = new MenuItem ( - _("Copy"), - TerminalWidget.ACTION_COPY - ); - copy_menuitem.set_attribute_value ("accel", new Variant ("s", TerminalWidget.ACCELS_COPY[0])); - - var copy_last_output_menuitem = new MenuItem ( - _("Copy Last Output"), - TerminalWidget.ACTION_COPY_OUTPUT - ); - copy_last_output_menuitem.set_attribute_value ("accel", new Variant ("s", TerminalWidget.ACCELS_COPY_OUTPUT[0])); - - var clear_screen_menuitem = new MenuItem ( - _("Clear Screen"), - TerminalWidget.ACTION_CLEAR_SCREEN - ); - clear_screen_menuitem.set_attribute_value ("accel", new Variant ("s", TerminalWidget.ACCELS_CLEAR_SCREEN[0])); - - var reset_menuitem = new MenuItem ( - _("Reset"), - TerminalWidget.ACTION_RESET - ); - reset_menuitem.set_attribute_value ("accel", new Variant ("s", TerminalWidget.ACCELS_RESET[0])); - - var paste_menuitem = new MenuItem ( - _("Paste"), - TerminalWidget.ACTION_PASTE - ); - paste_menuitem.set_attribute_value ("accel", new Variant ("s", TerminalWidget.ACCELS_PASTE[0])); - - var select_all_menuitem = new MenuItem ( - _("Select All"), - TerminalWidget.ACTION_SELECT_ALL - ); - select_all_menuitem.set_attribute_value ("accel", new Variant ("s", TerminalWidget.ACCELS_SELECT_ALL[0])); - - var terminal_action_section = new Menu (); - terminal_action_section.append_item (copy_menuitem); - terminal_action_section.append_item (copy_last_output_menuitem); - terminal_action_section.append_item (paste_menuitem); - terminal_action_section.append_item (select_all_menuitem); - - var terminal_clear_reset_section = new Menu (); - terminal_clear_reset_section.append_item (clear_screen_menuitem); - terminal_clear_reset_section.append_item (reset_menuitem); - - var context_menu_model = new Menu (); - context_menu_model.append_item (open_in_browser_menuitem); - context_menu_model.append_section (null, terminal_action_section); - context_menu_model.append_section (null, terminal_clear_reset_section); - - return context_menu_model; - } - public void add_tab_with_working_directory ( string directory = "", string command = "", @@ -605,35 +541,6 @@ namespace Terminal { } } - private string? get_current_selection_link_or_pwd () requires (current_terminal != null) { - var link_uri = current_terminal.link_uri; - if (link_uri == null) { - if (current_terminal.get_has_selection ()) { - current_terminal.copy_primary (); - try { - var cp = Gdk.Display.get_default ().get_primary_clipboard ().get_content (); - if (cp != null) { - var val = Value (typeof (string)); - cp.get_value (ref val); - return val.dup_string (); - } - } catch (Error e) { - critical ("Unable to get clipboard contents"); - } - - return null; - } else { - return current_terminal.get_shell_location (); - } - } else { - if (!link_uri.contains ("://")) { - link_uri = "http://" + link_uri; - } - - return link_uri; - } - } - private void action_close_tab () { notebook.close_tab (); } diff --git a/src/Widgets/TerminalWidget.vala b/src/Widgets/TerminalWidget.vala index 71484a193f..81807a5de2 100644 --- a/src/Widgets/TerminalWidget.vala +++ b/src/Widgets/TerminalWidget.vala @@ -32,7 +32,6 @@ namespace Terminal { // There may be no associated tab while made restorable or when closing public unowned Adw.TabPage? tab; - public string? link_uri; public const string ACTION_OPEN_IN_BROWSER = "term.open-in-browser"; public const string ACTION_COPY = "term.copy"; @@ -117,6 +116,7 @@ namespace Terminal { private long remembered_command_end_row = 0; /* Only need to remember row at the moment */ public bool last_key_was_return = true; private bool child_has_exited = false; + private string? link_uri = null; private Gtk.EventControllerScroll scroll_controller; private double scroll_delta = 0.0; @@ -235,7 +235,7 @@ namespace Terminal { ulong once = 0; once = realize.connect (() => { clipboard = Gdk.Display.get_default ().get_clipboard (); - clipboard.changed.connect (setup_menu); + clipboard.changed.connect (update_actions_state); disconnect (once); }); @@ -488,7 +488,7 @@ namespace Terminal { return false; } - private void setup_menu () { + private void update_actions_state () { // Update the "Open in" menu option var appinfo = Utils.get_default_app_for_uri (get_current_selection_link_or_pwd ()); open_in_browser_action.set_enabled (appinfo != null); @@ -502,12 +502,76 @@ namespace Terminal { copy_output_action.set_enabled (has_output); } - private void popup_context_menu (double x, double y) { - setup_menu (); + private Menu construct_context_menu_model () { + update_actions_state (); + + var show_in_browser_uri = get_current_selection_link_or_pwd (); + var appinfo = Utils.get_default_app_for_uri (show_in_browser_uri); + + var open_in_browser_menuitem = new MenuItem ( + _("Show in %s").printf (appinfo != null ? appinfo.get_display_name () : _("Default application")), + ACTION_OPEN_IN_BROWSER + ); + open_in_browser_menuitem.set_attribute_value ("accel", new Variant ("s", TerminalWidget.ACCELS_OPEN_IN_BROWSER[0])); + + var copy_menuitem = new MenuItem ( + _("Copy"), + ACTION_COPY + ); + copy_menuitem.set_attribute_value ("accel", new Variant ("s", TerminalWidget.ACCELS_COPY[0])); - var context_menu_model = main_window.construct_context_menu_model (); + var copy_last_output_menuitem = new MenuItem ( + _("Copy Last Output"), + ACTION_COPY_OUTPUT + ); + copy_last_output_menuitem.set_attribute_value ("accel", new Variant ("s", TerminalWidget.ACCELS_COPY_OUTPUT[0])); + + var clear_screen_menuitem = new MenuItem ( + _("Clear Screen"), + ACTION_CLEAR_SCREEN + ); + clear_screen_menuitem.set_attribute_value ("accel", new Variant ("s", TerminalWidget.ACCELS_CLEAR_SCREEN[0])); + + var reset_menuitem = new MenuItem ( + _("Reset"), + ACTION_RESET + ); + reset_menuitem.set_attribute_value ("accel", new Variant ("s", TerminalWidget.ACCELS_RESET[0])); + + var paste_menuitem = new MenuItem ( + _("Paste"), + ACTION_PASTE + ); + paste_menuitem.set_attribute_value ("accel", new Variant ("s", TerminalWidget.ACCELS_PASTE[0])); + + var select_all_menuitem = new MenuItem ( + _("Select All"), + ACTION_SELECT_ALL + ); + select_all_menuitem.set_attribute_value ("accel", new Variant ("s", TerminalWidget.ACCELS_SELECT_ALL[0])); + + var terminal_action_section = new Menu (); + terminal_action_section.append_item (copy_menuitem); + terminal_action_section.append_item (copy_last_output_menuitem); + terminal_action_section.append_item (paste_menuitem); + terminal_action_section.append_item (select_all_menuitem); + + var terminal_clear_reset_section = new Menu (); + terminal_clear_reset_section.append_item (clear_screen_menuitem); + terminal_clear_reset_section.append_item (reset_menuitem); + + var context_menu_model = new Menu (); + context_menu_model.append_item (open_in_browser_menuitem); + context_menu_model.append_section (null, terminal_action_section); + context_menu_model.append_section (null, terminal_clear_reset_section); + + return context_menu_model; + } + + private void popup_context_menu (double x, double y) { + var context_menu_model = construct_context_menu_model (); - //NOTE For some reason using the built in context_menu and context_menu_model of vte-2.91-gtk4 + // NOTE For some reason using the built in context_menu and context_menu_model of vte-2.91-gtk4 // does not work at the moment so create our own. var new_context_menu = new Gtk.PopoverMenu.from_model (context_menu_model) { has_arrow = false,