[gnome-terminal/gnome-3-34-ntfy-opn-ttl-ts: 16/16] Restore the rest of the title handling options and make it all work



commit 63541c407e116bbe6cbed7551f8e0c2f6b4cec61
Author: Debarshi Ray <debarshir gnome org>
Date:   Thu Jun 30 16:58:15 2016 +0200

    Restore the rest of the title handling options and make it all work
    
    This reverts commit f27bf0135a2d18ba22158d28bf1f8c5f6ec066c8 and makes
    it use the user_title API instead of sending an escape sequence.
    
    https://bugzilla.redhat.com/show_bug.cgi?id=1296110

 src/org.gnome.Terminal.gschema.xml |  12 ++
 src/preferences.ui                 |  33 ++++-
 src/profile-editor.c               |   9 ++
 src/terminal-enums.h               |   8 ++
 src/terminal-schemas.h             |   1 +
 src/terminal-screen.c              | 261 +++++++++++++++++++++++++++----------
 src/terminal-screen.h              |   8 +-
 src/terminal-window.c              |  11 +-
 8 files changed, 265 insertions(+), 78 deletions(-)
---
diff --git a/src/org.gnome.Terminal.gschema.xml b/src/org.gnome.Terminal.gschema.xml
index aaa9e0e9..641e0203 100644
--- a/src/org.gnome.Terminal.gschema.xml
+++ b/src/org.gnome.Terminal.gschema.xml
@@ -24,6 +24,13 @@
 -->
 <schemalist gettext-domain="gnome-terminal">
 
+  <enum id='org.gnome.Terminal.TitleMode'>
+    <value nick='replace' value='0'/>
+    <value nick='before' value='1'/>
+    <value nick='after' value='2'/>
+    <value nick='ignore' value='3'/>
+  </enum>
+
    <enum id='org.gnome.Terminal.NewTerminalMode'>
     <value nick='window' value='0'/>
     <value nick='tab' value='1'/>
@@ -183,6 +190,11 @@
       <summary>Highlight foreground colour</summary>
       <description>Custom color for the foreground of the text character at the terminal’s highlight 
position, as a color specification (can be HTML-style hex digits, or a color name such as “red”). This is 
ignored if highlight-colors-set is false.</description>
     </key>
+    <key name="title-mode" enum="org.gnome.Terminal.TitleMode">
+      <default>'replace'</default>
+      <summary>What to do with dynamic title</summary>
+      <description>If the application in the terminal sets the title (most typically people have their shell 
set up to do this), the dynamically-set title can erase the configured title, go before it, go after it, or 
replace it. The possible values are "replace", "before", "after", and "ignore".</description>
+    </key>
     <key name="title" type="s">
       <default l10n="messages" context="title">'Terminal'</default>
       <summary>Title for terminal</summary>
diff --git a/src/preferences.ui b/src/preferences.ui
index 18f7e097..188f3c77 100644
--- a/src/preferences.ui
+++ b/src/preferences.ui
@@ -1900,7 +1900,7 @@
                                             <property name="visible">True</property>
                                             <property name="can_focus">False</property>
                                             <property name="xalign">0</property>
-                                            <property name="label" translatable="yes">Title:</property>
+                                            <property name="label" translatable="yes">Initial 
_title:</property>
                                             <property name="use_underline">True</property>
                                             <property name="mnemonic_widget">title-entry</property>
                                           </object>
@@ -1920,6 +1920,37 @@
                                             <property name="left_attach">1</property>
                                           </packing>
                                         </child>
+                                        <child>
+                                          <object class="GtkLabel" id="title-mode-combobox-label">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="xalign">0</property>
+                                            <property name="label" translatable="yes">When terminal commands 
set their o_wn titles:</property>
+                                            <property name="use_underline">True</property>
+                                            <property name="mnemonic_widget">title-mode-combobox</property>
+                                          </object>
+                                          <packing>
+                                            <property name="top_attach">1</property>
+                                            <property name="left_attach">0</property>
+                                          </packing>
+                                        </child>
+                                        <child>
+                                          <object class="GtkComboBox" id="title-mode-combobox">
+                                            <property name="visible">True</property>
+                                            <property name="can_focus">False</property>
+                                            <property name="model">model2</property>
+                                            <child>
+                                              <object class="GtkCellRendererText"/>
+                                              <attributes>
+                                                <attribute name="text">0</attribute>
+                                              </attributes>
+                                            </child>
+                                          </object>
+                                          <packing>
+                                            <property name="top_attach">1</property>
+                                            <property name="left_attach">1</property>
+                                          </packing>
+                                        </child>
                                       </object>
                                     </child>
                                   </object>
