Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion locale/pt.po
Original file line number Diff line number Diff line change
Expand Up @@ -4755,7 +4755,7 @@ msgstr "Shell Unix/Linux"
# File: src/zashterminal/ui/dialogs/session_edit_dialog.py, line: 734
#: NEEDS WORK
msgid "Network Device CLI"
msgstr "CLI de Equipamento de Rede"
msgstr "Modo CLI"
#
# File: usr/share/zashterminal/ui/dialogs/session_edit_dialog.py, line: 309
#: NEEDS WORK
Expand Down
52 changes: 52 additions & 0 deletions locale/src/zashterminal/terminal/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -496,6 +496,7 @@ def __init__(self, parent_window, settings_manager: SettingsManager):
int, Any
] = {} # Dict[int, HighlightedTerminalProxy]
self._highlight_manager = None
self._selection_copy_timers: Dict[int, int] = {}
# Process check timer runs every 1 second for responsive context detection
self._process_check_timer_id = GLib.timeout_add_seconds(
1, self._periodic_process_check
Expand Down Expand Up @@ -1217,6 +1218,13 @@ def _setup_terminal_events(
)
terminal.zashterminal_handler_ids.append(handler_id)

handler_id = terminal.connect(
"selection-changed",
self._on_terminal_selection_changed,
terminal_id,
)
terminal.zashterminal_handler_ids.append(handler_id)

self.manual_ssh_tracker.track(terminal_id, terminal)

focus_controller = Gtk.EventControllerFocus()
Expand All @@ -1228,6 +1236,7 @@ def _setup_terminal_events(

click_controller = Gtk.GestureClick()
click_controller.set_button(1)
click_controller.set_propagation_phase(Gtk.PropagationPhase.BUBBLE)
click_controller.connect(
"pressed", self._on_terminal_clicked, terminal, terminal_id
)
Expand All @@ -1236,6 +1245,7 @@ def _setup_terminal_events(

right_click_controller = Gtk.GestureClick()
right_click_controller.set_button(3)
right_click_controller.set_propagation_phase(Gtk.PropagationPhase.BUBBLE)
right_click_controller.connect(
"pressed", self._on_terminal_right_clicked, terminal, terminal_id
)
Expand Down Expand Up @@ -1946,6 +1956,8 @@ def _cleanup_terminal(self, terminal: Vte.Terminal, terminal_id: int) -> None:
)
self.osc7_tracker.untrack_terminal(terminal)
self.manual_ssh_tracker.untrack(terminal_id)
if terminal_id in self._selection_copy_timers:
GLib.source_remove(self._selection_copy_timers.pop(terminal_id))

if hasattr(terminal, "zashterminal_handler_ids"):
for handler_id in terminal.zashterminal_handler_ids:
Expand Down Expand Up @@ -2427,8 +2439,48 @@ def get_session_connection_status(self, session_name: str) -> Dict[str, Any]:
}

def copy_selection(self, terminal: Vte.Terminal):
self._copy_terminal_selection_to_clipboard(terminal)

def _on_terminal_selection_changed(
self, terminal: Vte.Terminal, terminal_id: int
) -> None:
if terminal_id in self._selection_copy_timers:
GLib.source_remove(self._selection_copy_timers.pop(terminal_id))
self._selection_copy_timers[terminal_id] = GLib.timeout_add(
80, self._copy_selection_after_change, terminal, terminal_id
)

def _copy_selection_after_change(
self, terminal: Vte.Terminal, terminal_id: int
) -> bool:
self._selection_copy_timers.pop(terminal_id, None)
try:
self._copy_terminal_selection_to_clipboard(terminal)
except Exception as e:
self.logger.debug(
f"Selection auto-copy failed for terminal {terminal_id}: {e}"
)
return GLib.SOURCE_REMOVE

def _copy_terminal_selection_to_clipboard(self, terminal: Vte.Terminal) -> bool:
if terminal.get_has_selection():
terminal.copy_clipboard_format(Vte.Format.TEXT)
return True

if not hasattr(terminal, "get_text_selected"):
return False

selected_text = terminal.get_text_selected(Vte.Format.TEXT)
if not selected_text:
return False

clipboard = (
terminal.get_clipboard()
if hasattr(terminal, "get_clipboard")
else terminal.get_display().get_clipboard()
)
clipboard.set(selected_text)
return True

def paste_clipboard(self, terminal: Vte.Terminal):
terminal.paste_clipboard()
Expand Down
52 changes: 52 additions & 0 deletions src/zashterminal/terminal/manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,7 @@ def __init__(self, parent_window, settings_manager: SettingsManager):
self._balabit_gateway_prompt_shown: set[int] = set()
self._balabit_gateway_prompt_submitted: set[int] = set()
self._balabit_gateway_pending_auth: Dict[int, Dict[str, str]] = {}
self._selection_copy_timers: Dict[int, int] = {}
# Process check timer runs every 1 second for responsive context detection
self._process_check_timer_id = GLib.timeout_add_seconds(
1, self._periodic_process_check
Expand Down Expand Up @@ -1266,6 +1267,13 @@ def _setup_terminal_events(
)
terminal.zashterminal_handler_ids.append(handler_id)

handler_id = terminal.connect(
"selection-changed",
self._on_terminal_selection_changed,
terminal_id,
)
terminal.zashterminal_handler_ids.append(handler_id)

self.manual_ssh_tracker.track(terminal_id, terminal)

focus_controller = Gtk.EventControllerFocus()
Expand All @@ -1277,6 +1285,7 @@ def _setup_terminal_events(

click_controller = Gtk.GestureClick()
click_controller.set_button(1)
click_controller.set_propagation_phase(Gtk.PropagationPhase.BUBBLE)
click_controller.connect(
"pressed", self._on_terminal_clicked, terminal, terminal_id
)
Expand All @@ -1285,6 +1294,7 @@ def _setup_terminal_events(

right_click_controller = Gtk.GestureClick()
right_click_controller.set_button(3)
right_click_controller.set_propagation_phase(Gtk.PropagationPhase.BUBBLE)
right_click_controller.connect(
"pressed", self._on_terminal_right_clicked, terminal, terminal_id
)
Expand Down Expand Up @@ -2503,6 +2513,8 @@ def _cleanup_terminal(self, terminal: Vte.Terminal, terminal_id: int) -> None:
self._balabit_gateway_pending_auth.pop(terminal_id, None)
self._balabit_gateway_prompt_shown.discard(terminal_id)
self._balabit_gateway_prompt_submitted.discard(terminal_id)
if terminal_id in self._selection_copy_timers:
GLib.source_remove(self._selection_copy_timers.pop(terminal_id))

if hasattr(terminal, "zashterminal_handler_ids"):
for handler_id in terminal.zashterminal_handler_ids:
Expand Down Expand Up @@ -3030,8 +3042,48 @@ def get_session_connection_status(self, session_name: str) -> Dict[str, Any]:
}

def copy_selection(self, terminal: Vte.Terminal):
self._copy_terminal_selection_to_clipboard(terminal)

def _on_terminal_selection_changed(
self, terminal: Vte.Terminal, terminal_id: int
) -> None:
if terminal_id in self._selection_copy_timers:
GLib.source_remove(self._selection_copy_timers.pop(terminal_id))
self._selection_copy_timers[terminal_id] = GLib.timeout_add(
80, self._copy_selection_after_change, terminal, terminal_id
)

def _copy_selection_after_change(
self, terminal: Vte.Terminal, terminal_id: int
) -> bool:
self._selection_copy_timers.pop(terminal_id, None)
try:
self._copy_terminal_selection_to_clipboard(terminal)
except Exception as e:
self.logger.debug(
f"Selection auto-copy failed for terminal {terminal_id}: {e}"
)
return GLib.SOURCE_REMOVE

def _copy_terminal_selection_to_clipboard(self, terminal: Vte.Terminal) -> bool:
if terminal.get_has_selection():
terminal.copy_clipboard_format(Vte.Format.TEXT)
return True

if not hasattr(terminal, "get_text_selected"):
return False

selected_text = terminal.get_text_selected(Vte.Format.TEXT)
if not selected_text:
return False

clipboard = (
terminal.get_clipboard()
if hasattr(terminal, "get_clipboard")
else terminal.get_display().get_clipboard()
)
clipboard.set(selected_text)
return True

def paste_clipboard(self, terminal: Vte.Terminal):
terminal.paste_clipboard()
Expand Down