Blob Blame History Raw
From 100b3f8acecf8c68201d6bbb7fc05e9475d8d401 Mon Sep 17 00:00:00 2001
From: Debarshi Ray <debarshir@gnome.org>
Date: Wed, 7 Jan 2015 16:01:00 +0100
Subject: [PATCH 01/12] Add sequences and signals for desktop notification

Add sequences
  OSC 777 ; notify ; SUMMARY ; BODY BEL
  OSC 777 ; notify ; SUMMARY BEL
  OSC 777 ; notify ; SUMMARY ; BODY ST
  OSC 777 ; notify ; SUMMARY ST

that let terminal applications send a notification to the desktop
environment.

Based on Enlightenment's Terminology:
https://phab.enlightenment.org/T1765

https://bugzilla.gnome.org/show_bug.cgi?id=711059
---
 src/marshal.list      |  1 +
 src/vte.cc            |  9 +++++++++
 src/vte/vteterminal.h |  4 +++-
 src/vtegtk.cc         | 21 +++++++++++++++++++++
 src/vtegtk.hh         |  1 +
 src/vteinternal.hh    |  8 ++++++++
 src/vteseq.cc         | 32 +++++++++++++++++++++++++++++++-
 7 files changed, 74 insertions(+), 2 deletions(-)

diff --git a/src/marshal.list b/src/marshal.list
index 241128c3ccfe..4412cf3d5f5c 100644
--- a/src/marshal.list
+++ b/src/marshal.list
@@ -1,3 +1,4 @@
 VOID:STRING,BOXED
+VOID:STRING,STRING
 VOID:STRING,UINT
 VOID:UINT,UINT
diff --git a/src/vte.cc b/src/vte.cc
index cba606e853a4..ae49a07d7376 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -10239,6 +10239,15 @@ Terminal::emit_pending_signals()
 
 	emit_adjustment_changed();
 
+        if (m_notification_received) {
+                _vte_debug_print (VTE_DEBUG_SIGNALS,
+                                  "Emitting `notification-received'.\n");
+                g_signal_emit(object, signals[SIGNAL_NOTIFICATION_RECEIVED], 0,
+                              m_notification_summary.c_str(),
+                              m_notification_body.c_str());
+                m_notification_received = false;
+        }
+
 	if (m_window_title_changed) {
                 if (m_window_title != m_window_title_pending) {
                         m_window_title.swap(m_window_title_pending);
diff --git a/src/vte/vteterminal.h b/src/vte/vteterminal.h
index 31012518362e..6ad0987d22ca 100644
--- a/src/vte/vteterminal.h
+++ b/src/vte/vteterminal.h
@@ -104,8 +104,10 @@ struct _VteTerminalClass {
 
 	void (*bell)(VteTerminal* terminal);
 
+	void (*notification_received)(VteTerminal* terminal, const gchar *summary, const gchar *body);
+
         /* Padding for future expansion. */
-        gpointer padding[16];
+        gpointer padding[15];
 
         VteTerminalClassPrivate *priv;
 };
diff --git a/src/vtegtk.cc b/src/vtegtk.cc
index 5808a210d3d4..005423567073 100644
--- a/src/vtegtk.cc
+++ b/src/vtegtk.cc
@@ -738,6 +738,7 @@ vte_terminal_class_init(VteTerminalClass *klass)
 	klass->child_exited = NULL;
 	klass->encoding_changed = NULL;
 	klass->char_size_changed = NULL;
+	klass->notification_received = NULL;
 	klass->window_title_changed = NULL;
 	klass->icon_title_changed = NULL;
 	klass->selection_changed = NULL;
@@ -819,6 +820,26 @@ vte_terminal_class_init(VteTerminalClass *klass)
                                    G_OBJECT_CLASS_TYPE(klass),
                                    g_cclosure_marshal_VOID__INTv);
 
+        /**
+         * VteTerminal::notification-received:
+         * @vteterminal: the object which received the signal
+         * @summary: The summary
+         * @body: (allow-none): Extra optional text
+         *
+         * Emitted when a process running in the terminal wants to
+         * send a notification to the desktop environment.
+         */
+        signals[SIGNAL_NOTIFICATION_RECEIVED] =
+                g_signal_new(I_("notification-received"),
+                             G_OBJECT_CLASS_TYPE(klass),
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET(VteTerminalClass, notification_received),
+                             NULL,
+                             NULL,
+                             _vte_marshal_VOID__STRING_STRING,
+                             G_TYPE_NONE,
+                             2, G_TYPE_STRING, G_TYPE_STRING);
+
         /**
          * VteTerminal::window-title-changed:
          * @vteterminal: the object which received the signal
diff --git a/src/vtegtk.hh b/src/vtegtk.hh
index ae9fb08c310a..baf681e45b2c 100644
--- a/src/vtegtk.hh
+++ b/src/vtegtk.hh
@@ -56,6 +56,7 @@ enum {
         SIGNAL_TEXT_INSERTED,
         SIGNAL_TEXT_MODIFIED,
         SIGNAL_TEXT_SCROLLED,
+        SIGNAL_NOTIFICATION_RECEIVED,
         SIGNAL_WINDOW_TITLE_CHANGED,
         LAST_SIGNAL
 };
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index 93e905270c29..ae4f705ea80d 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -709,6 +709,11 @@ public:
         gboolean m_cursor_moved_pending;
         gboolean m_contents_changed_pending;
 
+        /* desktop notification */
+        bool m_notification_received{false};
+        std::string m_notification_summary;
+        std::string m_notification_body;
+
         std::string m_window_title{};
         std::string m_current_directory_uri{};
         std::string m_current_file_uri{};
@@ -1426,6 +1431,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 2d00ceec5509..2b69ca2c14f0 100644
--- a/src/vteseq.cc
+++ b/src/vteseq.cc
@@ -1377,6 +1377,33 @@ 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 == "notify") {
+                ++token;
+
+                if (token == endtoken)
+                        return;
+
+                m_notification_summary = *token;
+                m_notification_body.clear();
+                m_notification_received = true;
+                ++token;
+
+                if (token == endtoken)
+                        return;
+
+                m_notification_body = *token;
+                return;
+        }
+}
+
 bool
 Terminal::get_osc_color_index(int osc,
                                         int value,
@@ -6464,6 +6491,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:
@@ -6504,7 +6535,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;
-- 
2.24.1


From 2a509fab63f42995d4b0f77bac4a9d79e508880e Mon Sep 17 00:00:00 2001
From: Debarshi Ray <debarshir@gnome.org>
Date: Thu, 29 Jan 2015 13:09:17 +0100
Subject: [PATCH 02/12] vte.sh: Emit OSC 777 from PROMPT_COMMAND

For some reason, the three consecutive backslashes break the parsing.
As Christian Persch suggested, replacing the double quotes with
singles fixes it.

https://bugzilla.gnome.org/show_bug.cgi?id=711059
---
 src/vte.sh.in | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/vte.sh.in b/src/vte.sh.in
index 8b3153da0f1a..d6769de82766 100644
--- a/src/vte.sh.in
+++ b/src/vte.sh.in
@@ -27,10 +27,12 @@ __vte_osc7 () {
 }
 
 __vte_prompt_command() {
+  local command=$(HISTTIMEFORMAT= history 1 | sed 's/^ *[0-9]\+ *//')
+  command="${command//;/ }"
   local pwd='~'
   [ "$PWD" != "$HOME" ] && pwd=${PWD/#$HOME\//\~\/}
   pwd="${pwd//[[:cntrl:]]}"
-  printf "\033]0;%s@%s:%s\033\\" "${USER}" "${HOSTNAME%%.*}" "${pwd}"
+  printf '\033]777;notify;Command completed;%s\033\\\033]0;%s@%s:%s\033\\' "${command}" "${USER}" "${HOSTNAME%%.*}" "${pwd}"
   __vte_osc7
 }
 
-- 
2.24.1


From 268e1f1f5e71822b9e43ae4bfeea43710de32152 Mon Sep 17 00:00:00 2001
From: Debarshi Ray <debarshir@gnome.org>
Date: Thu, 22 Jan 2015 16:37:10 +0100
Subject: [PATCH 03/12] Test the notification-received signal

---
 bindings/vala/app.vala |  7 +++++++
 src/app/app.cc         | 10 ++++++++++
 2 files changed, 17 insertions(+)

diff --git a/bindings/vala/app.vala b/bindings/vala/app.vala
index fc26c2b0dfc3..634b8ddeeb91 100644
--- a/bindings/vala/app.vala
+++ b/bindings/vala/app.vala
@@ -309,6 +309,8 @@ class Window : Gtk.ApplicationWindow
     if (Options.object_notifications)
       terminal.notify.connect(notify_cb);
 
+    terminal.notification_received.connect(notification_received_cb);
+
     /* Settings */
     if (Options.no_double_buffer)
       terminal.set_double_buffered(false);
@@ -780,6 +782,11 @@ class Window : Gtk.ApplicationWindow
     set_title(terminal.get_window_title());
   }
 
+  private void notification_received_cb(Vte.Terminal terminal, string summary, string? body)
+  {
+    print ("[%s]: %s\n", summary, body);
+  }
+
 } /* class Window */
 
 class App : Gtk.Application
