[vte/wip/command-notify] emulation: Add sequences and signals for desktop notification



commit a5f5c26a8dbe788a67789b176112893a23b07cb3
Author: Debarshi Ray <debarshir gnome org>
Date:   Tue Mar 27 19:58:14 2018 +0200

    emulation: Add sequences and signals for desktop notification
    
    Add sequence handler for "OSC 777 ; notify", 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/app/app.cc        |   14 ++++++++++++++
 src/marshal.list      |    1 +
 src/vte.cc            |   17 +++++++++++++++++
 src/vte.sh            |    4 +++-
 src/vte/vteterminal.h |    4 +++-
 src/vtegtk.cc         |   23 +++++++++++++++++++++++
 src/vtegtk.hh         |    1 +
 src/vteinternal.hh    |    6 ++++++
 src/vteseq.cc         |   33 ++++++++++++++++++++++++++++++++-
 9 files changed, 100 insertions(+), 3 deletions(-)
---
diff --git a/src/app/app.cc b/src/app/app.cc
index 82f38ff..5f70a6e 100644
--- a/src/app/app.cc
+++ b/src/app/app.cc
@@ -55,6 +55,7 @@ public:
         gboolean no_rewrap{false};
         gboolean no_shell{false};
         gboolean object_notifications{false};
+        gboolean osc_notifications{false};
         gboolean reverse{false};
         gboolean test_mode{false};
         gboolean use_gregex{false};
@@ -395,6 +396,8 @@ public:
                           "Disable rewrapping on resize", nullptr },
                         { "no-shell", 'S', 0, G_OPTION_ARG_NONE, &no_shell,
                           "Disable spawning a shell inside the terminal", nullptr },
