|
Packit Service |
3bdf47 |
/*
|
|
Packit Service |
3bdf47 |
* Copyright © 2011, 2012 Christian Persch
|
|
Packit Service |
3bdf47 |
*
|
|
Packit Service |
3bdf47 |
* This program is free software: you can redistribute it and/or modify
|
|
Packit Service |
3bdf47 |
* it under the terms of the GNU General Public License as published by
|
|
Packit Service |
3bdf47 |
* the Free Software Foundation, either version 3 of the License, or
|
|
Packit Service |
3bdf47 |
* (at your option) any later version.
|
|
Packit Service |
3bdf47 |
*
|
|
Packit Service |
3bdf47 |
* This program is distributed in the hope that it will be useful,
|
|
Packit Service |
3bdf47 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit Service |
3bdf47 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
Packit Service |
3bdf47 |
* GNU General Public License for more details.
|
|
Packit Service |
3bdf47 |
*
|
|
Packit Service |
3bdf47 |
* You should have received a copy of the GNU General Public License
|
|
Packit Service |
3bdf47 |
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
Packit Service |
3bdf47 |
*/
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
#include "config.h"
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
#include "terminal-gdbus.h"
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
#include <gio/gio.h>
|
|
Packit Service |
3bdf47 |
#include <gio/gunixfdlist.h>
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
#include "terminal-app.h"
|
|
Packit Service |
3bdf47 |
#include "terminal-debug.h"
|
|
Packit Service |
3bdf47 |
#include "terminal-defines.h"
|
|
Packit Service |
3bdf47 |
#include "terminal-mdi-container.h"
|
|
Packit Service |
3bdf47 |
#include "terminal-util.h"
|
|
Packit Service |
3bdf47 |
#include "terminal-window.h"
|
|
Packit Service |
3bdf47 |
#include "terminal-libgsystem.h"
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
/* ------------------------------------------------------------------------- */
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
#define TERMINAL_RECEIVER_IMPL_GET_PRIVATE(impl)(G_TYPE_INSTANCE_GET_PRIVATE ((impl), TERMINAL_TYPE_RECEIVER_IMPL, TerminalReceiverImplPrivate))
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
struct _TerminalReceiverImplPrivate {
|
|
Packit Service |
3bdf47 |
TerminalScreen *screen; /* unowned! */
|
|
Packit Service |
3bdf47 |
};
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
enum {
|
|
Packit Service |
3bdf47 |
PROP_0,
|
|
Packit Service |
3bdf47 |
PROP_SCREEN
|
|
Packit Service |
3bdf47 |
};
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
/* helper functions */
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
static void
|
|
Packit Service |
3bdf47 |
child_exited_cb (VteTerminal *terminal,
|
|
Packit Service |
3bdf47 |
int exit_code,
|
|
Packit Service |
3bdf47 |
TerminalReceiver *receiver)
|
|
Packit Service |
3bdf47 |
{
|
|
Packit Service |
3bdf47 |
terminal_receiver_emit_child_exited (receiver, exit_code);
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
static void
|
|
Packit Service |
3bdf47 |
terminal_receiver_impl_set_screen (TerminalReceiverImpl *impl,
|
|
Packit Service |
3bdf47 |
TerminalScreen *screen)
|
|
Packit Service |
3bdf47 |
{
|
|
Packit Service |
3bdf47 |
TerminalReceiverImplPrivate *priv;
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
g_return_if_fail (TERMINAL_IS_RECEIVER_IMPL (impl));
|
|
Packit Service |
3bdf47 |
g_return_if_fail (screen == NULL || TERMINAL_IS_SCREEN (screen));
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
priv = impl->priv;
|
|
Packit Service |
3bdf47 |
if (priv->screen == screen)
|
|
Packit Service |
3bdf47 |
return;
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
if (priv->screen) {
|
|
Packit Service |
3bdf47 |
g_signal_handlers_disconnect_matched (priv->screen,
|
|
Packit Service |
3bdf47 |
G_SIGNAL_MATCH_DATA,
|
|
Packit Service |
3bdf47 |
0, 0, NULL, NULL, impl);
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
priv->screen = screen;
|
|
Packit Service |
3bdf47 |
if (screen) {
|
|
Packit Service |
3bdf47 |
g_signal_connect (screen, "child-exited",
|
|
Packit Service |
3bdf47 |
G_CALLBACK (child_exited_cb),
|
|
Packit Service |
3bdf47 |
impl);
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
g_object_notify (G_OBJECT (impl), "screen");
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
/* Class implementation */
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
static gboolean
|
|
Packit Service |
3bdf47 |
terminal_receiver_impl_exec (TerminalReceiver *receiver,
|
|
Packit Service |
3bdf47 |
GDBusMethodInvocation *invocation,
|
|
Packit Service |
3bdf47 |
GUnixFDList *fd_list,
|
|
Packit Service |
3bdf47 |
GVariant *options,
|
|
Packit Service |
3bdf47 |
GVariant *arguments)
|
|
Packit Service |
3bdf47 |
{
|
|
Packit Service |
3bdf47 |
TerminalReceiverImpl *impl = TERMINAL_RECEIVER_IMPL (receiver);
|
|
Packit Service |
3bdf47 |
TerminalReceiverImplPrivate *priv = impl->priv;
|
|
Packit Service |
3bdf47 |
const char *working_directory;
|
|
Packit Service |
3bdf47 |
gboolean shell;
|
|
Packit Service |
3bdf47 |
char **exec_argv, **envv;
|
|
Packit Service |
3bdf47 |
gsize exec_argc;
|
|
Packit Service |
3bdf47 |
GVariant *fd_array;
|
|
Packit Service |
3bdf47 |
GError *error;
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
if (priv->screen == NULL) {
|
|
Packit Service |
3bdf47 |
g_dbus_method_invocation_return_error_literal (invocation,
|
|
Packit Service |
3bdf47 |
G_DBUS_ERROR,
|
|
Packit Service |
3bdf47 |
G_DBUS_ERROR_FAILED,
|
|
Packit Service |
3bdf47 |
"Terminal already closed");
|
|
Packit Service |
3bdf47 |
goto out;
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
if (!g_variant_lookup (options, "cwd", "^&ay", &working_directory))
|
|
Packit Service |
3bdf47 |
working_directory = NULL;
|
|
Packit Service |
3bdf47 |
if (!g_variant_lookup (options, "shell", "b", &shell))
|
|
Packit Service |
3bdf47 |
shell = FALSE;
|
|
Packit Service |
3bdf47 |
if (!g_variant_lookup (options, "environ", "^a&ay", &envv))
|
|
Packit Service |
3bdf47 |
envv = NULL;
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
if (!g_variant_lookup (options, "fd-set", "@a(ih)", &fd_array))
|
|
Packit Service |
3bdf47 |
fd_array = NULL;
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
/* Check FD passing */
|
|
Packit Service |
3bdf47 |
if ((fd_list != NULL) ^ (fd_array != NULL)) {
|
|
Packit Service |
3bdf47 |
g_dbus_method_invocation_return_error_literal (invocation,
|
|
Packit Service |
3bdf47 |
G_DBUS_ERROR,
|
|
Packit Service |
3bdf47 |
G_DBUS_ERROR_INVALID_ARGS,
|
|
Packit Service |
3bdf47 |
"Must pass both fd-set options and a FD list");
|
|
Packit Service |
3bdf47 |
goto out;
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
if (fd_list != NULL && fd_array != NULL) {
|
|
Packit Service |
3bdf47 |
const int *fd_array_data;
|
|
Packit Service |
3bdf47 |
gsize fd_array_data_len, i;
|
|
Packit Service |
3bdf47 |
int n_fds;
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
fd_array_data = g_variant_get_fixed_array (fd_array, &fd_array_data_len, 2 * sizeof (int));
|
|
Packit Service |
3bdf47 |
n_fds = g_unix_fd_list_get_length (fd_list);
|
|
Packit Service |
3bdf47 |
for (i = 0; i < fd_array_data_len; i++) {
|
|
Packit Service |
3bdf47 |
const int fd = fd_array_data[2 * i];
|
|
Packit Service |
3bdf47 |
const int idx = fd_array_data[2 * i + 1];
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
if (fd == STDIN_FILENO ||
|
|
Packit Service |
3bdf47 |
fd == STDOUT_FILENO ||
|
|
Packit Service |
3bdf47 |
fd == STDERR_FILENO) {
|
|
Packit Service |
3bdf47 |
g_dbus_method_invocation_return_error (invocation,
|
|
Packit Service |
3bdf47 |
G_DBUS_ERROR,
|
|
Packit Service |
3bdf47 |
G_DBUS_ERROR_INVALID_ARGS,
|
|
Packit Service |
3bdf47 |
"Passing of std%s not supported",
|
|
Packit Service |
3bdf47 |
fd == STDIN_FILENO ? "in" : fd == STDOUT_FILENO ? "out" : "err");
|
|
Packit Service |
3bdf47 |
goto out;
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
if (idx < 0 || idx >= n_fds) {
|
|
Packit Service |
3bdf47 |
g_dbus_method_invocation_return_error_literal (invocation,
|
|
Packit Service |
3bdf47 |
G_DBUS_ERROR,
|
|
Packit Service |
3bdf47 |
G_DBUS_ERROR_INVALID_ARGS,
|
|
Packit Service |
3bdf47 |
"Handle out of range");
|
|
Packit Service |
3bdf47 |
goto out;
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
if (working_directory != NULL)
|
|
Packit Service |
3bdf47 |
_terminal_debug_print (TERMINAL_DEBUG_SERVER,
|
|
Packit Service |
3bdf47 |
"CWD is '%s'\n", working_directory);
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
exec_argv = (char **) g_variant_get_bytestring_array (arguments, &exec_argc);
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
error = NULL;
|
|
Packit Service |
3bdf47 |
if (!terminal_screen_exec (priv->screen,
|
|
Packit Service |
3bdf47 |
exec_argc > 0 ? exec_argv : NULL,
|
|
Packit Service |
3bdf47 |
envv,
|
|
Packit Service |
3bdf47 |
shell,
|
|
Packit Service |
3bdf47 |
working_directory,
|
|
Packit Service |
3bdf47 |
fd_list, fd_array,
|
|
Packit Service |
3bdf47 |
&error)) {
|
|
Packit Service |
3bdf47 |
g_dbus_method_invocation_take_error (invocation, error);
|
|
Packit Service |
3bdf47 |
} else {
|
|
Packit Service |
3bdf47 |
terminal_receiver_complete_exec (receiver, invocation, NULL /* outfdlist */);
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
g_free (exec_argv);
|
|
Packit Service |
3bdf47 |
g_free (envv);
|
|
Packit Service |
3bdf47 |
if (fd_array)
|
|
Packit Service |
3bdf47 |
g_variant_unref (fd_array);
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
out:
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
return TRUE; /* handled */
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
static void
|
|
Packit Service |
3bdf47 |
terminal_receiver_impl_iface_init (TerminalReceiverIface *iface)
|
|
Packit Service |
3bdf47 |
{
|
|
Packit Service |
3bdf47 |
iface->handle_exec = terminal_receiver_impl_exec;
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
G_DEFINE_TYPE_WITH_CODE (TerminalReceiverImpl, terminal_receiver_impl, TERMINAL_TYPE_RECEIVER_SKELETON,
|
|
Packit Service |
3bdf47 |
G_IMPLEMENT_INTERFACE (TERMINAL_TYPE_RECEIVER, terminal_receiver_impl_iface_init))
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
static void
|
|
Packit Service |
3bdf47 |
terminal_receiver_impl_init (TerminalReceiverImpl *impl)
|
|
Packit Service |
3bdf47 |
{
|
|
Packit Service |
3bdf47 |
impl->priv = TERMINAL_RECEIVER_IMPL_GET_PRIVATE (impl);
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
static void
|
|
Packit Service |
3bdf47 |
terminal_receiver_impl_dispose (GObject *object)
|
|
Packit Service |
3bdf47 |
{
|
|
Packit Service |
3bdf47 |
TerminalReceiverImpl *impl = TERMINAL_RECEIVER_IMPL (object);
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
terminal_receiver_impl_set_screen (impl, NULL);
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
G_OBJECT_CLASS (terminal_receiver_impl_parent_class)->dispose (object);
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
static void
|
|
Packit Service |
3bdf47 |
terminal_receiver_impl_get_property (GObject *object,
|
|
Packit Service |
3bdf47 |
guint prop_id,
|
|
Packit Service |
3bdf47 |
GValue *value,
|
|
Packit Service |
3bdf47 |
GParamSpec *pspec)
|
|
Packit Service |
3bdf47 |
{
|
|
Packit Service |
3bdf47 |
TerminalReceiverImpl *impl = TERMINAL_RECEIVER_IMPL (object);
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
switch (prop_id) {
|
|
Packit Service |
3bdf47 |
case PROP_SCREEN:
|
|
Packit Service |
3bdf47 |
g_value_set_object (value, terminal_receiver_impl_get_screen (impl));
|
|
Packit Service |
3bdf47 |
break;
|
|
Packit Service |
3bdf47 |
default:
|
|
Packit Service |
3bdf47 |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
Packit Service |
3bdf47 |
break;
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
static void
|
|
Packit Service |
3bdf47 |
terminal_receiver_impl_set_property (GObject *object,
|
|
Packit Service |
3bdf47 |
guint prop_id,
|
|
Packit Service |
3bdf47 |
const GValue *value,
|
|
Packit Service |
3bdf47 |
GParamSpec *pspec)
|
|
Packit Service |
3bdf47 |
{
|
|
Packit Service |
3bdf47 |
TerminalReceiverImpl *impl = TERMINAL_RECEIVER_IMPL (object);
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
switch (prop_id) {
|
|
Packit Service |
3bdf47 |
case PROP_SCREEN:
|
|
Packit Service |
3bdf47 |
terminal_receiver_impl_set_screen (impl, g_value_get_object (value));
|
|
Packit Service |
3bdf47 |
break;
|
|
Packit Service |
3bdf47 |
default:
|
|
Packit Service |
3bdf47 |
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
Packit Service |
3bdf47 |
break;
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
static void
|
|
Packit Service |
3bdf47 |
terminal_receiver_impl_class_init (TerminalReceiverImplClass *klass)
|
|
Packit Service |
3bdf47 |
{
|
|
Packit Service |
3bdf47 |
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
gobject_class->dispose = terminal_receiver_impl_dispose;
|
|
Packit Service |
3bdf47 |
gobject_class->get_property = terminal_receiver_impl_get_property;
|
|
Packit Service |
3bdf47 |
gobject_class->set_property = terminal_receiver_impl_set_property;
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
g_object_class_install_property
|
|
Packit Service |
3bdf47 |
(gobject_class,
|
|
Packit Service |
3bdf47 |
PROP_SCREEN,
|
|
Packit Service |
3bdf47 |
g_param_spec_object ("screen", NULL, NULL,
|
|
Packit Service |
3bdf47 |
TERMINAL_TYPE_SCREEN,
|
|
Packit Service |
3bdf47 |
G_PARAM_READWRITE |
|
|
Packit Service |
3bdf47 |
G_PARAM_CONSTRUCT_ONLY |
|
|
Packit Service |
3bdf47 |
G_PARAM_STATIC_STRINGS));
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
g_type_class_add_private (gobject_class, sizeof (TerminalReceiverImplPrivate));
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
/* public API */
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
/**
|
|
Packit Service |
3bdf47 |
* terminal_receiver_impl_new:
|
|
Packit Service |
3bdf47 |
* @screen: a #TerminalScreen
|
|
Packit Service |
3bdf47 |
*
|
|
Packit Service |
3bdf47 |
* Returns: a new #TerminalReceiverImpl for @screen
|
|
Packit Service |
3bdf47 |
*/
|
|
Packit Service |
3bdf47 |
TerminalReceiverImpl *
|
|
Packit Service |
3bdf47 |
terminal_receiver_impl_new (TerminalScreen *screen)
|
|
Packit Service |
3bdf47 |
{
|
|
Packit Service |
3bdf47 |
return g_object_new (TERMINAL_TYPE_RECEIVER_IMPL,
|
|
Packit Service |
3bdf47 |
"screen", screen,
|
|
Packit Service |
3bdf47 |
NULL);
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
/**
|
|
Packit Service |
3bdf47 |
* terminal_receiver_impl_get_screen:
|
|
Packit Service |
3bdf47 |
* @impl: a #TerminalReceiverImpl
|
|
Packit Service |
3bdf47 |
*
|
|
Packit Service |
3bdf47 |
* Returns: (transfer none): the impl's #TerminalScreen, or %NULL
|
|
Packit Service |
3bdf47 |
*/
|
|
Packit Service |
3bdf47 |
TerminalScreen *
|
|
Packit Service |
3bdf47 |
terminal_receiver_impl_get_screen (TerminalReceiverImpl *impl)
|
|
Packit Service |
3bdf47 |
{
|
|
Packit Service |
3bdf47 |
g_return_val_if_fail (TERMINAL_IS_RECEIVER_IMPL (impl), NULL);
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
return impl->priv->screen;
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
/**
|
|
Packit Service |
3bdf47 |
* terminal_receiver_impl_unget_screen:
|
|
Packit Service |
3bdf47 |
* @impl: a #TerminalReceiverImpl
|
|
Packit Service |
3bdf47 |
*
|
|
Packit Service |
3bdf47 |
* Unsets the impls #TerminalScreen.
|
|
Packit Service |
3bdf47 |
*/
|
|
Packit Service |
3bdf47 |
void
|
|
Packit Service |
3bdf47 |
terminal_receiver_impl_unset_screen (TerminalReceiverImpl *impl)
|
|
Packit Service |
3bdf47 |
{
|
|
Packit Service |
3bdf47 |
g_return_if_fail (TERMINAL_IS_RECEIVER_IMPL (impl));
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
terminal_receiver_impl_set_screen (impl, NULL);
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
/* ---------------------------------------------------------------------------
|
|
Packit Service |
3bdf47 |
* TerminalFactoryImpl
|
|
Packit Service |
3bdf47 |
* ---------------------------------------------------------------------------
|
|
Packit Service |
3bdf47 |
*/
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
struct _TerminalFactoryImplPrivate {
|
|
Packit Service |
3bdf47 |
gpointer dummy;
|
|
Packit Service |
3bdf47 |
};
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
static gboolean
|
|
Packit Service |
3bdf47 |
terminal_factory_impl_create_instance (TerminalFactory *factory,
|
|
Packit Service |
3bdf47 |
GDBusMethodInvocation *invocation,
|
|
Packit Service |
3bdf47 |
GVariant *options)
|
|
Packit Service |
3bdf47 |
{
|
|
Packit Service |
3bdf47 |
TerminalApp *app = terminal_app_get ();
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
/* If a parent screen is specified, use that to fill in missing information */
|
|
Packit Service |
3bdf47 |
TerminalScreen *parent_screen = NULL;
|
|
Packit Service |
3bdf47 |
const char *parent_screen_object_path;
|
|
Packit Service |
3bdf47 |
if (g_variant_lookup (options, "parent-screen", "&o", &parent_screen_object_path)) {
|
|
Packit Service |
3bdf47 |
parent_screen = terminal_app_get_screen_by_object_path (app, parent_screen_object_path);
|
|
Packit Service |
3bdf47 |
if (parent_screen == NULL) {
|
|
Packit Service |
3bdf47 |
g_dbus_method_invocation_return_error (invocation,
|
|
Packit Service |
3bdf47 |
G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
|
|
Packit Service |
3bdf47 |
"Failed to get screen from object path %s",
|
|
Packit Service |
3bdf47 |
parent_screen_object_path);
|
|
Packit Service |
3bdf47 |
return TRUE;
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
/* Try getting a parent window, first by parent screen then by window ID;
|
|
Packit Service |
3bdf47 |
* if that fails, create a new window.
|
|
Packit Service |
3bdf47 |
*/
|
|
Packit Service |
3bdf47 |
TerminalWindow *window = NULL;
|
|
Packit Service |
3bdf47 |
gboolean have_new_window = FALSE;
|
|
Packit Service |
3bdf47 |
const char *window_from_screen_object_path;
|
|
Packit Service |
3bdf47 |
if (g_variant_lookup (options, "window-from-screen", "&o", &window_from_screen_object_path)) {
|
|
Packit Service |
3bdf47 |
TerminalScreen *window_screen =
|
|
Packit Service |
3bdf47 |
terminal_app_get_screen_by_object_path (app, window_from_screen_object_path);
|
|
Packit Service |
3bdf47 |
if (window_screen == NULL) {
|
|
Packit Service |
3bdf47 |
g_dbus_method_invocation_return_error (invocation,
|
|
Packit Service |
3bdf47 |
G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
|
|
Packit Service |
3bdf47 |
"Failed to get screen from object path %s",
|
|
Packit Service |
3bdf47 |
parent_screen_object_path);
|
|
Packit Service |
3bdf47 |
return TRUE;
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
GtkWidget *win = gtk_widget_get_toplevel (GTK_WIDGET (window_screen));
|
|
Packit Service |
3bdf47 |
if (TERMINAL_IS_WINDOW (win))
|
|
Packit Service |
3bdf47 |
window = TERMINAL_WINDOW (win);
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
/* Support old client */
|
|
Packit Service |
3bdf47 |
guint window_id;
|
|
Packit Service |
3bdf47 |
if (window == NULL && g_variant_lookup (options, "window-id", "u", &window_id)) {
|
|
Packit Service |
3bdf47 |
GtkWindow *win = gtk_application_get_window_by_id (GTK_APPLICATION (app), window_id);
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
if (!TERMINAL_IS_WINDOW (win)) {
|
|
Packit Service |
3bdf47 |
g_dbus_method_invocation_return_error (invocation,
|
|
Packit Service |
3bdf47 |
G_DBUS_ERROR, G_DBUS_ERROR_INVALID_ARGS,
|
|
Packit Service |
3bdf47 |
"Nonexisting window %u referenced",
|
|
Packit Service |
3bdf47 |
window_id);
|
|
Packit Service |
3bdf47 |
return TRUE;
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
window = TERMINAL_WINDOW (win);
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
/* Still no parent window? Create a new one */
|
|
Packit Service |
3bdf47 |
if (window == NULL) {
|
|
Packit Service |
3bdf47 |
const char *startup_id, *role;
|
|
Packit Service |
3bdf47 |
gboolean start_maximized, start_fullscreen;
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
/* We don't do multi-display anymore */
|
|
Packit Service |
3bdf47 |
#if 0
|
|
Packit Service |
3bdf47 |
const char *display_name;
|
|
Packit Service |
3bdf47 |
if (g_variant_lookup (options, "display", "^&ay", &display_name)) {
|
|
Packit Service |
3bdf47 |
GdkDisplay *display = gdk_display_get_default ();
|
|
Packit Service |
3bdf47 |
const char *default_display_name = display ? gdk_display_get_name (display) : NULL;
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
if (g_strcmp0 (default_display_name, display_name) != 0)
|
|
Packit Service |
3bdf47 |
g_printerr ("Display \"%s\" requested but default display is \"%s\"\n",
|
|
Packit Service |
3bdf47 |
display_name, default_display_name);
|
|
Packit Service |
3bdf47 |
/* Open window on our display anyway */
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
#endif
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
int monitor = 0;
|
|
Packit Service |
3bdf47 |
window = terminal_app_new_window (app, monitor);
|
|
Packit Service |
3bdf47 |
have_new_window = TRUE;
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
if (g_variant_lookup (options, "desktop-startup-id", "^&ay", &startup_id))
|
|
Packit Service |
3bdf47 |
gtk_window_set_startup_id (GTK_WINDOW (window), startup_id);
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
/* Overwrite the default, unique window role set in terminal_window_init */
|
|
Packit Service |
3bdf47 |
if (g_variant_lookup (options, "role", "&s", &role))
|
|
Packit Service |
3bdf47 |
gtk_window_set_role (GTK_WINDOW (window), role);
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
gboolean show_menubar;
|
|
Packit Service |
3bdf47 |
if (g_variant_lookup (options, "show-menubar", "b", &show_menubar))
|
|
Packit Service |
3bdf47 |
terminal_window_set_menubar_visible (window, show_menubar);
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
if (g_variant_lookup (options, "fullscreen-window", "b", &start_fullscreen) &&
|
|
Packit Service |
3bdf47 |
start_fullscreen) {
|
|
Packit Service |
3bdf47 |
gtk_window_fullscreen (GTK_WINDOW (window));
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
if (g_variant_lookup (options, "maximize-window", "b", &start_maximized) &&
|
|
Packit Service |
3bdf47 |
start_maximized) {
|
|
Packit Service |
3bdf47 |
gtk_window_maximize (GTK_WINDOW (window));
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
have_new_window = TRUE;
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
g_assert_nonnull (window);
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
const char *title;
|
|
Packit Service |
3bdf47 |
if (!g_variant_lookup (options, "title", "&s", &title))
|
|
Packit Service |
3bdf47 |
title = NULL;
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
double zoom;
|
|
Packit Service |
3bdf47 |
if (!g_variant_lookup (options, "zoom", "d", &zoom)) {
|
|
Packit Service |
3bdf47 |
if (parent_screen != NULL)
|
|
Packit Service |
3bdf47 |
zoom = vte_terminal_get_font_scale (VTE_TERMINAL (parent_screen));
|
|
Packit Service |
3bdf47 |
else
|
|
Packit Service |
3bdf47 |
zoom = 1.0;
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
const char *encoding;
|
|
Packit Service |
3bdf47 |
if (!g_variant_lookup (options, "encoding", "&s", &encoding)) {
|
|
Packit Service |
3bdf47 |
if (parent_screen != NULL)
|
|
Packit Service |
3bdf47 |
encoding = vte_terminal_get_encoding (VTE_TERMINAL (parent_screen));
|
|
Packit Service |
3bdf47 |
else
|
|
Packit Service |
3bdf47 |
encoding = NULL; /* use profile encoding */
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
/* Look up the profile */
|
|
Packit Service |
3bdf47 |
gs_unref_object GSettings *profile = NULL;
|
|
Packit Service |
3bdf47 |
const char *profile_uuid;
|
|
Packit Service |
3bdf47 |
if (!g_variant_lookup (options, "profile", "&s", &profile_uuid))
|
|
Packit Service |
3bdf47 |
profile_uuid = NULL;
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
if (profile_uuid == NULL && parent_screen != NULL) {
|
|
Packit Service |
3bdf47 |
profile = terminal_screen_ref_profile (parent_screen);
|
|
Packit Service |
3bdf47 |
} else {
|
|
Packit Service |
3bdf47 |
GError *err = NULL;
|
|
Packit Service |
3bdf47 |
profile = terminal_profiles_list_ref_profile_by_uuid (terminal_app_get_profiles_list (app),
|
|
Packit Service |
3bdf47 |
profile_uuid /* default if NULL */,
|
|
Packit Service |
3bdf47 |
&err;;
|
|
Packit Service |
3bdf47 |
if (profile == NULL) {
|
|
Packit Service |
3bdf47 |
g_dbus_method_invocation_return_gerror (invocation, err);
|
|
Packit Service |
3bdf47 |
g_error_free (err);
|
|
Packit Service |
3bdf47 |
return TRUE;
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
g_assert_nonnull (profile);
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
/* Now we can create the new screen */
|
|
Packit Service |
3bdf47 |
TerminalScreen *screen = terminal_screen_new (profile, encoding, NULL, title, NULL, NULL, zoom);
|
|
Packit Service |
3bdf47 |
terminal_window_add_screen (window, screen, -1);
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
/* Apply window properties */
|
|
Packit Service |
3bdf47 |
gboolean active;
|
|
Packit Service |
3bdf47 |
if (g_variant_lookup (options, "active", "b", &active) &&
|
|
Packit Service |
3bdf47 |
active) {
|
|
Packit Service |
3bdf47 |
terminal_window_switch_screen (window, screen);
|
|
Packit Service |
3bdf47 |
gtk_widget_grab_focus (GTK_WIDGET (screen));
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
if (have_new_window) {
|
|
Packit Service |
3bdf47 |
const char *geometry;
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
if (g_variant_lookup (options, "geometry", "&s", &geometry) &&
|
|
Packit Service |
3bdf47 |
!terminal_window_parse_geometry (window, geometry))
|
|
Packit Service |
3bdf47 |
_terminal_debug_print (TERMINAL_DEBUG_GEOMETRY,
|
|
Packit Service |
3bdf47 |
"Invalid geometry string \"%s\"", geometry);
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
gboolean present_window;
|
|
Packit Service |
3bdf47 |
gboolean present_window_set = g_variant_lookup (options, "present-window", "b", &present_window);
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
if (have_new_window || (present_window_set && present_window))
|
|
Packit Service |
3bdf47 |
gtk_window_present (GTK_WINDOW (window));
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
gs_free char *object_path = terminal_app_dup_screen_object_path (app, screen);
|
|
Packit Service |
3bdf47 |
terminal_factory_complete_create_instance (factory, invocation, object_path);
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
return TRUE; /* handled */
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
static void
|
|
Packit Service |
3bdf47 |
terminal_factory_impl_iface_init (TerminalFactoryIface *iface)
|
|
Packit Service |
3bdf47 |
{
|
|
Packit Service |
3bdf47 |
iface->handle_create_instance = terminal_factory_impl_create_instance;
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
G_DEFINE_TYPE_WITH_CODE (TerminalFactoryImpl, terminal_factory_impl, TERMINAL_TYPE_FACTORY_SKELETON,
|
|
Packit Service |
3bdf47 |
G_IMPLEMENT_INTERFACE (TERMINAL_TYPE_FACTORY, terminal_factory_impl_iface_init))
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
static void
|
|
Packit Service |
3bdf47 |
terminal_factory_impl_init (TerminalFactoryImpl *impl)
|
|
Packit Service |
3bdf47 |
{
|
|
Packit Service |
3bdf47 |
impl->priv = G_TYPE_INSTANCE_GET_PRIVATE (impl, TERMINAL_TYPE_FACTORY_IMPL, TerminalFactoryImplPrivate);
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
static void
|
|
Packit Service |
3bdf47 |
terminal_factory_impl_class_init (TerminalFactoryImplClass *klass)
|
|
Packit Service |
3bdf47 |
{
|
|
Packit Service |
3bdf47 |
/* g_type_class_add_private (klass, sizeof (TerminalFactoryImplPrivate)); */
|
|
Packit Service |
3bdf47 |
}
|
|
Packit Service |
3bdf47 |
|
|
Packit Service |
3bdf47 |
/**
|
|
Packit Service |
3bdf47 |
* terminal_factory_impl_new:
|
|
Packit Service |
3bdf47 |
*
|
|
Packit Service |
3bdf47 |
* Returns: (transfer full): a new #TerminalFactoryImpl
|
|
Packit Service |
3bdf47 |
*/
|
|
Packit Service |
3bdf47 |
TerminalFactory *
|
|
Packit Service |
3bdf47 |
terminal_factory_impl_new (void)
|
|
Packit Service |
3bdf47 |
{
|
|
Packit Service |
3bdf47 |
return g_object_new (TERMINAL_TYPE_FACTORY_IMPL, NULL);
|
|
Packit Service |
3bdf47 |
}
|