diff --git a/src/app/app.cc b/src/app/app.cc
index 0c7eed5d18f1..6086c0a65db2 100644
--- a/src/app/app.cc
+++ b/src/app/app.cc
@@ -1639,6 +1639,14 @@ window_window_title_changed_cb(VteTerminal* terminal,
                              vte_terminal_get_window_title(window->terminal));
 }
 
+static void
+notification_received_cb(VteTerminal *terminal,
+                         const gchar *summary,
+                         const gchar *body)
+{
+        g_print("[%s]: %s\n", summary, body);
+}
+
 static void
 window_lower_window_cb(VteTerminal* terminal,
                        VteappWindow* window)
@@ -1871,6 +1879,8 @@ vteapp_window_constructed(GObject *object)
         if (options.object_notifications)
                 g_signal_connect(window->terminal, "notify", G_CALLBACK(window_notify_cb), window);
 
+        g_signal_connect(window->terminal, "notification-received", G_CALLBACK(notification_received_cb), NULL);
+
         /* Settings */
         if (options.no_double_buffer) {
                 G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
-- 
2.24.1


From 4756e38cc2678467d08245c192fd86b3b01049da Mon Sep 17 00:00:00 2001
From: Debarshi Ray <debarshir@gnome.org>
Date: Fri, 13 May 2016 17:53:54 +0200
Subject: [PATCH 04/12] Add a property to configure the scroll speed

By default, it is set to zero which gives the current behaviour of
moving the buffer by a function of the number of visible rows.

https://bugzilla.redhat.com/show_bug.cgi?id=1103380
---
 doc/reference/vte-sections.txt |  1 +
 src/vte.cc                     | 19 +++++++++++++-
 src/vte/vteterminal.h          |  4 +++
 src/vtegtk.cc                  | 45 ++++++++++++++++++++++++++++++++++
 src/vtegtk.hh                  |  1 +
 src/vteinternal.hh             |  2 ++
 6 files changed, 71 insertions(+), 1 deletion(-)

diff --git a/doc/reference/vte-sections.txt b/doc/reference/vte-sections.txt
index 20067c88bae3..2cc8d70ca4f9 100644
--- a/doc/reference/vte-sections.txt
+++ b/doc/reference/vte-sections.txt
@@ -52,6 +52,7 @@ vte_terminal_get_cursor_blink_mode
 vte_terminal_set_cursor_blink_mode
 vte_terminal_get_text_blink_mode
 vte_terminal_set_text_blink_mode
+vte_terminal_set_scroll_speed
 vte_terminal_set_scrollback_lines
 vte_terminal_get_scrollback_lines
 vte_terminal_set_font
diff --git a/src/vte.cc b/src/vte.cc
index ae49a07d7376..8fad2b477950 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -9443,6 +9443,7 @@ void
 Terminal::widget_scroll(GdkEventScroll *event)
 {
 	gdouble delta_x, delta_y;
+	gdouble scroll_speed;
 	gdouble v;
 	gint cnt, i;
 	int button;
@@ -9499,7 +9500,13 @@ Terminal::widget_scroll(GdkEventScroll *event)
 		return;
 	}
 
-        v = MAX (1., ceil (gtk_adjustment_get_page_increment (m_vadjustment.get()) / 10.));
+	if (m_scroll_speed == 0) {
+		scroll_speed = ceil (gtk_adjustment_get_page_increment (m_vadjustment.get()) / 10.);
+	} else {
+		scroll_speed = m_scroll_speed;
+	}
+
+	v = MAX (1., scroll_speed);
 	_vte_debug_print(VTE_DEBUG_EVENTS,
 			"Scroll speed is %d lines per non-smooth scroll unit\n",
 			(int) v);
@@ -9796,6 +9803,16 @@ Terminal::decscusr_cursor_shape() const noexcept
         }
 }
 
