Blame src/terminal-gdbus.c

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
}