[gnome-builder] libide-terminal: port to GTK 4 and IdeRunContext
- From: Christian Hergert <chergert src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder] libide-terminal: port to GTK 4 and IdeRunContext
- Date: Tue, 12 Jul 2022 06:39:13 +0000 (UTC)
commit 4c502626469e1d8a1257e11df12c63a940bcb1bb
Author: Christian Hergert <chergert redhat com>
Date: Mon Jul 11 22:03:54 2022 -0700
libide-terminal: port to GTK 4 and IdeRunContext
- Remove libdazzle usage
- Use VTE GTK 4 port (still very much WIP)
- Port to libpanel
- Revamp IdeTerminalLauncher to be cleaner thanks to IdeRunContext
and IdeRunCommand.
- Remove use of IdeTerminalSurface/IdeTerminalWorkspace as they are not
used. We could bring back the terminal workspace at some point, but it
would need really strong direction up-front to replace other tooling
used as container front-ends if we're to do that.
- Update availability macros
...de-terminal-workspace.h => ide-terminal-init.c} | 40 +-
src/libide/terminal/ide-terminal-launcher.c | 829 +++------------------
src/libide/terminal/ide-terminal-launcher.h | 67 +-
src/libide/terminal/ide-terminal-page-actions.c | 22 +-
src/libide/terminal/ide-terminal-page-private.h | 9 +-
src/libide/terminal/ide-terminal-page.c | 303 +++-----
src/libide/terminal/ide-terminal-page.h | 30 +-
src/libide/terminal/ide-terminal-page.ui | 20 +-
src/libide/terminal/ide-terminal-popover.c | 54 +-
src/libide/terminal/ide-terminal-popover.h | 6 +-
src/libide/terminal/ide-terminal-private.h | 4 +-
...urface.h => ide-terminal-run-command-private.h} | 28 +-
src/libide/terminal/ide-terminal-run-command.c | 144 ++++
src/libide/terminal/ide-terminal-search-private.h | 10 +-
src/libide/terminal/ide-terminal-search.c | 48 +-
src/libide/terminal/ide-terminal-search.h | 18 +-
src/libide/terminal/ide-terminal-search.ui | 277 +++----
src/libide/terminal/ide-terminal-surface.c | 108 ---
src/libide/terminal/ide-terminal-surface.ui | 10 -
src/libide/terminal/ide-terminal-util.c | 113 +--
src/libide/terminal/ide-terminal-util.h | 6 +-
src/libide/terminal/ide-terminal-workspace.c | 97 ---
src/libide/terminal/ide-terminal-workspace.ui | 45 --
src/libide/terminal/ide-terminal.c | 296 +++++---
src/libide/terminal/ide-terminal.h | 14 +-
src/libide/terminal/libide-terminal.gresource.xml | 2 -
src/libide/terminal/libide-terminal.h | 2 -
src/libide/terminal/meson.build | 10 +-
28 files changed, 799 insertions(+), 1813 deletions(-)
---
diff --git a/src/libide/terminal/ide-terminal-workspace.h b/src/libide/terminal/ide-terminal-init.c
similarity index 52%
rename from src/libide/terminal/ide-terminal-workspace.h
rename to src/libide/terminal/ide-terminal-init.c
index 23a3acd9f..d80246221 100644
--- a/src/libide/terminal/ide-terminal-workspace.h
+++ b/src/libide/terminal/ide-terminal-init.c
@@ -1,6 +1,6 @@
-/* ide-terminal-workspace.h
+/* ide-terminal-init.c
*
- * Copyright 2018-2019 Christian Hergert <chergert redhat com>
+ * Copyright 2022 Christian Hergert <chergert redhat com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -18,23 +18,19 @@
* SPDX-License-Identifier: GPL-3.0-or-later
*/
-#pragma once
-
-#if !defined (IDE_TERMINAL_INSIDE) && !defined (IDE_TERMINAL_COMPILATION)
-# error "Only <libide-terminal.h> can be included directly."
-#endif
-
-#include <libide-core.h>
-#include <libide-gui.h>
-
-G_BEGIN_DECLS
-
-#define IDE_TYPE_TERMINAL_WORKSPACE (ide_terminal_workspace_get_type())
-
-IDE_AVAILABLE_IN_3_32
-G_DECLARE_FINAL_TYPE (IdeTerminalWorkspace, ide_terminal_workspace, IDE, TERMINAL_WORKSPACE, IdeWorkspace)
-
-IDE_AVAILABLE_IN_3_34
-IdeTerminalWorkspace *ide_terminal_workspace_new (IdeApplication *application);
-
-G_END_DECLS
+#define G_LOG_DOMAIN "ide-terminal-init"
+
+#include "ide-terminal.h"
+#include "ide-terminal-launcher.h"
+#include "ide-terminal-page.h"
+#include "ide-terminal-private.h"
+#include "ide-terminal-search.h"
+
+void
+_ide_terminal_init (void)
+{
+ g_type_ensure (IDE_TYPE_TERMINAL);
+ g_type_ensure (IDE_TYPE_TERMINAL_LAUNCHER);
+ g_type_ensure (IDE_TYPE_TERMINAL_PAGE);
+ g_type_ensure (IDE_TYPE_TERMINAL_SEARCH);
+}
diff --git a/src/libide/terminal/ide-terminal-launcher.c b/src/libide/terminal/ide-terminal-launcher.c
index 7c8e76c26..728727f4a 100644
--- a/src/libide/terminal/ide-terminal-launcher.c
+++ b/src/libide/terminal/ide-terminal-launcher.c
@@ -23,175 +23,31 @@
#include "config.h"
#include <errno.h>
+
#include <glib/gi18n.h>
+
#include <libide-foundry.h>
#include <libide-threading.h>
-#include "ide-private.h"
-
#include "ide-terminal-launcher.h"
-#include "ide-terminal-util.h"
-
-typedef enum
-{
- LAUNCHER_KIND_HOST = 0,
- LAUNCHER_KIND_DEBUG,
- LAUNCHER_KIND_RUNTIME,
- LAUNCHER_KIND_RUNNER,
- LAUNCHER_KIND_LAUNCHER,
- LAUNCHER_KIND_CONFIG,
-} LauncherKind;
struct _IdeTerminalLauncher
{
- GObject parent_instance;
- gchar *cwd;
- gchar *shell;
- gchar *title;
- gchar **args;
- IdeRuntime *runtime;
- IdeContext *context;
- IdeConfig *config;
- IdeSubprocessLauncher *launcher;
- LauncherKind kind;
+ GObject parent_instance;
+ IdeRunCommand *run_command;
+ IdeContext *context;
};
G_DEFINE_FINAL_TYPE (IdeTerminalLauncher, ide_terminal_launcher, G_TYPE_OBJECT)
enum {
PROP_0,
- PROP_ARGS,
- PROP_CWD,
- PROP_SHELL,
- PROP_TITLE,
+ PROP_CONTEXT,
+ PROP_RUN_COMMAND,
N_PROPS
};
static GParamSpec *properties [N_PROPS];
-static const struct {
- const gchar *key;
- const gchar *value;
-} default_environment[] = {
- { "INSIDE_GNOME_BUILDER", PACKAGE_VERSION },
- { "TERM", "xterm-256color" },
-};
-
-static gboolean
-shell_supports_login (const gchar *shell)
-{
- g_autofree gchar *name = NULL;
-
- /* Shells that support --login */
- static const gchar *supported[] = {
- "sh", "bash",
- };
-
- if (shell == NULL)
- return FALSE;
-
- if (!(name = g_path_get_basename (shell)))
- return FALSE;
-
- for (guint i = 0; i < G_N_ELEMENTS (supported); i++)
- {
- if (g_str_equal (name, supported[i]))
- return TRUE;
- }
-
- return FALSE;
-}
-
-static void
-copy_envvars (gpointer instance)
-{
- static const gchar *copy_env[] = {
- "AT_SPI_BUS_ADDRESS",
- "COLORTERM",
- "DBUS_SESSION_BUS_ADDRESS",
- "DBUS_SYSTEM_BUS_ADDRESS",
- "DESKTOP_SESSION",
- "DISPLAY",
- "LANG",
- "SHELL",
- "SSH_AUTH_SOCK",
- "USER",
- "WAYLAND_DISPLAY",
- "XAUTHORITY",
- "XDG_CURRENT_DESKTOP",
-#if 0
- /* Can't copy these as they could mess up Flatpak */
- "XDG_DATA_DIRS",
- "XDG_RUNTIME_DIR",
-#endif
- "XDG_MENU_PREFIX",
- "XDG_SEAT",
- "XDG_SESSION_DESKTOP",
- "XDG_SESSION_ID",
- "XDG_SESSION_TYPE",
- "XDG_VTNR",
- };
- const gchar * const *host_environ;
- IdeEnvironment *env = NULL;
-
- g_assert (IDE_IS_SUBPROCESS_LAUNCHER (instance) || IDE_IS_RUNNER (instance));
-
- if (IDE_IS_RUNNER (instance))
- env = ide_runner_get_environment (instance);
-
- host_environ = _ide_host_environ ();
-
- for (guint i = 0; i < G_N_ELEMENTS (copy_env); i++)
- {
- const gchar *val = g_environ_getenv ((gchar **)host_environ, copy_env[i]);
-
- if (val != NULL)
- {
- if (IDE_IS_SUBPROCESS_LAUNCHER (instance))
- ide_subprocess_launcher_setenv (instance, copy_env[i], val, FALSE);
- else
- ide_environment_setenv (env, copy_env[i], val);
- }
- }
-}
-
-static void
-apply_pipeline_info (gpointer instance,
- IdeObject *object)
-{
- g_autoptr(GFile) workdir = NULL;
- IdeEnvironment *env = NULL;
- IdeContext *context;
-
- g_assert (IDE_IS_SUBPROCESS_LAUNCHER (instance) || IDE_IS_RUNNER (instance));
- g_assert (IDE_IS_OBJECT (object));
-
- context = ide_object_get_context (object);
- workdir = ide_context_ref_workdir (context);
-
- if (IDE_IS_RUNNER (instance))
- env = ide_runner_get_environment (instance);
-
- if (IDE_IS_SUBPROCESS_LAUNCHER (instance))
- ide_subprocess_launcher_setenv (instance, "SRCDIR", g_file_peek_path (workdir), FALSE);
- else
- ide_environment_setenv (env, "SRCDIR", g_file_peek_path (workdir));
-
- if (ide_context_has_project (context))
- {
- IdeBuildManager *build_manager = ide_build_manager_from_context (context);
- IdePipeline *pipeline = ide_build_manager_get_pipeline (build_manager);
-
- if (pipeline != NULL)
- {
- const gchar *builddir = ide_pipeline_get_builddir (pipeline);
-
- if (IDE_IS_SUBPROCESS_LAUNCHER (instance))
- ide_subprocess_launcher_setenv (instance, "BUILDDIR", builddir, FALSE);
- else
- ide_environment_setenv (env, "BUILDDIR", builddir);
- }
- }
-}
static void
ide_terminal_launcher_wait_check_cb (GObject *object,
@@ -202,6 +58,9 @@ ide_terminal_launcher_wait_check_cb (GObject *object,
g_autoptr(IdeTask) task = user_data;
g_autoptr(GError) error = NULL;
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
g_assert (IDE_IS_SUBPROCESS (subprocess));
g_assert (G_IS_ASYNC_RESULT (result));
g_assert (IDE_IS_TASK (task));
@@ -210,281 +69,8 @@ ide_terminal_launcher_wait_check_cb (GObject *object,
ide_task_return_error (task, g_steal_pointer (&error));
else
ide_task_return_boolean (task, TRUE);
-}
-
-static void
-spawn_host_launcher (IdeTerminalLauncher *self,
- IdeTask *task,
- gint pty_fd,
- gboolean run_on_host)
-{
- g_autoptr(IdeSubprocessLauncher) launcher = NULL;
- g_autoptr(IdeSubprocess) subprocess = NULL;
- g_autoptr(GError) error = NULL;
- const gchar *shell;
-
- g_assert (IDE_IS_TERMINAL_LAUNCHER (self));
- g_assert (IDE_IS_TASK (task));
- g_assert (pty_fd >= 0);
-
- if (!(shell = ide_terminal_launcher_get_shell (self)))
- shell = ide_get_user_shell ();
-
- /* We only have sh/bash in our flatpak */
- if (self->kind == LAUNCHER_KIND_DEBUG && ide_is_flatpak ())
- shell = "/bin/bash";
-
- launcher = ide_subprocess_launcher_new (0);
- ide_subprocess_launcher_set_run_on_host (launcher, run_on_host);
- ide_subprocess_launcher_set_cwd (launcher, self->cwd ? self->cwd : g_get_home_dir ());
- ide_subprocess_launcher_set_clear_env (launcher, FALSE);
-
- ide_subprocess_launcher_push_argv (launcher, shell);
- if (shell_supports_login (shell))
- ide_subprocess_launcher_push_argv (launcher, "--login");
-
- ide_subprocess_launcher_take_stdin_fd (launcher, dup (pty_fd));
- ide_subprocess_launcher_take_stdout_fd (launcher, dup (pty_fd));
- ide_subprocess_launcher_take_stderr_fd (launcher, dup (pty_fd));
-
- g_assert (ide_subprocess_launcher_get_needs_tty (launcher));
-
- for (guint i = 0; i < G_N_ELEMENTS (default_environment); i++)
- ide_subprocess_launcher_setenv (launcher,
- default_environment[i].key,
- default_environment[i].value,
- FALSE);
-
- ide_subprocess_launcher_setenv (launcher, "SHELL", shell, TRUE);
-
- if (self->context != NULL)
- {
- g_autoptr(GFile) workdir = ide_context_ref_workdir (self->context);
-
- ide_subprocess_launcher_setenv (launcher,
- "SRCDIR",
- g_file_peek_path (workdir),
- FALSE);
- }
-
- if (!(subprocess = ide_subprocess_launcher_spawn (launcher, NULL, &error)))
- ide_task_return_error (task, g_steal_pointer (&error));
- else
- ide_subprocess_wait_check_async (subprocess,
- ide_task_get_cancellable (task),
- ide_terminal_launcher_wait_check_cb,
- g_object_ref (task));
-}
-
-static void
-spawn_launcher (IdeTerminalLauncher *self,
- IdeTask *task,
- IdeSubprocessLauncher *launcher,
- gint pty_fd)
-{
- g_autoptr(IdeSubprocess) subprocess = NULL;
- g_autoptr(GError) error = NULL;
-
- g_assert (IDE_IS_TERMINAL_LAUNCHER (self));
- g_assert (IDE_IS_TASK (task));
- g_assert (!launcher || IDE_IS_SUBPROCESS_LAUNCHER (launcher));
- g_assert (pty_fd >= 0);
-
- if (launcher == NULL)
- {
- ide_task_return_new_error (task,
- G_IO_ERROR,
- G_IO_ERROR_FAILED,
- "process may only be spawned once");
- return;
- }
-
- ide_subprocess_launcher_set_flags (launcher, 0);
-
- ide_subprocess_launcher_take_stdin_fd (launcher, dup (pty_fd));
- ide_subprocess_launcher_take_stdout_fd (launcher, dup (pty_fd));
- ide_subprocess_launcher_take_stderr_fd (launcher, dup (pty_fd));
-
- if (!(subprocess = ide_subprocess_launcher_spawn (launcher, NULL, &error)))
- ide_task_return_error (task, g_steal_pointer (&error));
- else
- ide_subprocess_wait_check_async (subprocess,
- ide_task_get_cancellable (task),
- ide_terminal_launcher_wait_check_cb,
- g_object_ref (task));
-}
-
-static void
-spawn_runtime_launcher (IdeTerminalLauncher *self,
- IdeTask *task,
- IdeRuntime *runtime,
- IdeConfig *config,
- gint pty_fd)
-{
- g_autoptr(IdeSubprocessLauncher) launcher = NULL;
- g_autoptr(IdeSubprocess) subprocess = NULL;
- g_autoptr(GError) error = NULL;
- const gchar *shell;
-
- g_assert (IDE_IS_TERMINAL_LAUNCHER (self));
- g_assert (IDE_IS_TASK (task));
- g_assert (!runtime || IDE_IS_RUNTIME (runtime));
- g_assert (pty_fd >= 0);
-
- if (runtime == NULL)
- {
- ide_task_return_new_error (task,
- G_IO_ERROR,
- G_IO_ERROR_FAILED,
- _("Requested runtime is not installed"));
- return;
- }
-
- if (!(shell = ide_terminal_launcher_get_shell (self)))
- shell = ide_get_user_shell ();
-
- if (!(launcher = ide_runtime_create_launcher (runtime, NULL)))
- {
- ide_task_return_new_error (task,
- G_IO_ERROR,
- G_IO_ERROR_FAILED,
- _("Failed to create shell within runtime ā%sā"),
- ide_runtime_get_display_name (runtime));
- return;
- }
-
- ide_subprocess_launcher_set_flags (launcher, 0);
-
- if (!ide_runtime_contains_program_in_path (runtime, shell, NULL))
- shell = "/bin/sh";
-
- ide_subprocess_launcher_set_cwd (launcher, self->cwd ? self->cwd : g_get_home_dir ());
-
- ide_subprocess_launcher_push_argv (launcher, shell);
- if (shell_supports_login (shell))
- ide_subprocess_launcher_push_argv (launcher, "--login");
-
- ide_subprocess_launcher_take_stdin_fd (launcher, dup (pty_fd));
- ide_subprocess_launcher_take_stdout_fd (launcher, dup (pty_fd));
- ide_subprocess_launcher_take_stderr_fd (launcher, dup (pty_fd));
-
- g_assert (ide_subprocess_launcher_get_needs_tty (launcher));
-
- for (guint i = 0; i < G_N_ELEMENTS (default_environment); i++)
- ide_subprocess_launcher_setenv (launcher,
- default_environment[i].key,
- default_environment[i].value,
- FALSE);
-
- apply_pipeline_info (launcher, IDE_OBJECT (self->runtime));
- copy_envvars (launcher);
-
- ide_subprocess_launcher_setenv (launcher, "SHELL", shell, TRUE);
-
- if (config != NULL)
- ide_config_apply_path (config, launcher);
-
- if (!(subprocess = ide_subprocess_launcher_spawn (launcher, NULL, &error)))
- ide_task_return_error (task, g_steal_pointer (&error));
- else
- ide_subprocess_wait_check_async (subprocess,
- ide_task_get_cancellable (task),
- ide_terminal_launcher_wait_check_cb,
- g_object_ref (task));
-}
-
-static void
-ide_terminal_launcher_run_cb (GObject *object,
- GAsyncResult *result,
- gpointer user_data)
-{
- IdeRunner *runner = (IdeRunner *)object;
- g_autoptr(IdeTask) task = user_data;
- g_autoptr(GError) error = NULL;
-
- g_assert (IDE_IS_RUNNER (runner));
- g_assert (G_IS_ASYNC_RESULT (result));
- g_assert (IDE_IS_TASK (task));
-
- if (!ide_runner_run_finish (runner, result, &error))
- ide_task_return_error (task, g_steal_pointer (&error));
- else
- ide_task_return_boolean (task, TRUE);
-
- ide_object_destroy (IDE_OBJECT (runner));
-}
-
-static void
-spawn_runner_launcher (IdeTerminalLauncher *self,
- IdeTask *task,
- IdeRuntime *runtime,
- gint pty_fd)
-{
- g_autoptr(IdeSimpleBuildTarget) build_target = NULL;
- g_autoptr(IdeRunner) runner = NULL;
- g_autoptr(GPtrArray) argv = NULL;
- IdeEnvironment *env;
- const gchar *shell;
-
- g_assert (IDE_IS_TERMINAL_LAUNCHER (self));
- g_assert (IDE_IS_TASK (task));
- g_assert (!runtime || IDE_IS_RUNTIME (runtime));
- g_assert (pty_fd >= 0);
-
- if (runtime == NULL)
- {
- ide_task_return_new_error (task,
- G_IO_ERROR,
- G_IO_ERROR_FAILED,
- _("Requested runtime is not installed"));
- return;
- }
-
- if (!(shell = ide_terminal_launcher_get_shell (self)))
- shell = ide_get_user_shell ();
-
- if (!ide_runtime_contains_program_in_path (runtime, shell, NULL))
- shell = "/bin/sh";
-
- argv = g_ptr_array_new ();
- g_ptr_array_add (argv, (gchar *)shell);
-
- if (self->args == NULL)
- {
- if (shell_supports_login (shell))
- g_ptr_array_add (argv, (gchar *)"--login");
- }
- else
- {
- for (guint i = 0; self->args[i]; i++)
- g_ptr_array_add (argv, self->args[i]);
- }
-
- g_ptr_array_add (argv, NULL);
-
- build_target = ide_simple_build_target_new (NULL);
- ide_simple_build_target_set_argv (build_target, (const gchar * const *)argv->pdata);
- ide_simple_build_target_set_cwd (build_target, self->cwd ? self->cwd : g_get_home_dir ());
-
- /* Creating runner should always succeed, but run_async() may fail */
- runner = ide_runtime_create_runner (runtime, IDE_BUILD_TARGET (build_target));
- env = ide_runner_get_environment (runner);
- ide_runner_take_tty_fd (runner, dup (pty_fd));
- for (guint i = 0; i < G_N_ELEMENTS (default_environment); i++)
- ide_environment_setenv (env,
- default_environment[i].key,
- default_environment[i].value);
-
- apply_pipeline_info (runner, IDE_OBJECT (self->runtime));
- copy_envvars (runner);
-
- ide_environment_setenv (env, "SHELL", shell);
-
- ide_runner_run_async (runner,
- ide_task_get_cancellable (task),
- ide_terminal_launcher_run_cb,
- g_object_ref (task));
+ IDE_EXIT;
}
void
@@ -494,9 +80,14 @@ ide_terminal_launcher_spawn_async (IdeTerminalLauncher *self,
GAsyncReadyCallback callback,
gpointer user_data)
{
+ g_autoptr(IdeRunContext) run_context = NULL;
+ g_autoptr(IdeSubprocess) subprocess = NULL;
g_autoptr(IdeTask) task = NULL;
- gint pty_fd = -1;
+ g_autoptr(GError) error = NULL;
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
g_assert (IDE_IS_TERMINAL_LAUNCHER (self));
g_assert (VTE_IS_PTY (pty));
g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
@@ -504,44 +95,38 @@ ide_terminal_launcher_spawn_async (IdeTerminalLauncher *self,
task = ide_task_new (self, cancellable, callback, user_data);
ide_task_set_source_tag (task, ide_terminal_launcher_spawn_async);
- if ((pty_fd = ide_vte_pty_create_slave (pty)) == -1)
+ run_context = ide_run_context_new ();
+
+ /* Paranoia check to ensure we've been constructed right */
+ if (self->run_command == NULL || self->context == NULL)
{
- int errsv = errno;
ide_task_return_new_error (task,
G_IO_ERROR,
- g_io_error_from_errno (errsv),
- "%s", g_strerror (errsv));
- return;
+ G_IO_ERROR_NOT_INITIALIZED,
+ "%s is improperly configured",
+ G_OBJECT_TYPE_NAME (self));
+ IDE_EXIT;
}
- switch (self->kind)
- {
- case LAUNCHER_KIND_RUNTIME:
- spawn_runtime_launcher (self, task, self->runtime, NULL, pty_fd);
- break;
+ ide_run_command_prepare_to_run (self->run_command, run_context, self->context);
- case LAUNCHER_KIND_CONFIG:
- spawn_runtime_launcher (self, task, self->runtime, self->config, pty_fd);
- break;
+ /* Add some environment for custom bashrc, VTE, etc */
+ ide_run_context_setenv (run_context, "INSIDE_GNOME_BUILDER", PACKAGE_VERSION);
+ ide_run_context_setenv (run_context, "TERM", "xterm-256color");
- case LAUNCHER_KIND_RUNNER:
- spawn_runner_launcher (self, task, self->runtime, pty_fd);
- break;
-
- case LAUNCHER_KIND_LAUNCHER:
- spawn_launcher (self, task, self->launcher, pty_fd);
- g_clear_object (&self->launcher);
- break;
+ /* Attach the PTY to stdin/stdout/stderr */
+ ide_run_context_set_pty (run_context, pty);
- case LAUNCHER_KIND_DEBUG:
- case LAUNCHER_KIND_HOST:
- default:
- spawn_host_launcher (self, task, pty_fd, self->kind == LAUNCHER_KIND_HOST);
- break;
- }
+ /* Now attempt to spawn the process */
+ if (!(subprocess = ide_run_context_spawn (run_context, &error)))
+ ide_task_return_error (task, g_steal_pointer (&error));
+ else
+ ide_subprocess_wait_check_async (subprocess,
+ cancellable,
+ ide_terminal_launcher_wait_check_cb,
+ g_steal_pointer (&task));
- if (pty_fd != -1)
- close (pty_fd);
+ IDE_EXIT;
}
/**
@@ -552,34 +137,33 @@ ide_terminal_launcher_spawn_async (IdeTerminalLauncher *self,
*
* Returns: %TRUE if the process executed successfully; otherwise %FALSE
* and @error is set.
- *
- * Since: 3.34
*/
gboolean
ide_terminal_launcher_spawn_finish (IdeTerminalLauncher *self,
GAsyncResult *result,
GError **error)
{
+ gboolean ret;
+
+ IDE_ENTRY;
+
g_assert (IDE_IS_TERMINAL_LAUNCHER (self));
g_assert (IDE_IS_TASK (result));
- return ide_task_propagate_boolean (IDE_TASK (result), error);
+ ret = ide_task_propagate_boolean (IDE_TASK (result), error);
+
+ IDE_RETURN (ret);
}
static void
-ide_terminal_launcher_finalize (GObject *object)
+ide_terminal_launcher_dispose (GObject *object)
{
IdeTerminalLauncher *self = (IdeTerminalLauncher *)object;
- g_clear_pointer (&self->args, g_strfreev);
- g_clear_pointer (&self->cwd, g_free);
- g_clear_pointer (&self->shell, g_free);
- g_clear_pointer (&self->title, g_free);
- g_clear_object (&self->launcher);
- g_clear_object (&self->runtime);
- g_clear_object (&self->config);
+ g_clear_object (&self->context);
+ g_clear_object (&self->run_command);
- G_OBJECT_CLASS (ide_terminal_launcher_parent_class)->finalize (object);
+ G_OBJECT_CLASS (ide_terminal_launcher_parent_class)->dispose (object);
}
static void
@@ -592,20 +176,12 @@ ide_terminal_launcher_get_property (GObject *object,
switch (prop_id)
{
- case PROP_ARGS:
- g_value_set_boxed (value, ide_terminal_launcher_get_args (self));
+ case PROP_CONTEXT:
+ g_value_set_object (value, self->context);
break;
- case PROP_CWD:
- g_value_set_string (value, ide_terminal_launcher_get_cwd (self));
- break;
-
- case PROP_SHELL:
- g_value_set_string (value, ide_terminal_launcher_get_shell (self));
- break;
-
- case PROP_TITLE:
- g_value_set_string (value, ide_terminal_launcher_get_title (self));
+ case PROP_RUN_COMMAND:
+ g_value_set_object (value, self->run_command);
break;
default:
@@ -623,20 +199,12 @@ ide_terminal_launcher_set_property (GObject *object,
switch (prop_id)
{
- case PROP_ARGS:
- ide_terminal_launcher_set_args (self, g_value_get_boxed (value));
+ case PROP_CONTEXT:
+ g_set_object (&self->context, g_value_get_object (value));
break;
- case PROP_CWD:
- ide_terminal_launcher_set_cwd (self, g_value_get_string (value));
- break;
-
- case PROP_SHELL:
- ide_terminal_launcher_set_shell (self, g_value_get_string (value));
- break;
-
- case PROP_TITLE:
- ide_terminal_launcher_set_title (self, g_value_get_string (value));
+ case PROP_RUN_COMMAND:
+ g_set_object (&self->run_command, g_value_get_object (value));
break;
default:
@@ -649,36 +217,22 @@ ide_terminal_launcher_class_init (IdeTerminalLauncherClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
- object_class->finalize = ide_terminal_launcher_finalize;
+ object_class->dispose = ide_terminal_launcher_dispose;
object_class->get_property = ide_terminal_launcher_get_property;
object_class->set_property = ide_terminal_launcher_set_property;
- properties [PROP_ARGS] =
- g_param_spec_boxed ("args",
- "Args",
- "Arguments to shell",
- G_TYPE_STRV,
- (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- properties [PROP_CWD] =
- g_param_spec_string ("cwd",
- "Cwd",
- "The cwd to spawn in the subprocess",
- NULL,
- (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- properties [PROP_SHELL] =
- g_param_spec_string ("shell",
- "Shell",
- "The shell to spawn in the subprocess",
- NULL,
- (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- properties [PROP_TITLE] =
- g_param_spec_string ("title",
- "Title",
- "The title for the subprocess launcher",
- NULL,
+ properties [PROP_CONTEXT] =
+ g_param_spec_object ("context",
+ "Context",
+ "The context for the launcher",
+ IDE_TYPE_CONTEXT,
+ (G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS));
+
+ properties [PROP_RUN_COMMAND] =
+ g_param_spec_object ("run-command",
+ "Run Command",
+ "The run command to spawn",
+ IDE_TYPE_RUN_COMMAND,
(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_properties (object_class, N_PROPS, properties);
@@ -687,248 +241,45 @@ ide_terminal_launcher_class_init (IdeTerminalLauncherClass *klass)
static void
ide_terminal_launcher_init (IdeTerminalLauncher *self)
{
- self->cwd = NULL;
- self->shell = NULL;
- self->title = g_strdup (_("Untitled Terminal"));
-}
-
-const gchar *
-ide_terminal_launcher_get_cwd (IdeTerminalLauncher *self)
-{
- g_return_val_if_fail (IDE_IS_TERMINAL_LAUNCHER (self), NULL);
-
- return self->cwd;
-}
-
-void
-ide_terminal_launcher_set_cwd (IdeTerminalLauncher *self,
- const gchar *cwd)
-{
- g_return_if_fail (IDE_IS_TERMINAL_LAUNCHER (self));
-
- if (g_strcmp0 (self->cwd, cwd) != 0)
- {
- g_free (self->cwd);
- self->cwd = g_strdup (cwd);
- g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_CWD]);
- }
-}
-
-const gchar *
-ide_terminal_launcher_get_shell (IdeTerminalLauncher *self)
-{
- g_return_val_if_fail (IDE_IS_TERMINAL_LAUNCHER (self), NULL);
-
- return self->shell;
-}
-
-void
-ide_terminal_launcher_set_shell (IdeTerminalLauncher *self,
- const gchar *shell)
-{
- g_return_if_fail (IDE_IS_TERMINAL_LAUNCHER (self));
-
- if (g_strcmp0 (self->shell, shell) != 0)
- {
- g_free (self->shell);
- self->shell = g_strdup (shell);
- g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_SHELL]);
- }
-}
-
-const gchar *
-ide_terminal_launcher_get_title (IdeTerminalLauncher *self)
-{
- g_return_val_if_fail (IDE_IS_TERMINAL_LAUNCHER (self), NULL);
-
- return self->title;
-}
-
-void
-ide_terminal_launcher_set_title (IdeTerminalLauncher *self,
- const gchar *title)
-{
- g_return_if_fail (IDE_IS_TERMINAL_LAUNCHER (self));
-
- if (g_strcmp0 (self->title, title) != 0)
- {
- g_free (self->title);
- self->title = g_strdup (title);
- g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_TITLE]);
- }
}
/**
* ide_terminal_launcher_new:
+ * @context: an #IdeContext
+ * @run_command: an #IdeRunCommand to spawn
*
- * Create a new #IdeTerminalLauncher that will spawn a terminal on the host.
+ * Create an #IdeTerminalLauncher that spawns @run_command.
*
* Returns: (transfer full): a newly created #IdeTerminalLauncher
*/
IdeTerminalLauncher *
-ide_terminal_launcher_new (IdeContext *context)
+ide_terminal_launcher_new (IdeContext *context,
+ IdeRunCommand *run_command)
{
- IdeTerminalLauncher *self;
- g_autoptr(GFile) workdir = NULL;
-
g_return_val_if_fail (IDE_IS_CONTEXT (context), NULL);
+ g_return_val_if_fail (IDE_IS_RUN_COMMAND (run_command), NULL);
- workdir = ide_context_ref_workdir (context);
-
- self = g_object_new (IDE_TYPE_TERMINAL_LAUNCHER, NULL);
- self->kind = LAUNCHER_KIND_HOST;
- self->cwd = g_file_get_path (workdir);
- self->context = g_object_ref (context);
-
- return g_steal_pointer (&self);
-}
-
-/**
- * ide_terminal_launcher_new_for_launcher:
- * @launcher: an #IdeSubprocessLauncher
- *
- * Creates a new #IdeTerminalLauncher that can be used to launch a process
- * using the provided #IdeSubprocessLauncher.
- *
- * Returns: (transfer full): an #IdeTerminalLauncher
- *
- * Since: 3.34
- */
-IdeTerminalLauncher *
-ide_terminal_launcher_new_for_launcher (IdeSubprocessLauncher *launcher)
-{
- IdeTerminalLauncher *self;
-
- g_return_val_if_fail (IDE_IS_SUBPROCESS_LAUNCHER (launcher), NULL);
-
- self = g_object_new (IDE_TYPE_TERMINAL_LAUNCHER, NULL);
- self->kind = LAUNCHER_KIND_LAUNCHER;
- self->launcher = g_object_ref (launcher);
-
- return g_steal_pointer (&self);
+ return g_object_new (IDE_TYPE_TERMINAL_LAUNCHER,
+ "context", context,
+ "run-command", run_command,
+ NULL);
}
/**
- * ide_terminal_launcher_new_for_debug
+ * ide_terminal_launcher_copy:
+ * @self: an #IdeTerminalLauncher
*
- * Create a new #IdeTerminalLauncher that will spawn a terminal on the host.
+ * Copies @self into a new launcher.
*
* Returns: (transfer full): a newly created #IdeTerminalLauncher
*/
IdeTerminalLauncher *
-ide_terminal_launcher_new_for_debug (void)
-{
- IdeTerminalLauncher *self;
-
- self = g_object_new (IDE_TYPE_TERMINAL_LAUNCHER, NULL);
- self->kind = LAUNCHER_KIND_DEBUG;
-
- return g_steal_pointer (&self);
-}
-
-/**
- * ide_terminal_launcher_new_for_config:
- * @config: an #IdeConfig
- *
- * Create a new #IdeTerminalLauncher that will spawn a terminal in the runtime
- * of the configuration with various build options applied.
- *
- * Returns: (transfer full): a newly created #IdeTerminalLauncher
- */
-IdeTerminalLauncher *
-ide_terminal_launcher_new_for_config (IdeConfig *config)
-{
- IdeTerminalLauncher *self;
- IdeRuntime *runtime;
-
- g_return_val_if_fail (IDE_IS_CONFIG (config), NULL);
-
- runtime = ide_config_get_runtime (config);
-
- self = g_object_new (IDE_TYPE_TERMINAL_LAUNCHER, NULL);
- self->runtime = g_object_ref (runtime);
- self->config = g_object_ref (config);
- self->kind = LAUNCHER_KIND_CONFIG;
-
- ide_terminal_launcher_set_title (self, ide_runtime_get_name (runtime));
-
- return g_steal_pointer (&self);
-}
-
-/**
- * ide_terminal_launcher_new_for_runtime:
- * @runtime: an #IdeRuntime
- *
- * Create a new #IdeTerminalLauncher that will spawn a terminal in the runtime.
- *
- * Returns: (transfer full): a newly created #IdeTerminalLauncher
- */
-IdeTerminalLauncher *
-ide_terminal_launcher_new_for_runtime (IdeRuntime *runtime)
-{
- IdeTerminalLauncher *self;
-
- g_return_val_if_fail (IDE_IS_RUNTIME (runtime), NULL);
-
- self = g_object_new (IDE_TYPE_TERMINAL_LAUNCHER, NULL);
- self->runtime = g_object_ref (runtime);
- self->kind = LAUNCHER_KIND_RUNTIME;
-
- ide_terminal_launcher_set_title (self, ide_runtime_get_name (runtime));
-
- return g_steal_pointer (&self);
-}
-
-/**
- * ide_terminal_launcher_new_for_runner:
- * @runtime: an #IdeRuntime
- *
- * Create a new #IdeTerminalLauncher that will spawn a terminal in the runtime
- * but with a "runner" context similar to how the application would execute.
- *
- * Returns: (transfer full): a newly created #IdeTerminalLauncher
- */
-IdeTerminalLauncher *
-ide_terminal_launcher_new_for_runner (IdeRuntime *runtime)
-{
- IdeTerminalLauncher *self;
-
- g_return_val_if_fail (IDE_IS_RUNTIME (runtime), NULL);
-
- self = g_object_new (IDE_TYPE_TERMINAL_LAUNCHER, NULL);
- self->runtime = g_object_ref (runtime);
- self->kind = LAUNCHER_KIND_RUNNER;
-
- return g_steal_pointer (&self);
-}
-
-gboolean
-ide_terminal_launcher_can_respawn (IdeTerminalLauncher *self)
-{
- g_return_val_if_fail (IDE_IS_TERMINAL_LAUNCHER (self), FALSE);
-
- return self->kind != LAUNCHER_KIND_LAUNCHER;
-}
-
-const gchar * const *
-ide_terminal_launcher_get_args (IdeTerminalLauncher *self)
+ide_terminal_launcher_copy (IdeTerminalLauncher *self)
{
g_return_val_if_fail (IDE_IS_TERMINAL_LAUNCHER (self), NULL);
- return (const gchar * const *)self->args;
-}
-
-void
-ide_terminal_launcher_set_args (IdeTerminalLauncher *self,
- const gchar * const *args)
-{
- g_return_if_fail (IDE_IS_TERMINAL_LAUNCHER (self));
-
- if ((gchar **)args != self->args)
- {
- gchar **freeme = g_steal_pointer (&self->args);
- self->args = g_strdupv ((gchar **)args);
- g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_ARGS]);
- g_strfreev (freeme);
- }
+ return g_object_new (IDE_TYPE_TERMINAL_LAUNCHER,
+ "context", self->context,
+ "run-command", self->run_command,
+ NULL);
}
diff --git a/src/libide/terminal/ide-terminal-launcher.h b/src/libide/terminal/ide-terminal-launcher.h
index 22edaf991..f6e66196d 100644
--- a/src/libide/terminal/ide-terminal-launcher.h
+++ b/src/libide/terminal/ide-terminal-launcher.h
@@ -20,59 +20,34 @@
#pragma once
-#include <libide-gui.h>
+#if !defined (IDE_TERMINAL_INSIDE) && !defined (IDE_TERMINAL_COMPILATION)
+# error "Only <libide-terminal.h> can be included directly."
+#endif
+
+#include <libide-foundry.h>
#include <libide-threading.h>
G_BEGIN_DECLS
#define IDE_TYPE_TERMINAL_LAUNCHER (ide_terminal_launcher_get_type())
-IDE_AVAILABLE_IN_3_34
+IDE_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (IdeTerminalLauncher, ide_terminal_launcher, IDE, TERMINAL_LAUNCHER, GObject)
-IDE_AVAILABLE_IN_3_34
-IdeTerminalLauncher *ide_terminal_launcher_new (IdeContext *context);
-IDE_AVAILABLE_IN_3_34
-IdeTerminalLauncher *ide_terminal_launcher_new_for_launcher (IdeSubprocessLauncher *launcher);
-IDE_AVAILABLE_IN_42
-IdeTerminalLauncher *ide_terminal_launcher_new_for_config (IdeConfig *config);
-IDE_AVAILABLE_IN_3_34
-IdeTerminalLauncher *ide_terminal_launcher_new_for_debug (void);
-IDE_AVAILABLE_IN_3_34
-IdeTerminalLauncher *ide_terminal_launcher_new_for_runtime (IdeRuntime *runtime);
-IDE_AVAILABLE_IN_3_34
-IdeTerminalLauncher *ide_terminal_launcher_new_for_runner (IdeRuntime *runtime);
-IDE_AVAILABLE_IN_3_34
-gboolean ide_terminal_launcher_can_respawn (IdeTerminalLauncher *self);
-IDE_AVAILABLE_IN_3_34
-const gchar * const *ide_terminal_launcher_get_args (IdeTerminalLauncher *self);
-IDE_AVAILABLE_IN_3_34
-void ide_terminal_launcher_set_args (IdeTerminalLauncher *self,
- const gchar * const *args);
-IDE_AVAILABLE_IN_3_34
-const gchar *ide_terminal_launcher_get_cwd (IdeTerminalLauncher *self);
-IDE_AVAILABLE_IN_3_34
-void ide_terminal_launcher_set_cwd (IdeTerminalLauncher *self,
- const gchar *cwd);
-IDE_AVAILABLE_IN_3_34
-const gchar *ide_terminal_launcher_get_shell (IdeTerminalLauncher *self);
-IDE_AVAILABLE_IN_3_34
-void ide_terminal_launcher_set_shell (IdeTerminalLauncher *self,
- const gchar *shell);
-IDE_AVAILABLE_IN_3_34
-const gchar *ide_terminal_launcher_get_title (IdeTerminalLauncher *self);
-IDE_AVAILABLE_IN_3_34
-void ide_terminal_launcher_set_title (IdeTerminalLauncher *self,
- const gchar *title);
-IDE_AVAILABLE_IN_3_34
-void ide_terminal_launcher_spawn_async (IdeTerminalLauncher *self,
- VtePty *pty,
- GCancellable *cancellable,
- GAsyncReadyCallback callback,
- gpointer user_data);
-IDE_AVAILABLE_IN_3_34
-gboolean ide_terminal_launcher_spawn_finish (IdeTerminalLauncher *self,
- GAsyncResult *result,
- GError **error);
+IDE_AVAILABLE_IN_ALL
+IdeTerminalLauncher *ide_terminal_launcher_new (IdeContext *context,
+ IdeRunCommand *run_command);
+IDE_AVAILABLE_IN_ALL
+IdeTerminalLauncher *ide_terminal_launcher_copy (IdeTerminalLauncher *self);
+IDE_AVAILABLE_IN_ALL
+void ide_terminal_launcher_spawn_async (IdeTerminalLauncher *self,
+ VtePty *pty,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+IDE_AVAILABLE_IN_ALL
+gboolean ide_terminal_launcher_spawn_finish (IdeTerminalLauncher *self,
+ GAsyncResult *result,
+ GError **error);
G_END_DECLS
diff --git a/src/libide/terminal/ide-terminal-page-actions.c b/src/libide/terminal/ide-terminal-page-actions.c
index ad54c6713..b231bf3b9 100644
--- a/src/libide/terminal/ide-terminal-page-actions.c
+++ b/src/libide/terminal/ide-terminal-page-actions.c
@@ -165,8 +165,8 @@ save_as_cb (GObject *object,
}
else
{
- g_clear_object (&view->save_as_file_top);
- view->save_as_file_top = file;
+ g_clear_object (&view->save_as_file);
+ view->save_as_file = file;
}
}
@@ -175,8 +175,8 @@ get_last_focused_terminal_file (IdeTerminalPage *view)
{
GFile *file = NULL;
- if (G_IS_FILE (view->save_as_file_top))
- file = view->save_as_file_top;
+ if (G_IS_FILE (view->save_as_file))
+ file = view->save_as_file;
return file;
}
@@ -184,13 +184,14 @@ get_last_focused_terminal_file (IdeTerminalPage *view)
static VteTerminal *
get_last_focused_terminal (IdeTerminalPage *view)
{
- return VTE_TERMINAL (view->terminal_top);
+ return VTE_TERMINAL (view->terminal);
}
static gchar *
gb_terminal_get_selected_text (IdeTerminalPage *view,
- VteTerminal **terminal_p)
+ VteTerminal **terminal_p)
{
+#if 0
VteTerminal *terminal;
gchar *buf = NULL;
@@ -205,6 +206,9 @@ gb_terminal_get_selected_text (IdeTerminalPage *view,
}
return buf;
+#else
+ return g_strdup ("");
+#endif
}
static void
@@ -235,7 +239,7 @@ save_as_response (GtkWidget *widget,
break;
}
- gtk_widget_destroy (widget);
+ gtk_window_destroy (GTK_WINDOW (chooser));
}
static void
@@ -256,7 +260,7 @@ ide_terminal_page_actions_save_as (GSimpleAction *action,
*/
view->selection_buffer = gb_terminal_get_selected_text (view, NULL);
- toplevel = gtk_widget_get_toplevel (GTK_WIDGET (view));
+ toplevel = GTK_WIDGET (gtk_widget_get_native (GTK_WIDGET (view)));
dialog = g_object_new (GTK_TYPE_FILE_CHOOSER_DIALOG,
"action", GTK_FILE_CHOOSER_ACTION_SAVE,
"do-overwrite-confirmation", TRUE,
@@ -280,7 +284,7 @@ ide_terminal_page_actions_save_as (GSimpleAction *action,
suggested = gtk_dialog_get_widget_for_response (GTK_DIALOG (dialog), GTK_RESPONSE_OK);
gtk_style_context_add_class (gtk_widget_get_style_context (suggested),
- GTK_STYLE_CLASS_SUGGESTED_ACTION);
+ "suggested-action");
g_signal_connect (dialog, "response", G_CALLBACK (save_as_response), g_object_ref (view));
diff --git a/src/libide/terminal/ide-terminal-page-private.h b/src/libide/terminal/ide-terminal-page-private.h
index 404921835..fd2d5d6a6 100644
--- a/src/libide/terminal/ide-terminal-page-private.h
+++ b/src/libide/terminal/ide-terminal-page-private.h
@@ -31,14 +31,14 @@ struct _IdeTerminalPage
IdePage parent_instance;
IdeTerminalLauncher *launcher;
- GFile *save_as_file_top;
+ GFile *save_as_file;
gchar *selection_buffer;
VtePty *pty;
/* Template widgets */
- GtkOverlay *terminal_overlay_top;
- GtkRevealer *search_revealer_top;
- IdeTerminal *terminal_top;
+ GtkOverlay *terminal_overlay;
+ GtkRevealer *search_revealer;
+ IdeTerminal *terminal;
IdeTerminalSearch *tsearch;
gint64 last_respawn;
@@ -47,7 +47,6 @@ struct _IdeTerminalPage
guint manage_spawn : 1;
guint respawn_on_exit : 1;
guint close_on_exit : 1;
- guint needs_attention : 1;
guint exited : 1;
guint destroyed : 1;
};
diff --git a/src/libide/terminal/ide-terminal-page.c b/src/libide/terminal/ide-terminal-page.c
index 27d913c32..b85039e65 100644
--- a/src/libide/terminal/ide-terminal-page.c
+++ b/src/libide/terminal/ide-terminal-page.c
@@ -37,6 +37,7 @@
#include "ide-terminal-page.h"
#include "ide-terminal-page-private.h"
#include "ide-terminal-page-actions.h"
+#include "ide-terminal-run-command-private.h"
#define FLAPPING_DURATION_USEC (G_USEC_PER_SEC / 20)
@@ -52,13 +53,7 @@ enum {
N_PROPS
};
-enum {
- TEXT_INSERTED,
- N_SIGNALS
-};
-
static GParamSpec *properties [N_PROPS];
-static guint signals [N_SIGNALS];
static void ide_terminal_page_connect_terminal (IdeTerminalPage *self,
VteTerminal *terminal);
@@ -86,9 +81,7 @@ destroy_widget_in_idle (GtkWidget *widget)
g_assert (IDE_IS_TERMINAL_PAGE (self));
if (!self->destroyed)
- gtk_widget_destroy (widget);
-
- g_assert (self->destroyed);
+ panel_widget_close (PANEL_WIDGET (self));
IDE_RETURN (G_SOURCE_REMOVE);
}
@@ -127,10 +120,10 @@ ide_terminal_page_spawn_cb (GObject *object,
}
title = g_strdup_printf ("%s (%s)",
- ide_page_get_title (IDE_PAGE (self)) ?: _("Untitled terminal"),
+ panel_widget_get_title (PANEL_WIDGET (self)) ?: _("Untitled terminal"),
/* translators: exited describes that the terminal shell process has exited */
_("Exited"));
- ide_page_set_title (IDE_PAGE (self), title);
+ panel_widget_set_title (PANEL_WIDGET (self), title);
now = g_get_monotonic_time ();
maybe_flapping = ABS (now - self->last_respawn) < FLAPPING_DURATION_USEC;
@@ -138,12 +131,12 @@ ide_terminal_page_spawn_cb (GObject *object,
if (!self->respawn_on_exit)
{
if (self->close_on_exit && !maybe_flapping)
- gdk_threads_add_idle_full (G_PRIORITY_LOW + 1000,
- (GSourceFunc) destroy_widget_in_idle,
- g_object_ref (self),
- g_object_unref);
+ g_idle_add_full (G_PRIORITY_LOW + 1000,
+ (GSourceFunc) destroy_widget_in_idle,
+ g_object_ref (self),
+ g_object_unref);
else
- vte_terminal_set_input_enabled (VTE_TERMINAL (self->terminal_top), FALSE);
+ vte_terminal_set_input_enabled (VTE_TERMINAL (self->terminal), FALSE);
IDE_EXIT;
}
@@ -155,14 +148,14 @@ ide_terminal_page_spawn_cb (GObject *object,
}
g_clear_object (&self->pty);
- vte_terminal_reset (VTE_TERMINAL (self->terminal_top), TRUE, TRUE);
+ vte_terminal_reset (VTE_TERMINAL (self->terminal), TRUE, TRUE);
self->pty = vte_pty_new_sync (VTE_PTY_DEFAULT, NULL, NULL);
- vte_terminal_set_pty (VTE_TERMINAL (self->terminal_top), self->pty);
+ vte_terminal_set_pty (VTE_TERMINAL (self->terminal), self->pty);
/* Spawn our terminal and wait for it to exit */
self->last_respawn = now;
self->exited = FALSE;
- ide_page_set_title (IDE_PAGE (self), _("Untitled terminal"));
+ panel_widget_set_title (PANEL_WIDGET (self), _("Untitled terminal"));
ide_terminal_launcher_spawn_async (self->launcher,
self->pty,
NULL,
@@ -195,7 +188,7 @@ ide_terminal_page_do_spawn_in_idle (IdeTerminalPage *self)
}
}
- vte_terminal_set_pty (VTE_TERMINAL (self->terminal_top), self->pty);
+ vte_terminal_set_pty (VTE_TERMINAL (self->terminal), self->pty);
if (!self->manage_spawn)
IDE_RETURN (G_SOURCE_REMOVE);
@@ -234,59 +227,6 @@ ide_terminal_page_realize (GtkWidget *widget)
g_object_unref);
}
-static void
-ide_terminal_page_get_preferred_width (GtkWidget *widget,
- gint *min_width,
- gint *nat_width)
-{
- /*
- * Since we are placing the terminal in a GtkStack, we need
- * to fake the size a bit. Otherwise, GtkStack tries to keep the
- * widget at its natural size (which prevents us from getting
- * appropriate size requests.
- */
- GTK_WIDGET_CLASS (ide_terminal_page_parent_class)->get_preferred_width (widget, min_width, nat_width);
- *nat_width = *min_width;
-}
-
-static void
-ide_terminal_page_get_preferred_height (GtkWidget *widget,
- gint *min_height,
- gint *nat_height)
-{
- /*
- * Since we are placing the terminal in a GtkStack, we need
- * to fake the size a bit. Otherwise, GtkStack tries to keep the
- * widget at its natural size (which prevents us from getting
- * appropriate size requests.
- */
- GTK_WIDGET_CLASS (ide_terminal_page_parent_class)->get_preferred_height (widget, min_height, nat_height);
- *nat_height = *min_height;
-}
-
-static void
-ide_terminal_page_set_needs_attention (IdeTerminalPage *self,
- gboolean needs_attention)
-{
- GtkWidget *parent;
-
- g_assert (IDE_IS_TERMINAL_PAGE (self));
-
- parent = gtk_widget_get_parent (GTK_WIDGET (self));
-
- if (GTK_IS_STACK (parent) &&
- !gtk_widget_in_destruction (GTK_WIDGET (self)) &&
- !gtk_widget_in_destruction (parent))
- {
- if (!gtk_widget_in_destruction (GTK_WIDGET (self->terminal_top)))
- self->needs_attention = !!needs_attention;
-
- gtk_container_child_set (GTK_CONTAINER (parent), GTK_WIDGET (self),
- "needs-attention", needs_attention,
- NULL);
- }
-}
-
static void
notification_received_cb (VteTerminal *terminal,
const gchar *summary,
@@ -300,22 +240,18 @@ notification_received_cb (VteTerminal *terminal,
return;
if (!gtk_widget_has_focus (GTK_WIDGET (terminal)))
- ide_terminal_page_set_needs_attention (self, TRUE);
+ panel_widget_set_needs_attention (PANEL_WIDGET (self), TRUE);
}
-static gboolean
-focus_in_event_cb (VteTerminal *terminal,
- GdkEvent *event,
- IdeTerminalPage *self)
+static void
+focus_in_event_cb (GtkEventControllerFocus *focus,
+ IdeTerminalPage *self)
{
- g_assert (VTE_IS_TERMINAL (terminal));
+ g_assert (GTK_IS_EVENT_CONTROLLER_FOCUS (focus));
g_assert (IDE_IS_TERMINAL_PAGE (self));
- self->needs_attention = FALSE;
- ide_terminal_page_set_needs_attention (self, FALSE);
- gtk_revealer_set_reveal_child (self->search_revealer_top, FALSE);
-
- return GDK_EVENT_PROPAGATE;
+ panel_widget_set_needs_attention (PANEL_WIDGET (self), FALSE);
+ gtk_revealer_set_reveal_child (self->search_revealer, FALSE);
}
static void
@@ -330,37 +266,12 @@ window_title_changed_cb (VteTerminal *terminal,
if (self->destroyed)
return;
- title = vte_terminal_get_window_title (VTE_TERMINAL (self->terminal_top));
+ title = vte_terminal_get_window_title (VTE_TERMINAL (self->terminal));
if (title == NULL || title[0] == '\0')
title = _("Untitled terminal");
- ide_page_set_title (IDE_PAGE (self), title);
-}
-
-static void
-style_context_changed (GtkStyleContext *style_context,
- IdeTerminalPage *self)
-{
- GtkStateFlags state;
- GdkRGBA fg;
- GdkRGBA bg;
-
- g_assert (GTK_IS_STYLE_CONTEXT (style_context));
- g_assert (IDE_IS_TERMINAL_PAGE (self));
-
- state = gtk_style_context_get_state (style_context);
-
- G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
- gtk_style_context_get_color (style_context, state, &fg);
- gtk_style_context_get_background_color (style_context, state, &bg);
- G_GNUC_END_IGNORE_DEPRECATIONS;
-
- if (bg.alpha == 0.0)
- gdk_rgba_parse (&bg, "#f6f7f8");
-
- ide_page_set_primary_color_fg (IDE_PAGE (self), &fg);
- ide_page_set_primary_color_bg (IDE_PAGE (self), &bg);
+ panel_widget_set_title (PANEL_WIDGET (self), title);
}
static IdePage *
@@ -380,31 +291,36 @@ ide_terminal_page_create_split (IdePage *page)
NULL);
}
-static void
+static gboolean
ide_terminal_page_grab_focus (GtkWidget *widget)
{
IdeTerminalPage *self = (IdeTerminalPage *)widget;
g_assert (IDE_IS_TERMINAL_PAGE (self));
- gtk_widget_grab_focus (GTK_WIDGET (self->terminal_top));
+ return gtk_widget_grab_focus (GTK_WIDGET (self->terminal));
}
static void
ide_terminal_page_connect_terminal (IdeTerminalPage *self,
VteTerminal *terminal)
{
+ GtkEventController *controller;
+
g_assert (IDE_IS_TERMINAL_PAGE (self));
- g_assert (VTE_IS_TERMINAL (terminal));
+ g_assert (IDE_IS_TERMINAL (terminal));
if (self->destroyed)
return;
- g_signal_connect_object (terminal,
- "focus-in-event",
+ controller = gtk_event_controller_focus_new ();
+ g_signal_connect_object (controller,
+ "enter",
G_CALLBACK (focus_in_event_cb),
self,
0);
+ gtk_widget_add_controller (GTK_WIDGET (terminal), controller);
+
g_signal_connect_object (terminal,
"window-title-changed",
@@ -431,18 +347,14 @@ ide_terminal_page_context_set (GtkWidget *widget,
g_assert (IDE_IS_TERMINAL_PAGE (self));
g_assert (!context || IDE_IS_CONTEXT (context));
- if (self->launcher == NULL && context != NULL)
- self->launcher = ide_terminal_launcher_new (context);
-}
-
-static void
-ide_terminal_page_on_text_inserted_cb (IdeTerminalPage *self,
- VteTerminal *terminal)
-{
- g_assert (IDE_IS_TERMINAL_PAGE (self));
- g_assert (VTE_IS_TERMINAL (terminal));
+ if (context == NULL)
+ return;
- g_signal_emit (self, signals [TEXT_INSERTED], 0);
+ if (self->launcher == NULL)
+ {
+ g_autoptr(IdeRunCommand) run_command = ide_terminal_run_command_new (IDE_TERMINAL_RUN_ON_HOST);
+ self->launcher = ide_terminal_launcher_new (context, run_command);
+ }
}
static GFile *
@@ -456,8 +368,8 @@ ide_terminal_page_get_file_or_directory (IdePage *page)
if (self->destroyed)
return NULL;
- if (!(uri = vte_terminal_get_current_file_uri (VTE_TERMINAL (self->terminal_top))))
- uri = vte_terminal_get_current_directory_uri (VTE_TERMINAL (self->terminal_top));
+ if (!(uri = vte_terminal_get_current_file_uri (VTE_TERMINAL (self->terminal))))
+ uri = vte_terminal_get_current_directory_uri (VTE_TERMINAL (self->terminal));
if (uri != NULL)
return g_file_new_for_uri (uri);
@@ -466,26 +378,18 @@ ide_terminal_page_get_file_or_directory (IdePage *page)
}
static void
-ide_terminal_page_destroy (GtkWidget *widget)
+ide_terminal_page_dispose (GObject *object)
{
- IdeTerminalPage *self = (IdeTerminalPage *)widget;
+ IdeTerminalPage *self = IDE_TERMINAL_PAGE (object);
self->destroyed = TRUE;
- GTK_WIDGET_CLASS (ide_terminal_page_parent_class)->destroy (widget);
-}
-
-static void
-ide_terminal_page_finalize (GObject *object)
-{
- IdeTerminalPage *self = IDE_TERMINAL_PAGE (object);
-
g_clear_object (&self->launcher);
- g_clear_object (&self->save_as_file_top);
+ g_clear_object (&self->save_as_file);
g_clear_pointer (&self->selection_buffer, g_free);
g_clear_object (&self->pty);
- G_OBJECT_CLASS (ide_terminal_page_parent_class)->finalize (object);
+ G_OBJECT_CLASS (ide_terminal_page_parent_class)->dispose (object);
}
static void
@@ -565,22 +469,19 @@ ide_terminal_page_class_init (IdeTerminalPageClass *klass)
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
IdePageClass *page_class = IDE_PAGE_CLASS (klass);
- object_class->finalize = ide_terminal_page_finalize;
+ object_class->dispose = ide_terminal_page_dispose;
object_class->get_property = ide_terminal_page_get_property;
object_class->set_property = ide_terminal_page_set_property;
widget_class->realize = ide_terminal_page_realize;
- widget_class->get_preferred_width = ide_terminal_page_get_preferred_width;
- widget_class->get_preferred_height = ide_terminal_page_get_preferred_height;
widget_class->grab_focus = ide_terminal_page_grab_focus;
- widget_class->destroy = ide_terminal_page_destroy;
page_class->create_split = ide_terminal_page_create_split;
page_class->get_file_or_directory = ide_terminal_page_get_file_or_directory;
gtk_widget_class_set_template_from_resource (widget_class,
"/org/gnome/libide-terminal/ui/ide-terminal-page.ui");
- gtk_widget_class_bind_template_child (widget_class, IdeTerminalPage, terminal_top);
- gtk_widget_class_bind_template_child (widget_class, IdeTerminalPage, terminal_overlay_top);
+ gtk_widget_class_bind_template_child (widget_class, IdeTerminalPage, terminal);
+ gtk_widget_class_bind_template_child (widget_class, IdeTerminalPage, terminal_overlay);
properties [PROP_CLOSE_ON_EXIT] =
g_param_spec_boolean ("close-on-exit",
@@ -615,28 +516,14 @@ ide_terminal_page_class_init (IdeTerminalPageClass *klass)
"Launcher",
"The launcher to use for spawning",
IDE_TYPE_TERMINAL_LAUNCHER,
- (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ (G_PARAM_READWRITE | G_PARAM_EXPLICIT_NOTIFY | G_PARAM_STATIC_STRINGS));
g_object_class_install_properties (object_class, N_PROPS, properties);
-
- signals [TEXT_INSERTED] =
- g_signal_new ("text-inserted",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST,
- 0,
- NULL, NULL,
- g_cclosure_marshal_VOID__VOID,
- G_TYPE_NONE, 0);
- g_signal_set_va_marshaller (signals [TEXT_INSERTED],
- G_TYPE_FROM_CLASS (klass),
- g_cclosure_marshal_VOID__VOIDv);
}
static void
ide_terminal_page_init (IdeTerminalPage *self)
{
- GtkStyleContext *style_context;
-
self->close_on_exit = TRUE;
self->respawn_on_exit = TRUE;
self->manage_spawn = TRUE;
@@ -644,40 +531,39 @@ ide_terminal_page_init (IdeTerminalPage *self)
self->tsearch = g_object_new (IDE_TYPE_TERMINAL_SEARCH,
"visible", TRUE,
NULL);
- self->search_revealer_top = ide_terminal_search_get_revealer (self->tsearch);
+ self->search_revealer = ide_terminal_search_get_revealer (self->tsearch);
gtk_widget_init_template (GTK_WIDGET (self));
- g_signal_connect_object (self->terminal_top,
- "text-inserted",
- G_CALLBACK (ide_terminal_page_on_text_inserted_cb),
- self,
- G_CONNECT_SWAPPED);
-
- ide_page_set_icon_name (IDE_PAGE (self), "builder-terminal-symbolic");
+ panel_widget_set_icon_name (PANEL_WIDGET (self), "builder-terminal-symbolic");
ide_page_set_can_split (IDE_PAGE (self), TRUE);
ide_page_set_menu_id (IDE_PAGE (self), "ide-terminal-page-document-menu");
- gtk_overlay_add_overlay (self->terminal_overlay_top, GTK_WIDGET (self->tsearch));
+ gtk_overlay_add_overlay (self->terminal_overlay, GTK_WIDGET (self->tsearch));
- ide_terminal_page_connect_terminal (self, VTE_TERMINAL (self->terminal_top));
+ ide_terminal_page_connect_terminal (self, VTE_TERMINAL (self->terminal));
- ide_terminal_search_set_terminal (self->tsearch, VTE_TERMINAL (self->terminal_top));
+ ide_terminal_search_set_terminal (self->tsearch, VTE_TERMINAL (self->terminal));
ide_terminal_page_actions_init (self);
- style_context = gtk_widget_get_style_context (GTK_WIDGET (self->terminal_top));
- gtk_style_context_add_class (style_context, "terminal");
- g_signal_connect_object (style_context,
- "changed",
- G_CALLBACK (style_context_changed),
- self,
- 0);
- style_context_changed (style_context, self);
+ ide_widget_set_context_handler (self, ide_terminal_page_context_set);
+}
- gtk_widget_set_can_focus (GTK_WIDGET (self->terminal_top), TRUE);
+/**
+ * ide_terminal_page_get_pty:
+ * @self: a #IdeTerminalPage
+ *
+ * Gets the #VtePty for the page.
+ *
+ * Returns: (transfer none): a #VtePty
+ */
+VtePty *
+ide_terminal_page_get_pty (IdeTerminalPage *self)
+{
+ g_return_val_if_fail (IDE_IS_TERMINAL_PAGE (self), NULL);
- ide_widget_set_context_handler (self, ide_terminal_page_context_set);
+ return self->pty;
}
void
@@ -692,8 +578,8 @@ ide_terminal_page_set_pty (IdeTerminalPage *self,
if (g_set_object (&self->pty, pty))
{
- vte_terminal_reset (VTE_TERMINAL (self->terminal_top), TRUE, TRUE);
- vte_terminal_set_pty (VTE_TERMINAL (self->terminal_top), pty);
+ vte_terminal_reset (VTE_TERMINAL (self->terminal), TRUE, TRUE);
+ vte_terminal_set_pty (VTE_TERMINAL (self->terminal), pty);
}
}
@@ -704,8 +590,8 @@ ide_terminal_page_feed (IdeTerminalPage *self,
g_return_if_fail (IDE_IS_TERMINAL_PAGE (self));
g_return_if_fail (self->destroyed == FALSE);
- if (self->terminal_top != NULL)
- vte_terminal_feed (VTE_TERMINAL (self->terminal_top), message, -1);
+ if (self->terminal != NULL)
+ vte_terminal_feed (VTE_TERMINAL (self->terminal), message, -1);
}
void
@@ -718,21 +604,8 @@ ide_terminal_page_set_launcher (IdeTerminalPage *self,
if (g_set_object (&self->launcher, launcher))
{
- gboolean can_split;
-
- if (launcher != NULL)
- {
- const gchar *title = ide_terminal_launcher_get_title (launcher);
- ide_page_set_title (IDE_PAGE (self), title);
- can_split = ide_terminal_launcher_can_respawn (launcher);
- }
- else
- {
- self->manage_spawn = FALSE;
- can_split = FALSE;
- }
-
- ide_page_set_can_split (IDE_PAGE (self), can_split);
+ ide_page_set_can_split (IDE_PAGE (self), TRUE);
+ g_object_notify_by_pspec (G_OBJECT (self), properties [PROP_LAUNCHER]);
}
}
@@ -742,5 +615,29 @@ ide_terminal_page_get_current_directory_uri (IdeTerminalPage *self)
g_return_val_if_fail (IDE_IS_TERMINAL_PAGE (self), NULL);
g_return_val_if_fail (self->destroyed == FALSE, NULL);
- return vte_terminal_get_current_directory_uri (VTE_TERMINAL (self->terminal_top));
+ return vte_terminal_get_current_directory_uri (VTE_TERMINAL (self->terminal));
+}
+
+/**
+ * ide_terminal_page_get_launcher:
+ * @self: a #IdeTerminalPage
+ *
+ * Gets the launcher for the page.
+ *
+ * Returns: (transfer none) (nullable): an #IdeTerminalLauncher or %NULL
+ */
+IdeTerminalLauncher *
+ide_terminal_page_get_launcher (IdeTerminalPage *self)
+{
+ g_return_val_if_fail (IDE_IS_TERMINAL_PAGE (self), NULL);
+
+ return self->launcher;
+}
+
+gboolean
+ide_terminal_page_has_exited (IdeTerminalPage *self)
+{
+ g_return_val_if_fail (IDE_IS_TERMINAL_PAGE (self), FALSE);
+
+ return self->exited;
}
diff --git a/src/libide/terminal/ide-terminal-page.h b/src/libide/terminal/ide-terminal-page.h
index 5e2211a4d..c6dc9d4ce 100644
--- a/src/libide/terminal/ide-terminal-page.h
+++ b/src/libide/terminal/ide-terminal-page.h
@@ -34,19 +34,25 @@ G_BEGIN_DECLS
#define IDE_TYPE_TERMINAL_PAGE (ide_terminal_page_get_type())
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (IdeTerminalPage, ide_terminal_page, IDE, TERMINAL_PAGE, IdePage)
-IDE_AVAILABLE_IN_3_34
-void ide_terminal_page_set_launcher (IdeTerminalPage *self,
- IdeTerminalLauncher *launcher);
-IDE_AVAILABLE_IN_3_32
-void ide_terminal_page_set_pty (IdeTerminalPage *self,
- VtePty *pty);
-IDE_AVAILABLE_IN_3_32
-void ide_terminal_page_feed (IdeTerminalPage *self,
- const gchar *message);
-IDE_AVAILABLE_IN_3_34
-const gchar *ide_terminal_page_get_current_directory_uri (IdeTerminalPage *self);
+IDE_AVAILABLE_IN_ALL
+void ide_terminal_page_set_launcher (IdeTerminalPage *self,
+ IdeTerminalLauncher *launcher);
+IDE_AVAILABLE_IN_ALL
+IdeTerminalLauncher *ide_terminal_page_get_launcher (IdeTerminalPage *self);
+IDE_AVAILABLE_IN_ALL
+VtePty *ide_terminal_page_get_pty (IdeTerminalPage *self);
+IDE_AVAILABLE_IN_ALL
+void ide_terminal_page_set_pty (IdeTerminalPage *self,
+ VtePty *pty);
+IDE_AVAILABLE_IN_ALL
+void ide_terminal_page_feed (IdeTerminalPage *self,
+ const gchar *message);
+IDE_AVAILABLE_IN_ALL
+const gchar *ide_terminal_page_get_current_directory_uri (IdeTerminalPage *self);
+IDE_AVAILABLE_IN_ALL
+gboolean ide_terminal_page_has_exited (IdeTerminalPage *self);
G_END_DECLS
diff --git a/src/libide/terminal/ide-terminal-page.ui b/src/libide/terminal/ide-terminal-page.ui
index a8575b47e..81b06cdef 100644
--- a/src/libide/terminal/ide-terminal-page.ui
+++ b/src/libide/terminal/ide-terminal-page.ui
@@ -1,26 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <!-- interface-requires gtk+ 3.16 -->
<template class="IdeTerminalPage" parent="IdePage">
- <property name="visible">true</property>
+ <property name="can-maximize">true</property>
+ <property name="hexpand">true</property>
+ <property name="vexpand">true</property>
+ <property name="title" translatable="yes">Untitled Terminal</property>
<child>
<object class="GtkPaned" id="paned">
- <property name="expand">true</property>
<property name="orientation">vertical</property>
- <property name="visible">true</property>
<child>
- <object class="GtkOverlay" id="terminal_overlay_top">
- <property name="expand">true</property>
- <property name="visible">true</property>
+ <object class="GtkOverlay" id="terminal_overlay">
<child>
<object class="GtkScrolledWindow">
- <property name="expand">true</property>
- <property name="visible">true</property>
<child>
- <object class="IdeTerminal" id="terminal_top">
+ <object class="IdeTerminal" id="terminal">
<property name="audible-bell">false</property>
- <property name="expand">true</property>
- <property name="visible">true</property>
+ <property name="hexpand">true</property>
+ <property name="vexpand">true</property>
</object>
</child>
</object>
diff --git a/src/libide/terminal/ide-terminal-popover.c b/src/libide/terminal/ide-terminal-popover.c
index efb81519f..db5366c8a 100644
--- a/src/libide/terminal/ide-terminal-popover.c
+++ b/src/libide/terminal/ide-terminal-popover.c
@@ -22,7 +22,6 @@
#include "config.h"
-#include <dazzle.h>
#include <libide-foundry.h>
#include <libide-gui.h>
@@ -33,7 +32,7 @@ struct _IdeTerminalPopover
{
GtkPopover parent_instance;
- DzlListModelFilter *filter;
+ GtkFilterListModel *filter;
gchar *selected;
/* Template widgets */
@@ -43,21 +42,6 @@ struct _IdeTerminalPopover
G_DEFINE_FINAL_TYPE (IdeTerminalPopover, ide_terminal_popover, GTK_TYPE_POPOVER)
-static void
-ide_terminal_popover_update_selected_cb (GtkWidget *widget,
- gpointer user_data)
-{
- IdeTerminalPopoverRow *row = (IdeTerminalPopoverRow *)widget;
- IdeRuntime *runtime = user_data;
- gboolean selected;
-
- g_assert (IDE_IS_TERMINAL_POPOVER_ROW (row));
- g_assert (IDE_IS_RUNTIME (runtime));
-
- selected = runtime == ide_terminal_popover_row_get_runtime (row);
- ide_terminal_popover_row_set_selected (row, selected);
-}
-
static void
ide_terminal_popover_row_activated_cb (IdeTerminalPopover *self,
IdeTerminalPopoverRow *row,
@@ -74,9 +58,10 @@ ide_terminal_popover_row_activated_cb (IdeTerminalPopover *self,
g_free (self->selected);
self->selected = g_strdup (ide_runtime_get_id (runtime));
- gtk_container_foreach (GTK_CONTAINER (self->list_box),
- ide_terminal_popover_update_selected_cb,
- runtime);
+ for (GtkWidget *child = gtk_widget_get_first_child (GTK_WIDGET (self->list_box));
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ ide_terminal_popover_row_set_selected (row, runtime == ide_terminal_popover_row_get_runtime (row));
}
static GtkWidget *
@@ -96,23 +81,23 @@ ide_terminal_popover_create_row_cb (gpointer item,
}
static gboolean
-ide_terminal_popover_filter_func (GObject *item,
- gpointer user_data)
+ide_terminal_popover_filter_func (gpointer item,
+ gpointer user_data)
{
- DzlPatternSpec *spec = user_data;
- IdeRuntime *runtime = IDE_RUNTIME (item);
+ IdePatternSpec *spec = user_data;
+ IdeRuntime *runtime = item;
const gchar *str;
str = ide_runtime_get_id (runtime);
- if (dzl_pattern_spec_match (spec, str))
+ if (ide_pattern_spec_match (spec, str))
return TRUE;
str = ide_runtime_get_category (runtime);
- if (dzl_pattern_spec_match (spec, str))
+ if (ide_pattern_spec_match (spec, str))
return TRUE;
str = ide_runtime_get_display_name (runtime);
- if (dzl_pattern_spec_match (spec, str))
+ if (ide_pattern_spec_match (spec, str))
return TRUE;
return FALSE;
@@ -122,6 +107,7 @@ static void
ide_terminal_popover_search_changed_cb (IdeTerminalPopover *self,
GtkSearchEntry *entry)
{
+ GtkCustomFilter *filter;
const gchar *text;
g_assert (IDE_IS_TERMINAL_POPOVER (self));
@@ -130,14 +116,14 @@ ide_terminal_popover_search_changed_cb (IdeTerminalPopover *self,
if (self->filter == NULL)
return;
- text = gtk_entry_get_text (GTK_ENTRY (entry));
+ text = gtk_editable_get_text (GTK_EDITABLE (entry));
if (ide_str_empty0 (text))
text = NULL;
- dzl_list_model_filter_set_filter_func (self->filter,
- ide_terminal_popover_filter_func,
- dzl_pattern_spec_new (text),
- (GDestroyNotify) dzl_pattern_spec_unref);
+ filter = gtk_custom_filter_new (ide_terminal_popover_filter_func,
+ ide_pattern_spec_new (text),
+ (GDestroyNotify) ide_pattern_spec_unref);
+ gtk_filter_list_model_set_filter (self->filter, GTK_FILTER (filter));
}
static void
@@ -171,7 +157,7 @@ ide_terminal_popover_context_set_cb (GtkWidget *widget,
}
g_clear_object (&self->filter);
- self->filter = dzl_list_model_filter_new (G_LIST_MODEL (runtime_manager));
+ self->filter = gtk_filter_list_model_new (g_object_ref (G_LIST_MODEL (runtime_manager)), NULL);
gtk_list_box_bind_model (self->list_box,
G_LIST_MODEL (self->filter),
@@ -222,8 +208,6 @@ ide_terminal_popover_new (void)
* @self: a #IdeTerminalPopover
*
* Returns: (transfer none): an #IdeRuntime or %NULL
- *
- * Since: 3.32
*/
IdeRuntime *
ide_terminal_popover_get_runtime (IdeTerminalPopover *self)
diff --git a/src/libide/terminal/ide-terminal-popover.h b/src/libide/terminal/ide-terminal-popover.h
index 0d6a46105..247e60d0b 100644
--- a/src/libide/terminal/ide-terminal-popover.h
+++ b/src/libide/terminal/ide-terminal-popover.h
@@ -33,12 +33,12 @@ G_BEGIN_DECLS
#define IDE_TYPE_TERMINAL_POPOVER (ide_terminal_popover_get_type())
-IDE_AVAILABLE_IN_3_34
+IDE_AVAILABLE_IN_ALL
G_DECLARE_FINAL_TYPE (IdeTerminalPopover, ide_terminal_popover, IDE, TERMINAL_POPOVER, GtkPopover)
-IDE_AVAILABLE_IN_3_34
+IDE_AVAILABLE_IN_ALL
GtkWidget *ide_terminal_popover_new (void);
-IDE_AVAILABLE_IN_3_34
+IDE_AVAILABLE_IN_ALL
IdeRuntime *ide_terminal_popover_get_runtime (IdeTerminalPopover *self);
G_END_DECLS
diff --git a/src/libide/terminal/ide-terminal-private.h b/src/libide/terminal/ide-terminal-private.h
index 9b53f3b25..d9015f5b6 100644
--- a/src/libide/terminal/ide-terminal-private.h
+++ b/src/libide/terminal/ide-terminal-private.h
@@ -1,6 +1,6 @@
/* ide-terminal-private.h
*
- * Copyright 2018-2019 Christian Hergert <chergert redhat com>
+ * Copyright 2022 Christian Hergert <chergert redhat com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -24,6 +24,6 @@
G_BEGIN_DECLS
-void _ide_guess_shell (void);
+void _ide_terminal_init (void);
G_END_DECLS
diff --git a/src/libide/terminal/ide-terminal-surface.h
b/src/libide/terminal/ide-terminal-run-command-private.h
similarity index 56%
rename from src/libide/terminal/ide-terminal-surface.h
rename to src/libide/terminal/ide-terminal-run-command-private.h
index 4921aef4e..0ae78f6b8 100644
--- a/src/libide/terminal/ide-terminal-surface.h
+++ b/src/libide/terminal/ide-terminal-run-command-private.h
@@ -1,6 +1,6 @@
-/* ide-terminal-surface.h
+/* ide-terminal-run-command-private.h
*
- * Copyright 2018 Christian Hergert <unknown domain org>
+ * Copyright 2022 Christian Hergert <chergert redhat com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -20,20 +20,24 @@
#pragma once
-#if !defined (IDE_TERMINAL_INSIDE) && !defined (IDE_TERMINAL_COMPILATION)
-# error "Only <libide-terminal.h> can be included directly."
-#endif
-
-#include <libide-gui.h>
+#include <libide-foundry.h>
G_BEGIN_DECLS
-#define IDE_TYPE_TERMINAL_SURFACE (ide_terminal_surface_get_type())
+#define IDE_TYPE_TERMINAL_RUN_COMMAND (ide_terminal_run_command_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeTerminalRunCommand, ide_terminal_run_command, IDE, TERMINAL_RUN_COMMAND,
IdeRunCommand)
+
+typedef enum
+{
+ IDE_TERMINAL_RUN_ON_HOST,
+ IDE_TERMINAL_RUN_AS_SUBPROCESS,
+ IDE_TERMINAL_RUN_IN_PIPELINE,
+ IDE_TERMINAL_RUN_IN_RUNTIME,
-IDE_AVAILABLE_IN_3_32
-G_DECLARE_FINAL_TYPE (IdeTerminalSurface, ide_terminal_surface, IDE, TERMINAL_SURFACE, IdeSurface)
+ IDE_TERMINAL_RUN_LAST
+} IdeTerminalRunLocality;
-IDE_AVAILABLE_IN_3_32
-IdeTerminalSurface *ide_terminal_surface_new (void);
+IdeRunCommand *ide_terminal_run_command_new (IdeTerminalRunLocality locality);
G_END_DECLS
diff --git a/src/libide/terminal/ide-terminal-run-command.c b/src/libide/terminal/ide-terminal-run-command.c
new file mode 100644
index 000000000..03cbe65d3
--- /dev/null
+++ b/src/libide/terminal/ide-terminal-run-command.c
@@ -0,0 +1,144 @@
+/* ide-terminal-run-command.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "ide-terminal-run-command"
+
+#include "config.h"
+
+#include <libide-io.h>
+
+#include "ide-terminal-run-command-private.h"
+
+struct _IdeTerminalRunCommand
+{
+ IdeRunCommand parent_instance;
+ IdeTerminalRunLocality locality;
+};
+
+G_DEFINE_FINAL_TYPE (IdeTerminalRunCommand, ide_terminal_run_command, IDE_TYPE_RUN_COMMAND)
+
+static void
+ide_terminal_run_command_prepare_to_run (IdeRunCommand *run_command,
+ IdeRunContext *run_context,
+ IdeContext *context)
+{
+ IdeTerminalRunCommand *self = (IdeTerminalRunCommand *)run_command;
+ const char *user_shell;
+
+ IDE_ENTRY;
+
+ g_assert (IDE_IS_MAIN_THREAD ());
+ g_assert (IDE_IS_TERMINAL_RUN_COMMAND (self));
+ g_assert (IDE_IS_RUN_CONTEXT (run_context));
+ g_assert (IDE_IS_CONTEXT (context));
+
+ user_shell = ide_get_user_shell ();
+
+ switch (self->locality)
+ {
+ case IDE_TERMINAL_RUN_ON_HOST:
+ ide_run_context_push_host (run_context);
+ ide_run_context_add_minimal_environment (run_context);
+ ide_run_context_append_argv (run_context, user_shell);
+ if (ide_shell_supports_dash_login (user_shell))
+ ide_run_context_append_argv (run_context, "--login");
+ break;
+
+ case IDE_TERMINAL_RUN_AS_SUBPROCESS:
+ ide_run_context_add_minimal_environment (run_context);
+ if (g_find_program_in_path (user_shell))
+ {
+ ide_run_context_append_argv (run_context, user_shell);
+ if (ide_shell_supports_dash_login (user_shell))
+ ide_run_context_append_argv (run_context, "--login");
+ }
+ else
+ {
+ ide_run_context_append_argv (run_context, "/bin/sh");
+ ide_run_context_append_argv (run_context, "--login");
+ }
+ break;
+
+ case IDE_TERMINAL_RUN_IN_RUNTIME:
+ case IDE_TERMINAL_RUN_IN_PIPELINE:
+ {
+ IdeBuildManager *build_manager;
+ IdePipeline *pipeline;
+ IdeRuntime *runtime;
+
+ if (!ide_context_has_project (context) ||
+ !(build_manager = ide_build_manager_from_context (context)) ||
+ !(pipeline = ide_build_manager_get_pipeline (build_manager)) ||
+ !(runtime = ide_pipeline_get_runtime (pipeline)))
+ {
+ ide_run_context_push_error (run_context,
+ g_error_new (G_IO_ERROR,
+ G_IO_ERROR_NOT_INITIALIZED,
+ "Cannot spawn terminal without a pipeline"));
+ break;
+ }
+
+ if (!ide_runtime_contains_program_in_path (runtime, user_shell, NULL))
+ user_shell = "/bin/sh";
+
+ if (self->locality == IDE_TERMINAL_RUN_IN_PIPELINE)
+ ide_pipeline_prepare_run_context (pipeline, run_context);
+ else
+ ide_runtime_prepare_to_run (runtime, pipeline, run_context);
+
+ ide_run_context_append_argv (run_context, user_shell);
+ if (ide_shell_supports_dash_login (user_shell))
+ ide_run_context_append_argv (run_context, "--login");
+ }
+ break;
+
+ case IDE_TERMINAL_RUN_LAST:
+ default:
+ g_assert_not_reached ();
+ }
+
+ IDE_RUN_COMMAND_CLASS (ide_terminal_run_command_parent_class)->prepare_to_run (run_command, run_context,
context);
+
+ IDE_EXIT;
+}
+
+static void
+ide_terminal_run_command_class_init (IdeTerminalRunCommandClass *klass)
+{
+ IdeRunCommandClass *run_command_class = IDE_RUN_COMMAND_CLASS (klass);
+
+ run_command_class->prepare_to_run = ide_terminal_run_command_prepare_to_run;
+}
+
+static void
+ide_terminal_run_command_init (IdeTerminalRunCommand *self)
+{
+}
+
+IdeRunCommand *
+ide_terminal_run_command_new (IdeTerminalRunLocality locality)
+{
+ IdeTerminalRunCommand *self;
+
+ self = g_object_new (IDE_TYPE_TERMINAL_RUN_COMMAND, NULL);
+ self->locality = locality;
+
+ return IDE_RUN_COMMAND (self);
+}
diff --git a/src/libide/terminal/ide-terminal-search-private.h
b/src/libide/terminal/ide-terminal-search-private.h
index 2ace9737d..a61e68398 100644
--- a/src/libide/terminal/ide-terminal-search-private.h
+++ b/src/libide/terminal/ide-terminal-search-private.h
@@ -20,20 +20,21 @@
#pragma once
-#include <gtk/gtk.h>
-#include <libide-gui.h>
+#include "ide-terminal-search.h"
+
+#include <libide-gtk.h>
G_BEGIN_DECLS
struct _IdeTerminalSearch
{
- GtkBin parent_instance;
+ AdwBin parent_instance;
VteTerminal *terminal;
GtkRevealer *search_revealer;
- IdeTaggedEntry *search_entry;
+ IdeSearchEntry *search_entry;
GtkButton *search_prev_button;
GtkButton *search_next_button;
@@ -52,7 +53,6 @@ struct _IdeTerminalSearch
gchar *regex_pattern;
VteRegex *regex;
- GtkClipboard *clipboard;
gchar *selected_text;
gchar *selection_buffer;
};
diff --git a/src/libide/terminal/ide-terminal-search.c b/src/libide/terminal/ide-terminal-search.c
index a7e1c5627..2d96fa62e 100644
--- a/src/libide/terminal/ide-terminal-search.c
+++ b/src/libide/terminal/ide-terminal-search.c
@@ -24,16 +24,19 @@
#include "config.h"
#include <fcntl.h>
-#include <glib/gi18n.h>
#include <pcre2.h>
#include <stdlib.h>
-#include <vte/vte.h>
#include <unistd.h>
+#include <glib/gi18n.h>
+#include <vte/vte.h>
+
+#include <libide-gtk.h>
+
#include "ide-terminal-search.h"
#include "ide-terminal-search-private.h"
-G_DEFINE_FINAL_TYPE (IdeTerminalSearch, ide_terminal_search, GTK_TYPE_BIN)
+G_DEFINE_FINAL_TYPE (IdeTerminalSearch, ide_terminal_search, ADW_TYPE_BIN)
enum {
PROP_0,
@@ -101,7 +104,7 @@ update_regex (IdeTerminalSearch *self)
g_assert (IDE_IS_TERMINAL_SEARCH (self));
- search_text = gtk_entry_get_text (GTK_ENTRY (self->search_entry));
+ search_text = gtk_editable_get_text (GTK_EDITABLE (self->search_entry));
caseless = !gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->match_case_checkbutton));
if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (self->regex_checkbutton)))
@@ -150,7 +153,7 @@ update_regex (IdeTerminalSearch *self)
}
static void
-search_text_changed_cb (IdeTaggedEntry *search_entry,
+search_text_changed_cb (IdeSearchEntry *search_entry,
IdeTerminalSearch *self)
{
update_regex (self);
@@ -232,12 +235,19 @@ search_revealer_cb (GtkRevealer *search_revealer,
if (gtk_revealer_get_child_revealed (search_revealer))
{
+#if 0
if (vte_terminal_get_has_selection (self->terminal))
{
vte_terminal_copy_primary (self->terminal);
- self->selected_text = gtk_clipboard_wait_for_text (self->clipboard);
- gtk_entry_set_text (GTK_ENTRY (self->search_entry), self->selected_text);
+
+ g_clear_pointer (&self->selected_text, g_free);
+
+ /* TODO: Wait for async text read */
+
+ gtk_editable_set_text (GTK_EDITABLE (self->search_entry), self->selected_text);
}
+#endif
+
gtk_widget_grab_focus (GTK_WIDGET (self->search_entry));
}
else
@@ -246,6 +256,17 @@ search_revealer_cb (GtkRevealer *search_revealer,
}
}
+static void
+search_hide_action (GtkWidget *widget,
+ const char *action_name,
+ GVariant *param)
+{
+ IdeTerminalSearch *self = IDE_TERMINAL_SEARCH (widget);
+
+ gtk_revealer_set_reveal_child (self->search_revealer, FALSE);
+ gtk_widget_grab_focus (GTK_WIDGET (self->terminal));
+}
+
static void
ide_terminal_search_connect_terminal (IdeTerminalSearch *self)
{
@@ -312,6 +333,8 @@ ide_terminal_search_class_init (IdeTerminalSearchClass *klass)
gtk_widget_class_bind_template_child (widget_class, IdeTerminalSearch, search_revealer);
gtk_widget_class_bind_template_child (widget_class, IdeTerminalSearch, search_options);
+ gtk_widget_class_install_action (widget_class, "search.hide", NULL, search_hide_action);
+
signals[SEARCH] =
g_signal_new ("search",
G_OBJECT_CLASS_TYPE (object_class),
@@ -341,14 +364,12 @@ ide_terminal_search_init (IdeTerminalSearch *self)
self->regex_caseless = FALSE;
self->regex_pattern = 0;
- self->clipboard = gtk_clipboard_get (GDK_SELECTION_PRIMARY);
-
gtk_widget_init_template (GTK_WIDGET (self));
g_signal_connect (self->search_prev_button, "clicked", G_CALLBACK (search_button_clicked_cb), self);
g_signal_connect (self->search_next_button, "clicked", G_CALLBACK (search_button_clicked_cb), self);
g_signal_connect (self->close_button, "clicked", G_CALLBACK (close_clicked_cb), self);
- g_signal_connect (self->search_entry, "search-changed", G_CALLBACK (search_text_changed_cb), self);
+ g_signal_connect (self->search_entry, "changed", G_CALLBACK (search_text_changed_cb), self);
g_signal_connect (self->match_case_checkbutton, "toggled", G_CALLBACK (search_parameters_changed_cb),
self);
g_signal_connect (self->entire_word_checkbutton, "toggled", G_CALLBACK (search_parameters_changed_cb),
self);
g_signal_connect (self->regex_checkbutton, "toggled", G_CALLBACK (search_parameters_changed_cb), self);
@@ -360,8 +381,6 @@ ide_terminal_search_init (IdeTerminalSearch *self)
/**
* ide_terminal_search_set_terminal:
* @self: a #IdeTerminalSearch
- *
- * Since: 3.32
*/
void
ide_terminal_search_set_terminal (IdeTerminalSearch *self,
@@ -378,8 +397,6 @@ ide_terminal_search_set_terminal (IdeTerminalSearch *self,
* @self: a #IdeTerminalSearch
*
* Returns: (transfer none) (nullable): a #VteRegex or %NULL.
- *
- * Since: 3.32
*/
VteRegex *
ide_terminal_search_get_regex (IdeTerminalSearch *self)
@@ -394,7 +411,6 @@ ide_terminal_search_get_regex (IdeTerminalSearch *self)
* @self: a #IdeTerminalSearch
*
*
- * Since: 3.32
*/
gboolean
ide_terminal_search_get_wrap_around (IdeTerminalSearch *self)
@@ -411,8 +427,6 @@ ide_terminal_search_get_wrap_around (IdeTerminalSearch *self)
* Gets the revealer widget used for the terminal search.
*
* Returns: (transfer none): a #GtkRevealer
- *
- * Since: 3.32
*/
GtkRevealer *
ide_terminal_search_get_revealer (IdeTerminalSearch *self)
diff --git a/src/libide/terminal/ide-terminal-search.h b/src/libide/terminal/ide-terminal-search.h
index 1081b0d05..bacee6b00 100644
--- a/src/libide/terminal/ide-terminal-search.h
+++ b/src/libide/terminal/ide-terminal-search.h
@@ -4,7 +4,7 @@
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
+ * the Free Software Foundation, either version ALL the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
@@ -15,7 +15,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
- * SPDX-License-Identifier: GPL-3.0-or-later
+ * SPDX-License-Identifier: GPL-ALLor-later
*/
#pragma once
@@ -24,24 +24,26 @@
# error "Only <libide-terminal.h> can be included directly."
#endif
+#include <adwaita.h>
#include <vte/vte.h>
+
#include <libide-core.h>
G_BEGIN_DECLS
#define IDE_TYPE_TERMINAL_SEARCH (ide_terminal_search_get_type())
-IDE_AVAILABLE_IN_3_32
-G_DECLARE_FINAL_TYPE (IdeTerminalSearch, ide_terminal_search, IDE, TERMINAL_SEARCH, GtkBin)
+IDE_AVAILABLE_IN_ALL
+G_DECLARE_FINAL_TYPE (IdeTerminalSearch, ide_terminal_search, IDE, TERMINAL_SEARCH, AdwBin)
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
VteRegex *ide_terminal_search_get_regex (IdeTerminalSearch *self);
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
gboolean ide_terminal_search_get_wrap_around (IdeTerminalSearch *self);
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
void ide_terminal_search_set_terminal (IdeTerminalSearch *self,
VteTerminal *terminal);
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
GtkRevealer *ide_terminal_search_get_revealer (IdeTerminalSearch *self);
G_END_DECLS
diff --git a/src/libide/terminal/ide-terminal-search.ui b/src/libide/terminal/ide-terminal-search.ui
index e349e8927..bf995f65b 100644
--- a/src/libide/terminal/ide-terminal-search.ui
+++ b/src/libide/terminal/ide-terminal-search.ui
@@ -1,214 +1,141 @@
<?xml version="1.0" encoding="UTF-8"?>
<interface>
- <template class="IdeTerminalSearch" parent="GtkBin">
+ <template class="IdeTerminalSearch" parent="AdwBin">
<property name="halign">end</property>
<property name="valign">start</property>
<child>
<object class="GtkRevealer" id="search_revealer">
- <property name="visible">true</property>
<child>
- <object class="GtkFrame">
- <property name="visible">true</property>
+ <object class="GtkBox">
+ <property name="orientation">vertical</property>
+ <property name="spacing">7</property>
<property name="margin-end">12</property>
<style>
- <class name="search-frame"/>
+ <class name="searchbar"/>
</style>
<child>
- <object class="GtkBox">
- <property name="visible">true</property>
- <property name="orientation">vertical</property>
- <property name="spacing">7</property>
+ <object class="GtkGrid">
+ <property name="row_spacing">8</property>
+ <property name="column_spacing">8</property>
<child>
- <object class="GtkGrid">
- <property name="visible">true</property>
- <property name="can_focus">false</property>
- <property name="row_spacing">8</property>
- <property name="column_spacing">8</property>
- <child>
- <object class="IdeTaggedEntry" id="search_entry">
- <property name="visible">true</property>
- <property name="can_focus">true</property>
- <property name="width-chars">20</property>
- <property name="max-width-chars">30</property>
- <property name="primary_icon_name">edit-find-symbolic</property>
- <property name="primary_icon_activatable">false</property>
- <property name="primary_icon_sensitive">false</property>
- </object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkBox">
- <property name="homogeneous">true</property>
- <property name="visible">true</property>
- <property name="can_focus">false</property>
- <property name="valign">center</property>
- <style>
- <class name="linked"/>
- </style>
- <child>
- <object class="GtkButton" id="search_prev_button">
- <property name="visible">true</property>
- <property name="can_focus">false</property>
- <property name="receives_default">true</property>
- <child>
- <object class="GtkImage">
- <property name="visible">true</property>
- <property name="can_focus">false</property>
- <property name="icon_name">go-up-symbolic</property>
- <property name="icon_size">1</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">false</property>
- <property name="fill">true</property>
- <property name="position">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkButton" id="search_next_button">
- <property name="visible">true</property>
- <property name="can_focus">false</property>
- <property name="receives_default">true</property>
- <child>
- <object class="GtkImage">
- <property name="visible">true</property>
- <property name="can_focus">false</property>
- <property name="icon_name">go-down-symbolic</property>
- <property name="icon_size">1</property>
- </object>
- </child>
- </object>
- <packing>
- <property name="expand">false</property>
- <property name="fill">true</property>
- <property name="position">1</property>
- </packing>
- </child>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
+ <object class="IdeSearchEntry" id="search_entry">
+ <property name="width-chars">20</property>
+ <property name="max-width-chars">30</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkBox">
+ <property name="homogeneous">true</property>
+ <property name="valign">center</property>
+ <style>
+ <class name="linked"/>
+ </style>
<child>
- <object class="GtkToggleButton" id="reveal_button">
- <property name="action-target">true</property>
- <property name="tooltip-text" translatable="yes">Show or hide search options such as
case sensitivity</property>
- <property name="visible">true</property>
- <property name="can_focus">true</property>
- <property name="receives_default">true</property>
+ <object class="GtkButton" id="search_prev_button">
<child>
<object class="GtkImage">
- <property name="visible">true</property>
- <property name="can_focus">false</property>
- <property name="icon_name">emblem-system-symbolic</property>
+ <property name="icon_name">go-up-symbolic</property>
+ <property name="icon_size">1</property>
</object>
</child>
</object>
- <packing>
- <property name="left_attach">2</property>
- <property name="top_attach">0</property>
- </packing>
</child>
<child>
- <object class="GtkButton" id="close_button">
- <property name="visible">true</property>
- <property name="halign">center</property>
- <property name="valign">center</property>
- <property name="focus_on_click">false</property>
- <style>
- <class name="close"/>
- </style>
+ <object class="GtkButton" id="search_next_button">
<child>
<object class="GtkImage">
- <property name="visible">true</property>
- <property name="icon_name">window-close-symbolic</property>
+ <property name="icon_name">go-down-symbolic</property>
+ <property name="icon_size">1</property>
</object>
</child>
</object>
- <packing>
- <property name="left_attach">3</property>
- <property name="top_attach">0</property>
- </packing>
</child>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
</object>
- <packing>
- <property name="expand">false</property>
- <property name="fill">true</property>
- <property name="position">0</property>
- </packing>
</child>
<child>
- <object class="GtkGrid" id="search_options">
- <property name="visible">false</property>
- <property name="can_focus">false</property>
- <property name="column_spacing">8</property>
+ <object class="GtkToggleButton" id="reveal_button">
+ <property name="action-target">true</property>
+ <property name="tooltip-text" translatable="yes">Show or hide search options such as
case sensitivity</property>
<child>
- <object class="GtkCheckButton" id="regex_checkbutton">
- <property name="label" translatable="yes">Regex</property>
- <property name="visible">true</property>
- <property name="can_focus">false</property>
- <property name="receives_default">false</property>
- <property name="xalign">0</property>
- <property name="draw_indicator">true</property>
+ <object class="GtkImage">
+ <property name="icon_name">emblem-system-symbolic</property>
</object>
- <packing>
- <property name="left_attach">0</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkCheckButton" id="match_case_checkbutton">
- <property name="label" translatable="yes">Case sensitive</property>
- <property name="visible">true</property>
- <property name="can_focus">false</property>
- <property name="receives_default">false</property>
- <property name="xalign">0</property>
- <property name="draw_indicator">true</property>
- </object>
- <packing>
- <property name="left_attach">1</property>
- <property name="top_attach">0</property>
- </packing>
- </child>
- <child>
- <object class="GtkCheckButton" id="entire_word_checkbutton">
- <property name="label" translatable="yes">Match whole word</property>
- <property name="visible">true</property>
- <property name="can_focus">false</property>
- <property name="receives_default">false</property>
- <property name="xalign">0</property>
- <property name="draw_indicator">true</property>
- </object>
- <packing>
- <property name="left_attach">2</property>
- <property name="top_attach">0</property>
- </packing>
</child>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkButton" id="close_button">
+ <property name="halign">center</property>
+ <property name="valign">center</property>
+ <property name="focus_on_click">false</property>
+ <style>
+ <class name="flat"/>
+ <class name="circular"/>
+ </style>
<child>
- <object class="GtkCheckButton" id="wrap_around_checkbutton">
- <property name="label" translatable="yes">Wrap around</property>
- <property name="visible">true</property>
- <property name="can_focus">false</property>
- <property name="receives_default">false</property>
- <property name="xalign">0</property>
- <property name="draw_indicator">true</property>
+ <object class="GtkImage">
+ <property name="icon_name">window-close-symbolic</property>
</object>
- <packing>
- <property name="left_attach">3</property>
- <property name="top_attach">0</property>
- </packing>
</child>
+ <layout>
+ <property name="column">3</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ </object>
+ </child>
+ <child>
+ <object class="GtkGrid" id="search_options">
+ <property name="visible">false</property>
+ <property name="column_spacing">8</property>
+ <child>
+ <object class="GtkCheckButton" id="regex_checkbutton">
+ <property name="label" translatable="yes">Regex</property>
+ <layout>
+ <property name="column">0</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="match_case_checkbutton">
+ <property name="label" translatable="yes">Case sensitive</property>
+ <layout>
+ <property name="column">1</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="entire_word_checkbutton">
+ <property name="label" translatable="yes">Match whole word</property>
+ <layout>
+ <property name="column">2</property>
+ <property name="row">0</property>
+ </layout>
+ </object>
+ </child>
+ <child>
+ <object class="GtkCheckButton" id="wrap_around_checkbutton">
+ <property name="label" translatable="yes">Wrap around</property>
+ <layout>
+ <property name="column">3</property>
+ <property name="row">0</property>
+ </layout>
</object>
- <packing>
- <property name="expand">false</property>
- <property name="fill">true</property>
- <property name="position">1</property>
- </packing>
</child>
</object>
</child>
diff --git a/src/libide/terminal/ide-terminal-util.c b/src/libide/terminal/ide-terminal-util.c
index 1f2370eed..49f07ef06 100644
--- a/src/libide/terminal/ide-terminal-util.c
+++ b/src/libide/terminal/ide-terminal-util.c
@@ -29,119 +29,18 @@
#include <unistd.h>
#include <vte/vte.h>
-#include "ide-terminal-private.h"
#include "ide-terminal-util.h"
-static const gchar *user_shell = "/bin/sh";
-
-gint
-ide_vte_pty_create_slave (VtePty *pty)
+int
+ide_vte_pty_create_producer (VtePty *pty)
{
- gint master_fd;
+ int consumer_fd;
g_return_val_if_fail (VTE_IS_PTY (pty), IDE_PTY_FD_INVALID);
- master_fd = vte_pty_get_fd (pty);
- if (master_fd == IDE_PTY_FD_INVALID)
+ consumer_fd = vte_pty_get_fd (pty);
+ if (consumer_fd == IDE_PTY_FD_INVALID)
return IDE_PTY_FD_INVALID;
- return ide_pty_intercept_create_slave (master_fd, TRUE);
-}
-
-/**
- * ide_get_user_shell:
- *
- * Gets the user preferred shell on the host.
- *
- * If the background shell discovery has not yet finished due to
- * slow or misconfigured getent on the host, this will provide a
- * sensible fallback.
- *
- * Returns: (not nullable): a shell such as "/bin/sh"
- *
- * Since: 3.32
- */
-const gchar *
-ide_get_user_shell (void)
-{
- return user_shell;
-}
-
-static void
-ide_guess_shell_communicate_cb (GObject *object,
- GAsyncResult *result,
- gpointer user_data)
-{
- IdeSubprocess *subprocess = (IdeSubprocess *)object;
- g_autoptr(GError) error = NULL;
- g_autofree gchar *stdout_buf = NULL;
-
- g_assert (IDE_IS_SUBPROCESS (subprocess));
- g_assert (G_IS_ASYNC_RESULT (result));
- g_assert (user_data == NULL);
-
- if (!ide_subprocess_communicate_utf8_finish (subprocess, result, &stdout_buf, NULL, &error))
- {
- g_warning ("Failed to parse result from getent: %s", error->message);
- return;
- }
-
- if (stdout_buf != NULL)
- {
- g_strstrip (stdout_buf);
-
- if (stdout_buf[0] == '/')
- user_shell = g_steal_pointer (&stdout_buf);
- }
-}
-
-void
-_ide_guess_shell (void)
-{
- g_autoptr(IdeSubprocessLauncher) launcher = NULL;
- g_autoptr(IdeSubprocess) subprocess = NULL;
- g_autofree gchar *command = NULL;
- g_autoptr(GError) error = NULL;
- g_auto(GStrv) argv = NULL;
- g_autofree gchar *shell = NULL;
-
- /*
- * First ask VTE to guess, so we can use that while we discover
- * the real shell asynchronously (and possibly outside the container).
- */
- if ((shell = vte_get_user_shell ()))
- user_shell = g_strdup (shell);
-
- command = g_strdup_printf ("sh -c 'getent passwd %s | head -n1 | cut -f 7 -d :'",
- g_get_user_name ());
-
- if (!g_shell_parse_argv (command, NULL, &argv, &error))
- {
- g_warning ("Failed to parse command into argv: %s",
- error ? error->message : "unknown error");
- return;
- }
-
- /*
- * We don't use the runtime shell here, because we want to know
- * what the host thinks the user shell should be.
- */
- launcher = ide_subprocess_launcher_new (G_SUBPROCESS_FLAGS_STDOUT_PIPE);
-
- ide_subprocess_launcher_set_run_on_host (launcher, TRUE);
- ide_subprocess_launcher_set_clear_env (launcher, FALSE);
- ide_subprocess_launcher_set_cwd (launcher, g_get_home_dir ());
- ide_subprocess_launcher_push_args (launcher, (const gchar * const *)argv);
-
- if (!(subprocess = ide_subprocess_launcher_spawn (launcher, NULL, &error)))
- {
- g_warning ("Failed to spawn getent: %s", error->message);
- return;
- }
-
- ide_subprocess_communicate_utf8_async (subprocess,
- NULL,
- NULL,
- ide_guess_shell_communicate_cb,
- NULL);
+ return ide_pty_intercept_create_producer (consumer_fd, TRUE);
}
diff --git a/src/libide/terminal/ide-terminal-util.h b/src/libide/terminal/ide-terminal-util.h
index a07b35efc..fd4d7c66f 100644
--- a/src/libide/terminal/ide-terminal-util.h
+++ b/src/libide/terminal/ide-terminal-util.h
@@ -29,9 +29,7 @@
G_BEGIN_DECLS
-IDE_AVAILABLE_IN_3_32
-int ide_vte_pty_create_slave (VtePty *pty);
-IDE_AVAILABLE_IN_3_32
-const gchar *ide_get_user_shell (void);
+IDE_AVAILABLE_IN_ALL
+int ide_vte_pty_create_producer (VtePty *pty);
G_END_DECLS
diff --git a/src/libide/terminal/ide-terminal.c b/src/libide/terminal/ide-terminal.c
index f1270962b..ad5ccbd70 100644
--- a/src/libide/terminal/ide-terminal.c
+++ b/src/libide/terminal/ide-terminal.c
@@ -22,11 +22,12 @@
#include "config.h"
-#include <dazzle.h>
#include <glib/gi18n.h>
+
#include <libide-gui.h>
#include "ide-terminal.h"
+#include "ide-terminal-search.h"
#define BUILDER_PCRE2_MULTILINE 0x00000400u
#define BUILDER_PCRE2_UCP 0x00020000u
@@ -36,6 +37,8 @@ typedef struct
GtkWidget *popup_menu;
GSettings *settings;
gchar *url;
+ GdkRGBA bg;
+ GdkRGBA fg;
} IdeTerminalPrivate;
typedef struct
@@ -58,6 +61,7 @@ enum {
POPULATE_POPUP,
SELECT_ALL,
SEARCH_REVEAL,
+ COLORS_CHANGED,
N_SIGNALS
};
@@ -92,31 +96,53 @@ static const GdkRGBA solarized_palette[] = {
{ 0.992156, 0.964705, 0.890196, 1 },
};
+void
+ide_terminal_get_colors (IdeTerminal *self,
+ GdkRGBA *bg,
+ GdkRGBA *fg)
+{
+ IdeTerminalPrivate *priv = ide_terminal_get_instance_private (self);
+
+ g_return_if_fail (IDE_IS_TERMINAL (self));
+
+ if (bg)
+ *bg = priv->bg;
+
+ if (fg)
+ *fg = priv->fg;
+}
+
static void
-style_context_changed (IdeTerminal *self,
- GtkStyleContext *style_context)
+ide_terminal_css_changed (GtkWidget *widget,
+ GtkCssStyleChange *change)
{
- GtkStateFlags state;
+ IdeTerminal *self = (IdeTerminal *)widget;
+ IdeTerminalPrivate *priv = ide_terminal_get_instance_private (self);
+ GtkStyleContext *style_context;
GdkRGBA fg;
GdkRGBA bg;
- g_assert (GTK_IS_STYLE_CONTEXT (style_context));
- g_assert (IDE_IS_TERMINAL (self));
+ g_assert (IDE_IS_TERMINAL (widget));
- state = gtk_style_context_get_state (style_context);
+ style_context = gtk_widget_get_style_context (widget);
- G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
- gtk_style_context_get_color (style_context, state, &fg);
- gtk_style_context_get_background_color (style_context, state, &bg);
- G_GNUC_END_IGNORE_DEPRECATIONS;
+ if (!gtk_style_context_lookup_color (style_context, "window_fg_color", &fg))
+ gdk_rgba_parse (&fg, "#eeeeec");
- if (bg.alpha == 0.0)
- gdk_rgba_parse (&bg, "#f6f7f8");
+ if (!gtk_style_context_lookup_color (style_context, "window_bg_color", &bg))
+ gdk_rgba_parse (&bg, "#242424");
- vte_terminal_set_colors (VTE_TERMINAL (self), &fg, &bg,
+ vte_terminal_set_colors (VTE_TERMINAL (widget),
+ &fg, &bg,
solarized_palette, G_N_ELEMENTS (solarized_palette));
+
+ priv->fg = fg;
+ priv->bg = bg;
+
+ g_signal_emit (self, signals [COLORS_CHANGED], 0);
}
+#if 0
static void
popup_menu_detach (GtkWidget *attach_widget,
GtkMenu *menu)
@@ -218,49 +244,68 @@ ide_terminal_popup_menu (GtkWidget *widget)
return TRUE;
}
+#endif
-static gboolean
-ide_terminal_button_press_event (GtkWidget *widget,
- GdkEventButton *button)
+static void
+ide_terminal_click_pressed_cb (IdeTerminal *self,
+ int n_presses,
+ double x,
+ double y,
+ GtkGestureClick *click)
{
- IdeTerminal *self = (IdeTerminal *)widget;
IdeTerminalPrivate *priv = ide_terminal_get_instance_private (self);
+ int button;
+
+ IDE_ENTRY;
g_assert (IDE_IS_TERMINAL (self));
- g_assert (button != NULL);
+ g_assert (GTK_IS_GESTURE_CLICK (click));
- if (button->type == GDK_BUTTON_PRESS)
+ button = gtk_gesture_single_get_current_button (GTK_GESTURE_SINGLE (click));
+
+ if (button == 1)
{
- if (button->button == GDK_BUTTON_PRIMARY)
+ g_autofree gchar *pattern = NULL;
+ glong cell_width = vte_terminal_get_char_width (VTE_TERMINAL (self));
+ glong cell_height = vte_terminal_get_char_height (VTE_TERMINAL (self));
+ glong column, row;
+ int tag = 0;
+
+ /* crappy way to do this, but i dont see another option right
+ * now given we have to go through deprecated APIs in Vte
+ * until it gets things together for GTK 4.
+ */
+ column = x / cell_width;
+ row = y / cell_height;
+
+ /* no other option in VTE for GTK 4 right now */
+ G_GNUC_BEGIN_IGNORE_DEPRECATIONS
+ pattern = vte_terminal_match_check (VTE_TERMINAL (self), column, row, &tag);
+ G_GNUC_END_IGNORE_DEPRECATIONS
+
+ if (pattern != NULL)
{
- g_autofree gchar *pattern = NULL;
-
- pattern = vte_terminal_match_check_event (VTE_TERMINAL (self), (GdkEvent *)button, NULL);
-
- if (pattern != NULL)
- {
- gboolean ret = GDK_EVENT_PROPAGATE;
+ gboolean ret = GDK_EVENT_PROPAGATE;
- g_free (priv->url);
- priv->url = g_steal_pointer (&pattern);
+ ide_set_string (&priv->url, pattern);
- g_signal_emit (self, signals [OPEN_LINK], 0, &ret);
+ g_signal_emit (self, signals[OPEN_LINK], 0, &ret);
- return ret;
- }
+ if (ret)
+ gtk_gesture_set_state (GTK_GESTURE (click), GTK_EVENT_SEQUENCE_CLAIMED);
}
- else if (button->button == GDK_BUTTON_SECONDARY)
- {
- if (!gtk_widget_has_focus (GTK_WIDGET (self)))
- gtk_widget_grab_focus (GTK_WIDGET (self));
-
- ide_terminal_do_popup (self, (GdkEvent *)button);
+ }
+#if 0
+ else if (button == 3)
+ {
+ if (!gtk_widget_has_focus (GTK_WIDGET (self)))
+ gtk_widget_grab_focus (GTK_WIDGET (self));
- return GDK_EVENT_STOP;
- }
+ ide_terminal_do_popup (self, (GdkEvent *)button);
}
+#endif
- return GTK_WIDGET_CLASS (ide_terminal_parent_class)->button_press_event (widget, button);
+ IDE_EXIT;
}
static void
@@ -286,8 +331,7 @@ ide_terminal_copy_link_address (IdeTerminal *self)
if (ide_str_empty0 (priv->url))
return FALSE;
- gtk_clipboard_set_text (gtk_widget_get_clipboard (GTK_WIDGET (self), GDK_SELECTION_CLIPBOARD),
- priv->url, strlen (priv->url));
+ gdk_clipboard_set_text (gtk_widget_get_clipboard (GTK_WIDGET (self)), priv->url);
return TRUE;
}
@@ -312,7 +356,7 @@ ide_terminal_open_link_resolve_cb (GObject *object,
pos->line,
pos->column,
IDE_BUFFER_OPEN_FLAGS_NONE,
- NULL, NULL, NULL);
+ NULL, NULL, NULL, NULL);
g_slice_free (Position, pos);
}
@@ -366,9 +410,27 @@ ide_terminal_open_link (IdeTerminal *self)
return FALSE;
}
+static GtkWidget *
+find_child_typed (GtkWidget *parent,
+ GType child_type)
+{
+ for (GtkWidget *child = gtk_widget_get_first_child (parent);
+ child;
+ child = gtk_widget_get_next_sibling (child))
+ {
+ if (g_type_is_a (G_OBJECT_TYPE (child), child_type))
+ return child;
+ }
+
+ return NULL;
+}
+
static void
-ide_terminal_real_search_reveal (IdeTerminal *self)
+ide_terminal_search_reveal (GtkWidget *widget,
+ const char *action_name,
+ GVariant *param)
{
+ IdeTerminal *self = (IdeTerminal *)widget;
GtkWidget *parent_overlay;
g_assert (IDE_IS_TERMINAL (self));
@@ -377,10 +439,15 @@ ide_terminal_real_search_reveal (IdeTerminal *self)
if (parent_overlay != NULL)
{
- GtkRevealer *revealer = dzl_gtk_widget_find_child_typed (parent_overlay, GTK_TYPE_REVEALER);
+ IdeTerminalSearch *search = IDE_TERMINAL_SEARCH (find_child_typed (parent_overlay,
IDE_TYPE_TERMINAL_SEARCH));
+
+ if (search != NULL)
+ {
+ GtkRevealer *revealer = ide_terminal_search_get_revealer (search);
- if (revealer != NULL && !gtk_revealer_get_child_revealed (revealer))
- gtk_revealer_set_reveal_child (revealer, TRUE);
+ if (!gtk_revealer_get_child_revealed (revealer))
+ gtk_revealer_set_reveal_child (revealer, TRUE);
+ }
}
}
@@ -405,30 +472,28 @@ ide_terminal_font_changed (IdeTerminal *self,
}
static void
-ide_terminal_size_allocate (GtkWidget *widget,
- GtkAllocation *alloc)
+ide_terminal_size_allocate (GtkWidget *widget,
+ int width,
+ int height,
+ int baseline)
{
IdeTerminal *self = (IdeTerminal *)widget;
- glong width;
- glong height;
- glong columns;
- glong rows;
+ int char_width, char_height;
+ int columns, rows;
- GTK_WIDGET_CLASS (ide_terminal_parent_class)->size_allocate (widget, alloc);
+ GTK_WIDGET_CLASS (ide_terminal_parent_class)->size_allocate (widget, width, height, baseline);
- if ((alloc->width == 0) || (alloc->height == 0))
+ if (width == 0 || height == 0)
return;
- width = vte_terminal_get_char_width (VTE_TERMINAL (self));
- height = vte_terminal_get_char_height (VTE_TERMINAL (self));
-
- if ((width == 0) || (height == 0))
+ char_width = vte_terminal_get_char_width (VTE_TERMINAL (self));
+ char_height = vte_terminal_get_char_height (VTE_TERMINAL (self));
+ if (char_width == 0 || char_height == 0)
return;
- columns = alloc->width / width;
- rows = alloc->height / height;
-
- if ((columns < 2) || (rows < 2))
+ columns = width / char_width;
+ rows = height / char_height;
+ if (columns < 2 || rows < 2)
return;
vte_terminal_set_size (VTE_TERMINAL (self), columns, rows);
@@ -455,38 +520,59 @@ update_scrollback_cb (IdeTerminal *self,
}
static void
-ide_terminal_destroy (GtkWidget *widget)
+copy_clipboard_action (GtkWidget *widget,
+ const char *action_name,
+ GVariant *param)
{
- IdeTerminal *self = (IdeTerminal *)widget;
- IdeTerminalPrivate *priv = ide_terminal_get_instance_private (self);
+ g_signal_emit_by_name (widget, "copy-clipboard");
+}
- g_assert (IDE_IS_TERMINAL (self));
+static void
+paste_clipboard_action (GtkWidget *widget,
+ const char *action_name,
+ GVariant *param)
+{
+ g_signal_emit_by_name (widget, "paste-clipboard");
+}
+
+static void
+ide_terminal_dispose (GObject *object)
+{
+ IdeTerminal *self = (IdeTerminal *)object;
+ IdeTerminalPrivate *priv = ide_terminal_get_instance_private (self);
g_clear_object (&priv->settings);
g_clear_pointer (&priv->url, g_free);
- GTK_WIDGET_CLASS (ide_terminal_parent_class)->destroy (widget);
+ G_OBJECT_CLASS (ide_terminal_parent_class)->dispose (object);
}
static void
ide_terminal_class_init (IdeTerminalClass *klass)
{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
- GtkBindingSet *binding_set;
- widget_class->destroy = ide_terminal_destroy;
- widget_class->button_press_event = ide_terminal_button_press_event;
- widget_class->popup_menu = ide_terminal_popup_menu;
+ object_class->dispose = ide_terminal_dispose;
+
+ widget_class->css_changed = ide_terminal_css_changed;
widget_class->size_allocate = ide_terminal_size_allocate;
klass->copy_link_address = ide_terminal_copy_link_address;
klass->open_link = ide_terminal_open_link;
klass->select_all = ide_terminal_real_select_all;
- klass->search_reveal = ide_terminal_real_search_reveal;
filename_regex = g_regex_new (FILENAME_PLUS_LOCATION, 0, 0, NULL);
g_assert (filename_regex != NULL);
+ signals [COLORS_CHANGED] =
+ g_signal_new ("colors-changed",
+ G_TYPE_FROM_CLASS (klass),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL, NULL, NULL,
+ G_TYPE_NONE, 0);
+
signals [COPY_LINK_ADDRESS] =
g_signal_new ("copy-link-address",
G_TYPE_FROM_CLASS (klass),
@@ -496,23 +582,14 @@ ide_terminal_class_init (IdeTerminalClass *klass)
G_TYPE_BOOLEAN,
0);
- signals [SEARCH_REVEAL] =
- g_signal_new ("search-reveal",
- G_TYPE_FROM_CLASS (klass),
- G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
- G_STRUCT_OFFSET (IdeTerminalClass, search_reveal),
- NULL, NULL, NULL,
- G_TYPE_NONE,
- 0);
-
signals [OPEN_LINK] =
g_signal_new ("open-link",
G_TYPE_FROM_CLASS (klass),
G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION,
G_STRUCT_OFFSET (IdeTerminalClass, open_link),
- NULL, NULL, NULL,
- G_TYPE_BOOLEAN,
- 0);
+ g_signal_accumulator_true_handled, NULL,
+ NULL,
+ G_TYPE_BOOLEAN, 0);
signals [POPULATE_POPUP] =
g_signal_new ("populate-popup",
@@ -534,34 +611,24 @@ ide_terminal_class_init (IdeTerminalClass *klass)
1,
G_TYPE_BOOLEAN);
- binding_set = gtk_binding_set_by_class (klass);
-
- gtk_binding_entry_add_signal (binding_set,
- GDK_KEY_c,
- GDK_SHIFT_MASK | GDK_CONTROL_MASK,
- "copy-clipboard",
- 0);
-
- gtk_binding_entry_add_signal (binding_set,
- GDK_KEY_v,
- GDK_SHIFT_MASK | GDK_CONTROL_MASK,
- "paste-clipboard",
- 0);
-
- gtk_binding_entry_add_signal (binding_set,
- GDK_KEY_f,
- GDK_SHIFT_MASK | GDK_CONTROL_MASK,
- "search-reveal",
- 0);
+ gtk_widget_class_install_action (widget_class, "terminal.copy-clipboard", NULL, copy_clipboard_action);
+ gtk_widget_class_install_action (widget_class, "terminal.paste-clipboard", NULL, paste_clipboard_action);
+ gtk_widget_class_install_action (widget_class, "terminal.search-reveal", NULL, ide_terminal_search_reveal);
}
static void
ide_terminal_init (IdeTerminal *self)
{
IdeTerminalPrivate *priv = ide_terminal_get_instance_private (self);
- GtkStyleContext *style_context;
+ GtkEventController *gesture;
- dzl_widget_action_group_attach (self, "terminal");
+ gesture = GTK_EVENT_CONTROLLER (gtk_gesture_click_new ());
+ g_signal_connect_object (gesture,
+ "pressed",
+ G_CALLBACK (ide_terminal_click_pressed_cb),
+ self,
+ G_CONNECT_SWAPPED);
+ gtk_widget_add_controller (GTK_WIDGET (self), g_steal_pointer (&gesture));
for (guint i = 0; i < G_N_ELEMENTS (url_regexes); i++)
{
@@ -569,7 +636,7 @@ ide_terminal_init (IdeTerminal *self)
const gchar *pattern = url_regexes[i];
gint tag;
- regex = vte_regex_new_for_match (pattern, DZL_LITERAL_LENGTH (pattern),
+ regex = vte_regex_new_for_match (pattern, strlen (pattern),
VTE_REGEX_FLAGS_DEFAULT | BUILDER_PCRE2_MULTILINE | BUILDER_PCRE2_UCP,
NULL);
tag = vte_terminal_match_add_regex (VTE_TERMINAL (self), regex, 0);
@@ -599,17 +666,6 @@ ide_terminal_init (IdeTerminal *self)
ide_terminal_font_changed (self, NULL, priv->settings);
update_scrollback_cb (self, "scrollback-lines", priv->settings);
- style_context = gtk_widget_get_style_context (GTK_WIDGET (self));
- gtk_style_context_add_class (style_context, "terminal");
- g_signal_connect_object (style_context,
- "changed",
- G_CALLBACK (style_context_changed),
- self,
- G_CONNECT_SWAPPED);
- style_context_changed (self, style_context);
-
- gtk_widget_set_can_focus (GTK_WIDGET (self), TRUE);
-
vte_terminal_set_enable_fallback_scrolling (VTE_TERMINAL (self), FALSE);
vte_terminal_set_scroll_unit_is_pixels (VTE_TERMINAL (self), TRUE);
}
diff --git a/src/libide/terminal/ide-terminal.h b/src/libide/terminal/ide-terminal.h
index c4687e6c2..13e8e1ef9 100644
--- a/src/libide/terminal/ide-terminal.h
+++ b/src/libide/terminal/ide-terminal.h
@@ -31,7 +31,7 @@ G_BEGIN_DECLS
#define IDE_TYPE_TERMINAL (ide_terminal_get_type())
-IDE_AVAILABLE_IN_3_32
+IDE_AVAILABLE_IN_ALL
G_DECLARE_DERIVABLE_TYPE (IdeTerminal, ide_terminal, IDE, TERMINAL, VteTerminal)
struct _IdeTerminalClass
@@ -42,15 +42,15 @@ struct _IdeTerminalClass
GtkWidget *widget);
void (*select_all) (IdeTerminal *self,
gboolean all);
- void (*search_reveal) (IdeTerminal *self);
gboolean (*open_link) (IdeTerminal *self);
gboolean (*copy_link_address) (IdeTerminal *self);
-
- /*< private >*/
- gpointer padding[16];
};
-IDE_AVAILABLE_IN_3_32
-GtkWidget *ide_terminal_new (void);
+IDE_AVAILABLE_IN_ALL
+GtkWidget *ide_terminal_new (void);
+IDE_AVAILABLE_IN_ALL
+void ide_terminal_get_colors (IdeTerminal *self,
+ GdkRGBA *bg,
+ GdkRGBA *fg);
G_END_DECLS
diff --git a/src/libide/terminal/libide-terminal.gresource.xml
b/src/libide/terminal/libide-terminal.gresource.xml
index 25622585b..2a27dcbb6 100644
--- a/src/libide/terminal/libide-terminal.gresource.xml
+++ b/src/libide/terminal/libide-terminal.gresource.xml
@@ -8,7 +8,5 @@
<file preprocess="xml-stripblanks">ide-terminal-popover.ui</file>
<file preprocess="xml-stripblanks">ide-terminal-popover-row.ui</file>
<file preprocess="xml-stripblanks">ide-terminal-search.ui</file>
- <file preprocess="xml-stripblanks">ide-terminal-surface.ui</file>
- <file preprocess="xml-stripblanks">ide-terminal-workspace.ui</file>
</gresource>
</gresources>
diff --git a/src/libide/terminal/libide-terminal.h b/src/libide/terminal/libide-terminal.h
index 3953767f1..330bcf1ed 100644
--- a/src/libide/terminal/libide-terminal.h
+++ b/src/libide/terminal/libide-terminal.h
@@ -33,8 +33,6 @@
#include "ide-terminal-page.h"
#include "ide-terminal-popover.h"
#include "ide-terminal-search.h"
-#include "ide-terminal-surface.h"
#include "ide-terminal-util.h"
-#include "ide-terminal-workspace.h"
#undef IDE_TERMINAL_INSIDE
diff --git a/src/libide/terminal/meson.build b/src/libide/terminal/meson.build
index 6affcae14..1878d3ba7 100644
--- a/src/libide/terminal/meson.build
+++ b/src/libide/terminal/meson.build
@@ -15,9 +15,7 @@ libide_terminal_public_headers = [
'ide-terminal-popover.h',
'ide-terminal-launcher.h',
'ide-terminal-search.h',
- 'ide-terminal-surface.h',
'ide-terminal-util.h',
- 'ide-terminal-workspace.h',
'ide-terminal.h',
'libide-terminal.h',
]
@@ -32,8 +30,9 @@ libide_terminal_private_headers = [
'ide-terminal-page-actions.h',
'ide-terminal-page-private.h',
'ide-terminal-popover-row.h',
- 'ide-terminal-private.h',
+ 'ide-terminal-run-command-private.h',
'ide-terminal-search-private.h',
+ 'ide-terminal-private.h',
]
libide_terminal_public_sources = [
@@ -41,15 +40,15 @@ libide_terminal_public_sources = [
'ide-terminal-popover.c',
'ide-terminal-launcher.c',
'ide-terminal-search.c',
- 'ide-terminal-surface.c',
'ide-terminal-util.c',
- 'ide-terminal-workspace.c',
'ide-terminal.c',
]
libide_terminal_private_sources = [
+ 'ide-terminal-init.c',
'ide-terminal-page-actions.c',
'ide-terminal-popover-row.c',
+ 'ide-terminal-run-command.c',
]
#
@@ -71,7 +70,6 @@ libide_terminal_generated_headers += [libide_terminal_resources[1]]
libide_terminal_deps = [
libgio_dep,
libgtk_dep,
- libdazzle_dep,
libvte_dep,
libide_core_dep,
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]