[gnome-terminal/gnome-3-34-ntfy-opn-ttl-ts: 6/16] screen: Track the current foreground process
- From: Debarshi Ray <debarshir src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-terminal/gnome-3-34-ntfy-opn-ttl-ts: 6/16] screen: Track the current foreground process
- Date: Tue, 2 Apr 2019 16:17:17 +0000 (UTC)
commit 0d4fbcdae5ff15a0b7b21a35c7278d354cf6c660
Author: Debarshi Ray <debarshir gnome org>
Date: Thu May 3 16:49:28 2018 +0200
screen: Track the current foreground process
... using the interactive shell's precmd and preexec hooks, by
monitoring the contents of the terminal, and a combination of
tcgetpgrp(3) and /proc, instead of relying on the shell's history.
The shell's history cannot be reliably used to find out the current
foreground process. The history can be optionally turned off, and when
job control is in play, it will mistakenly record 'fg' as the current
process.
https://bugzilla.gnome.org/show_bug.cgi?id=711059
src/terminal-screen.c | 126 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 126 insertions(+)
---
diff --git a/src/terminal-screen.c b/src/terminal-screen.c
index db281cbf..1281a676 100644
--- a/src/terminal-screen.c
+++ b/src/terminal-screen.c
@@ -87,13 +87,17 @@ struct _TerminalScreenPrivate
GSettings *profile; /* never NULL */
guint profile_changed_id;
guint profile_forgotten_id;
+ char *current_cmdline;
char *initial_working_directory;
char **initial_env;
char **override_command;
+ gboolean between_preexec_and_precmd;
gboolean shell;
int child_pid;
GSList *match_tags;
+ guint contents_changed_source_id;
guint launch_child_source_id;
+ guint shell_preexec_source_id;
};
enum
@@ -147,6 +151,12 @@ static gboolean terminal_screen_do_exec (TerminalScreen *screen,
static void terminal_screen_child_exited (VteTerminal *terminal,
int status);
+static void terminal_screen_contents_changed (VteTerminal *terminal);
+
+static void terminal_screen_shell_precmd (VteTerminal *terminal);
+
+static void terminal_screen_shell_preexec (VteTerminal *terminal);
+
static void terminal_screen_window_title_changed (VteTerminal *vte_terminal,
TerminalScreen *screen);
@@ -480,6 +490,9 @@ terminal_screen_class_init (TerminalScreenClass *klass)
widget_class->hierarchy_changed = terminal_screen_hierarchy_changed;
terminal_class->child_exited = terminal_screen_child_exited;
+ terminal_class->contents_changed = terminal_screen_contents_changed;
+ terminal_class->shell_precmd = terminal_screen_shell_precmd;
+ terminal_class->shell_preexec = terminal_screen_shell_preexec;
signals[PROFILE_SET] =
g_signal_new (I_("profile-set"),
@@ -586,12 +599,24 @@ terminal_screen_dispose (GObject *object)
0, 0, NULL, NULL,
screen);
+ if (priv->contents_changed_source_id != 0)
+ {
+ g_source_remove (priv->contents_changed_source_id);
+ priv->contents_changed_source_id = 0;
+ }
+
if (priv->launch_child_source_id != 0)
{
g_source_remove (priv->launch_child_source_id);
priv->launch_child_source_id = 0;
}
+ if (priv->shell_preexec_source_id != 0)
+ {
+ g_source_remove (priv->shell_preexec_source_id);
+ priv->shell_preexec_source_id = 0;
+ }
+
G_OBJECT_CLASS (terminal_screen_parent_class)->dispose (object);
/* Unregister *after* chaining up to the parent's dispose,
@@ -617,6 +642,7 @@ terminal_screen_finalize (GObject *object)
terminal_screen_set_profile (screen, NULL);
+ g_free (priv->current_cmdline);
g_free (priv->initial_working_directory);
g_strfreev (priv->override_command);
g_strfreev (priv->initial_env);
@@ -1760,6 +1786,106 @@ terminal_screen_child_exited (VteTerminal *terminal,
}
}
+static gboolean
+terminal_screen_contents_changed_cb (TerminalScreen *screen)
+{
+ TerminalScreenPrivate *priv = screen->priv;
+ gs_free char *cmdline = NULL;
+
+ g_return_val_if_fail (priv->between_preexec_and_precmd, G_SOURCE_REMOVE);
+ g_return_val_if_fail (priv->shell_preexec_source_id == 0, G_SOURCE_REMOVE);
+
+ if (!terminal_screen_has_foreground_process (screen, NULL, &cmdline))
+ goto out;
+
+ if (g_strcmp0 (priv->current_cmdline, cmdline) == 0)
+ goto out;
+
+ priv->current_cmdline = g_steal_pointer (&cmdline);
+
+ out:
+ priv->contents_changed_source_id = 0;
+ return G_SOURCE_REMOVE;
+}
+
+static void
+terminal_screen_contents_changed (VteTerminal *terminal)
+{
+ TerminalScreen *screen = TERMINAL_SCREEN (terminal);
+ TerminalScreenPrivate *priv = screen->priv;
+
+ if (!priv->between_preexec_and_precmd)
+ return;
+
+ if (priv->shell_preexec_source_id != 0)
+ return;
+
+ if (priv->contents_changed_source_id != 0)
+ return;
+
+ priv->contents_changed_source_id = g_timeout_add (500,
+ (GSourceFunc) terminal_screen_contents_changed_cb,
+ screen);
+}
+
+static void
+terminal_screen_shell_precmd (VteTerminal *terminal)
+{
+ TerminalScreen *screen = TERMINAL_SCREEN (terminal);
+ TerminalScreenPrivate *priv = screen->priv;
+
+ priv->between_preexec_and_precmd = FALSE;
+
+ if (priv->contents_changed_source_id != 0)
+ {
+ g_source_remove (priv->contents_changed_source_id);
+ priv->contents_changed_source_id = 0;
+ }
+
+ if (priv->shell_preexec_source_id != 0)
+ {
+ g_source_remove (priv->shell_preexec_source_id);
+ priv->shell_preexec_source_id = 0;
+ }
+
+ g_clear_pointer (&priv->current_cmdline, g_free);
+}
+
+static gboolean
+terminal_screen_shell_preexec_cb (TerminalScreen *screen)
+{
+ TerminalScreenPrivate *priv = screen->priv;
+ gboolean retval = G_SOURCE_CONTINUE;
+ gs_free char *cmdline = NULL;
+
+ g_return_val_if_fail (priv->current_cmdline == NULL, G_SOURCE_REMOVE);
+
+ if (!terminal_screen_has_foreground_process (screen, NULL, &cmdline))
+ goto out;
+
+ priv->current_cmdline = g_steal_pointer (&cmdline);
+
+ priv->shell_preexec_source_id = 0;
+ retval = G_SOURCE_REMOVE;
+
+ out:
+ return retval;
+}
+
+static void
+terminal_screen_shell_preexec (VteTerminal *terminal)
+{
+ TerminalScreen *screen = TERMINAL_SCREEN (terminal);
+ TerminalScreenPrivate *priv = screen->priv;
+
+ g_return_if_fail (priv->contents_changed_source_id == 0);
+ g_return_if_fail (priv->shell_preexec_source_id == 0);
+
+ priv->between_preexec_and_precmd = TRUE;
+
+ priv->shell_preexec_source_id = g_timeout_add (200, (GSourceFunc) terminal_screen_shell_preexec_cb,
screen);
+}
+
static void
terminal_screen_drag_data_received (GtkWidget *widget,
GdkDragContext *context,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]