summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDebarshi Ray <debarshir@gnome.org>2021-03-22 19:02:31 +0100
committerChristian Persch <chpe@src.gnome.org>2021-03-22 19:02:31 +0100
commit2928a4fe80f7de085743697add509c17306b0c56 (patch)
tree8ecefad8b35d26294122ea6177ffbf1785c97bac
parentd3f75c5832a1f49254ffbf82f6e8107759727244 (diff)
downloadvte-wip/fedora-0-64.tar.gz
Support tracking the active container inside the terminalwip/fedora-0-64
Add sequences OSC 777 ; container ; push ; NAME ; RUNTIME ; UID BEL OSC 777 ; container ; push ; NAME ; RUNTIME ; UID ST OSC 777 ; container ; pop ; NAME ; RUNTIME ; UID BEL OSC 777 ; container ; pop ; NAME ; RUNTIME ; UID ST OSC 777 ; container ; push ; NAME ; RUNTIME BEL OSC 777 ; container ; push ; NAME ; RUNTIME ST OSC 777 ; container ; pop ; NAME ; RUNTIME BEL OSC 777 ; container ; pop ; NAME ; RUNTIME ST that let container tools notify the terminal emulator when entering and leaving a container environment. The RUNTIME argument namespaces the NAME and identifies the container tooling being used. eg., docker, flatpak, podman, toolbox, etc.. The UID argument is the real UID of the container tools. Only those containers that are used with the same real UID as the VTE process are tracked. The OSC 777 escape sequence is taken from Enlightenment's Terminology: https://phab.enlightenment.org/T1765 It's a VTE-specific extension until a standard escape sequence is agreed upon across multiple different terminal emulators [1]. [1] https://gitlab.freedesktop.org/terminal-wg/specifications/issues/17
-rw-r--r--src/vte.cc8
-rw-r--r--src/vte/vteterminal.h4
-rw-r--r--src/vtegtk.cc77
-rw-r--r--src/vtegtk.hh2
-rw-r--r--src/vteinternal.hh16
-rw-r--r--src/vteseq.cc86
6 files changed, 193 insertions, 0 deletions
diff --git a/src/vte.cc b/src/vte.cc
index 90488beb..b7f48fcd 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -10176,6 +10176,14 @@ Terminal::emit_pending_signals()
g_signal_emit(freezer.get(), signals[SIGNAL_SHELL_PRECMD], 0);
}
+ if (m_pending_changes & vte::to_integral(PendingChanges::CONTAINERS)) {
+ _vte_debug_print(VTE_DEBUG_SIGNALS,
+ "Notifying `current-container-name' and `current-container-runtime'.\n");
+
+ g_object_notify_by_pspec(freezer.get(), pspecs[PROP_CURRENT_CONTAINER_NAME]);
+ g_object_notify_by_pspec(freezer.get(), pspecs[PROP_CURRENT_CONTAINER_RUNTIME]);
+ }
+
m_pending_changes = 0;
/* Flush any pending "inserted" signals. */
diff --git a/src/vte/vteterminal.h b/src/vte/vteterminal.h
index 0b77566a..540fd25a 100644
--- a/src/vte/vteterminal.h
+++ b/src/vte/vteterminal.h
@@ -488,6 +488,10 @@ glong vte_terminal_get_column_count(VteTerminal *terminal) _VTE_CXX_NOEXCEPT _VT
_VTE_PUBLIC
const char *vte_terminal_get_window_title(VteTerminal *terminal) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1);
_VTE_PUBLIC
+const char *vte_terminal_get_current_container_name(VteTerminal *terminal) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1);
+_VTE_PUBLIC
+const char *vte_terminal_get_current_container_runtime(VteTerminal *terminal) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1);
+_VTE_PUBLIC
const char *vte_terminal_get_current_directory_uri(VteTerminal *terminal) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1);
_VTE_PUBLIC
const char *vte_terminal_get_current_file_uri(VteTerminal *terminal) _VTE_CXX_NOEXCEPT _VTE_GNUC_NONNULL(1);
diff --git a/src/vtegtk.cc b/src/vtegtk.cc
index 4b71437d..1446f3c7 100644
--- a/src/vtegtk.cc
+++ b/src/vtegtk.cc
@@ -707,6 +707,12 @@ try
case PROP_CURSOR_BLINK_MODE:
g_value_set_enum (value, vte_terminal_get_cursor_blink_mode (terminal));
break;
+ case PROP_CURRENT_CONTAINER_NAME:
+ g_value_set_string (value, vte_terminal_get_current_container_name (terminal));
+ break;
+ case PROP_CURRENT_CONTAINER_RUNTIME:
+ g_value_set_string (value, vte_terminal_get_current_container_runtime (terminal));
+ break;
case PROP_CURRENT_DIRECTORY_URI:
g_value_set_string (value, vte_terminal_get_current_directory_uri (terminal));
break;
@@ -2100,6 +2106,27 @@ vte_terminal_class_init(VteTerminalClass *klass)
(GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY));
/**
+ * VteTerminal:current-container-name:
+ *
+ * The name of the current container, or %NULL if unset.
+ */
+ pspecs[PROP_CURRENT_CONTAINER_NAME] =
+ g_param_spec_string ("current-container-name", NULL, NULL,
+ NULL,
+ (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY));
+
+ /**
+ * VteTerminal:current-container-runtime:
+ *
+ * The name of the runtime toolset used to set up the current
+ * container, or %NULL if unset.
+ */
+ pspecs[PROP_CURRENT_CONTAINER_RUNTIME] =
+ g_param_spec_string ("current-container-runtime", NULL, NULL,
+ NULL,
+ (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY));
+
+ /**
* VteTerminal:current-directory-uri:
*
* The current directory URI, or %NULL if unset.
@@ -4575,6 +4602,56 @@ catch (...)
}
/**
+ * vte_terminal_get_current_container_name:
+ * @terminal: a #VteTerminal
+ *
+ * Returns: (nullable) (transfer none): the name of the current
+ * container, or %NULL
+ */
+const char *
+vte_terminal_get_current_container_name(VteTerminal *terminal) noexcept
+try
+{
+ g_return_val_if_fail(VTE_IS_TERMINAL(terminal), NULL);
+ auto impl = IMPL(terminal);
+ if (impl->m_containers.empty())
+ return NULL;
+
+ const VteContainer &container = impl->m_containers.top();
+ return container.m_name.c_str();
+}
+catch (...)
+{
+ vte::log_exception();
+ return NULL;
+}
+
+/**
+ * vte_terminal_get_current_container_runtime:
+ * @terminal: a #VteTerminal
+ *
+ * Returns: (nullable) (transfer none): the name of the runtime
+ * toolset used to set up the current container, or %NULL
+ */
+const char *
+vte_terminal_get_current_container_runtime(VteTerminal *terminal) noexcept
+try
+{
+ g_return_val_if_fail(VTE_IS_TERMINAL(terminal), NULL);
+ auto impl = IMPL(terminal);
+ if (impl->m_containers.empty())
+ return NULL;
+
+ const VteContainer &container = impl->m_containers.top();
+ return container.m_runtime.c_str();
+}
+catch (...)
+{
+ vte::log_exception();
+ return NULL;
+}
+
+/**
* vte_terminal_get_current_directory_uri:
* @terminal: a #VteTerminal
*
diff --git a/src/vtegtk.hh b/src/vtegtk.hh
index 93a6dde3..65196143 100644
--- a/src/vtegtk.hh
+++ b/src/vtegtk.hh
@@ -76,6 +76,8 @@ enum {
PROP_CJK_AMBIGUOUS_WIDTH,
PROP_CURSOR_BLINK_MODE,
PROP_CURSOR_SHAPE,
+ PROP_CURRENT_CONTAINER_NAME,
+ PROP_CURRENT_CONTAINER_RUNTIME,
PROP_CURRENT_DIRECTORY_URI,
PROP_CURRENT_FILE_URI,
PROP_DELETE_BINDING,
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index 25253c0a..570c70b0 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -59,6 +59,7 @@
#include <list>
#include <queue>
#include <optional>
+#include <stack>
#include <string>
#include <variant>
#include <vector>
@@ -97,6 +98,18 @@ typedef enum _VteCharacterReplacement {
VTE_CHARACTER_REPLACEMENT_LINE_DRAWING
} VteCharacterReplacement;
+struct VteContainer {
+public:
+ VteContainer(const std::string &name, const std::string &runtime) :
+ m_name{name},
+ m_runtime{runtime}
+ {
+ }
+
+ std::string m_name;
+ std::string m_runtime;
+};
+
typedef struct _VtePaletteColor {
struct {
vte::color::rgb color;
@@ -622,6 +635,8 @@ public:
gboolean m_cursor_moved_pending;
gboolean m_contents_changed_pending;
+ std::stack<VteContainer> m_containers;
+
/* desktop notification */
std::string m_notification_summary;
std::string m_notification_body;
@@ -642,6 +657,7 @@ public:
NOTIFICATION = 1u << 3,
SHELL_PREEXEC = 1u << 4,
SHELL_PRECMD = 1u << 5,
+ CONTAINERS = 1u << 6,
};
unsigned m_pending_changes{0};
diff --git a/src/vteseq.cc b/src/vteseq.cc
index 10b494bd..2a2ba4b4 100644
--- a/src/vteseq.cc
+++ b/src/vteseq.cc
@@ -19,10 +19,14 @@
#include "config.h"
+#include <string>
+
#include <search.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
+#include <unistd.h>
+#include <sys/types.h>
#ifdef HAVE_SYS_SYSLIMITS_H
#include <sys/syslimits.h>
#endif
@@ -1385,6 +1389,88 @@ Terminal::handle_urxvt_extension(vte::parser::Sequence const& seq,
if (token == endtoken)
return;
+ if (*token == "container") {
+ ++token;
+
+ if (token == endtoken)
+ return;
+
+ const std::string sub_command = *token;
+ ++token;
+
+ if (sub_command == "pop") {
+ if (token == endtoken)
+ return;
+
+ ++token;
+
+ if (token == endtoken)
+ return;
+
+ ++token;
+
+ if (token == endtoken) {
+ if (!m_containers.empty()) {
+ m_containers.pop();
+ m_pending_changes |= vte::to_integral(PendingChanges::CONTAINERS);
+ }
+
+ return;
+ }
+
+ const std::string uid_token = *token;
+ ++token;
+
+ const uid_t uid = getuid();
+ const std::string uid_str = std::to_string(uid);
+
+ if (uid_token == uid_str) {
+ if (!m_containers.empty()) {
+ m_containers.pop();
+ m_pending_changes |= vte::to_integral(PendingChanges::CONTAINERS);
+ }
+
+ return;
+ }
+
+ return;
+ } else if (sub_command == "push") {
+ if (token == endtoken)
+ return;
+
+ const std::string name = *token;
+ ++token;
+
+ if (token == endtoken)
+ return;
+
+ const std::string runtime = *token;
+ ++token;
+
+ if (token == endtoken) {
+ m_containers.emplace(name, runtime);
+ m_pending_changes |= vte::to_integral(PendingChanges::CONTAINERS);
+ return;
+ }
+
+ const std::string uid_token = *token;
+ ++token;
+
+ const uid_t uid = getuid();
+ const std::string uid_str = std::to_string(uid);
+
+ if (uid_token == uid_str) {
+ m_containers.emplace(name, runtime);
+ m_pending_changes |= vte::to_integral(PendingChanges::CONTAINERS);
+ return;
+ }
+
+ return;
+ }
+
+ return;
+ }
+
if (*token == "notify") {
++token;