[vte/wip/rishi/container-escape-sequence: 1/2] Support tracking the active container inside the terminal, if any



commit bf70e2b8aaa5356d0f68f3c281bfc925fd773121
Author: Debarshi Ray <debarshir gnome org>
Date:   Mon Jun 10 20:30:18 2019 +0200

    Support tracking the active container inside the terminal, if any
    
    https://gitlab.freedesktop.org/terminal-wg/specifications/issues/17

 src/vte.cc            |  20 +++++++++
 src/vte/vteterminal.h |   9 ++++-
 src/vtegtk.cc         | 109 ++++++++++++++++++++++++++++++++++++++++++++++++++
 src/vtegtk.hh         |   4 ++
 src/vteinternal.hh    |  20 +++++++++
 src/vteseq.cc         |  45 ++++++++++++++++++++-
 6 files changed, 205 insertions(+), 2 deletions(-)
---
diff --git a/src/vte.cc b/src/vte.cc
index ee1c673f..886dc0a7 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -10156,6 +10156,26 @@ Terminal::emit_pending_signals()
                 m_window_title_changed = false;
        }
 
+        if (m_containers_popped) {
+                _vte_debug_print(VTE_DEBUG_SIGNALS,
+                                 "Emitting `current-container-popped'.\n");
+
+                g_signal_emit(object, signals[SIGNAL_CURRENT_CONTAINER_POPPED], 0);
+                g_object_notify_by_pspec(object, pspecs[PROP_CURRENT_CONTAINER_NAME]);
+                g_object_notify_by_pspec(object, pspecs[PROP_CURRENT_CONTAINER_RUNTIME]);
+                m_containers_popped = false;
+        }
+
+        if (m_containers_pushed) {
+                _vte_debug_print(VTE_DEBUG_SIGNALS,
+                                 "Emitting `current-container-pushed'.\n");
+
+                g_signal_emit(object, signals[SIGNAL_CURRENT_CONTAINER_PUSHED], 0);
+                g_object_notify_by_pspec(object, pspecs[PROP_CURRENT_CONTAINER_NAME]);
+                g_object_notify_by_pspec(object, pspecs[PROP_CURRENT_CONTAINER_RUNTIME]);
+                m_containers_pushed = false;
+        }
+
        if (m_current_directory_uri_changed) {
                 if (m_current_directory_uri != m_current_directory_uri_pending) {
                         m_current_directory_uri.swap(m_current_directory_uri_pending);
diff --git a/src/vte/vteterminal.h b/src/vte/vteterminal.h
index db82d9e4..87a6ffd4 100644
--- a/src/vte/vteterminal.h
+++ b/src/vte/vteterminal.h
@@ -104,8 +104,11 @@ struct _VteTerminalClass {
 
        void (*bell)(VteTerminal* terminal);
 
+       void (*current_container_popped)(VteTerminal *terminal);
+       void (*current_container_pushed)(VteTerminal *terminal);
+
         /* Padding for future expansion. */
-        gpointer padding[16];
+        gpointer padding[14];
 
         VteTerminalClassPrivate *priv;
 };
@@ -446,6 +449,10 @@ glong vte_terminal_get_column_count(VteTerminal *terminal) _VTE_GNUC_NONNULL(1);
 _VTE_PUBLIC
 const char *vte_terminal_get_window_title(VteTerminal *terminal) _VTE_GNUC_NONNULL(1);
 _VTE_PUBLIC
+const char *vte_terminal_get_current_container_name(VteTerminal *terminal) _VTE_GNUC_NONNULL(1);
+_VTE_PUBLIC
+const char *vte_terminal_get_current_container_runtime(VteTerminal *terminal) _VTE_GNUC_NONNULL(1);
+_VTE_PUBLIC
 const char *vte_terminal_get_current_directory_uri(VteTerminal *terminal) _VTE_GNUC_NONNULL(1);
 _VTE_PUBLIC
 const char *vte_terminal_get_current_file_uri(VteTerminal *terminal) _VTE_GNUC_NONNULL(1);
diff --git a/src/vtegtk.cc b/src/vtegtk.cc
index aab8e20d..884b2c0e 100644
--- a/src/vtegtk.cc
+++ b/src/vtegtk.cc
@@ -478,6 +478,12 @@ vte_terminal_get_property (GObject *object,
                 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;
@@ -846,6 +852,50 @@ vte_terminal_class_init(VteTerminalClass *klass)
                                    G_OBJECT_CLASS_TYPE(klass),
                                    g_cclosure_marshal_VOID__VOIDv);
 
+        /**
+         * VteTerminal::current-container-popped:
+         * @vteterminal: the object which received the signal
+         *
+         * Emitted when leaving the current container being used
+         * inside the terminal. There must have been a matching
+         * #VteTerminal::current-container-pushed signal when this
+         * container was entered.
+         */
+        signals[SIGNAL_CURRENT_CONTAINER_POPPED] =
+                g_signal_new(I_("current-container-popped"),
+                             G_OBJECT_CLASS_TYPE(klass),
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET(VteTerminalClass, current_container_popped),
+                             NULL,
+                             NULL,
+                             g_cclosure_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
+        g_signal_set_va_marshaller(signals[SIGNAL_CURRENT_CONTAINER_POPPED],
+                                   G_OBJECT_CLASS_TYPE(klass),
+                                   g_cclosure_marshal_VOID__VOIDv);
+
+        /**
+         * VteTerminal::current-container-pushed:
+         * @vteterminal: the object which received the signal
+         *
+         * Emitted when spawning a child process inside a new
+         * container. There should be a matching
+         * #VteTerminal::current-container-popped signal when this
+         * process exits.
+         */
+        signals[SIGNAL_CURRENT_CONTAINER_PUSHED] =
+                g_signal_new(I_("current-container-pushed"),
+                             G_OBJECT_CLASS_TYPE(klass),
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET(VteTerminalClass, current_container_pushed),
+                             NULL,
+                             NULL,
+                             g_cclosure_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
+        g_signal_set_va_marshaller(signals[SIGNAL_CURRENT_CONTAINER_PUSHED],
+                                   G_OBJECT_CLASS_TYPE(klass),
+                                   g_cclosure_marshal_VOID__VOIDv);
+
         /**
          * VteTerminal::current-directory-uri-changed:
          * @vteterminal: the object which received the signal
@@ -1698,6 +1748,27 @@ vte_terminal_class_init(VteTerminalClass *klass)
                                      NULL,
                                      (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:
          *
@@ -3573,6 +3644,44 @@ vte_terminal_get_column_count(VteTerminal *terminal)
        return IMPL(terminal)->m_column_count;
 }
 
+/**
+ * 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)
+{
+        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();
+}
+
+/**
+ * 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)
+{
+        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();
+}
+
 /**
  * vte_terminal_get_current_directory_uri:
  * @terminal: a #VteTerminal
diff --git a/src/vtegtk.hh b/src/vtegtk.hh
index c49754ef..f31c07b9 100644
--- a/src/vtegtk.hh
+++ b/src/vtegtk.hh
@@ -32,6 +32,8 @@ enum {
         SIGNAL_COMMIT,
         SIGNAL_CONTENTS_CHANGED,
         SIGNAL_COPY_CLIPBOARD,
+        SIGNAL_CURRENT_CONTAINER_POPPED,
+        SIGNAL_CURRENT_CONTAINER_PUSHED,
         SIGNAL_CURRENT_DIRECTORY_URI_CHANGED,
         SIGNAL_CURRENT_FILE_URI_CHANGED,
         SIGNAL_CURSOR_MOVED,
@@ -73,6 +75,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 f321105e..40f74939 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -40,6 +40,7 @@
 
 #include <list>
 #include <queue>
+#include <stack>
 #include <string>
 #include <vector>
 
@@ -109,6 +110,18 @@ typedef enum _VteCharacterReplacement {
         VTE_CHARACTER_REPLACEMENT_BRITISH
 } 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;
@@ -555,6 +568,10 @@ public:
         gboolean m_cursor_moved_pending;
         gboolean m_contents_changed_pending;
 
+        bool m_containers_popped{false};
+        bool m_containers_pushed{false};
+        std::stack<VteContainer> m_containers;
+
         std::string m_window_title{};
         std::string m_current_directory_uri{};
         std::string m_current_file_uri{};
@@ -1286,6 +1303,9 @@ public:
                              int osc) noexcept;
 
         /* OSC handlers */
+        void handle_urxvt_extension(vte::parser::Sequence const& seq,
+                                    vte::parser::StringTokeniser::const_iterator& token,
+                                    vte::parser::StringTokeniser::const_iterator const& endtoken) noexcept;
         void set_color(vte::parser::Sequence const& seq,
                        vte::parser::StringTokeniser::const_iterator& token,
                        vte::parser::StringTokeniser::const_iterator const& endtoken,
diff --git a/src/vteseq.cc b/src/vteseq.cc
index d596d8b9..fe9170f2 100644
--- a/src/vteseq.cc
+++ b/src/vteseq.cc
@@ -1334,6 +1334,46 @@ Terminal::delete_lines(vte::grid::row_t param)
         m_text_deleted_flag = TRUE;
 }
 
+void
+Terminal::handle_urxvt_extension(vte::parser::Sequence const& seq,
+                                 vte::parser::StringTokeniser::const_iterator& token,
+                                 vte::parser::StringTokeniser::const_iterator const& endtoken) noexcept
+{
+        if (token == endtoken)
+                return;
+
+        if (*token == "container") {
+                ++token;
+
+                if (token == endtoken)
+                        return;
+
+                const std::string sub_command = *token;
+                ++token;
+
+                if (sub_command == "pop") {
+                        if (!m_containers.empty()) {
+                                m_containers.pop();
+                                m_containers_popped = true;
+                        }
+                } else if (sub_command == "push") {
+                        if (token == endtoken)
+                                return;
+
+                        const std::string name = *token;
+                        ++token;
+
+                        if (token == endtoken)
+                                return;
+
+                        const std::string runtime = *token;
+
+                        m_containers.emplace(name, runtime);
+                        m_containers_pushed = true;
+                }
+        }
+}
+
 bool
 Terminal::get_osc_color_index(int osc,
                                         int value,
@@ -6411,6 +6451,10 @@ Terminal::OSC(vte::parser::Sequence const& seq)
                 reset_color(VTE_HIGHLIGHT_FG, VTE_COLOR_SOURCE_ESCAPE);
                 break;
 
+        case VTE_OSC_URXVT_EXTENSION:
+                handle_urxvt_extension(seq, it, cend);
+                break;
+
         case VTE_OSC_XTERM_SET_ICON_TITLE:
         case VTE_OSC_XTERM_SET_XPROPERTY:
         case VTE_OSC_XTERM_SET_COLOR_MOUSE_CURSOR_FG:
@@ -6451,7 +6495,6 @@ Terminal::OSC(vte::parser::Sequence const& seq)
         case VTE_OSC_URXVT_SET_FONT_BOLD_ITALIC:
         case VTE_OSC_URXVT_VIEW_UP:
         case VTE_OSC_URXVT_VIEW_DOWN:
-        case VTE_OSC_URXVT_EXTENSION:
         case VTE_OSC_YF_RQGWR:
         default:
                 break;


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]