[gnome-terminal] gterminal: Initial commit
- From: Christian Persch <chpe src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-terminal] gterminal: Initial commit
- Date: Sun, 11 May 2014 16:40:00 +0000 (UTC)
commit 1bbe740bb91f743032544bde430009e7cbfd418a
Author: Christian Persch <chpe gnome org>
Date: Sun May 4 11:27:14 2014 +0200
gterminal: Initial commit
.dir-locals.el | 7 +-
configure.ac | 31 ++-
src/Makefile.am | 67 +++--
src/client.c | 818 ------------------------------------------
src/client.vapi | 44 +++
src/config.vapi | 7 +
src/gterminal.vala | 581 ++++++++++++++++++++++++++++++
src/profiles.vapi | 67 ++++
src/terminal-client-utils.c | 37 ++-
src/terminal-client-utils.h | 13 +-
src/terminal-nautilus.c | 1 +
src/terminal-profiles-list.c | 4 +-
src/terminal-profiles-list.h | 2 +-
src/terminal-window.c | 4 +-
src/terminal.c | 3 +-
15 files changed, 822 insertions(+), 864 deletions(-)
---
diff --git a/.dir-locals.el b/.dir-locals.el
index 7e193c7..f377013 100644
--- a/.dir-locals.el
+++ b/.dir-locals.el
@@ -2,4 +2,9 @@
(indent-tabs-mode . nil)
(c-basic-offset . 2)
(tab-width . 8)
- (show-trailing-whitespace . t))))
+ (show-trailing-whitespace . t)))
+(vala-mode . ((c-file-style . "GNU")
+ (indent-tabs-mode . nil)
+ (c-basic-offset . 2)
+ (tab-width . 8)
+ (show-trailing-whitespace . t))))
diff --git a/configure.ac b/configure.ac
index 47277b4..96be878 100644
--- a/configure.ac
+++ b/configure.ac
@@ -79,6 +79,31 @@ PKG_CHECK_MODULES([TERM],
$PLATFORM_DEPS])
# ****
+# Vala
+# ****
+
+AC_MSG_CHECKING([whether vala is requested])
+AC_ARG_WITH([vala],[AS_HELP_STRING([--without-vala],[Disable vala programmes])],
+ [],[with_vala=yes])
+AC_MSG_RESULT([$with_vala])
+
+if test "$with_vala" = "yes"; then
+ AM_PROG_VALAC([0.24])
+
+ VALA_CHECK_PACKAGES([glib-2.0 gio-2.0 gio-unix-2.0 linux posix])
+ PKG_CHECK_MODULES([GTERMINAL],
+ [glib-2.0 >= $GLIB_REQUIRED
+ gio-2.0 >= $GIO_REQUIRED
+ gio-unix-2.0 >= $GIO_REQUIRED
+ gtk+-$GTK_API_VERSION >= $GTK_REQUIRED
+ dconf >= $DCONF_REQUIRED
+ uuid
+ $PLATFORM_DEPS])
+fi
+
+AM_CONDITIONAL([WITH_VALA],[test "$with_vala" = "yes"])
+
+# ****
# DBus
# ****
@@ -244,7 +269,8 @@ fi
# Compilation
# ***********
-CC_CHECK_FLAGS_APPEND([AM_CFLAGS],[CFLAGS],[ \
+WARN_CFLAGS=
+CC_CHECK_FLAGS_APPEND([WARN_CFLAGS],[CFLAGS],[ \
-pipe \
-Waggregate-return \
-Wall \
@@ -314,6 +340,8 @@ AC_SUBST([TERMINAL_MAJOR_VERSION],[gt_version_major])
AC_SUBST([TERMINAL_MINOR_VERSION],[gt_version_minor])
AC_SUBST([TERMINAL_MICRO_VERSION],[gt_version_micro])
AC_SUBST([TERMINAL_API_VERSION],[gt_api_version])
+AC_SUBST([GTK_API_VERSION])
+AC_SUBST([WARN_CFLAGS])
AC_SUBST([AM_CPPFLAGS])
AC_SUBST([AM_CFLAGS])
AC_SUBST([AM_LDFLAGS])
@@ -338,6 +366,7 @@ gnome-terminal-$VERSION:
prefix: ${prefix}
source code location: ${srcdir}
compiler: ${CC}
+ Vala: ${with_vala}
DBus interface dir: ${dbusinterfacedir}
DBus service dir: ${dbusservicedir}
Debug: ${enable_debug}
diff --git a/src/Makefile.am b/src/Makefile.am
index faea290..5e3b115 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -4,7 +4,7 @@ BUILT_SOURCES =
bin_PROGRAMS = gnome-terminal
libexec_PROGRAMS = gnome-terminal-server
-noinst_PROGRAMS = gnome-terminal-client
+noinst_PROGRAMS =
if WITH_NAUTILUS_EXTENSION
nautilusextension_LTLIBRARIES = libterminal-nautilus.la
@@ -91,6 +91,7 @@ gnome_terminal_server_CPPFLAGS = \
gnome_terminal_server_CFLAGS = \
$(TERM_CFLAGS) \
+ $(WARN_CFLAGS) \
$(AM_CFLAGS)
gnome_terminal_server_LDFLAGS = \
@@ -150,47 +151,64 @@ terminal-resources.h terminal-resources.c: terminal.gresource.xml Makefile $(she
# Terminal client
-gnome_terminal_client_SOURCES = \
- client.c \
+if WITH_VALA
+
+noinst_PROGRAMS += gterminal
+
+gterminal_SOURCES = \
+ gterminal.vala \
+ client.vapi \
+ config.vapi \
+ profiles.vapi \
terminal-client-utils.c \
terminal-client-utils.h \
terminal-debug.c \
terminal-debug.h \
- terminal-defines.h \
- terminal-i18n.c \
- terminal-i18n.h \
- terminal-libgsystem.h \
terminal-profiles-list.c \
terminal-profiles-list.h \
- terminal-schemas.h \
terminal-settings-list.c \
terminal-settings-list.h \
$(NULL)
-nodist_gnome_terminal_client_SOURCES = \
- terminal-gdbus-generated.c \
- terminal-gdbus-generated.h \
+nodist_gterminal_SOURCES = \
terminal-type-builtins.c \
terminal-type-builtins.h \
$(NULL)
-gnome_terminal_client_CPPFLAGS = \
+gterminal_VALAFLAGS = \
+ --vapidir . \
+ --pkg glib-2.0 \
+ --pkg gio-2.0 \
+ --pkg gio-unix-2.0 \
+ --pkg posix \
+ --pkg gtk+-$(GTK_API_VERSION) \
+ $(GTERMINAL_VALAFLAGS) \
+ $(AM_VALAFLAGS)
+gterminal_CPPFLAGS = \
+ -I$(top_builddir) \
-DTERMINAL_COMPILATION \
-DTERMINAL_CLIENT \
- -DTERM_DATADIR="\"$(datadir)\"" \
- -DTERM_LOCALEDIR="\"$(datadir)/locale\"" \
- -DTERM_PKGDATADIR="\"$(pkgdatadir)\"" \
+ -DLOCALEDIR="\"$(datadir)/locale\"" \
$(AM_CPPFLAGS)
-
-gnome_terminal_client_CFLAGS = \
- $(TERM_CFLAGS) \
- $(AM_CFLAGS)
-
-gnome_terminal_client_LDFLAGS = \
+# See bug #710862 about -Wsuggest-attribute=format
+gterminal_CFLAGS = \
+ $(GTERMINAL_CFLAGS) \
+ $(AM_CFLAGS) \
+ $(WARN_CFLAGS) \
+ -Wno-cast-qual \
+ -Wno-suggest-attribute=format \
+ -Wno-unused-but-set-variable \
+ -Wno-unused-function \
+ -Wno-unused-variable \
+ -Wno-write-strings \
+ $(NULL)
+gterminal_LDFLAGS = \
$(AM_LDFLAGS)
+gterminal_LDADD = \
+ $(GTERMINAL_LIBS) \
+ $(NULL)
-gnome_terminal_client_LDADD = \
- $(TERM_LIBS)
+endif # WITH_VALA
# Legacy terminal client
@@ -230,6 +248,7 @@ gnome_terminal_CPPFLAGS = \
gnome_terminal_CFLAGS = \
$(TERM_CFLAGS) \
+ $(WARN_CFLAGS) \
$(AM_CFLAGS)
gnome_terminal_LDFLAGS = \
@@ -263,6 +282,7 @@ libterminal_nautilus_la_CPPFLAGS = \
libterminal_nautilus_la_CFLAGS = \
$(NAUTILUS_CFLAGS) \
+ $(WARN_CFLAGS) \
$(AM_CFLAGS)
libterminal_nautilus_la_LDFLAGS = \
@@ -299,6 +319,7 @@ gnome_terminal_migration_CPPFLAGS = \
$(AM_CPPFLAGS)
gnome_terminal_migration_CFLAGS = \
$(MIGRATOR_CFLAGS) \
+ $(WARN_CFLAGS) \
$(AM_CFLAGS)
gnome_terminal_migration_LDFLAGS = \
$(AM_LDFLAGS)
diff --git a/src/client.vapi b/src/client.vapi
new file mode 100644
index 0000000..7eed2bf
--- /dev/null
+++ b/src/client.vapi
@@ -0,0 +1,44 @@
+/*
+ * Copyright © 2014 Christian Persch
+ *
+ * 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/>.
+ */
+
+[CCode (lower_case_cprefix = "terminal_client_", cheader_filename = "terminal-client-utils.h")]
+namespace Terminal.Client {
+
+ public void append_create_instance_options (GLib.VariantBuilder builder,
+ string display_name,
+ string? startup_id,
+ string? geometry,
+ string? role,
+ string? profile,
+ string? title,
+ bool maximise_window,
+ bool fullscreen_window);
+
+ [CCode (cname = "PassFdElement", has_type_id = false)]
+ [SimpleType]
+ public struct PassFdElement {
+ public int index;
+ public int fd;
+ }
+
+ public void append_exec_options (GLib.VariantBuilder builder,
+ string? working_directory,
+ PassFdElement[]? fd_array,
+ bool shell);
+
+ public string? get_fallback_startup_id ();
+}
diff --git a/src/config.vapi b/src/config.vapi
new file mode 100644
index 0000000..9b20284
--- /dev/null
+++ b/src/config.vapi
@@ -0,0 +1,7 @@
+[CCode (cprefix = "", lower_case_cprefix = "", cheader_filename = "config.h")]
+namespace Config
+{
+ public const string GETTEXT_PACKAGE;
+ public const string LOCALEDIR;
+ public const string VERSION;
+}
diff --git a/src/gterminal.vala b/src/gterminal.vala
new file mode 100644
index 0000000..8e76b82
--- /dev/null
+++ b/src/gterminal.vala
@@ -0,0 +1,581 @@
+/*
+ * Copyright © 2014 Christian Persch
+ *
+ * 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/>.
+ */
+
+namespace GTerminal
+{
+ /* Output handling */
+
+ public struct Output
+ {
+ private static bool quiet = false;
+ private static bool verbose = false;
+
+ private static const OptionEntry[] entries = {
+ { "quiet", 0, OptionFlags.HIDDEN, OptionArg.NONE, ref quiet,
+ "Suppress output", null },
+ { "verbose", 'v', OptionFlags.HIDDEN, OptionArg.NONE, ref verbose,
+ "Verbose output", null },
+ { null, 0, 0, 0, null, null, null }
+ };
+
+ public static void set_quiet (bool value)
+ {
+ quiet = value;
+ }
+
+ public GLib.OptionGroup get_option_group ()
+ {
+ var group = new GLib.OptionGroup ("output",
+ "Output options:",
+ "Show output options",
+ null, null);
+ group.add_entries (entries);
+ group.set_translation_domain(Config.GETTEXT_PACKAGE);
+ return group;
+ }
+
+ [PrintfFormat]
+ public void print(string format,
+ ...)
+ {
+ if (!quiet)
+ stdout.vprintf (format, va_list());
+ }
+
+ [PrintfFormat]
+ public void printerr(string format, ...)
+ {
+ if (!quiet)
+ stderr.vprintf (format, va_list());
+ }
+
+ [PrintfFormat]
+ public void info(string format, ...)
+ {
+ if (verbose)
+ stderr.vprintf (format, va_list());
+ }
+ }
+
+ /* Global options */
+
+ public struct GlobalOptions {
+ public static string? app_id = null;
+
+ private static bool option_app_id (string option_name,
+ string value,
+ void *unused_user_data) throws OptionError
+ {
+ if (!GLib.Application.id_is_valid (value))
+ throw new OptionError.BAD_VALUE ("\"%s\" is not a valid application ID", value);
+ app_id = value;
+ return true;
+ }
+
+ public static string get_app_id ()
+ {
+ return app_id != null ? app_id : "org.gnome.Terminal";
+ }
+
+ private static const OptionEntry[] entries = {
+ { "app-id", 0, OptionFlags.HIDDEN, OptionArg.CALLBACK, (void*) option_app_id,
+ "Server application ID", "ID" },
+ { null, 0, 0, 0, null, null, null }
+ };
+
+ public static GLib.OptionGroup get_option_group ()
+ {
+ var group = new GLib.OptionGroup ("global",
+ "Global options:",
+ "Show global options",
+ null, null);
+ group.add_entries (entries);
+ group.set_translation_domain(Config.GETTEXT_PACKAGE);
+ return group;
+ }
+ }
+
+ public struct OpenOptions {
+
+ [CCode (array_length = false, array_null_terminated = true)]
+ private static string[]? pass_fds = null;
+ private static bool pass_stdin = false;
+ private static bool pass_stdout = false;
+ private static bool pass_stderr = false;
+ private static Terminal.Client.PassFdElement[]? fd_array = null;
+ public static GLib.UnixFDList? fd_list = null;
+
+ private static bool post_parse (OptionContext context,
+ OptionGroup group,
+ void *unused_user_data) throws Error
+ {
+ if (pass_stdin || pass_stdout || pass_stderr)
+ throw new OptionError.BAD_VALUE ("FD passing of std%s is not supported",
+ pass_stdin ? "in" : pass_stdout ? "out" : "err");
+
+ if (pass_fds == null)
+ return true;
+
+ fd_list = new GLib.UnixFDList ();
+ Terminal.Client.PassFdElement[] arr = {};
+
+ for (uint i = 0; i < pass_fds.length; i++) {
+ int64 v;
+ if (!int64.try_parse (pass_fds[i], out v) ||
+ v == -1 || v < int.MIN || v > int.MAX)
+ throw new OptionError.BAD_VALUE ("Invalid argument \"%s\" to --fd option", pass_fds[i]);
+
+ int fd = (int) v;
+
+ if (fd == Posix.STDIN_FILENO ||
+ fd == Posix.STDOUT_FILENO ||
+ fd == Posix.STDERR_FILENO)
+ throw new OptionError.BAD_VALUE ("FD passing of std%s is not supported",
+ fd == Posix.STDIN_FILENO ? "in" :
+ fd == Posix.STDOUT_FILENO ? "out" : "err");
+
+ for (uint j = 0; j < arr.length; j++) {
+ if (arr[j].fd == fd)
+ throw new OptionError.BAD_VALUE ("Cannot pass FD %d twice", fd);
+ }
+
+ var idx = fd_list.append (fd);
+ Terminal.Client.PassFdElement e = { idx, fd };
+ arr += e;
+
+ if (fd == Posix.STDOUT_FILENO ||
+ fd == Posix.STDERR_FILENO) {
+ GTerminal.Output.set_quiet (true);
+ }
+#if 0
+ if (fd == Posix.STDIN_FILENO)
+ data->wait = TRUE;
+#endif
+ }
+
+ fd_array = arr;
+ return true;
+ }
+
+ private static const OptionEntry[] exec_entries = {
+ { "stdin", 0, OptionFlags.HIDDEN, OptionArg.NONE, ref pass_stdin,
+ "Forward stdin", null },
+ { "stdout", 0, OptionFlags.HIDDEN, OptionArg.NONE, ref pass_stdout,
+ "Forward stdout", null },
+ { "stderr", 0, OptionFlags.HIDDEN, OptionArg.NONE, ref pass_stderr,
+ "Forward stderr", null },
+ { "fd", 0, 0, OptionArg.STRING_ARRAY, ref pass_fds,
+ "Forward file descriptor", "FD" },
+ { null, 0, 0, 0, null, null, null }
+ };
+
+ public static GLib.OptionGroup get_exec_option_group ()
+ {
+ var group = new GLib.OptionGroup ("exec",
+ "Exec options:",
+ "Show exec options",
+ null, null);
+ group.add_entries (exec_entries);
+ group.set_translation_domain(Config.GETTEXT_PACKAGE);
+ group.set_parse_hooks (null, (OptionParseFunc)post_parse);
+ return group;
+ }
+
+ /* Window options */
+
+ public static string? geometry = null;
+ public static string? role = null;
+ public static bool show_menubar = true;
+ public static bool show_menubar_set = false;
+ public static bool maximise = false;
+ public static bool fullscreen = false;
+
+ private static const OptionEntry[] window_entries = {
+ { "maximise", 0, 0, OptionArg.NONE, ref maximise,
+ "Maximise the window", null },
+ { "fullscreen", 0, 0, OptionArg.NONE, ref fullscreen,
+ "Full-screen the window", null },
+ { "geometry", 0, 0, OptionArg.STRING, ref geometry,
+ "Set the window size; for example: 80x24, or 80x24+200+200 (COLSxROWS+X+Y)",
+ "GEOMETRY" },
+ { "role", 0, 0, OptionArg.STRING, ref role,
+ "Set the window role", "ROLE" },
+ { null, 0, 0, 0, null, null, null }
+ };
+
+ public static GLib.OptionGroup get_window_option_group()
+ {
+ var group = new GLib.OptionGroup ("window",
+ "Window options:",
+ "Show window options",
+ null, null);
+ group.add_entries (window_entries);
+ group.set_translation_domain(Config.GETTEXT_PACKAGE);
+ return group;
+ }
+
+ /* Terminal options */
+
+ public static string? working_directory = null;
+ public static string? profile = null;
+ public static string? title = null;
+ public static double zoom = 1.0;
+
+ private static bool option_profile (string option_name,
+ string? value,
+ void *unused_user_data) throws Error
+ {
+ if (profile != null)
+ throw new OptionError.BAD_VALUE ("May only use option %s once", option_name);
+
+ var profiles = new Terminal.ProfilesList ();
+ profile = profiles.dup_uuid (value);
+ return true;
+ }
+
+ private static bool option_zoom (string option_name,
+ string? value,
+ void *unused_user_data) throws Error
+ {
+ double v;
+ if (!double.try_parse (value, out v))
+ throw new OptionError.BAD_VALUE ("\"%s\" is not a valid zoom factor",
+ value);
+
+ if (v < 0.25 || v > 4.0)
+ throw new OptionError.BAD_VALUE ("Zoom value \"%s\" is outside allowed range",
+ value);
+
+ zoom = v;
+ return true;
+ }
+
+ private static const OptionEntry[] terminal_entries = {
+ { "profile", 0, 0, OptionArg.CALLBACK, (void*) option_profile,
+ "Use the given profile instead of the default profile",
+ "UUID" },
+ { "title", 0, 0, OptionArg.STRING, ref title,
+ "Set the terminal title", "TITLE" },
+ { "cwd", 0, 0, OptionArg.FILENAME, ref working_directory,
+ "Set the working directory", "DIRNAME" },
+ { "zoom", 0, 0, OptionArg.CALLBACK, (void*) option_zoom,
+ "Set the terminal's zoom factor (1.0 = normal size)",
+ "ZOOM" },
+ { null, 0, 0, 0, null, null, null }
+ };
+
+ public static GLib.OptionGroup get_terminal_option_group ()
+ {
+ var group = new GLib.OptionGroup ("terminal",
+ "Terminal options:",
+ "Show terminal options",
+ null, null);
+ group.add_entries (terminal_entries);
+ group.set_translation_domain(Config.GETTEXT_PACKAGE);
+ return group;
+ }
+
+ /* Processing options */
+
+ public static bool wait_for_remote = false;
+
+ private static const OptionEntry[] processing_entries = {
+ { "wait", 0, 0, OptionArg.NONE, ref wait_for_remote,
+ "Wait until the child exits", null },
+ { null, 0, 0, 0, null, null, null }
+ };
+
+ public static GLib.OptionGroup get_processing_option_group ()
+ {
+ var group = new GLib.OptionGroup ("processing",
+ "Processing options:",
+ "Show processing options",
+ null, null);
+ group.add_entries (processing_entries);
+ group.set_translation_domain(Config.GETTEXT_PACKAGE);
+ return group;
+ }
+
+ /* Argument parsing */
+
+ [CCode (array_length = false, array_null_terminated = true)]
+ public static string[]? argv_pre = null;
+ [CCode (array_length = false, array_null_terminated = true)]
+ public static string[]? argv_post = null;
+ public static string? display_name = null;
+ public static string? startup_id = null;
+
+ public static void parse_argv (string[] argv) throws Error
+ {
+ /* Need to save this before gtk_init is being called! */
+ startup_id = Environment.get_variable ("DESKTOP_STARTUP_ID");
+
+ /* If there's a '--' argument with other arguments after it,
+ * strip them off. Need to do this before parsing the options!
+ */
+
+ bool found_dashdash = false;
+ for (uint i = 0; i < argv.length; i++) {
+ if (argv[i] != "--")
+ continue;
+
+ if (i > 0)
+ argv_pre = argv[0:i];
+ else
+ argv_pre = null;
+
+ if (i + 1 < argv.length)
+ argv_post = argv[i+1:argv.length];
+ else
+ argv_post = null;
+
+ found_dashdash = true;
+ break;
+ }
+
+ if (!found_dashdash) {
+ argv_pre = argv;
+ argv_post = null;
+ }
+
+ var context = new GLib.OptionContext ("— terminal client");
+ context.set_translation_domain (Config.GETTEXT_PACKAGE);
+ context.add_group (Gtk.get_option_group (true));
+ context.add_group (GlobalOptions.get_option_group ());
+ context.add_group (get_window_option_group ());
+ context.add_group (get_terminal_option_group ());
+ context.add_group (get_exec_option_group ());
+ context.add_group (get_processing_option_group ());
+
+ context.parse_strv (ref argv_pre);
+
+ if (working_directory == null)
+ working_directory = Environment.get_current_dir ();
+
+ /* Do this here so that gdk_display is initialized */
+ if (startup_id == null)
+ startup_id = Terminal.Client.get_fallback_startup_id ();
+
+ display_name = Gdk.Display.get_default ().get_name ();
+ }
+
+ } /* struct OpenOptions */
+
+ /* DBUS Interfaces */
+
+ [DBus (name = "org.gnome.Terminal.Factory0")]
+ interface Server : DBusProxy {
+ public const string SERVICE_NAME = "org.gnome.Terminal";
+ public const string INTERFACE_NAME = "org.gnome.Terminal.Factory0";
+ public const string OBJECT_PATH = "/org/gnome/Terminal/Factory0";
+
+ /* public abstract GLib.ObjectPath CreateInstance (HashTable<string, Variant> dict) throws IOError; */
+ }
+
+ [DBus (name = "org.gnome.Terminal.Terminal0")]
+ interface Receiver : DBusProxy {
+ public const string INTERFACE_NAME = "org.gnome.Terminal.Terminal0";
+
+ /* public abstract void Exec (HashTable<string, Variant> options,
+ [DBus (signature = "aay")] string[] arguments) throws IOError; */
+ public signal void ChildExited (int exit_code);
+ }
+
+ /* DBus helper functions */
+
+ private Server get_server () throws IOError
+ {
+ return Bus.get_proxy_sync (BusType.SESSION,
+ GlobalOptions.get_app_id (),
+ Server.OBJECT_PATH,
+ DBusProxyFlags.DO_NOT_LOAD_PROPERTIES |
+ DBusProxyFlags.DO_NOT_CONNECT_SIGNALS);
+ }
+
+ private Receiver create_terminal () throws Error
+ {
+ var server = get_server ();
+
+ var builder = new GLib.VariantBuilder (VariantType.VARDICT);
+ Terminal.Client.append_create_instance_options (builder,
+ OpenOptions.display_name,
+ OpenOptions.startup_id,
+ OpenOptions.geometry,
+ OpenOptions.role,
+ OpenOptions.profile,
+ OpenOptions.title,
+ OpenOptions.maximise,
+ OpenOptions.fullscreen);
+ if (OpenOptions.show_menubar_set)
+ builder.add ("{sv}", "show-menubar", new Variant.boolean (OpenOptions.show_menubar));
+
+ /* FIXME: Not using the proxy method since the generated code seems broken… */
+ var path = server.call_sync ("CreateInstance" /* (a{sv}) */,
+ new Variant ("(a{sv})", builder),
+ DBusCallFlags.NO_AUTO_START, -1,
+ null);
+
+ string obj_path;
+ path.get ("(o)", out obj_path);
+
+ return Bus.get_proxy_sync (BusType.SESSION,
+ GlobalOptions.get_app_id (),
+ obj_path,
+ DBusProxyFlags.DO_NOT_LOAD_PROPERTIES);
+ }
+
+ /* Helper functions */
+
+ private int mangle_exit_code (int status)
+ {
+ if (Process.if_exited (status))
+ return Process.exit_status (status).clamp (0, 127);
+ else if (Process.if_signaled (status))
+ return 128 + (int) Process.term_sig (status);
+ else
+ return 127;
+ }
+
+ /* Verbs */
+
+ private int run (Receiver receiver)
+ {
+ int status = 0;
+ var loop = new GLib.MainLoop ();
+ var id = receiver.ChildExited.connect((s) => {
+ if (loop.is_running ())
+ loop.quit ();
+ status = s;
+ });
+
+ loop.run ();
+ receiver.disconnect(id);
+
+ return mangle_exit_code (status);
+ }
+
+ private int open (string[] argv) throws Error
+ {
+ OpenOptions.parse_argv (argv);
+
+ if (argv[0] == "run" && OpenOptions.argv_post == null)
+ throw new OptionError.BAD_VALUE ("'%s' needs the command to run as arguments after '--'",
+ argv[0]);
+
+ var receiver = create_terminal ();
+
+ var builder = new GLib.VariantBuilder (VariantType.TUPLE);
+ builder.open (VariantType.VARDICT); {
+ Terminal.Client.append_exec_options (builder,
+ OpenOptions.working_directory,
+ OpenOptions.fd_array,
+ argv[0] == "shell");
+ } builder.close ();
+ builder.add_value (new Variant.bytestring_array (OpenOptions.argv_post));
+
+ receiver.call_with_unix_fd_list_sync ("Exec" /* (a{sv}aay) */,
+ builder.end (),
+ DBusCallFlags.NO_AUTO_START, -1,
+ OpenOptions.fd_list);
+
+ if (!OpenOptions.wait_for_remote)
+ return Posix.EXIT_SUCCESS;
+
+ return run (receiver);
+ }
+
+ private int help (string[] argv) throws Error
+ {
+ /* FIXME: launch man pager for gterminal(1) */
+ return Posix.EXIT_SUCCESS;
+ }
+
+ private int complete (string[] argv) throws Error
+ {
+ if (argv.length < 2)
+ throw new OptionError.UNKNOWN_OPTION ("Missing argument");
+
+ if (argv[1] == "commands") {
+ string? prefix = argv.length > 2 ? argv[2] : null;
+ for (uint i = 0; i < commands.length; i++) {
+ if (commands[i].verb.has_prefix ("_"))
+ continue;
+ if (prefix == null || commands[i].verb.has_prefix (prefix))
+ print ("%s\n", commands[i].verb);
+ }
+
+ return Posix.EXIT_SUCCESS;
+ } else if (argv[1] == "profiles") {
+ var service = new Terminal.ProfilesList ();
+ var profiles = service.dupv_children ();
+ string? prefix = argv.length > 2 ? argv[2] : null;
+ for (uint i = 0; i < profiles.length; i++) {
+ if (prefix == null || profiles[i].has_prefix (prefix))
+ print ("%s\n", profiles[i]);
+ }
+
+ return Posix.EXIT_SUCCESS;
+ }
+
+ throw new OptionError.UNKNOWN_OPTION ("Unknown completion request for \"%s\"", argv[0]);
+ }
+
+ private delegate int CommandFunc (string[] args) throws Error;
+
+ private struct CommandMap {
+ unowned string verb;
+ unowned CommandFunc func;
+ }
+
+ private static const CommandMap[] commands = {
+ { "help", help },
+ { "open", open },
+ { "shell", open },
+ { "_complete", complete },
+ };
+
+ public static int main (string[] argv)
+ {
+ Environment.set_prgname ("gterminal");
+
+ //Intl.setlocale (LocaleCategory.ALL, "");
+ //Intl.bindtextdomain (Config.GETTEXT_PACKAGE, Config.LOCALEDIR);
+ //Intl.bind_textdomain_codeset (Config.GETTEXT_PACKAGE, "UTF-8");
+ //Intl.textdomain (Config.GETTEXT_PACKAGE);
+ Environment.set_application_name ("GTerminal");
+
+ try {
+ if (argv.length == 1) {
+ throw new OptionError.FAILED ("Missing command");
+ }
+
+ for (uint i = 0; i < commands.length; i++) {
+ if (commands[i].verb == argv[1]) {
+ return commands[i].func (argv[1:argv.length]);
+ }
+ }
+
+ throw new OptionError.FAILED ("Unknown command \"%s\"", argv[1]);
+ } catch (Error e) {
+ DBusError.strip_remote_error (e);
+
+ printerr ("Error processing arguments: %s\n", e.message);
+ return Posix.EXIT_FAILURE;
+ }
+ }
+
+} /* namespace GTerminal */
diff --git a/src/profiles.vapi b/src/profiles.vapi
new file mode 100644
index 0000000..6da9633
--- /dev/null
+++ b/src/profiles.vapi
@@ -0,0 +1,67 @@
+/*
+ * Copyright © 2014 Christian Persch
+ *
+ * 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/>.
+ */
+
+[CCode (cprefix = "Terminal", lower_case_cprefix = "terminal_")]
+namespace Terminal {
+
+ [CCode (cheader_filename = "terminal-settings-list.h", type_id = "terminal_settings_list_get_type")]
+ public class SettingsList : GLib.Object {
+
+ [Flags, CCode (cprefix = "TERMINAL_SETTINGS_LIST_FLAG_", has_type_id = false)]
+ public enum Flags {
+ NONE,
+ HAS_DEFAULT,
+ ALLOW_EMPTY
+ }
+
+ [CCode (has_construct_function = false)]
+ public SettingsList (string path, string schema_id, string child_schema_id, Flags flags = Flags.NONE);
+
+ [CCode (array_length = false, array_null_terminated = true)]
+ public string[]? dupv_children ();
+ public GLib.List<GLib.Settings> ref_children ();
+
+ public bool has_child (string uuid);
+ public GLib.Settings? ref_child (string uuid);
+
+ public string add_child ();
+ public string clone_child (string uuid);
+ public void remove_child (string uuid);
+
+ public string dup_uuid_from_child (GLib.Settings child);
+ public GLib.Settings? ref_default_child ();
+ public string dup_default_child ();
+ public void set_default_child (string uuid);
+
+ public static bool valid_uuid (string uuid);
+ }
+
+ [CCode (cname = "TerminalSettingsList", cprefix = "terminal_profiles_list_", cheader_filename =
"terminal-profiles-list.h", type_id = "terminal_settings_list_get_type")]
+ public class ProfilesList : SettingsList {
+
+ public ProfilesList ();
+
+ public GLib.List<GLib.Settings> ref_children_sorted ();
+
+ public string dup_uuid (string uuid) throws GLib.Error;
+ public string dup_uuid_or_name (string uuid_or_name) throws GLib.Error;
+
+ public GLib.Settings ref_profile_by_uuid (string uuid) throws GLib.Error;
+ public GLib.Settings ref_profile_by_uuid_or_name (string uuid_or_name) throws GLib.Error;
+ }
+
+}
diff --git a/src/terminal-client-utils.c b/src/terminal-client-utils.c
index a0756a2..b2295d8 100644
--- a/src/terminal-client-utils.c
+++ b/src/terminal-client-utils.c
@@ -99,6 +99,8 @@ terminal_client_append_create_instance_options (GVariantBuilder *builder,
void
terminal_client_append_exec_options (GVariantBuilder *builder,
const char *working_directory,
+ PassFdElement *fd_array,
+ gsize fd_array_len,
gboolean shell)
{
gs_strfreev char **envv;
@@ -121,21 +123,39 @@ terminal_client_append_exec_options (GVariantBuilder *builder,
g_variant_new_bytestring_array ((const char * const *) envv, -1));
if (working_directory)
- g_variant_builder_add (builder, "{sv}",
+ g_variant_builder_add (builder, "{sv}",
"cwd", g_variant_new_bytestring (working_directory));
if (shell)
g_variant_builder_add (builder, "{sv}",
"shell",
g_variant_new_boolean (TRUE));
+
+ if (fd_array_len) {
+ gsize i;
+
+ g_variant_builder_open (builder, G_VARIANT_TYPE ("{sv}"));
+ g_variant_builder_add (builder, "s", "fd-set");
+
+ g_variant_builder_open (builder, G_VARIANT_TYPE ("v"));
+ g_variant_builder_open (builder, G_VARIANT_TYPE ("a(ih)"));
+ for (i = 0; i < fd_array_len; i++) {
+ g_variant_builder_add (builder, "(ih)", fd_array[i].fd, fd_array[i].index);
+ }
+ g_variant_builder_close (builder); /* a(ih) */
+ g_variant_builder_close (builder); /* v */
+
+ g_variant_builder_close (builder); /* {sv} */
+ }
}
/**
* terminal_client_get_fallback_startup_id:
- * @startup_id: (inout):
+ *
+ * Returns: a fallback startup ID, or %NULL
*/
-void
-terminal_client_get_fallback_startup_id (char **startup_id)
+char *
+terminal_client_get_fallback_startup_id (void)
{
#if defined(TERMINAL_COMPILATION) && defined(GDK_WINDOWING_X11)
GdkDisplay *display;
@@ -188,13 +208,8 @@ terminal_client_get_fallback_startup_id (char **startup_id)
XDestroyWindow(xdisplay, xwindow);
- if (startup_id)
- *startup_id = g_strdup_printf ("_TIME%lu", event.xproperty.time);
-
- return;
-
+ return g_strdup_printf ("_TIME%lu", event.xproperty.time);
out:
#endif
- if (startup_id)
- *startup_id = NULL;
+ return NULL;
}
diff --git a/src/terminal-client-utils.h b/src/terminal-client-utils.h
index 3f9a30b..57d711a 100644
--- a/src/terminal-client-utils.h
+++ b/src/terminal-client-utils.h
@@ -19,12 +19,10 @@
#define TERMINAL_CLIENT_UTILS_H
#include <gio/gio.h>
+#include <gio/gunixfdlist.h>
G_BEGIN_DECLS
-char *terminal_client_get_profile (const char *name_or_id,
- GError **error);
-
void terminal_client_append_create_instance_options (GVariantBuilder *builder,
const char *display_name,
const char *startup_id,
@@ -35,11 +33,18 @@ void terminal_client_append_create_instance_options (GVariantBuilder *builder,
gboolean maximise_window,
gboolean fullscreen_window);
+typedef struct {
+ int index;
+ int fd;
+} PassFdElement;
+
void terminal_client_append_exec_options (GVariantBuilder *builder,
const char *working_directory,
+ PassFdElement *fd_array,
+ gsize fd_array_len,
gboolean shell);
-void terminal_client_get_fallback_startup_id (char **startup_id);
+char * terminal_client_get_fallback_startup_id (void);
G_END_DECLS
diff --git a/src/terminal-nautilus.c b/src/terminal-nautilus.c
index 28290ac..3474783 100644
--- a/src/terminal-nautilus.c
+++ b/src/terminal-nautilus.c
@@ -424,6 +424,7 @@ create_terminal (ExecData *data /* transfer full */)
terminal_client_append_exec_options (&builder,
data->path,
+ NULL, 0, /* FD array */
TRUE /* shell */);
if (data->info == FILE_INFO_SFTP &&
diff --git a/src/terminal-profiles-list.c b/src/terminal-profiles-list.c
index 64795d5..721dbff 100644
--- a/src/terminal-profiles-list.c
+++ b/src/terminal-profiles-list.c
@@ -100,13 +100,13 @@ get_profile_names (TerminalSettingsList *list,
}
/**
- * terminal_profiles_list_get_children:
+ * terminal_profiles_list_ref_children_sorted:
* @list:
*
* Returns: (transfer full):
*/
GList *
-terminal_profiles_list_ref_children (TerminalSettingsList *list)
+terminal_profiles_list_ref_children_sorted (TerminalSettingsList *list)
{
return g_list_sort (terminal_settings_list_ref_children (list),
terminal_profiles_compare);
diff --git a/src/terminal-profiles-list.h b/src/terminal-profiles-list.h
index 42ed11c..179d3e3 100644
--- a/src/terminal-profiles-list.h
+++ b/src/terminal-profiles-list.h
@@ -27,7 +27,7 @@ G_BEGIN_DECLS
TerminalSettingsList *terminal_profiles_list_new (void);
-GList *terminal_profiles_list_ref_children (TerminalSettingsList *list);
+GList *terminal_profiles_list_ref_children_sorted (TerminalSettingsList *list);
char *terminal_profiles_list_dup_uuid (TerminalSettingsList *list,
const char *uuid,
diff --git a/src/terminal-window.c b/src/terminal-window.c
index 3b3ac81..90b58d3 100644
--- a/src/terminal-window.c
+++ b/src/terminal-window.c
@@ -1295,7 +1295,7 @@ terminal_window_update_set_profile_menu (TerminalWindow *window)
}
profiles_list = terminal_app_get_profiles_list (terminal_app_get ());
- profiles = terminal_profiles_list_ref_children (profiles_list);
+ profiles = terminal_profiles_list_ref_children_sorted (profiles_list);
action = gtk_action_group_get_action (priv->action_group, "TerminalProfiles");
single_profile = !profiles || profiles->next == NULL; /* list length <= 1 */
@@ -1413,7 +1413,7 @@ terminal_window_update_new_terminal_menus (TerminalWindow *window)
}
profiles_list = terminal_app_get_profiles_list (terminal_app_get ());
- profiles = terminal_profiles_list_ref_children (profiles_list);
+ profiles = terminal_profiles_list_ref_children_sorted (profiles_list);
have_single_profile = !profiles || !profiles->next;
diff --git a/src/terminal.c b/src/terminal.c
index 18b860c..2dd5a6d 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -178,6 +178,7 @@ handle_options (TerminalFactory *factory,
terminal_client_append_exec_options (&builder,
it->working_dir ? it->working_dir
: options->default_working_dir,
+ NULL, 0, /* FD array */
argc == 0);
if (!terminal_receiver_call_exec_sync (receiver,
@@ -243,7 +244,7 @@ main (int argc, char **argv)
/* Do this here so that gdk_display is initialized */
if (options->startup_id == NULL)
- terminal_client_get_fallback_startup_id (&options->startup_id);
+ options->startup_id = terminal_client_get_fallback_startup_id ();
display = gdk_display_get_default ();
display_name = gdk_display_get_name (display);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]