+bool
+Terminal::set_scroll_speed(unsigned int scroll_speed)
+{
+        if (scroll_speed == m_scroll_speed)
+                return false;
+
+        m_scroll_speed = scroll_speed;
+        return true;
+}
+
 bool
 Terminal::set_scrollback_lines(long lines)
 {
diff --git a/src/vte/vteterminal.h b/src/vte/vteterminal.h
index 6ad0987d22ca..94febee1d494 100644
--- a/src/vte/vteterminal.h
+++ b/src/vte/vteterminal.h
@@ -287,6 +287,10 @@ void vte_terminal_set_cursor_shape(VteTerminal *terminal,
 _VTE_PUBLIC
 VteCursorShape vte_terminal_get_cursor_shape(VteTerminal *terminal) _VTE_GNUC_NONNULL(1);
 
+_VTE_PUBLIC
+void vte_terminal_set_scroll_speed(VteTerminal *terminal,
+                                   guint scroll_speed) _VTE_GNUC_NONNULL(1);
+
 /* Set the number of scrollback lines, above or at an internal minimum. */
 _VTE_PUBLIC
 void vte_terminal_set_scrollback_lines(VteTerminal *terminal,
diff --git a/src/vtegtk.cc b/src/vtegtk.cc
index 005423567073..ecd004a814e7 100644
--- a/src/vtegtk.cc
+++ b/src/vtegtk.cc
@@ -528,6 +528,9 @@ vte_terminal_get_property (GObject *object,
                 case PROP_REWRAP_ON_RESIZE:
                         g_value_set_boolean (value, vte_terminal_get_rewrap_on_resize (terminal));
                         break;
+                case PROP_SCROLL_SPEED:
+                        g_value_set_uint (value, impl->m_scroll_speed);
+                        break;
                 case PROP_SCROLLBACK_LINES:
                         g_value_set_uint (value, vte_terminal_get_scrollback_lines(terminal));
                         break;
@@ -635,6 +638,9 @@ vte_terminal_set_property (GObject *object,
                 case PROP_REWRAP_ON_RESIZE:
                         vte_terminal_set_rewrap_on_resize (terminal, g_value_get_boolean (value));
                         break;
+                case PROP_SCROLL_SPEED:
+                        vte_terminal_set_scroll_speed (terminal, g_value_get_uint (value));
+                        break;
                 case PROP_SCROLLBACK_LINES:
                         vte_terminal_set_scrollback_lines (terminal, g_value_get_uint (value));
                         break;
@@ -1708,6 +1714,21 @@ vte_terminal_class_init(VteTerminalClass *klass)
                                       TRUE,
                                       (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY));
 
+        /**
+         * VteTerminal:scroll-speed:
+         *
+         * The number of lines by which the buffer is moved when
+         * scrolling with a mouse wheel on top of the terminal
+         * Setting it to zero will cause the buffer to be moved by an
+         * amount depending on the number of visible rows the widget
+         * can display.
+         */
+        pspecs[PROP_SCROLL_SPEED] =
+                g_param_spec_uint ("scroll-speed", NULL, NULL,
+                                   0, G_MAXUINT,
+                                   0,
+                                   (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_EXPLICIT_NOTIFY));
+
         /**
          * VteTerminal:scrollback-lines:
          *
@@ -4434,6 +4455,30 @@ vte_terminal_get_row_count(VteTerminal *terminal)
 	return IMPL(terminal)->m_row_count;
 }
 
+/**
+ * vte_terminal_set_scroll_speed:
+ * @terminal: a #VteTerminal
+ * @scroll_speed: move the buffer by this number of lines while scrolling
+ *
+ * Sets the number of lines by which the buffer is moved when
+ * scrolling with a mouse wheel. Setting it to zero will cause the
+ * buffer to be moved by an amount depending on the number of visible
+ * rows the widget can display.
+ */
+void
+vte_terminal_set_scroll_speed(VteTerminal *terminal, guint scroll_speed)
+{
+        g_return_if_fail(VTE_IS_TERMINAL(terminal));
+
+        GObject *object = G_OBJECT(terminal);
+        g_object_freeze_notify(object);
+
+        if (IMPL(terminal)->set_scroll_speed(scroll_speed))
+                g_object_notify_by_pspec(object, pspecs[PROP_SCROLL_SPEED]);
+
+        g_object_thaw_notify(object);
+}
+
 /**
  * vte_terminal_set_scrollback_lines:
  * @terminal: a #VteTerminal
diff --git a/src/vtegtk.hh b/src/vtegtk.hh
index baf681e45b2c..a9c256635948 100644
--- a/src/vtegtk.hh
+++ b/src/vtegtk.hh
@@ -88,6 +88,7 @@ enum {
         PROP_MOUSE_POINTER_AUTOHIDE,
         PROP_PTY,
         PROP_REWRAP_ON_RESIZE,
+        PROP_SCROLL_SPEED,
         PROP_SCROLLBACK_LINES,
         PROP_SCROLL_ON_KEYSTROKE,
         PROP_SCROLL_ON_OUTPUT,
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index ae4f705ea80d..9c0b8b454468 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -487,6 +487,7 @@ public:
 	/* Scrolling options. */
         bool m_scroll_on_output{false};
         bool m_scroll_on_keystroke{true};
+        guint m_scroll_speed;
         vte::grid::row_t m_scrollback_lines{0};
 
         /* Restricted scrolling */
@@ -1304,6 +1305,7 @@ public:
         bool set_input_enabled(bool enabled);
         bool set_mouse_autohide(bool autohide);
         bool set_rewrap_on_resize(bool rewrap);
+        bool set_scroll_speed(unsigned int scroll_speed);
         bool set_scrollback_lines(long lines);
         bool set_scroll_on_keystroke(bool scroll);
         bool set_scroll_on_output(bool scroll);
-- 
2.24.1


From 4a319241ad18071b85acea28f929b332d00e24da Mon Sep 17 00:00:00 2001
From: Debarshi Ray <debarshir@gnome.org>
Date: Fri, 13 May 2016 17:54:57 +0200
Subject: [PATCH 05/12] Test the scroll-speed property

https://bugzilla.redhat.com/show_bug.cgi?id=1103380
---
 bindings/vala/app.vala | 4 ++++
 src/app/app.cc         | 4 ++++
 2 files changed, 8 insertions(+)

diff --git a/bindings/vala/app.vala b/bindings/vala/app.vala
index 634b8ddeeb91..c984b868246d 100644
--- a/bindings/vala/app.vala
+++ b/bindings/vala/app.vala
@@ -335,6 +335,7 @@ class Window : Gtk.ApplicationWindow
     terminal.set_rewrap_on_resize(!Options.no_rewrap);
     terminal.set_scroll_on_output(false);
     terminal.set_scroll_on_keystroke(true);
+    terminal.set_scroll_speed(Options.scroll_speed);
     terminal.set_scrollback_lines(Options.scrollback_lines);
 
     /* Style */
@@ -857,6 +858,7 @@ class App : Gtk.Application
     public static bool object_notifications = false;
     public static string? output_filename = null;
     public static bool reverse = false;
+    public static uint scroll_speed = 0;
     public static int scrollback_lines = 512;
     public static int transparency_percent = 0;
     public static bool version = false;
@@ -1050,6 +1052,8 @@ class App : Gtk.Application
         "Save terminal contents to file at exit", null },
       { "reverse", 0, 0, OptionArg.NONE, ref reverse,
         "Reverse foreground/background colors", null },
+      { "scroll-speed", 0, 0, OptionArg.INT, ref scroll_speed,
+        "Specify the scroll speed", null },
       { "scrollback-lines", 'n', 0, OptionArg.INT, ref scrollback_lines,
         "Specify the number of scrollback-lines", null },
       { "transparent", 'T', 0, OptionArg.INT, ref transparency_percent,
diff --git a/src/app/app.cc b/src/app/app.cc
index 6086c0a65db2..0c7a70bf6da5 100644
--- a/src/app/app.cc
+++ b/src/app/app.cc
@@ -98,6 +98,7 @@ public:
         int verbosity{0};
         double cell_height_scale{1.0};
         double cell_width_scale{1.0};
+        unsigned int scroll_speed{0};
         VteCursorBlinkMode cursor_blink_mode{VTE_CURSOR_BLINK_SYSTEM};
         VteCursorShape cursor_shape{VTE_CURSOR_SHAPE_BLOCK};
         VteTextBlinkMode text_blink_mode{VTE_TEXT_BLINK_ALWAYS};
@@ -418,6 +419,8 @@ public:
                           "Reverse foreground/background colors", nullptr },
                         { "require-systemd-scope", 0, 0, G_OPTION_ARG_NONE, &require_systemd_scope,
                           "Require use of a systemd user scope", nullptr },
+                        { "scroll-speed", 0, 0, G_OPTION_ARG_INT, &scroll_speed,
+                          "Specify the scroll speed", nullptr },
                         { "scrollback-lines", 'n', 0, G_OPTION_ARG_INT, &scrollback_lines,
                           "Specify the number of scrollback-lines (-1 for infinite)", nullptr },
                         { "transparent", 'T', 0, G_OPTION_ARG_INT, &transparency_percent,
@@ -1912,6 +1915,7 @@ vteapp_window_constructed(GObject *object)
         vte_terminal_set_rewrap_on_resize(window->terminal, !options.no_rewrap);
         vte_terminal_set_scroll_on_output(window->terminal, false);
         vte_terminal_set_scroll_on_keystroke(window->terminal, true);
+        vte_terminal_set_scroll_speed(window->terminal, options.scroll_speed);
         vte_terminal_set_scrollback_lines(window->terminal, options.scrollback_lines);
         vte_terminal_set_text_blink_mode(window->terminal, options.text_blink_mode);
 
-- 
2.24.1


From 1df88d4cb8ebdbcac0ad55c43ed17e91b7396ea6 Mon Sep 17 00:00:00 2001
From: Debarshi Ray <debarshir@gnome.org>
Date: Wed, 7 Jan 2015 16:01:00 +0100
Subject: [PATCH 06/12] Support preexec notifications from an interactive shell

Add sequences
  OSC 777 ; preexec BEL
  OSC 777 ; preexec ST

that can be used from an interactive shell's preexec hook to notify
the terminal emulator that a new command is about to be executed.
Examples of such hooks are Bash's PS0 and Zsh's preexec.

The OSC 777 escape sequence is taken from Enlightenment's Terminology:
https://phab.enlightenment.org/T1765

https://bugzilla.gnome.org/show_bug.cgi?id=711059
https://bugzilla.gnome.org/show_bug.cgi?id=711060
---
 src/vte.cc            |  7 +++++++
 src/vte.sh.in         |  2 +-
 src/vte/vteterminal.h |  3 ++-
 src/vtegtk.cc         | 18 ++++++++++++++++++
 src/vtegtk.hh         |  1 +
 src/vteinternal.hh    |  2 ++
 src/vteseq.cc         |  4 ++++
 7 files changed, 35 insertions(+), 2 deletions(-)

diff --git a/src/vte.cc b/src/vte.cc
index 8fad2b477950..b103f3cee0ce 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -10265,6 +10265,13 @@ Terminal::emit_pending_signals()
                 m_notification_received = false;
         }
 
+        if (m_shell_preexec) {
+                _vte_debug_print (VTE_DEBUG_SIGNALS,
+                                  "Emitting `shell-preexec'.\n");
+                g_signal_emit(object, signals[SIGNAL_SHELL_PREEXEC], 0);
+                m_shell_preexec = FALSE;
+        }
+
 	if (m_window_title_changed) {
                 if (m_window_title != m_window_title_pending) {
                         m_window_title.swap(m_window_title_pending);
diff --git a/src/vte.sh.in b/src/vte.sh.in
index d6769de82766..c7a3b07f9ea4 100644
--- a/src/vte.sh.in
+++ b/src/vte.sh.in
@@ -38,7 +38,7 @@ __vte_prompt_command() {
 
 case "$TERM" in
   xterm*|vte*)
-    [ -n "$BASH_VERSION" ] && PROMPT_COMMAND="__vte_prompt_command"
+    [ -n "$BASH_VERSION" ] && PROMPT_COMMAND="__vte_prompt_command" && PS0=$(printf "\033]777;preexec\033\\")
     [ -n "$ZSH_VERSION"  ] && precmd_functions+=(__vte_osc7)
     ;;
 esac
diff --git a/src/vte/vteterminal.h b/src/vte/vteterminal.h
index 94febee1d494..2d757afbdcc0 100644
--- a/src/vte/vteterminal.h
+++ b/src/vte/vteterminal.h
@@ -105,9 +105,10 @@ struct _VteTerminalClass {
 	void (*bell)(VteTerminal* terminal);
 
 	void (*notification_received)(VteTerminal* terminal, const gchar *summary, const gchar *body);
+	void (*shell_preexec)(VteTerminal* terminal);
 
         /* Padding for future expansion. */
-        gpointer padding[15];
+        gpointer padding[14];
 
         VteTerminalClassPrivate *priv;
 };
diff --git a/src/vtegtk.cc b/src/vtegtk.cc
index ecd004a814e7..1b3e2690164f 100644
--- a/src/vtegtk.cc
+++ b/src/vtegtk.cc
@@ -745,6 +745,7 @@ vte_terminal_class_init(VteTerminalClass *klass)
 	klass->encoding_changed = NULL;
 	klass->char_size_changed = NULL;
 	klass->notification_received = NULL;
+	klass->shell_preexec = NULL;
 	klass->window_title_changed = NULL;
 	klass->icon_title_changed = NULL;
 	klass->selection_changed = NULL;
@@ -846,6 +847,23 @@ vte_terminal_class_init(VteTerminalClass *klass)
                              G_TYPE_NONE,
                              2, G_TYPE_STRING, G_TYPE_STRING);
 
+        /**
+         * VteTerminal::shell-preexec:
+         * @vteterminal: the object which received the signal
+         *
+         * Emitted when the interactive shell has read in a complete
+         * command and is about to execute it.
+         */
+        signals[SIGNAL_SHELL_PREEXEC] =
+                g_signal_new(I_("shell-preexec"),
+                             G_OBJECT_CLASS_TYPE(klass),
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET(VteTerminalClass, shell_preexec),
+                             NULL,
+                             NULL,
+                             g_cclosure_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
+
         /**
          * VteTerminal::window-title-changed:
          * @vteterminal: the object which received the signal
diff --git a/src/vtegtk.hh b/src/vtegtk.hh
index a9c256635948..79c528ea8243 100644
--- a/src/vtegtk.hh
+++ b/src/vtegtk.hh
@@ -52,6 +52,7 @@ enum {
         SIGNAL_RESIZE_WINDOW,
         SIGNAL_RESTORE_WINDOW,
         SIGNAL_SELECTION_CHANGED,
+        SIGNAL_SHELL_PREEXEC,
         SIGNAL_TEXT_DELETED,
         SIGNAL_TEXT_INSERTED,
         SIGNAL_TEXT_MODIFIED,
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index 9c0b8b454468..dd98905860f4 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -715,6 +715,8 @@ public:
         std::string m_notification_summary;
         std::string m_notification_body;
 
+        gboolean m_shell_preexec;
+
         std::string m_window_title{};
         std::string m_current_directory_uri{};
         std::string m_current_file_uri{};
diff --git a/src/vteseq.cc b/src/vteseq.cc
index 2b69ca2c14f0..d8866cbeb225 100644
--- a/src/vteseq.cc
+++ b/src/vteseq.cc
@@ -1402,6 +1402,10 @@ Terminal::handle_urxvt_extension(vte::parser::Sequence const& seq,
                 m_notification_body = *token;
                 return;
         }
+
+        if (*token == "preexec") {
+                m_shell_preexec = TRUE;
+        }
 }
 
 bool
-- 
2.24.1


From f2581b1532eebc4bcfc2337eb367abfd5599dd0c Mon Sep 17 00:00:00 2001
From: Debarshi Ray <debarshir@gnome.org>
Date: Fri, 20 Apr 2018 18:21:53 +0200
Subject: [PATCH 07/12] Test the shell-preexec signal

https://bugzilla.gnome.org/show_bug.cgi?id=711059
https://bugzilla.gnome.org/show_bug.cgi?id=711060
---
 bindings/vala/app.vala | 6 ++++++
 src/app/app.cc         | 7 +++++++
 2 files changed, 13 insertions(+)

diff --git a/bindings/vala/app.vala b/bindings/vala/app.vala
index c984b868246d..83af686be106 100644
--- a/bindings/vala/app.vala
+++ b/bindings/vala/app.vala
@@ -310,6 +310,7 @@ class Window : Gtk.ApplicationWindow
       terminal.notify.connect(notify_cb);
 
     terminal.notification_received.connect(notification_received_cb);
+    terminal.shell_preexec.connect(shell_preexec_cb);
 
     /* Settings */
     if (Options.no_double_buffer)
@@ -788,6 +789,11 @@ class Window : Gtk.ApplicationWindow
     print ("[%s]: %s\n", summary, body);
   }
 
+  private void shell_preexec_cb(Vte.Terminal terminal)
+  {
+    print("[shell] executing command\n");
+  }
+
 } /* class Window */
 
 class App : Gtk.Application
diff --git a/src/app/app.cc b/src/app/app.cc
index 0c7a70bf6da5..2dece3ddb724 100644
--- a/src/app/app.cc
+++ b/src/app/app.cc
@@ -1650,6 +1650,12 @@ notification_received_cb(VteTerminal *terminal,
         g_print("[%s]: %s\n", summary, body);
 }
 
+static void
+shell_preexec_cb(VteTerminal *terminal)
+{
+        g_print("[shell] executing command\n");
+}
+
 static void
 window_lower_window_cb(VteTerminal* terminal,
                        VteappWindow* window)
@@ -1883,6 +1889,7 @@ vteapp_window_constructed(GObject *object)
                 g_signal_connect(window->terminal, "notify", G_CALLBACK(window_notify_cb), window);
 
         g_signal_connect(window->terminal, "notification-received", G_CALLBACK(notification_received_cb), NULL);
+        g_signal_connect(window->terminal, "shell-preexec", G_CALLBACK(shell_preexec_cb), NULL);
 
         /* Settings */
         if (options.no_double_buffer) {
-- 
2.24.1


From cee3f876af49aa199955e557001a57b317f93634 Mon Sep 17 00:00:00 2001
From: Debarshi Ray <debarshir@gnome.org>
Date: Wed, 2 May 2018 17:20:30 +0200
Subject: [PATCH 08/12] Support precmd notifications from an interactive shell

Add sequences
  OSC 777 ; precmd BEL
  OSC 777 ; precmd ST

that can be used from an interactive shell's precmd hook to notify the
terminal emulator that a first level prompt is about to be shown.
Examples of such hooks are Bash's PROMPT_COMMAND and Zsh's precmd.

The OSC 777 escape sequence is taken from Enlightenment's Terminology:
https://phab.enlightenment.org/T1765

https://bugzilla.gnome.org/show_bug.cgi?id=711059
https://bugzilla.gnome.org/show_bug.cgi?id=711060
---
 src/vte.cc            |  7 +++++++
 src/vte.sh.in         |  2 +-
 src/vte/vteterminal.h |  3 ++-
 src/vtegtk.cc         | 18 ++++++++++++++++++
 src/vtegtk.hh         |  1 +
 src/vteinternal.hh    |  1 +
 src/vteseq.cc         |  4 +++-
 7 files changed, 33 insertions(+), 3 deletions(-)

diff --git a/src/vte.cc b/src/vte.cc
index b103f3cee0ce..1bda2bfbca39 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -10272,6 +10272,13 @@ Terminal::emit_pending_signals()
                 m_shell_preexec = FALSE;
         }
 
+        if (m_shell_precmd) {
+                _vte_debug_print (VTE_DEBUG_SIGNALS,
+                                  "Emitting `shell-precmd'.\n");
+                g_signal_emit(object, signals[SIGNAL_SHELL_PRECMD], 0);
+                m_shell_precmd = FALSE;
+        }
+
 	if (m_window_title_changed) {
                 if (m_window_title != m_window_title_pending) {
                         m_window_title.swap(m_window_title_pending);
diff --git a/src/vte.sh.in b/src/vte.sh.in
index c7a3b07f9ea4..4cff7dd1fb71 100644
--- a/src/vte.sh.in
+++ b/src/vte.sh.in
@@ -32,7 +32,7 @@ __vte_prompt_command() {
   local pwd='~'
   [ "$PWD" != "$HOME" ] && pwd=${PWD/#$HOME\//\~\/}
   pwd="${pwd//[[:cntrl:]]}"
-  printf '\033]777;notify;Command completed;%s\033\\\033]0;%s@%s:%s\033\\' "${command}" "${USER}" "${HOSTNAME%%.*}" "${pwd}"
+  printf '\033]777;notify;Command completed;%s\033\\\033]777;precmd\033\\\033]0;%s@%s:%s\033\\' "${command}" "${USER}" "${HOSTNAME%%.*}" "${pwd}"
   __vte_osc7
 }
 
diff --git a/src/vte/vteterminal.h b/src/vte/vteterminal.h
index 2d757afbdcc0..a75ae7ee2640 100644
--- a/src/vte/vteterminal.h
+++ b/src/vte/vteterminal.h
@@ -105,10 +105,11 @@ struct _VteTerminalClass {
 	void (*bell)(VteTerminal* terminal);
 
 	void (*notification_received)(VteTerminal* terminal, const gchar *summary, const gchar *body);
+	void (*shell_precmd)(VteTerminal* terminal);
 	void (*shell_preexec)(VteTerminal* terminal);
 
         /* Padding for future expansion. */
-        gpointer padding[14];
+        gpointer padding[13];
 
         VteTerminalClassPrivate *priv;
 };
diff --git a/src/vtegtk.cc b/src/vtegtk.cc
index 1b3e2690164f..0d61f90cda76 100644
--- a/src/vtegtk.cc
+++ b/src/vtegtk.cc
@@ -745,6 +745,7 @@ vte_terminal_class_init(VteTerminalClass *klass)
 	klass->encoding_changed = NULL;
 	klass->char_size_changed = NULL;
 	klass->notification_received = NULL;
+	klass->shell_precmd = NULL;
 	klass->shell_preexec = NULL;
 	klass->window_title_changed = NULL;
 	klass->icon_title_changed = NULL;
@@ -847,6 +848,23 @@ vte_terminal_class_init(VteTerminalClass *klass)
                              G_TYPE_NONE,
                              2, G_TYPE_STRING, G_TYPE_STRING);
 
+        /**
+         * VteTerminal::shell-precmd:
+         * @vteterminal: the object which received the signal
+         *
+         * Emitted right before an interactive shell shows a
+         * first-level prompt.
+         */
+        signals[SIGNAL_SHELL_PRECMD] =
+                g_signal_new(I_("shell-precmd"),
+                             G_OBJECT_CLASS_TYPE(klass),
+                             G_SIGNAL_RUN_LAST,
+                             G_STRUCT_OFFSET(VteTerminalClass, shell_precmd),
+                             NULL,
+                             NULL,
+                             g_cclosure_marshal_VOID__VOID,
+                             G_TYPE_NONE, 0);
+
         /**
          * VteTerminal::shell-preexec:
          * @vteterminal: the object which received the signal
diff --git a/src/vtegtk.hh b/src/vtegtk.hh
index 79c528ea8243..534298ada75c 100644
--- a/src/vtegtk.hh
+++ b/src/vtegtk.hh
@@ -52,6 +52,7 @@ enum {
         SIGNAL_RESIZE_WINDOW,
         SIGNAL_RESTORE_WINDOW,
         SIGNAL_SELECTION_CHANGED,
+        SIGNAL_SHELL_PRECMD,
         SIGNAL_SHELL_PREEXEC,
         SIGNAL_TEXT_DELETED,
         SIGNAL_TEXT_INSERTED,
diff --git a/src/vteinternal.hh b/src/vteinternal.hh
index dd98905860f4..6b1feb377df7 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -715,6 +715,7 @@ public:
         std::string m_notification_summary;
         std::string m_notification_body;
 
+        gboolean m_shell_precmd;
         gboolean m_shell_preexec;
 
         std::string m_window_title{};
diff --git a/src/vteseq.cc b/src/vteseq.cc
index d8866cbeb225..f6669f853204 100644
--- a/src/vteseq.cc
+++ b/src/vteseq.cc
@@ -1403,7 +1403,9 @@ Terminal::handle_urxvt_extension(vte::parser::Sequence const& seq,
                 return;
         }
 
-        if (*token == "preexec") {
+        if (*token == "precmd") {
+                m_shell_precmd = TRUE;
+        } else if (*token == "preexec") {
                 m_shell_preexec = TRUE;
         }
 }
-- 
2.24.1


From 827f0406565cad98f835909451a854c7f8f3ead1 Mon Sep 17 00:00:00 2001
From: Debarshi Ray <debarshir@gnome.org>
Date: Wed, 2 May 2018 17:30:48 +0200
Subject: [PATCH 09/12] Test the shell-precmd signal

https://bugzilla.gnome.org/show_bug.cgi?id=711059
https://bugzilla.gnome.org/show_bug.cgi?id=711060
---
 bindings/vala/app.vala | 6 ++++++
 src/app/app.cc         | 7 +++++++
 2 files changed, 13 insertions(+)

diff --git a/bindings/vala/app.vala b/bindings/vala/app.vala
index 83af686be106..300384f5c74b 100644
--- a/bindings/vala/app.vala
+++ b/bindings/vala/app.vala
@@ -310,6 +310,7 @@ class Window : Gtk.ApplicationWindow
       terminal.notify.connect(notify_cb);
 
     terminal.notification_received.connect(notification_received_cb);
+    terminal.shell_precmd.connect(shell_precmd_cb);
     terminal.shell_preexec.connect(shell_preexec_cb);
 
     /* Settings */
@@ -789,6 +790,11 @@ class Window : Gtk.ApplicationWindow
     print ("[%s]: %s\n", summary, body);
   }
 
+  private void shell_precmd_cb(Vte.Terminal terminal)
+  {
+    print("[shell] showing command prompt\n");
+  }
+
   private void shell_preexec_cb(Vte.Terminal terminal)
   {
     print("[shell] executing command\n");
diff --git a/src/app/app.cc b/src/app/app.cc
index 2dece3ddb724..960aadc3cdc8 100644
--- a/src/app/app.cc
+++ b/src/app/app.cc
@@ -1650,6 +1650,12 @@ notification_received_cb(VteTerminal *terminal,
         g_print("[%s]: %s\n", summary, body);
 }
 
+static void
+shell_precmd_cb(VteTerminal *terminal)
+{
+        g_print("[shell] showing command prompt\n");
+}
+
 static void
 shell_preexec_cb(VteTerminal *terminal)
 {
@@ -1889,6 +1895,7 @@ vteapp_window_constructed(GObject *object)
                 g_signal_connect(window->terminal, "notify", G_CALLBACK(window_notify_cb), window);
 
         g_signal_connect(window->terminal, "notification-received", G_CALLBACK(notification_received_cb), NULL);
+        g_signal_connect(window->terminal, "shell-precmd", G_CALLBACK(shell_precmd_cb), NULL);
         g_signal_connect(window->terminal, "shell-preexec", G_CALLBACK(shell_preexec_cb), NULL);
 
         /* Settings */
-- 
2.24.1


From 55c7d02eaad2bc37bc18c46152825fb2959f2db0 Mon Sep 17 00:00:00 2001
From: Debarshi Ray <debarshir@gnome.org>
Date: Mon, 10 Jun 2019 20:30:18 +0200
Subject: [PATCH 10/12] Support tracking the active container inside the
 terminal

Add sequences
  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 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
---
 src/vte.cc            |  9 ++++++
 src/vte/vteterminal.h |  4 +++
 src/vtegtk.cc         | 65 +++++++++++++++++++++++++++++++++++++++++++
 src/vtegtk.hh         |  2 ++
 src/vteinternal.hh    | 16 +++++++++++
 src/vteseq.cc         | 31 +++++++++++++++++++++
 6 files changed, 127 insertions(+)

diff --git a/src/vte.cc b/src/vte.cc
index 1bda2bfbca39..aeca73d55934 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -10293,6 +10293,15 @@ Terminal::emit_pending_signals()
                 m_window_title_changed = false;
 	}
 
+        if (m_containers_changed) {
+                _vte_debug_print(VTE_DEBUG_SIGNALS,
+                                 "Notifying `current-container-name' and `current-container-runtime'.\n");
+
+                g_object_notify_by_pspec(object, pspecs[PROP_CURRENT_CONTAINER_NAME]);
+                g_object_notify_by_pspec(object, pspecs[PROP_CURRENT_CONTAINER_RUNTIME]);
+                m_containers_changed = 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 a75ae7ee2640..53de9c737000 100644
--- a/src/vte/vteterminal.h
+++ b/src/vte/vteterminal.h
@@ -458,6 +458,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 0d61f90cda76..15a7f1ab1ce0 100644
--- a/src/vtegtk.cc
+++ b/src/vtegtk.cc
@@ -483,6 +483,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;
@@ -1827,6 +1833,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:
          *
@@ -3811,6 +3838,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 534298ada75c..66d2f1425fad 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 6b1feb377df7..2329d7fd4c13 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -61,6 +61,7 @@
 #include <list>
 #include <queue>
 #include <optional>
+#include <stack>
 #include <string>
 #include <variant>
 #include <vector>
@@ -98,6 +99,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;
@@ -710,6 +723,9 @@ public:
         gboolean m_cursor_moved_pending;
         gboolean m_contents_changed_pending;
 
+        bool m_containers_changed{false};
+        std::stack<VteContainer> m_containers;
+
         /* desktop notification */
         bool m_notification_received{false};
         std::string m_notification_summary;
diff --git a/src/vteseq.cc b/src/vteseq.cc
index f6669f853204..2b9dd9df820a 100644
--- a/src/vteseq.cc
+++ b/src/vteseq.cc
@@ -1385,6 +1385,37 @@ 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 (!m_containers.empty()) {
+                                m_containers.pop();
+                                m_containers_changed = 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_changed = true;
+                }
+        }
+
         if (*token == "notify") {
                 ++token;
 
-- 
2.24.1


From e2c44d1e7cf544f26dddfe7ea21452eb53800b83 Mon Sep 17 00:00:00 2001
From: Jakub Steiner <jimmac@gmail.com>
Date: Thu, 2 Apr 2020 18:20:44 +0200
Subject: [PATCH 11/12] widget: Improve legibility when using colours from the
 system theme

https://gitlab.gnome.org/GNOME/vte/-/issues/225
---
 src/vtegtk.cc | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/vtegtk.cc b/src/vtegtk.cc
index 15a7f1ab1ce0..5999272c0648 100644
--- a/src/vtegtk.cc
+++ b/src/vtegtk.cc
@@ -1922,7 +1922,7 @@ vte_terminal_class_init(VteTerminalClass *klass)
                                          "VteTerminal, " VTE_TERMINAL_CSS_NAME " {\n"
                                          "padding: 1px 1px 1px 1px;\n"
                                          "background-color: @theme_base_color;\n"
-                                         "color: @theme_fg_color;\n"
+                                         "color: @theme_text_color;\n"
                                          "}\n",
                                          -1, NULL);
 
-- 
2.24.1


From 68d735ef2649df34f4a283d70555a88f04231ecc Mon Sep 17 00:00:00 2001
From: Jakub Steiner <jimmac@gmail.com>
Date: Tue, 31 Mar 2020 20:55:23 +0200
Subject: [PATCH 12/12] widget: Improve legibility by tweaking the system
 theme's base colour

Some changes by Debarshi Ray.

https://gitlab.gnome.org/GNOME/vte/-/issues/226
---
 src/vtegtk.cc | 67 ++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 58 insertions(+), 9 deletions(-)

diff --git a/src/vtegtk.cc b/src/vtegtk.cc
index 5999272c0648..a54c85b42e9d 100644
--- a/src/vtegtk.cc
+++ b/src/vtegtk.cc
@@ -73,7 +73,8 @@
 #define VTE_TERMINAL_CSS_NAME "vte-terminal"
 
 struct _VteTerminalClassPrivate {
-        GtkStyleProvider *style_provider;
+        GtkStyleProvider *style_provider_dark;
+        GtkStyleProvider *style_provider_light;
 };
 
 #ifdef VTE_DEBUG
@@ -127,6 +128,41 @@ valid_color(GdkRGBA const* color)
                color->alpha >= 0. && color->alpha <= 1.;
 }
 
+static void
+vte_terminal_theme_update (VteTerminal *terminal)
+{
+        GtkSettings *settings;
+        GtkStyleContext *context;
+        gboolean application_prefer_dark_theme;
+
+        settings = gtk_settings_get_default ();
+        g_object_get (settings, "gtk-application-prefer-dark-theme", &application_prefer_dark_theme, nullptr);
+
+        context = gtk_widget_get_style_context (&terminal->widget);
+
+        if (application_prefer_dark_theme) {
+                gtk_style_context_remove_provider (context,
+                                                   VTE_TERMINAL_GET_CLASS (terminal)->priv->style_provider_light);
+
+                gtk_style_context_add_provider (context,
+                                                VTE_TERMINAL_GET_CLASS (terminal)->priv->style_provider_dark,
+                                                GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+        } else {
+                gtk_style_context_remove_provider (context,
+                                                   VTE_TERMINAL_GET_CLASS (terminal)->priv->style_provider_dark);
+
+                gtk_style_context_add_provider (context,
+                                                VTE_TERMINAL_GET_CLASS (terminal)->priv->style_provider_light,
+                                                GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+        }
+}
+
+static void
+vte_terminal_theme_changed (VteTerminal *terminal)
+{
+        vte_terminal_theme_update (terminal);
+}
+
 static void
 vte_terminal_set_hadjustment(VteTerminal *terminal,
                              GtkAdjustment *adjustment)
@@ -392,14 +428,18 @@ static void
 vte_terminal_init(VteTerminal *terminal)
 {
         void *place;
-	GtkStyleContext *context;
+        GtkSettings *settings;
 
 	_vte_debug_print(VTE_DEBUG_LIFECYCLE, "vte_terminal_init()\n");
 
-        context = gtk_widget_get_style_context(&terminal->widget);
-        gtk_style_context_add_provider (context,
-                                        VTE_TERMINAL_GET_CLASS (terminal)->priv->style_provider,
-                                        GTK_STYLE_PROVIDER_PRIORITY_APPLICATION);
+        vte_terminal_theme_update (terminal);
+
+        settings = gtk_settings_get_default ();
+        g_signal_connect_object (settings,
+                                 "notify::gtk-application-prefer-dark-theme",
+                                 G_CALLBACK (vte_terminal_theme_changed),
+                                 terminal,
+                                 G_CONNECT_SWAPPED);
 
 	/* Initialize private data. NOTE: place is zeroed */
 	place = vte_terminal_get_instance_private(terminal);
@@ -1917,11 +1957,20 @@ vte_terminal_class_init(VteTerminalClass *klass)
 
         klass->priv = G_TYPE_CLASS_GET_PRIVATE (klass, VTE_TYPE_TERMINAL, VteTerminalClassPrivate);
 
-        klass->priv->style_provider = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
-        gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (klass->priv->style_provider),
+        klass->priv->style_provider_dark = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
+        gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (klass->priv->style_provider_dark),
+                                         "VteTerminal, " VTE_TERMINAL_CSS_NAME " {\n"
+                                         "padding: 1px 1px 1px 1px;\n"
+                                         "background-color: shade(@theme_base_color, 0.67);\n"
+                                         "color: @theme_text_color;\n"
+                                         "}\n",
+                                         -1, NULL);
+
+        klass->priv->style_provider_light = GTK_STYLE_PROVIDER (gtk_css_provider_new ());
+        gtk_css_provider_load_from_data (GTK_CSS_PROVIDER (klass->priv->style_provider_light),
                                          "VteTerminal, " VTE_TERMINAL_CSS_NAME " {\n"
                                          "padding: 1px 1px 1px 1px;\n"
-                                         "background-color: @theme_base_color;\n"
+                                         "background-color: shade(@theme_base_color, 1.1);\n"
                                          "color: @theme_text_color;\n"
                                          "}\n",
                                          -1, NULL);
-- 
2.24.1