[gnome-terminal/gnome-3-34-ntfy-opn-ttl-ts: 7/16] Notify when a long-running foreground process group terminates



commit b1c4708111e014bed131e96f5956bcf28a384da4
Author: Debarshi Ray <debarshir gnome org>
Date:   Thu May 10 19:23:16 2018 +0200

    Notify when a long-running foreground process group terminates
    
    Notifications are only sent if the VteTerminal in which the process
    was running doesn't have the keyboard focus. If it's a tab in the
    currently active window then the dialog-information-symbolic icon is
    used to highlight the tab's label; otherwise a desktop-wide
    notification is sent.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=711059

 src/terminal-app.c       |  32 +++++++++++++++
 src/terminal-screen.c    | 102 +++++++++++++++++++++++++++++++++++++++++++++++
 src/terminal-tab-label.c |  30 +++++++++++++-
 src/terminal-tab-label.h |   4 ++
 4 files changed, 167 insertions(+), 1 deletion(-)
---
diff --git a/src/terminal-app.c b/src/terminal-app.c
index ab1c81a6..34c53f40 100644
--- a/src/terminal-app.c
+++ b/src/terminal-app.c
@@ -747,6 +747,31 @@ app_menu_quit_cb (GSimpleAction *action,
     gtk_widget_destroy (GTK_WIDGET (window));
 }
 
+/* Other action callbacks */
+
+static void
+action_activate_tab_cb (GSimpleAction *action,
+                        GVariant      *parameter,
+                        gpointer       user_data)
+{
+  GtkApplication *application = user_data;
+  GtkWidget *toplevel;
+  TerminalScreen *screen;
+  const char *uuid;
+
+  g_variant_get (parameter, "&s", &uuid);
+  screen = terminal_app_get_screen_by_uuid (TERMINAL_APP (application), uuid);
+  if (screen == NULL)
+    return;
+
+  toplevel = gtk_widget_get_toplevel (GTK_WIDGET (screen));
+  if (!gtk_widget_is_toplevel (toplevel))
+    return;
+
+  terminal_window_switch_screen (TERMINAL_WINDOW (toplevel), screen);
+  gtk_window_present (GTK_WINDOW (toplevel));
+}
+
 /* Class implementation */
 
 G_DEFINE_TYPE (TerminalApp, terminal_app, GTK_TYPE_APPLICATION)
@@ -770,6 +795,10 @@ terminal_app_startup (GApplication *application)
     { "quit",        app_menu_quit_cb,          NULL, NULL, NULL }
   };
 
+  const GActionEntry other_actions[] = {
+    { "activate-tab",   action_activate_tab_cb, "s",  NULL, NULL }
+  };
+
   g_application_set_resource_base_path (application, TERMINAL_RESOURCES_PATH_PREFIX);
 
   G_APPLICATION_CLASS (terminal_app_parent_class)->startup (application);
@@ -780,6 +809,9 @@ terminal_app_startup (GApplication *application)
   g_action_map_add_action_entries (G_ACTION_MAP (application),
                                    action_entries, G_N_ELEMENTS (action_entries),
                                    application);
+  g_action_map_add_action_entries (G_ACTION_MAP (application),
+                                   other_actions, G_N_ELEMENTS (other_actions),
+                                   application);
 
   app_load_css (application);
 
diff --git a/src/terminal-screen.c b/src/terminal-screen.c
index 1281a676..dacc3823 100644
--- a/src/terminal-screen.c
+++ b/src/terminal-screen.c
@@ -55,6 +55,7 @@
 #include "terminal-marshal.h"
 #include "terminal-schemas.h"
 #include "terminal-screen-container.h"
+#include "terminal-tab-label.h"
 #include "terminal-util.h"
 #include "terminal-window.h"
 #include "terminal-info-bar.h"