diff --git a/src/profile-editor.c b/src/profile-editor.c
index da8a7fdc..fb4e9dd3 100644
--- a/src/profile-editor.c
+++ b/src/profile-editor.c
@@ -1206,6 +1206,15 @@ profile_prefs_load (const char *uuid, GSettings *profile)
                                gtk_builder_get_object (builder, "title-entry"),
                                "text",
                                G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET);
+  profile_prefs_settings_bind_with_mapping (profile,
+                                            TERMINAL_PROFILE_TITLE_MODE_KEY,
+                                            gtk_builder_get_object (builder,
+                                                                    "title-mode-combobox"),
+                                            "active",
+                                            G_SETTINGS_BIND_GET | G_SETTINGS_BIND_SET,
+                                            (GSettingsBindGetMapping) string_to_enum,
+                                            (GSettingsBindSetMapping) enum_to_string,
+                                            terminal_title_mode_get_type, NULL);
   profile_prefs_settings_bind (profile, TERMINAL_PROFILE_USE_CUSTOM_COMMAND_KEY,
                                gtk_builder_get_object (builder,
                                                        "use-custom-command-checkbutton"),
diff --git a/src/terminal-enums.h b/src/terminal-enums.h
index bdd354e3..731dcf2a 100644
--- a/src/terminal-enums.h
+++ b/src/terminal-enums.h
@@ -30,6 +30,14 @@ typedef enum {
 } TerminalNewTerminalMode;
 
 typedef enum
+{
+  TERMINAL_TITLE_REPLACE,
+  TERMINAL_TITLE_BEFORE,
+  TERMINAL_TITLE_AFTER,
+  TERMINAL_TITLE_IGNORE
+} TerminalTitleMode;
+
+typedef enum 
 {
   TERMINAL_EXIT_CLOSE,
   TERMINAL_EXIT_RESTART,
diff --git a/src/terminal-schemas.h b/src/terminal-schemas.h
index f9222855..c5682c5e 100644
--- a/src/terminal-schemas.h
+++ b/src/terminal-schemas.h
@@ -66,6 +66,7 @@ G_BEGIN_DECLS
 #define TERMINAL_PROFILE_SCROLL_ON_KEYSTROKE_KEY        "scroll-on-keystroke"
 #define TERMINAL_PROFILE_SCROLL_ON_OUTPUT_KEY           "scroll-on-output"
 #define TERMINAL_PROFILE_TEXT_BLINK_MODE_KEY            "text-blink-mode"
+#define TERMINAL_PROFILE_TITLE_MODE_KEY                 "title-mode"
 #define TERMINAL_PROFILE_TITLE_KEY                      "title"
 #define TERMINAL_PROFILE_USE_CUSTOM_COMMAND_KEY         "use-custom-command"
 #define TERMINAL_PROFILE_USE_SKEY_KEY                   "use-skey"
diff --git a/src/terminal-screen.c b/src/terminal-screen.c
index 181552df..2204de70 100644
--- a/src/terminal-screen.c
+++ b/src/terminal-screen.c
@@ -89,13 +89,16 @@ struct _TerminalScreenPrivate
   guint profile_changed_id;
   guint profile_forgotten_id;
   char *current_cmdline;
-  char *title;
+  char *raw_title;
+  char *cooked_title;
+  char *override_title;
   char *initial_working_directory;
   char **initial_env;
   char **override_command;
   gboolean between_preexec_and_precmd;
   gboolean shell;
   int child_pid;
+  gboolean user_title; /* title was manually set */
   GSList *match_tags;
   guint contents_changed_source_id;
   guint launch_child_source_id;
@@ -115,7 +118,6 @@ enum {
   PROP_0,
   PROP_PROFILE,
   PROP_TITLE,
-  PROP_DESCRIPTION,
   PROP_INITIAL_ENVIRONMENT
 };
 
@@ -170,8 +172,13 @@ static void terminal_screen_window_title_changed      (VteTerminal *vte_terminal
 
 static void update_color_scheme                      (TerminalScreen *screen);
 
+static gboolean terminal_screen_format_title (TerminalScreen *screen, const char *raw_title, char 
**old_cooked_title);
+
+static void terminal_screen_cook_title      (TerminalScreen *screen);
+
 static char* terminal_screen_check_hyperlink   (TerminalScreen            *screen,
                                                 GdkEvent                  *event);
+
 static void terminal_screen_check_extra (TerminalScreen *screen,
                                          GdkEvent       *event,
                                          char           **number_info);
@@ -410,6 +417,9 @@ terminal_screen_init (TerminalScreen *screen)
   gtk_target_table_free (targets, n_targets);
   gtk_target_list_unref (target_list);
 
+  priv->override_title = NULL;
+  priv->user_title = FALSE;
+  
   g_signal_connect (screen, "window-title-changed",
                     G_CALLBACK (terminal_screen_window_title_changed),
                     screen);
@@ -446,9 +456,6 @@ terminal_screen_get_property (GObject *object,
       case PROP_TITLE:
         g_value_set_string (value, terminal_screen_get_title (screen));
         break;
-      case PROP_DESCRIPTION:
-        g_value_take_string (value, terminal_screen_get_description (screen));
-        break;
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
         break;
@@ -472,7 +479,6 @@ terminal_screen_set_property (GObject *object,
         terminal_screen_set_initial_environment (screen, g_value_get_boxed (value));
         break;
       case PROP_TITLE:
-      case PROP_DESCRIPTION:
         /* not writable */
       default:
         G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -562,13 +568,6 @@ terminal_screen_class_init (TerminalScreenClass *klass)
                           NULL,
                           G_PARAM_READABLE | G_PARAM_STATIC_NAME | G_PARAM_STATIC_NICK | 
G_PARAM_STATIC_BLURB));
 
-  g_object_class_install_property (object_class,
-                                   PROP_DESCRIPTION,
-                                   g_param_spec_string ("description", NULL, NULL,
-                                                        NULL,
-                                                        G_PARAM_READABLE | 
-                                                        G_PARAM_STATIC_STRINGS));
-
   g_object_class_install_property
     (object_class,
      PROP_INITIAL_ENVIRONMENT,
@@ -667,7 +666,9 @@ terminal_screen_finalize (GObject *object)
   terminal_screen_set_profile (screen, NULL);
 
   g_free (priv->current_cmdline);
-  g_free (priv->title);
+  g_free (priv->raw_title);
+  g_free (priv->cooked_title);
+  g_free (priv->override_title);
   g_free (priv->initial_working_directory);
   g_strfreev (priv->override_command);
   g_strfreev (priv->initial_env);
@@ -714,28 +715,8 @@ terminal_screen_new (GSettings       *profile,
                          g_settings_get_int (profile, TERMINAL_PROFILE_DEFAULT_SIZE_COLUMNS_KEY),
                          g_settings_get_int (profile, TERMINAL_PROFILE_DEFAULT_SIZE_ROWS_KEY));
 
-  /* If given an initial title, strip it of control characters and
-   * feed it to the terminal.
-   */
-  if (title) {
-    GString *seq;
-    const char *p;
-
-    seq = g_string_new ("\033]0;");
-    for (p = title; *p; p = g_utf8_next_char (p)) {
-      gunichar c = g_utf8_get_char (p);
-      if (c < 0x20 || (c >= 0x7f && c <= 0x9f))
-        continue;
-      else if (c == ';')
-        break;
-
-      g_string_append_unichar (seq, c);
-    }
-    g_string_append (seq, "\033\\");
-
-    vte_terminal_feed (VTE_TERMINAL (screen), seq->str, seq->len);
-    g_string_free (seq, TRUE);
-  }
+  if (title)
+    terminal_screen_set_override_title (screen, title);
 
   priv->initial_working_directory = g_strdup (working_dir);
 
@@ -790,34 +771,145 @@ terminal_screen_exec (TerminalScreen *screen,
   return terminal_screen_do_exec (screen, data, error);
 }
 
+const char*
+terminal_screen_get_raw_title (TerminalScreen *screen)
+{
+  TerminalScreenPrivate *priv = screen->priv;
+  
+  if (priv->raw_title)
+    return priv->raw_title;
+
+  return "";
+}
+
 const char*
 terminal_screen_get_title (TerminalScreen *screen)
 {
-  return vte_terminal_get_window_title (VTE_TERMINAL (screen));
+  TerminalScreenPrivate *priv = screen->priv;
+  
+  if (priv->cooked_title == NULL)
+    terminal_screen_cook_title (screen);
+
+  /* cooked_title may still be NULL */
+  if (priv->cooked_title != NULL)
+    return priv->cooked_title;
+  else
+    return "";
+}
+
+/* Supported format specifiers:
+ * %S = static title
+ * %D = dynamic title
+ * %A = dynamic title, falling back to static title if empty
+ * %- = separator, if not at start or end of string (excluding whitespace)
+ */
+static const char *
+terminal_screen_get_title_format (TerminalScreen *screen)
+{
+  TerminalScreenPrivate *priv = screen->priv;
+  static const char *formats[] = {
+    "%A"      /* TERMINAL_TITLE_REPLACE */,
+    "%D%-%S"  /* TERMINAL_TITLE_BEFORE  */,
+    "%S%-%D"  /* TERMINAL_TITLE_AFTER   */,
+    "%S"      /* TERMINAL_TITLE_IGNORE  */
+  };
+
+  return formats[g_settings_get_enum (priv->profile, TERMINAL_PROFILE_TITLE_MODE_KEY)];
 }
 
-char *
-terminal_screen_get_description (TerminalScreen *screen)
+/**
+ * terminal_screen_format_title::
+ * @screen:
+ * @raw_title: main ingredient
+ * @titleptr <inout>: pointer of the current title string
+ * 
+ * Format title according @format, and stores it in <literal>*titleptr</literal>.
+ * Always ensures that *titleptr will be non-NULL.
+ *
+ * Returns: %TRUE iff the title changed
+ */
+static gboolean
+terminal_screen_format_title (TerminalScreen *screen,
+                              const char *raw_title,
+                              char **titleptr)
 {
   TerminalScreenPrivate *priv = screen->priv;
-  gs_free char *title_string = NULL;
-  const char *title;
+  gs_free char *static_title_string = NULL;
+  const char *format, *arg;
+  const char *static_title = NULL;
+  GString *title;
+  gboolean add_sep = FALSE;
+
+  g_assert (titleptr);
 
   /* use --title argument if one was supplied, otherwise ask the profile */
-  if (priv->title)
-    title = priv->title;
+  if (priv->override_title)
+    static_title = priv->override_title;
   else
-    title = title_string = g_settings_get_string (priv->profile, TERMINAL_PROFILE_TITLE_KEY);
+    static_title = static_title_string = g_settings_get_string (priv->profile, TERMINAL_PROFILE_TITLE_KEY);
+
+  title = g_string_sized_new (128);
+
+  format = terminal_screen_get_title_format (screen);
+  for (arg = format; *arg; arg += 2)
+    {
+      const char *text_to_append = NULL;
 
-  return g_strdup_printf ("%s — %d",
-                          title && title[0] ? title : _("Terminal"),
-                          screen->priv->child_pid);
+      g_assert (arg[0] == '%');
+
+      switch (arg[1])
+        {
+          case 'A':
+            text_to_append = raw_title ? raw_title : static_title;
+            break;
+          case 'D':
+            text_to_append = raw_title;
+            break;
+          case 'S':
+            text_to_append = static_title;
+            break;
+          case '-':
+            text_to_append = NULL;
+            add_sep = TRUE;
+            break;
+          default:
+            g_assert_not_reached ();
+        }
+
+      if (!text_to_append || !text_to_append[0])
+        continue;
+
+      if (add_sep && title->len > 0)
+        g_string_append (title, " - ");
+
+      g_string_append (title, text_to_append);
+      add_sep = FALSE;
+    }
+
+  if (*titleptr == NULL || strcmp (title->str, *titleptr) != 0)
+    {
+      g_free (*titleptr);
+      *titleptr = g_string_free (title, FALSE);
+      return TRUE;
+    }
+
+  g_string_free (title, TRUE);
+  return FALSE;
+}
+
+static void 
+terminal_screen_cook_title (TerminalScreen *screen)
+{
+  TerminalScreenPrivate *priv = screen->priv;
+  
+  if (terminal_screen_format_title (screen, priv->raw_title, &priv->cooked_title))
+    g_object_notify (G_OBJECT (screen), "title");
 }
 
 static void
 terminal_screen_profile_changed_cb (GSettings     *profile,
                                     const char    *prop_name,
-                                    TerminalScreen *screen)
+                                   TerminalScreen *screen)
 {
   TerminalScreenPrivate *priv = screen->priv;
   GObject *object = G_OBJECT (screen);
@@ -853,9 +945,10 @@ terminal_screen_profile_changed_cb (GSettings     *profile,
     }
 
   if (!prop_name ||
+      prop_name == I_(TERMINAL_PROFILE_TITLE_MODE_KEY) ||
       prop_name == I_(TERMINAL_PROFILE_TITLE_KEY))
     {
-      g_object_notify (object, "description");
+      terminal_screen_cook_title (screen);
     }
 
   if (gtk_widget_get_realized (GTK_WIDGET (screen)) &&
@@ -1137,7 +1230,6 @@ terminal_screen_set_profile (TerminalScreen *screen,
     g_object_unref (old_profile);
 
   g_object_notify (G_OBJECT (screen), "profile");
-  g_object_notify (G_OBJECT (screen), "description");
 }
 
 GSettings*
@@ -1468,8 +1560,6 @@ spawn_result_cb (VteTerminal *terminal,
 
   priv->child_pid = pid;
 
-  g_object_notify (G_OBJECT (screen), "description");
-
   if (error) {
     GtkWidget *info_bar;
 
@@ -1781,33 +1871,45 @@ terminal_screen_focus_in (GtkWidget     *widget,
   return GTK_WIDGET_CLASS (terminal_screen_parent_class)->focus_in_event (widget, event);
 }
 
-void
-terminal_screen_set_user_title (TerminalScreen *screen,
-                                const char     *title)
+static void
+terminal_screen_set_dynamic_title (TerminalScreen *screen,
+                                   const char     *title,
+                                  gboolean       userset)
 {
   TerminalScreenPrivate *priv = screen->priv;
 
-  g_return_if_fail (TERMINAL_IS_SCREEN (screen));
-
-  if (g_strcmp0 (priv->title, title) == 0)
+  g_assert (TERMINAL_IS_SCREEN (screen));
+  
+  if ((priv->user_title && !userset) ||
+      (priv->raw_title && title &&
+       strcmp (priv->raw_title, title) == 0))
     return;
 
-  g_free (priv->title);
-  priv->title = title && title[0] ? g_strdup (title) : NULL;
-
-  g_object_notify (G_OBJECT (screen), "description");
+  g_free (priv->raw_title);
+  priv->raw_title = g_strdup (title);
+  terminal_screen_cook_title (screen);
 }
 
-const char*
-terminal_screen_get_user_title (TerminalScreen *screen)
+void
+terminal_screen_set_override_title (TerminalScreen *screen,
+                                    const char     *title)
 {
-  TerminalScreenPrivate *priv;
+  TerminalScreenPrivate *priv = screen->priv;
+  char *old_title;
 
-  g_return_val_if_fail (TERMINAL_IS_SCREEN (screen), NULL);
+  old_title = priv->override_title;
+  priv->override_title = g_strdup (title);
+  g_free (old_title);
 
-  priv = screen->priv;
+  terminal_screen_set_dynamic_title (screen, title, FALSE);
+}
 
-  return priv->title ? priv->title : _("Terminal");
+const char*
+terminal_screen_get_dynamic_title (TerminalScreen *screen)
+{
+  g_return_val_if_fail (TERMINAL_IS_SCREEN (screen), NULL);
+  
+  return screen->priv->raw_title;
 }
 
 /**
@@ -1840,7 +1942,9 @@ static void
 terminal_screen_window_title_changed (VteTerminal *vte_terminal,
                                       TerminalScreen *screen)
 {
-  g_object_notify (G_OBJECT (screen), "title");
+  terminal_screen_set_dynamic_title (screen,
+                                     vte_terminal_get_window_title (vte_terminal),
+                                    FALSE);
 }
 
 static void
@@ -1863,8 +1967,6 @@ terminal_screen_child_exited (VteTerminal *terminal,
 
   priv->child_pid = -1;
   
-  g_object_notify (G_OBJECT (screen), "description");
-
   action = g_settings_get_enum (priv->profile, TERMINAL_PROFILE_EXIT_ACTION_KEY);
   
   switch (action)
@@ -1908,6 +2010,23 @@ terminal_screen_child_exited (VteTerminal *terminal,
     }
 }
 
+void
+terminal_screen_set_user_title (TerminalScreen *screen,
+                                const char *text)
+{
+  TerminalScreenPrivate *priv = screen->priv;
+
+  /* The user set the title to nothing, let's understand that as a
+     request to revert to dynamically setting the title again. */
+  if (!text || !text[0])
+    priv->user_title = FALSE;
+  else
+    {
+      priv->user_title = TRUE;
+      terminal_screen_set_dynamic_title (screen, text, TRUE);
+    }
+}
+
 static gboolean
 terminal_screen_contents_changed_cb (TerminalScreen *screen)
 {
diff --git a/src/terminal-screen.h b/src/terminal-screen.h
index af9583e7..a75bd4f0 100644
--- a/src/terminal-screen.h
+++ b/src/terminal-screen.h
@@ -103,13 +103,17 @@ void         terminal_screen_set_initial_environment (TerminalScreen  *screen,
                                                       char           **argv);
 char **      terminal_screen_get_initial_environment (TerminalScreen  *screen);
 
-const char *terminal_screen_get_user_title     (TerminalScreen *screen);
+const char* terminal_screen_get_raw_title      (TerminalScreen *screen);
 const char* terminal_screen_get_title          (TerminalScreen *screen);
-char *      terminal_screen_get_description    (TerminalScreen *screen);
 
 void terminal_screen_set_user_title (TerminalScreen *screen,
                                      const char *text);
 
+void        terminal_screen_set_override_title     (TerminalScreen *screen,
+                                                    const char     *title);
+
+const char *terminal_screen_get_dynamic_title      (TerminalScreen *screen);
+
 char *terminal_screen_get_current_dir (TerminalScreen *screen);
 
 void       terminal_screen_get_size (TerminalScreen *screen,
diff --git a/src/terminal-window.c b/src/terminal-window.c
index 7fda0fe5..6f81c7da 100644
--- a/src/terminal-window.c
+++ b/src/terminal-window.c
@@ -765,6 +765,12 @@ terminal_set_title_dialog_response_cb (GtkWidget *dialog,
   gtk_widget_destroy (dialog);
 }
 
+static const char *
+terminal_screen_get_user_title (TerminalScreen *screen)
+{
+  return terminal_screen_get_raw_title (screen);
+}
+
 static void
 action_set_title_cb (GSimpleAction *action,
                      GVariant *parameter,
@@ -2555,14 +2561,11 @@ sync_screen_title (TerminalScreen *screen,
                    TerminalWindow *window)
 {
   TerminalWindowPrivate *priv = window->priv;
-  const char *title;
 
   if (screen != priv->active_screen)
     return;
 
-  title = terminal_screen_get_title (screen);
-  gtk_window_set_title (GTK_WINDOW (window),
-                        title && title[0] ? title : _("Terminal"));
+  gtk_window_set_title (GTK_WINDOW (window), terminal_screen_get_title (screen));
 }
 
 static void


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