diff options
author | Debarshi Ray <debarshir@gnome.org> | 2018-03-27 19:58:14 +0200 |
---|---|---|
committer | Christian Persch <chpe@src.gnome.org> | 2018-03-27 19:58:14 +0200 |
commit | a5f5c26a8dbe788a67789b176112893a23b07cb3 (patch) | |
tree | 6f8cd12d3c3a091442422a0e5d5243a9f3e39247 | |
parent | 073a5600c11025660893a6558ae7db7bc9ecf874 (diff) | |
download | vte-wip/command-notify.tar.gz |
emulation: Add sequences and signals for desktop notificationwip/command-notify
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
-rw-r--r-- | src/app/app.cc | 14 | ||||
-rw-r--r-- | src/marshal.list | 1 | ||||
-rw-r--r-- | src/vte.cc | 17 | ||||
-rw-r--r-- | src/vte.sh | 4 | ||||
-rw-r--r-- | src/vte/vteterminal.h | 4 | ||||
-rw-r--r-- | src/vtegtk.cc | 23 | ||||
-rw-r--r-- | src/vtegtk.hh | 1 | ||||
-rw-r--r-- | src/vteinternal.hh | 6 | ||||
-rw-r--r-- | src/vteseq.cc | 33 |
9 files changed, 100 insertions, 3 deletions
diff --git a/src/app/app.cc b/src/app/app.cc index 82f38ff0..5f70a6ea 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 1e4d0c1b..3385b475 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 @@ -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) { @@ -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 d468f669..6be1c2c5 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 ab472fb4..219a7e6f 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 c49754ef..126d2932 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 1fcfea5e..bd025268 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 cec74fa6..b7a66e30 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; } |