@@ -143,8 +144,13 @@ static void terminal_screen_system_font_changed_cb (GSettings *,
 static gboolean terminal_screen_popup_menu (GtkWidget *widget);
 static gboolean terminal_screen_button_press (GtkWidget *widget,
                                               GdkEventButton *event);
+
+static gboolean terminal_screen_focus_in (GtkWidget *widget,
+                                          GdkEventFocus *event);
+
 static void terminal_screen_hierarchy_changed (GtkWidget *widget,
                                                GtkWidget *previous_toplevel);
+
 static gboolean terminal_screen_do_exec (TerminalScreen *screen,
                                          FDSetupData    *data,
                                          GError **error);
@@ -482,6 +488,7 @@ terminal_screen_class_init (TerminalScreenClass *klass)
   object_class->get_property = terminal_screen_get_property;
   object_class->set_property = terminal_screen_set_property;
 
+  widget_class->focus_in_event = terminal_screen_focus_in;
   widget_class->realize = terminal_screen_realize;
   widget_class->style_updated = terminal_screen_style_updated;
   widget_class->drag_data_received = terminal_screen_drag_data_received;
@@ -588,6 +595,10 @@ terminal_screen_dispose (GObject *object)
   TerminalScreen *screen = TERMINAL_SCREEN (object);
   TerminalScreenPrivate *priv = screen->priv;
   GtkSettings *settings;
+  TerminalApp *app;
+
+  app = terminal_app_get ();
+  g_application_withdraw_notification (G_APPLICATION (app), priv->uuid);
 
   /* Unset child PID so that when an eventual child-exited signal arrives,
    * we don't emit "close".
@@ -1690,6 +1701,43 @@ terminal_screen_button_press (GtkWidget      *widget,
   return FALSE;
 }
 
+static gboolean
+terminal_screen_focus_in (GtkWidget     *widget,
+                          GdkEventFocus *event)
+{
+  TerminalScreen *screen = TERMINAL_SCREEN (widget);
+  TerminalApp *app;
+  TerminalWindow *window;
+
+  window = terminal_screen_get_window (screen);
+  if (window != NULL)
+    {
+      TerminalScreenContainer *screen_container;
+
+      screen_container = terminal_screen_container_get_from_screen (screen);
+      if (screen_container != NULL)
+        {
+          GtkWidget *mdi_container;
+
+          mdi_container = terminal_window_get_mdi_container (window);
+          /* FIXME: add interface method to retrieve tab label */
+          if (GTK_IS_NOTEBOOK (mdi_container))
+            {
+              GtkWidget *tab_label;
+
+              tab_label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (mdi_container), GTK_WIDGET 
(screen_container));
+              terminal_tab_label_set_bold (TERMINAL_TAB_LABEL (tab_label), FALSE);
+              terminal_tab_label_set_icon (TERMINAL_TAB_LABEL (tab_label), NULL, NULL);
+            }
+        }
+    }
+
+  app = terminal_app_get ();
+  g_application_withdraw_notification (G_APPLICATION (app), screen->priv->uuid);
+
+  return GTK_WIDGET_CLASS (terminal_screen_parent_class)->focus_in_event (widget, event);
+}
+
 /**
  * terminal_screen_get_current_dir:
  * @screen:
@@ -1828,6 +1876,57 @@ terminal_screen_contents_changed (VteTerminal *terminal)
                                                     screen);
 }
 
+static void
+terminal_screen_show_notification (TerminalScreen *screen)
+{
+  TerminalScreenPrivate *priv = screen->priv;
+  TerminalWindow *window;
+
+  window = terminal_screen_get_window (screen);
+  if (window == NULL)
+    return;
+
+  if (gtk_window_is_active (GTK_WINDOW (window)))
+    {
+      GtkWidget *mdi_container;
+      TerminalScreenContainer *screen_container;
+
+      if (screen == terminal_window_get_active (window))
+        return;
+
+      screen_container = terminal_screen_container_get_from_screen (screen);
+      if (screen_container == NULL)
+        return;
+
+      mdi_container = terminal_window_get_mdi_container (window);
+      /* FIXME: add interface method to retrieve tab label */
+      if (GTK_IS_NOTEBOOK (mdi_container))
+        {
+          GtkWidget *tab_label;
+
+          tab_label = gtk_notebook_get_tab_label (GTK_NOTEBOOK (mdi_container), GTK_WIDGET 
(screen_container));
+          terminal_tab_label_set_bold (TERMINAL_TAB_LABEL (tab_label), TRUE);
+          terminal_tab_label_set_icon (TERMINAL_TAB_LABEL (tab_label),
+                                       "dialog-information-symbolic",
+                                       _("Command completed"));
+        }
+    }
+  else
+    {
+      gs_unref_object GNotification *notification = NULL;
+      TerminalApp *app;
+      gs_free char *detailed_action = NULL;
+
+      notification = g_notification_new (_("Command completed"));
+      g_notification_set_body (notification, priv->current_cmdline);
+      detailed_action = g_strdup_printf ("app.activate-tab::%s", priv->uuid);
+      g_notification_set_default_action (notification, detailed_action);
+
+      app = terminal_app_get ();
+      g_application_send_notification (G_APPLICATION (app), priv->uuid, notification);
+    }
+}
+
 static void
 terminal_screen_shell_precmd (VteTerminal *terminal)
 {
@@ -1848,6 +1947,9 @@ terminal_screen_shell_precmd (VteTerminal *terminal)
       priv->shell_preexec_source_id = 0;
     }
 