+                        { "notifications", 0, 0, G_OPTION_ARG_NONE, &osc_notifications,
+                          "Print OSC 777 notifications received", nullptr },
                         { "object-notifications", 'N', 0, G_OPTION_ARG_NONE, &object_notifications,
                           "Print VteTerminal object notifications", nullptr },
                         { "output-file", 0, 0, G_OPTION_ARG_FILENAME, &output_filename,
@@ -1589,6 +1592,15 @@ window_window_title_changed_cb(VteTerminal* terminal,
 }
 
 static void
+window_notification_received_cb(VteTerminal* terminal,
+                                char const* summary,
+                                char const* body,
+                                VteappWindow* window)
+{
+        g_print("Notification summary=\"%s\" body=\"%s\"\n", summary, body);
+}
+
+static void
 window_lower_window_cb(VteTerminal* terminal,
                        VteappWindow* window)
 {
@@ -1814,6 +1826,8 @@ vteapp_window_constructed(GObject *object)
         g_signal_connect(window->terminal, "window-title-changed", 
G_CALLBACK(window_window_title_changed_cb), window);
         if (options.object_notifications)
                 g_signal_connect(window->terminal, "notify", G_CALLBACK(window_notify_cb), window);
+        if (options.osc_notifications)
+                g_signal_connect(window->terminal, "notification-received", 
G_CALLBACK(window_notification_received_cb), window);
 
         /* Settings */
         if (options.no_double_buffer)
diff --git a/src/marshal.list b/src/marshal.list
index 1e4d0c1..3385b47 100644
--- a/src/marshal.list
+++ b/src/marshal.list
@@ -1,5 +1,6 @@
 VOID:INT,INT
 VOID:OBJECT,OBJECT
 VOID:STRING,BOXED
+VOID:STRING,STRING
 VOID:STRING,UINT
 VOID:UINT,UINT
diff --git a/src/vte.cc b/src/vte.cc
index 605f3c6..76268b4 100644
--- a/src/vte.cc
+++ b/src/vte.cc
@@ -10542,6 +10542,11 @@ VteTerminalPrivate::reset(bool clear_tabstops,
                 m_window_title_stack.clear();
         }
 
+        /* Notification */
+        m_notification_summary.clear();
+        m_notification_body.clear();
+        m_notification_pending = false;
+
         update_mouse_protocol();
 
        /* Reset the color palette. Only the 256 indexed colors, not the special ones, as per xterm. */
@@ -10872,6 +10877,18 @@ VteTerminalPrivate::emit_pending_signals()
                 m_current_file_uri_changed = false;
         }
 
+       if (m_notification_pending) {
+                _vte_debug_print (VTE_DEBUG_SIGNALS,
+                                  "Emitting `notification-received'.\n");
+                g_signal_emit(object, signals[SIGNAL_NOTIFICATION_RECEIVED], 0,
+                              m_notification_summary.data(),
+                              m_notification_body.data());
+
+                m_notification_summary.clear();
+                m_notification_body.clear();
+                m_notification_pending = false;
+       }
+
        /* Flush any pending "inserted" signals. */
 
         if (m_cursor_moved_pending) {
diff --git a/src/vte.sh b/src/vte.sh
index 5fb1699..44c2539 100644
--- a/src/vte.sh
+++ b/src/vte.sh
@@ -50,9 +50,11 @@ __vte_osc7 () {
 }
 
 __vte_prompt_command() {
+  local command=$(HISTTIMEFORMAT= history 1 | sed 's/^ *[0-9]\+ *//')
+  command="${command//;/ }"
   local pwd='~'
   [ "$PWD" != "$HOME" ] && pwd=${PWD/#$HOME\//\~\/}
-  printf "\u009D0;%s@%s:%s\u009C%s" "${USER}" "${HOSTNAME%%.*}" "${pwd}" "$(__vte_osc7)"
+  printf "\u009D777;notify;%s\u009C\u009D0;%s@%s:%s\u009C%s" "${command}" "${USER}" "${HOSTNAME%%.*}" 
"${pwd}" "$(__vte_osc7)"
 }
 
 case "$TERM" in
diff --git a/src/vte/vteterminal.h b/src/vte/vteterminal.h
index d468f66..6be1c2c 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 ab472fb..219a7e6 100644
--- a/src/vtegtk.cc
+++ b/src/vtegtk.cc
@@ -709,6 +709,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;
@@ -785,6 +786,28 @@ vte_terminal_class_init(VteTerminalClass *klass)
                              1, G_TYPE_INT);
 
         /**
+         * 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),
+                             nullptr,
+                             nullptr,
+                             _vte_marshal_VOID__STRING_STRING,
+                             G_TYPE_NONE,
+                             2,
+                             G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE,
+                             G_TYPE_STRING | G_SIGNAL_TYPE_STATIC_SCOPE);
+
+        /**
          * VteTerminal::window-title-changed:
          * @vteterminal: the object which received the signal
          *
diff --git a/src/vtegtk.hh b/src/vtegtk.hh
index c49754e..126d293 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 1fcfea5..bd02526 100644
--- a/src/vteinternal.hh
+++ b/src/vteinternal.hh
@@ -566,9 +566,12 @@ public:
         std::string m_window_title_pending{};
         std::string m_current_directory_uri_pending{};
         std::string m_current_file_uri_pending{};
+        std::string m_notification_summary{};
+        std::string m_notification_body{};
         bool m_window_title_changed{false};
         bool m_current_directory_uri_changed{false};
         bool m_current_file_uri_changed{false};
+        bool m_notification_pending;
 
         std::vector<std::string> m_window_title_stack{};
 
@@ -1331,6 +1334,9 @@ public:
         void set_current_hyperlink(vte::parser::Sequence const& seq,
                                    vte::parser::StringTokeniser::const_iterator& token,
                                    vte::parser::StringTokeniser::const_iterator const& endtoken) noexcept;
+        void set_notification(vte::parser::Sequence const& seq,
+                              vte::parser::StringTokeniser::const_iterator& token,
+                              vte::parser::StringTokeniser::const_iterator const& endtoken) noexcept;
 
         /* Sequence handlers */
         bool m_line_wrapped; // signals line wrapped from character insertion
diff --git a/src/vteseq.cc b/src/vteseq.cc
index cec74fa..b7a66e3 100644
--- a/src/vteseq.cc
+++ b/src/vteseq.cc
@@ -1602,6 +1602,32 @@ VteTerminalPrivate::set_current_hyperlink(vte::parser::Sequence const& seq,
         m_defaults.attr.hyperlink_idx = idx;
 }
 
+void
+VteTerminalPrivate::set_notification(vte::parser::Sequence const& seq,
+                                     vte::parser::StringTokeniser::const_iterator& token,
+                                     vte::parser::StringTokeniser::const_iterator const& endtoken) noexcept
+{
+        if (token == endtoken || *token != "notify")
+                return;
+
+        if (++token == endtoken) {
+                m_notification_summary.clear();
+                m_notification_body.clear();
+                m_notification_pending = false;
+                return;
+        }
+
+        std::string summary = *token;
+        std::string body;
+
+        if (++token != endtoken && !summary.empty())
+                body = token.string_remaining();
+
+        m_notification_summary.swap(summary);
+        m_notification_body.swap(body);
+        m_notification_pending = !m_notification_summary.empty();
+}
+
 /*
  * Command Handlers
  * This is the unofficial documentation of all the VTE_CMD_* definitions.
@@ -6341,6 +6367,10 @@ VteTerminalPrivate::OSC(vte::parser::Sequence const& seq)
                 reset_color(VTE_HIGHLIGHT_FG, VTE_COLOR_SOURCE_ESCAPE);
                 break;
 
+        case VTE_OSC_URXVT_EXTENSION:
+                set_notification(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:
@@ -6381,8 +6411,9 @@ VteTerminalPrivate::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:
+                break;
+
         default:
                 break;
         }


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