mutter/src/core/meta-launch-context.c
Jonas Ådahl dd2beae6a8 core: Setup and use ownership chains
As with other parts, make objects have the ability to walk up the
ownership chain to the context, to get things like the Wayland
compositor or backend instances.

Contains these squashed commits:

display: Don't get backend from singleton

window: Don't get backend from singleton

keybindings: Don't get backend from singleton

workspace: Don't get backend from singleton

display: Don't get Wayland compositor from singleton

selection: Add display getter

context/main: Get backend directly from the context

clipboard-manager: Don't get display from singleton

stack-tracker: Don't use singleton MetaLater API

startup-notification: Hook up sequences and activations to display

This allows using context aware API directly.

Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/2718>
2022-12-17 15:13:48 +01:00

271 lines
8.2 KiB
C

/*
* Copyright (C) 2018 Red Hat
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Carlos Garnacho <carlosg@gnome.org>
*/
#include "config.h"
#include <gio/gdesktopappinfo.h>
#include "core/display-private.h"
#include "meta/meta-launch-context.h"
#include "x11/meta-startup-notification-x11.h"
typedef struct _MetaLaunchContext MetaLaunchContext;
struct _MetaLaunchContext
{
GAppLaunchContext parent_instance;
MetaDisplay *display;
MetaWorkspace *workspace;
uint32_t timestamp;
};
G_DEFINE_TYPE (MetaLaunchContext, meta_launch_context,
G_TYPE_APP_LAUNCH_CONTEXT)
enum
{
PROP_DISPLAY = 1,
PROP_WORKSPACE,
PROP_TIMESTAMP,
N_PROPS
};
static GParamSpec *props[N_PROPS] = { 0, };
static void
meta_launch_context_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
MetaLaunchContext *context = META_LAUNCH_CONTEXT (object);
switch (prop_id)
{
case PROP_DISPLAY:
context->display = g_value_get_object (value);
break;
case PROP_WORKSPACE:
meta_launch_context_set_workspace (context,
g_value_get_object (value));
break;
case PROP_TIMESTAMP:
meta_launch_context_set_timestamp (context,
g_value_get_uint (value));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
meta_launch_context_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
MetaLaunchContext *context = META_LAUNCH_CONTEXT (object);
switch (prop_id)
{
case PROP_DISPLAY:
g_value_set_object (value, context->display);
break;
case PROP_WORKSPACE:
g_value_set_object (value, context->workspace);
break;
case PROP_TIMESTAMP:
g_value_set_uint (value, context->timestamp);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
}
}
static void
meta_launch_context_finalize (GObject *object)
{
G_OBJECT_CLASS (meta_launch_context_parent_class)->finalize (object);
}
static void
meta_launch_context_constructed (GObject *object)
{
MetaLaunchContext *context = META_LAUNCH_CONTEXT (object);
const char *x11_display, *wayland_display;
G_OBJECT_CLASS (meta_launch_context_parent_class)->constructed (object);
x11_display = getenv ("DISPLAY");
wayland_display = getenv ("WAYLAND_DISPLAY");
if (x11_display)
{
g_app_launch_context_setenv (G_APP_LAUNCH_CONTEXT (context),
"DISPLAY", x11_display);
}
if (wayland_display)
{
g_app_launch_context_setenv (G_APP_LAUNCH_CONTEXT (context),
"WAYLAND_DISPLAY", wayland_display);
}
}
static gchar *
meta_launch_context_get_startup_notify_id (GAppLaunchContext *launch_context,
GAppInfo *info,
GList *files)
{
MetaLaunchContext *context = META_LAUNCH_CONTEXT (launch_context);
MetaDisplay *display = context->display;
int workspace_idx = -1;
char *startup_id = NULL;
if (context->workspace)
workspace_idx = meta_workspace_index (context->workspace);
if (display->x11_display)
{
/* If there is a X11 display, we prefer going entirely through
* libsn, as SnMonitor expects to keep a view of the full lifetime
* of the startup sequence. We can't avoid it when launching and
* expect that a "remove" message from a X11 client will be handled.
*/
startup_id =
meta_x11_startup_notification_launch (display->x11_display,
info,
context->timestamp,
workspace_idx);
}
if (!startup_id)
{
const char *application_id = NULL;
MetaStartupNotification *sn;
MetaStartupSequence *seq;
startup_id = g_uuid_string_random ();
/* Fallback through inserting our own startup sequence, this
* will be enough for wayland clients.
*/
if (G_IS_DESKTOP_APP_INFO (info))
{
application_id =
g_desktop_app_info_get_filename (G_DESKTOP_APP_INFO (info));
}
sn = meta_display_get_startup_notification (context->display);
seq = g_object_new (META_TYPE_STARTUP_SEQUENCE,
"display", context->display,
"id", startup_id,
"application-id", application_id,
"name", g_app_info_get_name (info),
"workspace", workspace_idx,
"timestamp", (uint64_t) context->timestamp,
NULL);
meta_startup_notification_add_sequence (sn, seq);
g_object_unref (seq);
}
return startup_id;
}
static void
meta_launch_context_launch_failed (GAppLaunchContext *launch_context,
const gchar *startup_notify_id)
{
MetaLaunchContext *context = META_LAUNCH_CONTEXT (launch_context);
MetaStartupNotification *sn;
MetaStartupSequence *seq;
sn = meta_display_get_startup_notification (context->display);
seq = meta_startup_notification_lookup_sequence (sn, startup_notify_id);
if (seq)
{
meta_startup_sequence_complete (seq);
meta_startup_notification_remove_sequence (sn, seq);
}
}
static void
meta_launch_context_class_init (MetaLaunchContextClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS (klass);
GAppLaunchContextClass *ctx_class = G_APP_LAUNCH_CONTEXT_CLASS (klass);
object_class->finalize = meta_launch_context_finalize;
object_class->constructed = meta_launch_context_constructed;
object_class->set_property = meta_launch_context_set_property;
object_class->get_property = meta_launch_context_get_property;
ctx_class->get_startup_notify_id = meta_launch_context_get_startup_notify_id;
ctx_class->launch_failed = meta_launch_context_launch_failed;
props[PROP_DISPLAY] =
g_param_spec_object ("display",
"display",
"Display",
META_TYPE_DISPLAY,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY);
props[PROP_WORKSPACE] =
g_param_spec_object ("workspace",
"workspace",
"Workspace",
META_TYPE_WORKSPACE,
G_PARAM_READWRITE);
props[PROP_TIMESTAMP] =
g_param_spec_uint ("timestamp",
"timestamp",
"Timestamp",
0, G_MAXUINT32, 0,
G_PARAM_READWRITE);
g_object_class_install_properties (object_class, N_PROPS, props);
}
static void
meta_launch_context_init (MetaLaunchContext *context)
{
}
void
meta_launch_context_set_workspace (MetaLaunchContext *context,
MetaWorkspace *workspace)
{
g_return_if_fail (META_IS_LAUNCH_CONTEXT (context));
g_return_if_fail (META_IS_WORKSPACE (workspace));
g_set_object (&context->workspace, workspace);
}
void
meta_launch_context_set_timestamp (MetaLaunchContext *context,
uint32_t timestamp)
{
g_return_if_fail (META_IS_LAUNCH_CONTEXT (context));
context->timestamp = timestamp;
}