+  if (priv->current_cmdline != NULL)
+    terminal_screen_show_notification (screen);
+
   g_clear_pointer (&priv->current_cmdline, g_free);
 }
 
diff --git a/src/terminal-tab-label.c b/src/terminal-tab-label.c
index cdd73d06..7f202695 100644
--- a/src/terminal-tab-label.c
+++ b/src/terminal-tab-label.c
@@ -34,6 +34,7 @@
 struct _TerminalTabLabelPrivate
 {
   TerminalScreen *screen;
+  GtkWidget *icon;
   GtkWidget *label;
   GtkWidget *close_button;
   gboolean bold;
@@ -179,7 +180,7 @@ terminal_tab_label_constructed (GObject *object)
 {
   TerminalTabLabel *tab_label = TERMINAL_TAB_LABEL (object);
   TerminalTabLabelPrivate *priv = tab_label->priv;
-  GtkWidget *hbox, *label, *close_button;
+  GtkWidget *hbox, *icon, *label, *close_button;
 
   G_OBJECT_CLASS (terminal_tab_label_parent_class)->constructed (object);
 
@@ -189,6 +190,10 @@ terminal_tab_label_constructed (GObject *object)
   
   gtk_box_set_spacing (GTK_BOX (hbox), SPACING);
 
+  priv->icon = icon = gtk_image_new ();
+  gtk_widget_set_no_show_all (icon, TRUE);
+  gtk_box_pack_start (GTK_BOX (hbox), icon, FALSE, FALSE, 0);
+
   priv->label = label = gtk_label_new (NULL);
   gtk_widget_set_halign (label, GTK_ALIGN_CENTER);
   gtk_widget_set_valign (label, GTK_ALIGN_BASELINE);
@@ -376,6 +381,29 @@ terminal_tab_label_set_bold (TerminalTabLabel *tab_label,
     pango_attr_list_unref (attr_list);
 }
 
+/**
+ * terminal_tab_label_set_icon:
+ * @tab_label: a #TerminalTabLabel
+ * @icon_name: (allow-none): an icon name
+ * @tooltip: (allow-none): text to be used as tooltip
+ *
+ * Shows an icon at the beginning of @tab_label. If @icon_name is
+ * %NULL, then the icon will be hidden.
+ */
+void
+terminal_tab_label_set_icon (TerminalTabLabel *tab_label,
+                             const char *icon_name,
+                             const char *tooltip)
+{
+  TerminalTabLabelPrivate *priv = tab_label->priv;
+
+  g_return_if_fail (TERMINAL_IS_TAB_LABEL (tab_label));
+
+  gtk_widget_set_visible (priv->icon, icon_name != NULL);
+  gtk_image_set_from_icon_name (GTK_IMAGE (priv->icon), icon_name, GTK_ICON_SIZE_MENU);
+  gtk_widget_set_tooltip_text (GTK_WIDGET (priv->icon), tooltip);
+}
+
 /**
  * terminal_tab_label_get_screen:
  * @tab_label: a #TerminalTabLabel
diff --git a/src/terminal-tab-label.h b/src/terminal-tab-label.h
index 20cfbceb..a987025e 100644
--- a/src/terminal-tab-label.h
+++ b/src/terminal-tab-label.h
@@ -59,6 +59,10 @@ GtkWidget *     terminal_tab_label_new        (TerminalScreen *screen);
 void            terminal_tab_label_set_bold   (TerminalTabLabel *tab_label,
                                                gboolean bold);
 
+void            terminal_tab_label_set_icon   (TerminalTabLabel *tab_label,
+                                               const char *icon_name,
+                                               const char *tooltip);
+
 TerminalScreen *terminal_tab_label_get_screen (TerminalTabLabel *tab_label);
 
 G_END_DECLS


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