2017-06-21 02:23:44 -04:00
|
|
|
/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2017 Red Hat Inc.
|
|
|
|
*
|
|
|
|
* 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
|
2023-08-07 05:50:23 -04:00
|
|
|
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
2017-06-21 02:23:44 -04:00
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
|
|
|
#include "backends/meta-screen-cast-stream.h"
|
|
|
|
|
2023-08-29 14:34:05 -04:00
|
|
|
#include "backends/meta-remote-desktop-session.h"
|
2018-12-12 05:35:58 -05:00
|
|
|
#include "backends/meta-screen-cast-session.h"
|
|
|
|
|
2020-04-21 10:54:54 -04:00
|
|
|
#include "meta-private-enum-types.h"
|
|
|
|
|
2017-09-04 23:38:42 -04:00
|
|
|
#define META_SCREEN_CAST_STREAM_DBUS_IFACE "org.gnome.Mutter.ScreenCast.Stream"
|
2017-06-21 02:23:44 -04:00
|
|
|
#define META_SCREEN_CAST_STREAM_DBUS_PATH "/org/gnome/Mutter/ScreenCast/Stream"
|
|
|
|
|
|
|
|
enum
|
|
|
|
{
|
|
|
|
PROP_0,
|
|
|
|
|
2018-12-12 05:35:58 -05:00
|
|
|
PROP_SESSION,
|
2017-06-21 02:23:44 -04:00
|
|
|
PROP_CONNECTION,
|
2018-12-14 11:47:57 -05:00
|
|
|
PROP_CURSOR_MODE,
|
2020-04-21 10:54:54 -04:00
|
|
|
PROP_FLAGS,
|
2023-09-04 05:44:48 -04:00
|
|
|
PROP_IS_CONFIGURED,
|
2023-09-04 05:43:01 -04:00
|
|
|
|
|
|
|
N_PROPS
|
2017-06-21 02:23:44 -04:00
|
|
|
};
|
|
|
|
|
2023-09-04 05:43:01 -04:00
|
|
|
static GParamSpec *obj_props[N_PROPS];
|
|
|
|
|
2017-06-21 02:23:44 -04:00
|
|
|
enum
|
|
|
|
{
|
|
|
|
CLOSED,
|
|
|
|
|
|
|
|
N_SIGNALS
|
|
|
|
};
|
|
|
|
|
|
|
|
static guint signals[N_SIGNALS];
|
|
|
|
|
|
|
|
typedef struct _MetaScreenCastStreamPrivate
|
|
|
|
{
|
2018-12-12 05:35:58 -05:00
|
|
|
MetaScreenCastSession *session;
|
|
|
|
|
2017-06-21 02:23:44 -04:00
|
|
|
GDBusConnection *connection;
|
|
|
|
char *object_path;
|
|
|
|
|
2018-12-14 11:47:57 -05:00
|
|
|
MetaScreenCastCursorMode cursor_mode;
|
2020-04-21 10:54:54 -04:00
|
|
|
MetaScreenCastFlag flags;
|
2023-09-04 05:44:48 -04:00
|
|
|
gboolean is_configured;
|
2018-12-14 11:47:57 -05:00
|
|
|
|
2017-06-21 02:23:44 -04:00
|
|
|
MetaScreenCastStreamSrc *src;
|
2023-08-29 14:34:05 -04:00
|
|
|
|
|
|
|
char *mapping_id;
|
2017-06-21 02:23:44 -04:00
|
|
|
} MetaScreenCastStreamPrivate;
|
|
|
|
|
2021-07-31 14:46:23 -04:00
|
|
|
static void
|
|
|
|
meta_screen_cast_stream_init_iface (MetaDBusScreenCastStreamIface *iface);
|
|
|
|
|
2017-06-21 02:23:44 -04:00
|
|
|
static void
|
|
|
|
meta_screen_cast_stream_init_initable_iface (GInitableIface *iface);
|
|
|
|
|
|
|
|
G_DEFINE_TYPE_WITH_CODE (MetaScreenCastStream,
|
|
|
|
meta_screen_cast_stream,
|
|
|
|
META_DBUS_TYPE_SCREEN_CAST_STREAM_SKELETON,
|
2021-07-31 14:46:23 -04:00
|
|
|
G_IMPLEMENT_INTERFACE (META_DBUS_TYPE_SCREEN_CAST_STREAM,
|
|
|
|
meta_screen_cast_stream_init_iface)
|
2017-06-21 02:23:44 -04:00
|
|
|
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE,
|
|
|
|
meta_screen_cast_stream_init_initable_iface)
|
|
|
|
G_ADD_PRIVATE (MetaScreenCastStream))
|
|
|
|
|
|
|
|
static MetaScreenCastStreamSrc *
|
|
|
|
meta_screen_cast_stream_create_src (MetaScreenCastStream *stream,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
return META_SCREEN_CAST_STREAM_GET_CLASS (stream)->create_src (stream,
|
|
|
|
error);
|
|
|
|
}
|
|
|
|
|
2017-09-11 21:19:51 -04:00
|
|
|
static void
|
|
|
|
meta_screen_cast_stream_set_parameters (MetaScreenCastStream *stream,
|
|
|
|
GVariantBuilder *parameters_builder)
|
|
|
|
{
|
|
|
|
META_SCREEN_CAST_STREAM_GET_CLASS (stream)->set_parameters (stream,
|
|
|
|
parameters_builder);
|
|
|
|
}
|
|
|
|
|
2017-06-26 00:50:26 -04:00
|
|
|
static void
|
|
|
|
on_stream_src_closed (MetaScreenCastStreamSrc *src,
|
|
|
|
MetaScreenCastStream *stream)
|
|
|
|
{
|
|
|
|
MetaScreenCastStreamPrivate *priv =
|
|
|
|
meta_screen_cast_stream_get_instance_private (stream);
|
|
|
|
|
|
|
|
if (priv->src)
|
|
|
|
meta_screen_cast_stream_close (stream);
|
|
|
|
}
|
|
|
|
|
2017-06-28 03:17:32 -04:00
|
|
|
static void
|
|
|
|
on_stream_src_ready (MetaScreenCastStreamSrc *src,
|
|
|
|
uint32_t node_id,
|
|
|
|
MetaScreenCastStream *stream)
|
|
|
|
{
|
2017-09-04 23:38:42 -04:00
|
|
|
MetaScreenCastStreamPrivate *priv =
|
|
|
|
meta_screen_cast_stream_get_instance_private (stream);
|
|
|
|
GDBusConnection *connection = priv->connection;
|
|
|
|
char *peer_name;
|
|
|
|
|
|
|
|
peer_name = meta_screen_cast_session_get_peer_name (priv->session);
|
|
|
|
g_dbus_connection_emit_signal (connection,
|
|
|
|
peer_name,
|
|
|
|
priv->object_path,
|
|
|
|
META_SCREEN_CAST_STREAM_DBUS_IFACE,
|
|
|
|
"PipeWireStreamAdded",
|
|
|
|
g_variant_new ("(u)", node_id),
|
|
|
|
NULL);
|
2017-06-28 03:17:32 -04:00
|
|
|
}
|
|
|
|
|
2018-12-12 05:35:58 -05:00
|
|
|
MetaScreenCastSession *
|
|
|
|
meta_screen_cast_stream_get_session (MetaScreenCastStream *stream)
|
|
|
|
{
|
|
|
|
MetaScreenCastStreamPrivate *priv =
|
|
|
|
meta_screen_cast_stream_get_instance_private (stream);
|
|
|
|
|
|
|
|
return priv->session;
|
|
|
|
}
|
|
|
|
|
2017-06-21 02:23:44 -04:00
|
|
|
gboolean
|
|
|
|
meta_screen_cast_stream_start (MetaScreenCastStream *stream,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
MetaScreenCastStreamPrivate *priv =
|
|
|
|
meta_screen_cast_stream_get_instance_private (stream);
|
|
|
|
MetaScreenCastStreamSrc *src;
|
|
|
|
|
2021-07-31 14:46:23 -04:00
|
|
|
if (priv->src)
|
|
|
|
{
|
|
|
|
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
|
|
|
|
"Stream already started");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
2017-06-28 03:17:32 -04:00
|
|
|
src = meta_screen_cast_stream_create_src (stream, error);
|
2017-06-21 02:23:44 -04:00
|
|
|
if (!src)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
priv->src = src;
|
2017-06-28 03:17:32 -04:00
|
|
|
g_signal_connect (src, "ready", G_CALLBACK (on_stream_src_ready), stream);
|
2017-06-26 00:50:26 -04:00
|
|
|
g_signal_connect (src, "closed", G_CALLBACK (on_stream_src_closed), stream);
|
2017-06-21 02:23:44 -04:00
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_screen_cast_stream_close (MetaScreenCastStream *stream)
|
|
|
|
{
|
|
|
|
MetaScreenCastStreamPrivate *priv =
|
|
|
|
meta_screen_cast_stream_get_instance_private (stream);
|
|
|
|
|
|
|
|
g_clear_object (&priv->src);
|
|
|
|
|
|
|
|
g_signal_emit (stream, signals[CLOSED], 0);
|
|
|
|
}
|
|
|
|
|
|
|
|
char *
|
|
|
|
meta_screen_cast_stream_get_object_path (MetaScreenCastStream *stream)
|
|
|
|
{
|
|
|
|
MetaScreenCastStreamPrivate *priv =
|
|
|
|
meta_screen_cast_stream_get_instance_private (stream);
|
|
|
|
|
|
|
|
return priv->object_path;
|
|
|
|
}
|
|
|
|
|
2021-01-27 17:36:51 -05:00
|
|
|
MetaScreenCastStreamSrc *
|
|
|
|
meta_screen_cast_stream_get_src (MetaScreenCastStream *stream)
|
|
|
|
{
|
|
|
|
MetaScreenCastStreamPrivate *priv =
|
|
|
|
meta_screen_cast_stream_get_instance_private (stream);
|
|
|
|
|
|
|
|
return priv->src;
|
|
|
|
}
|
|
|
|
|
2021-01-30 17:52:00 -05:00
|
|
|
gboolean
|
2018-01-29 01:46:13 -05:00
|
|
|
meta_screen_cast_stream_transform_position (MetaScreenCastStream *stream,
|
|
|
|
double stream_x,
|
|
|
|
double stream_y,
|
|
|
|
double *x,
|
|
|
|
double *y)
|
|
|
|
{
|
2021-01-30 17:52:00 -05:00
|
|
|
MetaScreenCastStreamClass *klass = META_SCREEN_CAST_STREAM_GET_CLASS (stream);
|
|
|
|
|
|
|
|
return klass->transform_position (stream, stream_x, stream_y, x, y);
|
2018-01-29 01:46:13 -05:00
|
|
|
}
|
|
|
|
|
2018-12-14 11:47:57 -05:00
|
|
|
MetaScreenCastCursorMode
|
|
|
|
meta_screen_cast_stream_get_cursor_mode (MetaScreenCastStream *stream)
|
|
|
|
{
|
|
|
|
MetaScreenCastStreamPrivate *priv =
|
|
|
|
meta_screen_cast_stream_get_instance_private (stream);
|
|
|
|
|
|
|
|
return priv->cursor_mode;
|
|
|
|
}
|
|
|
|
|
2020-04-21 10:54:54 -04:00
|
|
|
MetaScreenCastFlag
|
|
|
|
meta_screen_cast_stream_get_flags (MetaScreenCastStream *stream)
|
|
|
|
{
|
|
|
|
MetaScreenCastStreamPrivate *priv =
|
|
|
|
meta_screen_cast_stream_get_instance_private (stream);
|
|
|
|
|
|
|
|
return priv->flags;
|
|
|
|
}
|
|
|
|
|
2023-08-29 14:34:05 -04:00
|
|
|
const char *
|
|
|
|
meta_screen_cast_stream_get_mapping_id (MetaScreenCastStream *stream)
|
|
|
|
{
|
|
|
|
MetaScreenCastStreamPrivate *priv =
|
|
|
|
meta_screen_cast_stream_get_instance_private (stream);
|
|
|
|
|
|
|
|
return priv->mapping_id;
|
|
|
|
}
|
|
|
|
|
2023-09-04 05:44:48 -04:00
|
|
|
gboolean
|
|
|
|
meta_screen_cast_stream_is_configured (MetaScreenCastStream *stream)
|
|
|
|
{
|
|
|
|
MetaScreenCastStreamPrivate *priv =
|
|
|
|
meta_screen_cast_stream_get_instance_private (stream);
|
|
|
|
|
|
|
|
return priv->is_configured;
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
meta_screen_cast_stream_notify_is_configured (MetaScreenCastStream *stream)
|
|
|
|
{
|
|
|
|
MetaScreenCastStreamPrivate *priv =
|
|
|
|
meta_screen_cast_stream_get_instance_private (stream);
|
|
|
|
|
|
|
|
priv->is_configured = TRUE;
|
|
|
|
g_object_notify_by_pspec (G_OBJECT (stream), obj_props[PROP_IS_CONFIGURED]);
|
|
|
|
}
|
|
|
|
|
2017-06-21 02:23:44 -04:00
|
|
|
static void
|
|
|
|
meta_screen_cast_stream_set_property (GObject *object,
|
|
|
|
guint prop_id,
|
|
|
|
const GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
MetaScreenCastStream *stream = META_SCREEN_CAST_STREAM (object);
|
|
|
|
MetaScreenCastStreamPrivate *priv =
|
|
|
|
meta_screen_cast_stream_get_instance_private (stream);
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
{
|
2018-12-12 05:35:58 -05:00
|
|
|
case PROP_SESSION:
|
|
|
|
priv->session = g_value_get_object (value);
|
|
|
|
break;
|
2017-06-21 02:23:44 -04:00
|
|
|
case PROP_CONNECTION:
|
|
|
|
priv->connection = g_value_get_object (value);
|
|
|
|
break;
|
2018-12-14 11:47:57 -05:00
|
|
|
case PROP_CURSOR_MODE:
|
|
|
|
priv->cursor_mode = g_value_get_uint (value);
|
|
|
|
break;
|
2020-04-21 10:54:54 -04:00
|
|
|
case PROP_FLAGS:
|
|
|
|
priv->flags = g_value_get_flags (value);
|
|
|
|
break;
|
2023-09-04 05:44:48 -04:00
|
|
|
case PROP_IS_CONFIGURED:
|
|
|
|
priv->is_configured = g_value_get_boolean (value);
|
|
|
|
break;
|
2017-06-21 02:23:44 -04:00
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_screen_cast_stream_get_property (GObject *object,
|
|
|
|
guint prop_id,
|
|
|
|
GValue *value,
|
|
|
|
GParamSpec *pspec)
|
|
|
|
{
|
|
|
|
MetaScreenCastStream *stream = META_SCREEN_CAST_STREAM (object);
|
|
|
|
MetaScreenCastStreamPrivate *priv =
|
|
|
|
meta_screen_cast_stream_get_instance_private (stream);
|
|
|
|
|
|
|
|
switch (prop_id)
|
|
|
|
{
|
2018-12-12 05:35:58 -05:00
|
|
|
case PROP_SESSION:
|
|
|
|
g_value_set_object (value, priv->session);
|
|
|
|
break;
|
2017-06-21 02:23:44 -04:00
|
|
|
case PROP_CONNECTION:
|
|
|
|
g_value_set_object (value, priv->connection);
|
|
|
|
break;
|
2018-12-14 11:47:57 -05:00
|
|
|
case PROP_CURSOR_MODE:
|
|
|
|
g_value_set_uint (value, priv->cursor_mode);
|
|
|
|
break;
|
2020-04-21 10:54:54 -04:00
|
|
|
case PROP_FLAGS:
|
|
|
|
g_value_set_flags (value, priv->flags);
|
|
|
|
break;
|
2023-09-04 05:44:48 -04:00
|
|
|
case PROP_IS_CONFIGURED:
|
|
|
|
g_value_set_boolean (value, priv->is_configured);
|
|
|
|
break;
|
2017-06-21 02:23:44 -04:00
|
|
|
default:
|
|
|
|
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_screen_cast_stream_finalize (GObject *object)
|
|
|
|
{
|
|
|
|
MetaScreenCastStream *stream = META_SCREEN_CAST_STREAM (object);
|
|
|
|
MetaScreenCastStreamPrivate *priv =
|
|
|
|
meta_screen_cast_stream_get_instance_private (stream);
|
2023-09-12 07:17:27 -04:00
|
|
|
MetaRemoteDesktopSession *remote_desktop_session;
|
2017-06-21 02:23:44 -04:00
|
|
|
|
|
|
|
if (priv->src)
|
|
|
|
meta_screen_cast_stream_close (stream);
|
|
|
|
|
2023-09-12 07:17:27 -04:00
|
|
|
remote_desktop_session =
|
|
|
|
meta_screen_cast_session_get_remote_desktop_session (priv->session);
|
|
|
|
if (remote_desktop_session && priv->mapping_id)
|
|
|
|
{
|
|
|
|
meta_remote_desktop_session_release_mapping_id (remote_desktop_session,
|
|
|
|
priv->mapping_id);
|
|
|
|
}
|
|
|
|
|
2017-06-21 02:23:44 -04:00
|
|
|
g_clear_pointer (&priv->object_path, g_free);
|
2023-08-29 14:34:05 -04:00
|
|
|
g_clear_pointer (&priv->mapping_id, g_free);
|
2017-06-21 02:23:44 -04:00
|
|
|
|
|
|
|
G_OBJECT_CLASS (meta_screen_cast_stream_parent_class)->finalize (object);
|
|
|
|
}
|
|
|
|
|
2021-07-31 14:46:23 -04:00
|
|
|
static gboolean
|
|
|
|
check_permission (MetaScreenCastStream *stream,
|
|
|
|
GDBusMethodInvocation *invocation)
|
|
|
|
{
|
|
|
|
MetaScreenCastStreamPrivate *priv =
|
|
|
|
meta_screen_cast_stream_get_instance_private (stream);
|
|
|
|
char *peer_name;
|
|
|
|
|
|
|
|
peer_name = meta_screen_cast_session_get_peer_name (priv->session);
|
|
|
|
return g_strcmp0 (peer_name,
|
|
|
|
g_dbus_method_invocation_get_sender (invocation)) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
static gboolean
|
|
|
|
handle_start (MetaDBusScreenCastStream *skeleton,
|
|
|
|
GDBusMethodInvocation *invocation)
|
|
|
|
{
|
|
|
|
MetaScreenCastStream *stream = META_SCREEN_CAST_STREAM (skeleton);
|
|
|
|
MetaScreenCastStreamPrivate *priv =
|
|
|
|
meta_screen_cast_stream_get_instance_private (stream);
|
|
|
|
g_autoptr (GError) error = NULL;
|
|
|
|
|
|
|
|
if (!check_permission (stream, invocation))
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_ACCESS_DENIED,
|
|
|
|
"Permission denied");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!meta_screen_cast_session_is_active (priv->session))
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Failed to start stream: "
|
|
|
|
"session not started");
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!meta_screen_cast_stream_start (stream, &error))
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_FAILED,
|
|
|
|
"Failed to start stream: %s",
|
|
|
|
error->message);
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
meta_dbus_screen_cast_stream_complete_start (skeleton, invocation);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
screencast: Add ability to stop streams
When a stream is destroyed by a consumer, mutter won't be able to
recognize that.
For mutter, the stream just paused, but did not disconnect, because the
connection state of a PipeWire stream only represents, whether the
respective PipeWire context is connected to PipeWire.
In addition to that, it may be the case, that the stream consumer just
recreates the stream.
So even if mutter would be able to know, when the stream consumer
destroyed a stream, but not the whole screencast or remote-desktop
session, then mutter would not know, whether the stream will be resumed
eventually or not.
So, add an explicit API call to the screencast interface to stop a
stream.
For virtual streams, this also means, that the respective virtual
monitor is destroyed.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2889
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3307>
2023-09-29 06:33:17 -04:00
|
|
|
static gboolean
|
|
|
|
handle_stop (MetaDBusScreenCastStream *skeleton,
|
|
|
|
GDBusMethodInvocation *invocation)
|
|
|
|
{
|
|
|
|
MetaScreenCastStream *stream = META_SCREEN_CAST_STREAM (skeleton);
|
|
|
|
MetaScreenCastStreamPrivate *priv =
|
|
|
|
meta_screen_cast_stream_get_instance_private (stream);
|
|
|
|
|
|
|
|
if (!check_permission (stream, invocation))
|
|
|
|
{
|
|
|
|
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
|
|
|
|
G_DBUS_ERROR_ACCESS_DENIED,
|
|
|
|
"Permission denied");
|
|
|
|
return G_DBUS_METHOD_INVOCATION_HANDLED;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (priv->src)
|
|
|
|
meta_screen_cast_stream_close (stream);
|
|
|
|
|
|
|
|
meta_dbus_screen_cast_stream_complete_stop (skeleton, invocation);
|
|
|
|
|
|
|
|
return G_DBUS_METHOD_INVOCATION_HANDLED;
|
|
|
|
}
|
|
|
|
|
2021-07-31 14:46:23 -04:00
|
|
|
static void
|
|
|
|
meta_screen_cast_stream_init_iface (MetaDBusScreenCastStreamIface *iface)
|
|
|
|
{
|
|
|
|
iface->handle_start = handle_start;
|
screencast: Add ability to stop streams
When a stream is destroyed by a consumer, mutter won't be able to
recognize that.
For mutter, the stream just paused, but did not disconnect, because the
connection state of a PipeWire stream only represents, whether the
respective PipeWire context is connected to PipeWire.
In addition to that, it may be the case, that the stream consumer just
recreates the stream.
So even if mutter would be able to know, when the stream consumer
destroyed a stream, but not the whole screencast or remote-desktop
session, then mutter would not know, whether the stream will be resumed
eventually or not.
So, add an explicit API call to the screencast interface to stop a
stream.
For virtual streams, this also means, that the respective virtual
monitor is destroyed.
Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/2889
Part-of: <https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/3307>
2023-09-29 06:33:17 -04:00
|
|
|
iface->handle_stop = handle_stop;
|
2021-07-31 14:46:23 -04:00
|
|
|
}
|
|
|
|
|
2017-06-21 02:23:44 -04:00
|
|
|
static gboolean
|
|
|
|
meta_screen_cast_stream_initable_init (GInitable *initable,
|
|
|
|
GCancellable *cancellable,
|
|
|
|
GError **error)
|
|
|
|
{
|
|
|
|
MetaScreenCastStream *stream = META_SCREEN_CAST_STREAM (initable);
|
2017-09-11 21:19:51 -04:00
|
|
|
MetaDBusScreenCastStream *skeleton = META_DBUS_SCREEN_CAST_STREAM (stream);
|
2017-06-21 02:23:44 -04:00
|
|
|
MetaScreenCastStreamPrivate *priv =
|
|
|
|
meta_screen_cast_stream_get_instance_private (stream);
|
2023-08-29 14:34:05 -04:00
|
|
|
MetaRemoteDesktopSession *remote_desktop_session;
|
2017-09-11 21:19:51 -04:00
|
|
|
GVariantBuilder parameters_builder;
|
|
|
|
GVariant *parameters_variant;
|
2017-06-21 02:23:44 -04:00
|
|
|
static unsigned int global_stream_number = 0;
|
|
|
|
|
2017-09-11 21:19:51 -04:00
|
|
|
g_variant_builder_init (¶meters_builder, G_VARIANT_TYPE_VARDICT);
|
|
|
|
meta_screen_cast_stream_set_parameters (stream, ¶meters_builder);
|
|
|
|
|
2023-08-29 14:34:05 -04:00
|
|
|
remote_desktop_session =
|
|
|
|
meta_screen_cast_session_get_remote_desktop_session (priv->session);
|
|
|
|
if (remote_desktop_session)
|
|
|
|
{
|
|
|
|
const char *mapping_id;
|
|
|
|
|
|
|
|
mapping_id =
|
|
|
|
meta_remote_desktop_session_acquire_mapping_id (remote_desktop_session);
|
|
|
|
priv->mapping_id = g_strdup (mapping_id);
|
|
|
|
g_variant_builder_add (¶meters_builder, "{sv}",
|
|
|
|
"mapping-id",
|
|
|
|
g_variant_new ("s", priv->mapping_id));
|
|
|
|
}
|
|
|
|
|
2017-09-11 21:19:51 -04:00
|
|
|
parameters_variant = g_variant_builder_end (¶meters_builder);
|
|
|
|
meta_dbus_screen_cast_stream_set_parameters (skeleton, parameters_variant);
|
|
|
|
|
2017-06-21 02:23:44 -04:00
|
|
|
priv->object_path =
|
|
|
|
g_strdup_printf (META_SCREEN_CAST_STREAM_DBUS_PATH "/u%u",
|
|
|
|
++global_stream_number);
|
|
|
|
if (!g_dbus_interface_skeleton_export (G_DBUS_INTERFACE_SKELETON (stream),
|
|
|
|
priv->connection,
|
|
|
|
priv->object_path,
|
|
|
|
error))
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_screen_cast_stream_init_initable_iface (GInitableIface *iface)
|
|
|
|
{
|
|
|
|
iface->init = meta_screen_cast_stream_initable_init;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_screen_cast_stream_init (MetaScreenCastStream *stream)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
static void
|
|
|
|
meta_screen_cast_stream_class_init (MetaScreenCastStreamClass *klass)
|
|
|
|
{
|
|
|
|
GObjectClass *object_class = G_OBJECT_CLASS (klass);
|
|
|
|
|
|
|
|
object_class->finalize = meta_screen_cast_stream_finalize;
|
|
|
|
object_class->set_property = meta_screen_cast_stream_set_property;
|
|
|
|
object_class->get_property = meta_screen_cast_stream_get_property;
|
|
|
|
|
2023-09-04 05:43:01 -04:00
|
|
|
obj_props[PROP_SESSION] =
|
|
|
|
g_param_spec_object ("session", NULL, NULL,
|
|
|
|
META_TYPE_SCREEN_CAST_SESSION,
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
obj_props[PROP_CONNECTION] =
|
|
|
|
g_param_spec_object ("connection", NULL, NULL,
|
|
|
|
G_TYPE_DBUS_CONNECTION,
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
obj_props[PROP_CURSOR_MODE] =
|
|
|
|
g_param_spec_uint ("cursor-mode", NULL, NULL,
|
|
|
|
META_SCREEN_CAST_CURSOR_MODE_HIDDEN,
|
|
|
|
META_SCREEN_CAST_CURSOR_MODE_METADATA,
|
|
|
|
META_SCREEN_CAST_CURSOR_MODE_HIDDEN,
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
|
|
|
obj_props[PROP_FLAGS] =
|
|
|
|
g_param_spec_flags ("flags", NULL, NULL,
|
|
|
|
META_TYPE_SCREEN_CAST_FLAG,
|
|
|
|
META_SCREEN_CAST_FLAG_NONE,
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
G_PARAM_CONSTRUCT_ONLY |
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2023-09-04 05:44:48 -04:00
|
|
|
obj_props[PROP_IS_CONFIGURED] =
|
|
|
|
g_param_spec_boolean ("is-configured", NULL, NULL,
|
|
|
|
FALSE,
|
|
|
|
G_PARAM_READWRITE |
|
|
|
|
G_PARAM_CONSTRUCT |
|
|
|
|
G_PARAM_STATIC_STRINGS);
|
2023-09-04 05:43:01 -04:00
|
|
|
g_object_class_install_properties (object_class, N_PROPS, obj_props);
|
2020-04-21 10:54:54 -04:00
|
|
|
|
2017-06-21 02:23:44 -04:00
|
|
|
signals[CLOSED] = g_signal_new ("closed",
|
|
|
|
G_TYPE_FROM_CLASS (klass),
|
|
|
|
G_SIGNAL_RUN_LAST,
|
|
|
|
0,
|
|
|
|
NULL, NULL, NULL,
|
|
|
|
G_TYPE_NONE, 0);
|
|
|
|
}
|