From 9be189daa728cac44d8ae14c887239d1f922bed2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Mon, 21 Jan 2019 14:32:05 +0100 Subject: [PATCH 01/15] screen-cast: Move cursor metadata setting to generic source Make the monitor implementation do things strictly related to its own source type, leaving the Spa related logic and cursor read back in the generic layer, later to be reused by the window source type implementation. https://gitlab.gnome.org/GNOME/mutter/merge_requests/413 --- .../meta-screen-cast-monitor-stream-src.c | 162 +++------------ src/backends/meta-screen-cast-stream-src.c | 196 ++++++++++++++++++ src/backends/meta-screen-cast-stream-src.h | 20 ++ 3 files changed, 241 insertions(+), 137 deletions(-) diff --git a/src/backends/meta-screen-cast-monitor-stream-src.c b/src/backends/meta-screen-cast-monitor-stream-src.c index 036c573a577..cb9823148ce 100644 --- a/src/backends/meta-screen-cast-monitor-stream-src.c +++ b/src/backends/meta-screen-cast-monitor-stream-src.c @@ -344,64 +344,6 @@ meta_screen_cast_monitor_stream_src_record_frame (MetaScreenCastStreamSrc *src, return TRUE; } -static gboolean -draw_cursor_sprite_via_offscreen (MetaScreenCastMonitorStreamSrc *monitor_src, - CoglTexture *cursor_texture, - int bitmap_width, - int bitmap_height, - uint32_t *bitmap_data, - GError **error) -{ - MetaBackend *backend = get_backend (monitor_src); - ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); - CoglContext *cogl_context = - clutter_backend_get_cogl_context (clutter_backend); - CoglTexture2D *bitmap_texture; - CoglOffscreen *offscreen; - CoglFramebuffer *fb; - CoglPipeline *pipeline; - CoglColor clear_color; - - bitmap_texture = cogl_texture_2d_new_with_size (cogl_context, - bitmap_width, bitmap_height); - cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (bitmap_texture), - FALSE); - if (!cogl_texture_allocate (COGL_TEXTURE (bitmap_texture), error)) - { - cogl_object_unref (bitmap_texture); - return FALSE; - } - - offscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (bitmap_texture)); - fb = COGL_FRAMEBUFFER (offscreen); - cogl_object_unref (bitmap_texture); - if (!cogl_framebuffer_allocate (fb, error)) - { - cogl_object_unref (fb); - return FALSE; - } - - pipeline = cogl_pipeline_new (cogl_context); - cogl_pipeline_set_layer_texture (pipeline, 0, cursor_texture); - cogl_pipeline_set_layer_filters (pipeline, 0, - COGL_PIPELINE_FILTER_LINEAR, - COGL_PIPELINE_FILTER_LINEAR); - cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0); - cogl_framebuffer_clear (fb, COGL_BUFFER_BIT_COLOR, &clear_color); - cogl_framebuffer_draw_rectangle (fb, pipeline, - -1, 1, 1, -1); - cogl_object_unref (pipeline); - - cogl_framebuffer_read_pixels (fb, - 0, 0, - bitmap_width, bitmap_height, - COGL_PIXEL_FORMAT_RGBA_8888_PRE, - (uint8_t *) bitmap_data); - cogl_object_unref (fb); - - return TRUE; -} - static void meta_screen_cast_monitor_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src, struct spa_meta_cursor *spa_meta_cursor) @@ -412,10 +354,7 @@ meta_screen_cast_monitor_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc MetaCursorRenderer *cursor_renderer = meta_backend_get_cursor_renderer (backend); MetaRenderer *renderer = meta_backend_get_renderer (backend); - MetaSpaType *spa_type = meta_screen_cast_stream_src_get_spa_type (src); - GError *error = NULL; MetaCursorSprite *cursor_sprite; - CoglTexture *cursor_texture; MetaMonitor *monitor; MetaLogicalMonitor *logical_monitor; MetaRectangle logical_monitor_layout; @@ -423,17 +362,14 @@ meta_screen_cast_monitor_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc MetaRendererView *view; float view_scale; ClutterPoint cursor_position; - struct spa_meta_bitmap *spa_meta_bitmap; + int x, y; cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer); - if (cursor_sprite) - cursor_texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); - else - cursor_texture = NULL; if (!is_cursor_in_stream (monitor_src)) { - spa_meta_cursor->id = 0; + meta_screen_cast_stream_src_unset_cursor_metadata (src, + spa_meta_cursor); return; } @@ -456,86 +392,38 @@ meta_screen_cast_monitor_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc cursor_position.x *= view_scale; cursor_position.y *= view_scale; - spa_meta_cursor->id = 1; - spa_meta_cursor->position.x = (int32_t) roundf (cursor_position.x); - spa_meta_cursor->position.y = (int32_t) roundf (cursor_position.y); + x = (int) roundf (cursor_position.x); + y = (int) roundf (cursor_position.y); - if (!monitor_src->cursor_bitmap_invalid) + if (monitor_src->cursor_bitmap_invalid) { - spa_meta_cursor->hotspot.x = 0; - spa_meta_cursor->hotspot.y = 0; - spa_meta_cursor->bitmap_offset = 0; - return; - } - monitor_src->cursor_bitmap_invalid = FALSE; - - spa_meta_cursor->bitmap_offset = sizeof (struct spa_meta_cursor); - - spa_meta_bitmap = SPA_MEMBER (spa_meta_cursor, - spa_meta_cursor->bitmap_offset, - struct spa_meta_bitmap); - spa_meta_bitmap->format = spa_type->video_format.RGBA; - spa_meta_bitmap->offset = sizeof (struct spa_meta_bitmap); - - if (cursor_texture) - { - float cursor_scale; - float bitmap_scale; - int hotspot_x, hotspot_y; - int texture_width, texture_height; - int bitmap_width, bitmap_height; - uint32_t *bitmap_data; - - cursor_scale = meta_cursor_sprite_get_texture_scale (cursor_sprite); - bitmap_scale = view_scale * cursor_scale; - - meta_cursor_sprite_get_hotspot (cursor_sprite, &hotspot_x, &hotspot_y); - spa_meta_cursor->hotspot.x = (int32_t) roundf (hotspot_x * bitmap_scale); - spa_meta_cursor->hotspot.y = (int32_t) roundf (hotspot_y * bitmap_scale); - - texture_width = cogl_texture_get_width (cursor_texture); - texture_height = cogl_texture_get_height (cursor_texture); - bitmap_width = texture_width * bitmap_scale; - bitmap_height = texture_height * bitmap_scale; - - spa_meta_bitmap->size.width = bitmap_width; - spa_meta_bitmap->size.height = bitmap_height; - spa_meta_bitmap->stride = bitmap_width * 4; - - bitmap_data = SPA_MEMBER (spa_meta_bitmap, - spa_meta_bitmap->offset, - uint32_t); - - if (texture_width == bitmap_width && - texture_height == bitmap_height) + if (cursor_sprite) { - cogl_texture_get_data (cursor_texture, - COGL_PIXEL_FORMAT_RGBA_8888_PRE, - texture_width * 4, - (uint8_t *) bitmap_data); + float cursor_scale; + float scale; + + cursor_scale = meta_cursor_sprite_get_texture_scale (cursor_sprite); + scale = view_scale * cursor_scale; + meta_screen_cast_stream_src_set_cursor_sprite_metadata (src, + spa_meta_cursor, + cursor_sprite, + x, y, + scale); } else { - if (!draw_cursor_sprite_via_offscreen (monitor_src, - cursor_texture, - bitmap_width, - bitmap_height, - bitmap_data, - &error)) - { - g_warning ("Failed to draw cursor via offscreen: %s", - error->message); - g_error_free (error); - spa_meta_cursor->id = 0; - } + meta_screen_cast_stream_src_set_empty_cursor_sprite_metadata (src, + spa_meta_cursor, + x, y); } + + monitor_src->cursor_bitmap_invalid = FALSE; } else { - spa_meta_cursor->hotspot.x = 0; - spa_meta_cursor->hotspot.y = 0; - - *spa_meta_bitmap = (struct spa_meta_bitmap) { 0 }; + meta_screen_cast_stream_src_set_cursor_position_metadata (src, + spa_meta_cursor, + x, y); } } diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c index 7e11bd06726..ba800debf1c 100644 --- a/src/backends/meta-screen-cast-stream-src.c +++ b/src/backends/meta-screen-cast-stream-src.c @@ -32,6 +32,7 @@ #include #include +#include "backends/meta-screen-cast-session.h" #include "backends/meta-screen-cast-stream.h" #include "clutter/clutter-mutter.h" #include "core/meta-fraction.h" @@ -159,6 +160,201 @@ meta_screen_cast_stream_src_get_spa_type (MetaScreenCastStreamSrc *src) return &priv->spa_type; } +static gboolean +draw_cursor_sprite_via_offscreen (MetaScreenCastStreamSrc *src, + CoglTexture *cursor_texture, + int bitmap_width, + int bitmap_height, + uint32_t *bitmap_data, + GError **error) +{ + MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); + MetaScreenCastSession *session = meta_screen_cast_stream_get_session (stream); + MetaScreenCast *screen_cast = + meta_screen_cast_session_get_screen_cast (session); + MetaBackend *backend = meta_screen_cast_get_backend (screen_cast); + ClutterBackend *clutter_backend = meta_backend_get_clutter_backend (backend); + CoglContext *cogl_context = + clutter_backend_get_cogl_context (clutter_backend); + CoglTexture2D *bitmap_texture; + CoglOffscreen *offscreen; + CoglFramebuffer *fb; + CoglPipeline *pipeline; + CoglColor clear_color; + + bitmap_texture = cogl_texture_2d_new_with_size (cogl_context, + bitmap_width, bitmap_height); + cogl_primitive_texture_set_auto_mipmap (COGL_PRIMITIVE_TEXTURE (bitmap_texture), + FALSE); + if (!cogl_texture_allocate (COGL_TEXTURE (bitmap_texture), error)) + { + cogl_object_unref (bitmap_texture); + return FALSE; + } + + offscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (bitmap_texture)); + fb = COGL_FRAMEBUFFER (offscreen); + cogl_object_unref (bitmap_texture); + if (!cogl_framebuffer_allocate (fb, error)) + { + cogl_object_unref (fb); + return FALSE; + } + + pipeline = cogl_pipeline_new (cogl_context); + cogl_pipeline_set_layer_texture (pipeline, 0, cursor_texture); + cogl_pipeline_set_layer_filters (pipeline, 0, + COGL_PIPELINE_FILTER_LINEAR, + COGL_PIPELINE_FILTER_LINEAR); + cogl_color_init_from_4ub (&clear_color, 0, 0, 0, 0); + cogl_framebuffer_clear (fb, COGL_BUFFER_BIT_COLOR, &clear_color); + cogl_framebuffer_draw_rectangle (fb, pipeline, + -1, 1, 1, -1); + cogl_object_unref (pipeline); + + cogl_framebuffer_read_pixels (fb, + 0, 0, + bitmap_width, bitmap_height, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + (uint8_t *) bitmap_data); + cogl_object_unref (fb); + + return TRUE; +} + +void +meta_screen_cast_stream_src_unset_cursor_metadata (MetaScreenCastStreamSrc *src, + struct spa_meta_cursor *spa_meta_cursor) +{ + spa_meta_cursor->id = 1; +} + +void +meta_screen_cast_stream_src_set_cursor_position_metadata (MetaScreenCastStreamSrc *src, + struct spa_meta_cursor *spa_meta_cursor, + int x, + int y) +{ + spa_meta_cursor->id = 1; + spa_meta_cursor->position.x = x; + spa_meta_cursor->position.y = y; + spa_meta_cursor->hotspot.x = 0; + spa_meta_cursor->hotspot.y = 0; + spa_meta_cursor->bitmap_offset = 0; +} + +void +meta_screen_cast_stream_src_set_empty_cursor_sprite_metadata (MetaScreenCastStreamSrc *src, + struct spa_meta_cursor *spa_meta_cursor, + int x, + int y) +{ + MetaScreenCastStreamSrcPrivate *priv = + meta_screen_cast_stream_src_get_instance_private (src); + MetaSpaType *spa_type = &priv->spa_type; + struct spa_meta_bitmap *spa_meta_bitmap; + + spa_meta_cursor->id = 1; + spa_meta_cursor->position.x = x; + spa_meta_cursor->position.y = y; + + spa_meta_cursor->bitmap_offset = sizeof (struct spa_meta_cursor); + + spa_meta_bitmap = SPA_MEMBER (spa_meta_cursor, + spa_meta_cursor->bitmap_offset, + struct spa_meta_bitmap); + spa_meta_bitmap->format = spa_type->video_format.RGBA; + spa_meta_bitmap->offset = sizeof (struct spa_meta_bitmap); + + spa_meta_cursor->hotspot.x = 0; + spa_meta_cursor->hotspot.y = 0; + + *spa_meta_bitmap = (struct spa_meta_bitmap) { 0 }; +} + +void +meta_screen_cast_stream_src_set_cursor_sprite_metadata (MetaScreenCastStreamSrc *src, + struct spa_meta_cursor *spa_meta_cursor, + MetaCursorSprite *cursor_sprite, + int x, + int y, + float scale) +{ + MetaScreenCastStreamSrcPrivate *priv = + meta_screen_cast_stream_src_get_instance_private (src); + MetaSpaType *spa_type = &priv->spa_type; + CoglTexture *cursor_texture; + struct spa_meta_bitmap *spa_meta_bitmap; + int hotspot_x, hotspot_y; + int texture_width, texture_height; + int bitmap_width, bitmap_height; + uint32_t *bitmap_data; + + cursor_texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); + if (!cursor_texture) + { + meta_screen_cast_stream_src_set_empty_cursor_sprite_metadata (src, + spa_meta_cursor, + x, y); + return; + } + + spa_meta_cursor->id = 1; + spa_meta_cursor->position.x = x; + spa_meta_cursor->position.y = y; + + spa_meta_cursor->bitmap_offset = sizeof (struct spa_meta_cursor); + + spa_meta_bitmap = SPA_MEMBER (spa_meta_cursor, + spa_meta_cursor->bitmap_offset, + struct spa_meta_bitmap); + spa_meta_bitmap->format = spa_type->video_format.RGBA; + spa_meta_bitmap->offset = sizeof (struct spa_meta_bitmap); + + meta_cursor_sprite_get_hotspot (cursor_sprite, &hotspot_x, &hotspot_y); + spa_meta_cursor->hotspot.x = (int32_t) roundf (hotspot_x * scale); + spa_meta_cursor->hotspot.y = (int32_t) roundf (hotspot_y * scale); + + texture_width = cogl_texture_get_width (cursor_texture); + texture_height = cogl_texture_get_height (cursor_texture); + bitmap_width = texture_width * scale; + bitmap_height = texture_height * scale; + + spa_meta_bitmap->size.width = bitmap_width; + spa_meta_bitmap->size.height = bitmap_height; + spa_meta_bitmap->stride = bitmap_width * 4; + + bitmap_data = SPA_MEMBER (spa_meta_bitmap, + spa_meta_bitmap->offset, + uint32_t); + + if (texture_width == bitmap_width && + texture_height == bitmap_height) + { + cogl_texture_get_data (cursor_texture, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + texture_width * 4, + (uint8_t *) bitmap_data); + } + else + { + GError *error = NULL; + + if (!draw_cursor_sprite_via_offscreen (src, + cursor_texture, + bitmap_width, + bitmap_height, + bitmap_data, + &error)) + { + g_warning ("Failed to draw cursor via offscreen: %s", + error->message); + g_error_free (error); + spa_meta_cursor->id = 0; + } + } +} + static void add_cursor_metadata (MetaScreenCastStreamSrc *src, struct spa_buffer *spa_buffer) diff --git a/src/backends/meta-screen-cast-stream-src.h b/src/backends/meta-screen-cast-stream-src.h index f2f96f2130f..108582893cf 100644 --- a/src/backends/meta-screen-cast-stream-src.h +++ b/src/backends/meta-screen-cast-stream-src.h @@ -76,4 +76,24 @@ MetaScreenCastStream * meta_screen_cast_stream_src_get_stream (MetaScreenCastStr MetaSpaType * meta_screen_cast_stream_src_get_spa_type (MetaScreenCastStreamSrc *src); +void meta_screen_cast_stream_src_unset_cursor_metadata (MetaScreenCastStreamSrc *src, + struct spa_meta_cursor *spa_meta_cursor); + +void meta_screen_cast_stream_src_set_cursor_position_metadata (MetaScreenCastStreamSrc *src, + struct spa_meta_cursor *spa_meta_cursor, + int x, + int y); + +void meta_screen_cast_stream_src_set_empty_cursor_sprite_metadata (MetaScreenCastStreamSrc *src, + struct spa_meta_cursor *spa_meta_cursor, + int x, + int y); + +void meta_screen_cast_stream_src_set_cursor_sprite_metadata (MetaScreenCastStreamSrc *src, + struct spa_meta_cursor *spa_meta_cursor, + MetaCursorSprite *cursor_sprite, + int x, + int y, + float scale); + #endif /* META_SCREEN_CAST_STREAM_SRC_H */ -- GitLab From 176b50802941600ab7cac6196c0a2bb66bc836b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 24 Jan 2019 18:36:34 +0100 Subject: [PATCH 02/15] screen-cast-src: Change offscreen cursor helper to take a `uint8_t *` Instead of a `uint32_t *`. Eventually we shouldn't assume pixels are always 32 bit, and this gets rid of some casts while at it. https://gitlab.gnome.org/GNOME/mutter/merge_requests/413 --- src/backends/meta-screen-cast-stream-src.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c index ba800debf1c..a9097ff026c 100644 --- a/src/backends/meta-screen-cast-stream-src.c +++ b/src/backends/meta-screen-cast-stream-src.c @@ -165,7 +165,7 @@ draw_cursor_sprite_via_offscreen (MetaScreenCastStreamSrc *src, CoglTexture *cursor_texture, int bitmap_width, int bitmap_height, - uint32_t *bitmap_data, + uint8_t *bitmap_data, GError **error) { MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); @@ -216,7 +216,7 @@ draw_cursor_sprite_via_offscreen (MetaScreenCastStreamSrc *src, 0, 0, bitmap_width, bitmap_height, COGL_PIXEL_FORMAT_RGBA_8888_PRE, - (uint8_t *) bitmap_data); + bitmap_data); cogl_object_unref (fb); return TRUE; @@ -288,7 +288,7 @@ meta_screen_cast_stream_src_set_cursor_sprite_metadata (MetaScreenCastStreamSrc int hotspot_x, hotspot_y; int texture_width, texture_height; int bitmap_width, bitmap_height; - uint32_t *bitmap_data; + uint8_t *bitmap_data; cursor_texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); if (!cursor_texture) @@ -326,7 +326,7 @@ meta_screen_cast_stream_src_set_cursor_sprite_metadata (MetaScreenCastStreamSrc bitmap_data = SPA_MEMBER (spa_meta_bitmap, spa_meta_bitmap->offset, - uint32_t); + uint8_t); if (texture_width == bitmap_width && texture_height == bitmap_height) @@ -334,7 +334,7 @@ meta_screen_cast_stream_src_set_cursor_sprite_metadata (MetaScreenCastStreamSrc cogl_texture_get_data (cursor_texture, COGL_PIXEL_FORMAT_RGBA_8888_PRE, texture_width * 4, - (uint8_t *) bitmap_data); + bitmap_data); } else { -- GitLab From 183de60d91f1fa3539bc394722e35604ff881dfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 24 Jan 2019 19:00:24 +0100 Subject: [PATCH 03/15] screen-cast-src: Move back MetaSpaType to C file It's not needed by the monitor source anymore. https://gitlab.gnome.org/GNOME/mutter/merge_requests/413 --- src/backends/meta-screen-cast-stream-src.c | 18 +++++++++--------- src/backends/meta-screen-cast-stream-src.h | 11 ----------- 2 files changed, 9 insertions(+), 20 deletions(-) diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c index a9097ff026c..3fc6084afbc 100644 --- a/src/backends/meta-screen-cast-stream-src.c +++ b/src/backends/meta-screen-cast-stream-src.c @@ -62,6 +62,15 @@ enum static guint signals[N_SIGNALS]; +typedef struct _MetaSpaType +{ + struct spa_type_media_type media_type; + struct spa_type_media_subtype media_subtype; + struct spa_type_format_video format_video; + struct spa_type_video_format video_format; + uint32_t meta_cursor; +} MetaSpaType; + typedef struct _MetaPipeWireSource { GSource base; @@ -151,15 +160,6 @@ meta_screen_cast_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src, klass->set_cursor_metadata (src, spa_meta_cursor); } -MetaSpaType * -meta_screen_cast_stream_src_get_spa_type (MetaScreenCastStreamSrc *src) -{ - MetaScreenCastStreamSrcPrivate *priv = - meta_screen_cast_stream_src_get_instance_private (src); - - return &priv->spa_type; -} - static gboolean draw_cursor_sprite_via_offscreen (MetaScreenCastStreamSrc *src, CoglTexture *cursor_texture, diff --git a/src/backends/meta-screen-cast-stream-src.h b/src/backends/meta-screen-cast-stream-src.h index 108582893cf..3f8c6fa27d0 100644 --- a/src/backends/meta-screen-cast-stream-src.h +++ b/src/backends/meta-screen-cast-stream-src.h @@ -35,15 +35,6 @@ #include "cogl/cogl.h" #include "meta/boxes.h" -typedef struct _MetaSpaType -{ - struct spa_type_media_type media_type; - struct spa_type_media_subtype media_subtype; - struct spa_type_format_video format_video; - struct spa_type_video_format video_format; - uint32_t meta_cursor; -} MetaSpaType; - typedef struct _MetaScreenCastStream MetaScreenCastStream; #define META_TYPE_SCREEN_CAST_STREAM_SRC (meta_screen_cast_stream_src_get_type ()) @@ -74,8 +65,6 @@ void meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *sr MetaScreenCastStream * meta_screen_cast_stream_src_get_stream (MetaScreenCastStreamSrc *src); -MetaSpaType * meta_screen_cast_stream_src_get_spa_type (MetaScreenCastStreamSrc *src); - void meta_screen_cast_stream_src_unset_cursor_metadata (MetaScreenCastStreamSrc *src, struct spa_meta_cursor *spa_meta_cursor); -- GitLab From c22edeff1f5ad6307086d2c9fe6ab0d72aa8d17b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Mon, 21 Jan 2019 19:16:19 +0100 Subject: [PATCH 04/15] screen-cast-window-stream: Use initable to initialize Move the initialization from _new() to an initable implementation. This will allow us to initialize fields before MetaScreenCastStream initializes. https://gitlab.gnome.org/GNOME/mutter/merge_requests/413 --- src/backends/meta-screen-cast-window-stream.c | 115 ++++++++++-------- 1 file changed, 63 insertions(+), 52 deletions(-) diff --git a/src/backends/meta-screen-cast-window-stream.c b/src/backends/meta-screen-cast-window-stream.c index 4c922711645..748affb38a1 100644 --- a/src/backends/meta-screen-cast-window-stream.c +++ b/src/backends/meta-screen-cast-window-stream.c @@ -48,9 +48,16 @@ struct _MetaScreenCastWindowStream unsigned long window_unmanaged_handler_id; }; -G_DEFINE_TYPE (MetaScreenCastWindowStream, - meta_screen_cast_window_stream, - META_TYPE_SCREEN_CAST_STREAM) +static GInitableIface *initable_parent_iface; + +static void +meta_screen_cast_window_stream_init_initable_iface (GInitableIface *iface); + +G_DEFINE_TYPE_WITH_CODE (MetaScreenCastWindowStream, + meta_screen_cast_window_stream, + META_TYPE_SCREEN_CAST_STREAM, + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, + meta_screen_cast_window_stream_init_initable_iface)) MetaWindow * meta_screen_cast_window_stream_get_window (MetaScreenCastWindowStream *window_stream) @@ -76,38 +83,13 @@ meta_screen_cast_window_stream_new (MetaScreenCastSession *session, MetaWindow *window, GError **error) { - MetaScreenCastWindowStream *window_stream; - MetaLogicalMonitor *logical_monitor; - int scale; - - logical_monitor = meta_window_get_main_logical_monitor (window); - if (!logical_monitor) - { - g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, - "Main logical monitor not found"); - return NULL; - } - - window_stream = g_initable_new (META_TYPE_SCREEN_CAST_WINDOW_STREAM, - NULL, - error, - "session", session, - "connection", connection, - "window", window, - NULL); - if (!window_stream) - return NULL; - - window_stream->window = window; - /* We cannot set the stream size to the exact size of the window, because - * windows can be resized, whereas streams cannot. - * So we set a size equals to the size of the logical monitor for the window. - */ - scale = (int) ceil (meta_logical_monitor_get_scale (logical_monitor)); - window_stream->stream_width = logical_monitor->rect.width * scale; - window_stream->stream_height = logical_monitor->rect.height * scale; - - return window_stream; + return g_initable_new (META_TYPE_SCREEN_CAST_WINDOW_STREAM, + NULL, + error, + "session", session, + "connection", connection, + "window", window, + NULL); } static MetaScreenCastStreamSrc * @@ -175,20 +157,6 @@ on_window_unmanaged (MetaScreenCastWindowStream *window_stream) meta_screen_cast_stream_close (META_SCREEN_CAST_STREAM (window_stream)); } -static void -meta_screen_cast_window_stream_constructed (GObject *object) -{ - MetaScreenCastWindowStream *window_stream = - META_SCREEN_CAST_WINDOW_STREAM (object); - - window_stream->window_unmanaged_handler_id = - g_signal_connect_swapped (window_stream->window, "unmanaged", - G_CALLBACK (on_window_unmanaged), - window_stream); - - G_OBJECT_CLASS (meta_screen_cast_window_stream_parent_class)->constructed (object); -} - static void meta_screen_cast_window_stream_set_property (GObject *object, guint prop_id, @@ -233,12 +201,56 @@ meta_screen_cast_window_stream_finalize (GObject *object) MetaScreenCastWindowStream *window_stream = META_SCREEN_CAST_WINDOW_STREAM (object); - g_signal_handler_disconnect (window_stream->window, - window_stream->window_unmanaged_handler_id); + if (window_stream->window_unmanaged_handler_id) + g_signal_handler_disconnect (window_stream->window, + window_stream->window_unmanaged_handler_id); G_OBJECT_CLASS (meta_screen_cast_window_stream_parent_class)->finalize (object); } +static gboolean +meta_screen_cast_window_stream_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + MetaScreenCastWindowStream *window_stream = + META_SCREEN_CAST_WINDOW_STREAM (initable); + MetaWindow *window = window_stream->window; + MetaLogicalMonitor *logical_monitor; + int scale; + + logical_monitor = meta_window_get_main_logical_monitor (window); + if (!logical_monitor) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Main logical monitor not found"); + return FALSE; + } + + window_stream->window_unmanaged_handler_id = + g_signal_connect_swapped (window, "unmanaged", + G_CALLBACK (on_window_unmanaged), + window_stream); + + /* We cannot set the stream size to the exact size of the window, because + * windows can be resized, whereas streams cannot. + * So we set a size equals to the size of the logical monitor for the window. + */ + scale = (int) ceil (meta_logical_monitor_get_scale (logical_monitor)); + window_stream->stream_width = logical_monitor->rect.width * scale; + window_stream->stream_height = logical_monitor->rect.height * scale; + + return initable_parent_iface->init (initable, cancellable, error); +} + +static void +meta_screen_cast_window_stream_init_initable_iface (GInitableIface *iface) +{ + initable_parent_iface = g_type_interface_peek_parent (iface); + + iface->init = meta_screen_cast_window_stream_initable_init; +} + static void meta_screen_cast_window_stream_init (MetaScreenCastWindowStream *window_stream) { @@ -251,7 +263,6 @@ meta_screen_cast_window_stream_class_init (MetaScreenCastWindowStreamClass *klas MetaScreenCastStreamClass *stream_class = META_SCREEN_CAST_STREAM_CLASS (klass); - object_class->constructed = meta_screen_cast_window_stream_constructed; object_class->set_property = meta_screen_cast_window_stream_set_property; object_class->get_property = meta_screen_cast_window_stream_get_property; object_class->finalize = meta_screen_cast_window_stream_finalize; -- GitLab From 870f38542dcb6cfcf95eb5a6d7a00c98a7442eb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Mon, 21 Jan 2019 19:17:57 +0100 Subject: [PATCH 05/15] screen-cast-window-stream: Set the size property to the logical size As the stream size is the logical monitor size multiplied with the ceil of the logical monitor scale, the corresponding logical size, which is what should be passed via the size property on the D-Bus object, should be the logical monitor size. https://gitlab.gnome.org/GNOME/mutter/merge_requests/413 --- src/backends/meta-screen-cast-window-stream.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/backends/meta-screen-cast-window-stream.c b/src/backends/meta-screen-cast-window-stream.c index 748affb38a1..0cb39bb1450 100644 --- a/src/backends/meta-screen-cast-window-stream.c +++ b/src/backends/meta-screen-cast-window-stream.c @@ -44,6 +44,8 @@ struct _MetaScreenCastWindowStream int stream_width; int stream_height; + int logical_width; + int logical_height; unsigned long window_unmanaged_handler_id; }; @@ -128,8 +130,8 @@ meta_screen_cast_window_stream_set_parameters (MetaScreenCastStream *stream, g_variant_builder_add (parameters_builder, "{sv}", "size", g_variant_new ("(ii)", - bounds.width, - bounds.height)); + window_stream->logical_width, + window_stream->logical_height)); } static void @@ -237,6 +239,8 @@ meta_screen_cast_window_stream_initable_init (GInitable *initable, * So we set a size equals to the size of the logical monitor for the window. */ scale = (int) ceil (meta_logical_monitor_get_scale (logical_monitor)); + window_stream->logical_width = logical_monitor->rect.width; + window_stream->logical_height = logical_monitor->rect.height; window_stream->stream_width = logical_monitor->rect.width * scale; window_stream->stream_height = logical_monitor->rect.height * scale; -- GitLab From 11bd847896445028beb077bc601897386699a400 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Mon, 21 Jan 2019 19:20:04 +0100 Subject: [PATCH 06/15] screen-cast-window-stream: Don't set the position property It was not meant to be set for window streams, and was set to (0, 0) anyway. This removes the corresponding MetaScreenCastWindow API, as it's not needed anymore. https://gitlab.gnome.org/GNOME/mutter/merge_requests/413 --- src/backends/meta-screen-cast-window-stream.c | 10 ---------- src/backends/meta-screen-cast-window.c | 8 -------- src/backends/meta-screen-cast-window.h | 6 ------ src/compositor/meta-window-actor.c | 15 --------------- 4 files changed, 39 deletions(-) diff --git a/src/backends/meta-screen-cast-window-stream.c b/src/backends/meta-screen-cast-window-stream.c index 0cb39bb1450..19645540c3d 100644 --- a/src/backends/meta-screen-cast-window-stream.c +++ b/src/backends/meta-screen-cast-window-stream.c @@ -116,16 +116,6 @@ meta_screen_cast_window_stream_set_parameters (MetaScreenCastStream *stream, { MetaScreenCastWindowStream *window_stream = META_SCREEN_CAST_WINDOW_STREAM (stream); - MetaScreenCastWindow *screen_cast_window = - META_SCREEN_CAST_WINDOW (meta_window_actor_from_window (window_stream->window)); - MetaRectangle bounds; - - meta_screen_cast_window_get_buffer_bounds (screen_cast_window, &bounds); - - g_variant_builder_add (parameters_builder, "{sv}", - "position", - g_variant_new ("(ii)", - bounds.x, bounds.y)); g_variant_builder_add (parameters_builder, "{sv}", "size", diff --git a/src/backends/meta-screen-cast-window.c b/src/backends/meta-screen-cast-window.c index 21629a0cd55..9878b223f56 100644 --- a/src/backends/meta-screen-cast-window.c +++ b/src/backends/meta-screen-cast-window.c @@ -29,14 +29,6 @@ meta_screen_cast_window_default_init (MetaScreenCastWindowInterface *iface) { } -void -meta_screen_cast_window_get_buffer_bounds (MetaScreenCastWindow *screen_cast_window, - MetaRectangle *bounds) -{ - META_SCREEN_CAST_WINDOW_GET_IFACE (screen_cast_window)->get_buffer_bounds (screen_cast_window, - bounds); -} - void meta_screen_cast_window_get_frame_bounds (MetaScreenCastWindow *screen_cast_window, MetaRectangle *bounds) diff --git a/src/backends/meta-screen-cast-window.h b/src/backends/meta-screen-cast-window.h index e023d3e174c..ba70f9b85b0 100644 --- a/src/backends/meta-screen-cast-window.h +++ b/src/backends/meta-screen-cast-window.h @@ -36,9 +36,6 @@ struct _MetaScreenCastWindowInterface { GTypeInterface parent_iface; - void (*get_buffer_bounds) (MetaScreenCastWindow *screen_cast_window, - MetaRectangle *bounds); - void (*get_frame_bounds) (MetaScreenCastWindow *screen_cast_window, MetaRectangle *bounds); @@ -53,9 +50,6 @@ struct _MetaScreenCastWindowInterface uint8_t *data); }; -void meta_screen_cast_window_get_buffer_bounds (MetaScreenCastWindow *screen_cast_window, - MetaRectangle *bounds); - void meta_screen_cast_window_get_frame_bounds (MetaScreenCastWindow *screen_cast_window, MetaRectangle *bounds); diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index 20a22062fa9..0af96becaa4 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -1850,20 +1850,6 @@ meta_window_actor_from_window (MetaWindow *window) return META_WINDOW_ACTOR (meta_window_get_compositor_private (window)); } -static void -meta_window_actor_get_buffer_bounds (MetaScreenCastWindow *screen_cast_window, - MetaRectangle *bounds) -{ - MetaWindowActor *window_actor = META_WINDOW_ACTOR (screen_cast_window); - ClutterActor *clutter_actor; - - clutter_actor = CLUTTER_ACTOR (meta_window_actor_get_texture (window_actor)); - bounds->x = 0; - bounds->y = 0; - bounds->width = (int) clutter_actor_get_width (clutter_actor); - bounds->height = (int) clutter_actor_get_height (clutter_actor); -} - static void meta_window_actor_get_frame_bounds (MetaScreenCastWindow *screen_cast_window, MetaRectangle *bounds) @@ -1978,7 +1964,6 @@ meta_window_actor_capture_into (MetaScreenCastWindow *screen_cast_window, static void screen_cast_window_iface_init (MetaScreenCastWindowInterface *iface) { - iface->get_buffer_bounds = meta_window_actor_get_buffer_bounds; iface->get_frame_bounds = meta_window_actor_get_frame_bounds; iface->transform_relative_position = meta_window_actor_transform_relative_position; iface->capture_into = meta_window_actor_capture_into; -- GitLab From 14c6a347c13fac6860a6bab946e6ba2debf6af00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 23 Jan 2019 18:20:42 +0100 Subject: [PATCH 07/15] screen-cast-window-src: Rename painted callback to after_paint We'll add a before_paint soon, so better have the names somewhat match. https://gitlab.gnome.org/GNOME/mutter/merge_requests/413 --- .../meta-screen-cast-window-stream-src.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/backends/meta-screen-cast-window-stream-src.c b/src/backends/meta-screen-cast-window-stream-src.c index 32df9f1275c..3bb18c10b2f 100644 --- a/src/backends/meta-screen-cast-window-stream-src.c +++ b/src/backends/meta-screen-cast-window-stream-src.c @@ -33,7 +33,7 @@ struct _MetaScreenCastWindowStreamSrc MetaWindowActor *window_actor; - unsigned long actor_painted_handler_id; + unsigned long actor_after_paint_handler_id; unsigned long actor_destroyed_handler_id; }; @@ -144,10 +144,10 @@ meta_screen_cast_window_stream_src_stop (MetaScreenCastWindowStreamSrc *window_s if (!window_src->window_actor) return; - if (window_src->actor_painted_handler_id) + if (window_src->actor_after_paint_handler_id) g_signal_handler_disconnect (window_src->window_actor, - window_src->actor_painted_handler_id); - window_src->actor_painted_handler_id = 0; + window_src->actor_after_paint_handler_id); + window_src->actor_after_paint_handler_id = 0; if (window_src->actor_destroyed_handler_id) g_signal_handler_disconnect (window_src->window_actor, @@ -156,8 +156,8 @@ meta_screen_cast_window_stream_src_stop (MetaScreenCastWindowStreamSrc *window_s } static void -window_actor_painted (MetaWindowActor *actor, - MetaScreenCastWindowStreamSrc *window_src) +window_actor_after_paint (MetaWindowActor *actor, + MetaScreenCastWindowStreamSrc *window_src) { MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src); @@ -185,10 +185,10 @@ meta_screen_cast_window_stream_src_enable (MetaScreenCastStreamSrc *src) window_src->window_actor = window_actor; - window_src->actor_painted_handler_id = + window_src->actor_after_paint_handler_id = g_signal_connect_after (window_src->window_actor, "paint", - G_CALLBACK (window_actor_painted), + G_CALLBACK (window_actor_after_paint), window_src); window_src->actor_destroyed_handler_id = -- GitLab From c80ba819e77799ecead543a579f8b4ddde6ef111 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 23 Jan 2019 18:29:14 +0100 Subject: [PATCH 08/15] screen-cast-window-src: Keep a screen cast window instead of an actor Practically it's the same object, but ideally, we should not deal with "actors" anywhere here. https://gitlab.gnome.org/GNOME/mutter/merge_requests/413 --- .../meta-screen-cast-window-stream-src.c | 59 +++++++++---------- 1 file changed, 29 insertions(+), 30 deletions(-) diff --git a/src/backends/meta-screen-cast-window-stream-src.c b/src/backends/meta-screen-cast-window-stream-src.c index 3bb18c10b2f..0448b443fa4 100644 --- a/src/backends/meta-screen-cast-window-stream-src.c +++ b/src/backends/meta-screen-cast-window-stream-src.c @@ -31,10 +31,10 @@ struct _MetaScreenCastWindowStreamSrc { MetaScreenCastStreamSrc parent; - MetaWindowActor *window_actor; + MetaScreenCastWindow *screen_cast_window; - unsigned long actor_after_paint_handler_id; - unsigned long actor_destroyed_handler_id; + unsigned long screen_cast_window_after_paint_handler_id; + unsigned long screen_cast_window_destroyed_handler_id; }; G_DEFINE_TYPE (MetaScreenCastWindowStreamSrc, @@ -88,15 +88,14 @@ capture_into (MetaScreenCastWindowStreamSrc *window_src, uint8_t *data) { MetaRectangle stream_rect; - MetaScreenCastWindow *screen_cast_window; stream_rect.x = 0; stream_rect.y = 0; stream_rect.width = get_stream_width (window_src); stream_rect.height = get_stream_height (window_src); - screen_cast_window = META_SCREEN_CAST_WINDOW (window_src->window_actor); - meta_screen_cast_window_capture_into (screen_cast_window, &stream_rect, data); + meta_screen_cast_window_capture_into (window_src->screen_cast_window, + &stream_rect, data); return TRUE; } @@ -121,11 +120,10 @@ meta_screen_cast_window_stream_src_get_videocrop (MetaScreenCastStreamSrc *src, { MetaScreenCastWindowStreamSrc *window_src = META_SCREEN_CAST_WINDOW_STREAM_SRC (src); - MetaScreenCastWindow *screen_cast_window; MetaRectangle stream_rect; - screen_cast_window = META_SCREEN_CAST_WINDOW (window_src->window_actor); - meta_screen_cast_window_get_frame_bounds (screen_cast_window, crop_rect); + meta_screen_cast_window_get_frame_bounds (window_src->screen_cast_window, + crop_rect); stream_rect.x = 0; stream_rect.y = 0; @@ -141,23 +139,24 @@ static void meta_screen_cast_window_stream_src_stop (MetaScreenCastWindowStreamSrc *window_src) { - if (!window_src->window_actor) + if (!window_src->screen_cast_window) return; - if (window_src->actor_after_paint_handler_id) - g_signal_handler_disconnect (window_src->window_actor, - window_src->actor_after_paint_handler_id); - window_src->actor_after_paint_handler_id = 0; - if (window_src->actor_destroyed_handler_id) - g_signal_handler_disconnect (window_src->window_actor, - window_src->actor_destroyed_handler_id); - window_src->actor_destroyed_handler_id = 0; + if (window_src->screen_cast_window_after_paint_handler_id) + g_signal_handler_disconnect (window_src->screen_cast_window, + window_src->screen_cast_window_after_paint_handler_id); + window_src->screen_cast_window_after_paint_handler_id = 0; + + if (window_src->screen_cast_window_destroyed_handler_id) + g_signal_handler_disconnect (window_src->screen_cast_window, + window_src->screen_cast_window_destroyed_handler_id); + window_src->screen_cast_window_destroyed_handler_id = 0; } static void -window_actor_after_paint (MetaWindowActor *actor, - MetaScreenCastWindowStreamSrc *window_src) +screen_cast_window_after_paint (MetaScreenCastWindow *screen_cast_window, + MetaScreenCastWindowStreamSrc *window_src) { MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src); @@ -165,11 +164,11 @@ window_actor_after_paint (MetaWindowActor *actor, } static void -window_actor_destroyed (MetaWindowActor *actor, - MetaScreenCastWindowStreamSrc *window_src) +screen_cast_window_destroyed (MetaScreenCastWindow *screen_cast_window, + MetaScreenCastWindowStreamSrc *window_src) { meta_screen_cast_window_stream_src_stop (window_src); - window_src->window_actor = NULL; + window_src->screen_cast_window = NULL; } static void @@ -183,18 +182,18 @@ meta_screen_cast_window_stream_src_enable (MetaScreenCastStreamSrc *src) if (!window_actor) return; - window_src->window_actor = window_actor; + window_src->screen_cast_window = META_SCREEN_CAST_WINDOW (window_actor); - window_src->actor_after_paint_handler_id = - g_signal_connect_after (window_src->window_actor, + window_src->screen_cast_window_after_paint_handler_id = + g_signal_connect_after (window_src->screen_cast_window, "paint", - G_CALLBACK (window_actor_after_paint), + G_CALLBACK (screen_cast_window_after_paint), window_src); - window_src->actor_destroyed_handler_id = - g_signal_connect (window_src->window_actor, + window_src->screen_cast_window_destroyed_handler_id = + g_signal_connect (window_src->screen_cast_window, "destroy", - G_CALLBACK (window_actor_destroyed), + G_CALLBACK (screen_cast_window_destroyed), window_src); } -- GitLab From 6372e3e4dbe546d6b4c9c6d3e3cbbd74797faedc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 23 Jan 2019 18:40:07 +0100 Subject: [PATCH 09/15] clutter: Add clutter_actor_has_damage() API Will be used to check whether there are any damage to an actor. https://gitlab.gnome.org/GNOME/mutter/merge_requests/413 --- clutter/clutter/clutter-actor.c | 7 +++++++ clutter/clutter/clutter-mutter.h | 3 +++ 2 files changed, 10 insertions(+) diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c index 100b804597b..c11bb4cb665 100644 --- a/clutter/clutter/clutter-actor.c +++ b/clutter/clutter/clutter-actor.c @@ -635,6 +635,7 @@ #include "clutter-interval.h" #include "clutter-main.h" #include "clutter-marshal.h" +#include "clutter-mutter.h" #include "clutter-paint-nodes.h" #include "clutter-paint-node-private.h" #include "clutter-paint-volume-private.h" @@ -16467,6 +16468,12 @@ clutter_actor_is_in_clone_paint (ClutterActor *self) return FALSE; } +gboolean +clutter_actor_has_damage (ClutterActor *actor) +{ + return actor->priv->is_dirty; +} + static gboolean set_direction_recursive (ClutterActor *actor, gpointer user_data) diff --git a/clutter/clutter/clutter-mutter.h b/clutter/clutter/clutter-mutter.h index d5d0340ff74..788757140a6 100644 --- a/clutter/clutter/clutter-mutter.h +++ b/clutter/clutter/clutter-mutter.h @@ -49,6 +49,9 @@ void clutter_stage_freeze_updates (ClutterStage *stage); CLUTTER_EXPORT void clutter_stage_thaw_updates (ClutterStage *stage); +CLUTTER_EXPORT +gboolean clutter_actor_has_damage (ClutterActor *actor); + #undef __CLUTTER_H_INSIDE__ #endif /* __CLUTTER_MUTTER_H__ */ -- GitLab From a76107a19fea1162c31665d26d7427b298527ed8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 23 Jan 2019 19:09:17 +0100 Subject: [PATCH 10/15] screen-cast-window: Add API to transform cursor state To be used to translate absolute cursor positions to relative positions, as well as to determine whether a cursor sprite is inside the stream or not. It also helps calculating the scale the cursor sprite needs to be scaled with to be in stream coordinate space. https://gitlab.gnome.org/GNOME/mutter/merge_requests/413 --- src/backends/meta-screen-cast-window.c | 16 +++++++++ src/backends/meta-screen-cast-window.h | 13 +++++++ src/compositor/meta-window-actor.c | 47 ++++++++++++++++++++++++++ 3 files changed, 76 insertions(+) diff --git a/src/backends/meta-screen-cast-window.c b/src/backends/meta-screen-cast-window.c index 9878b223f56..5df8a34165c 100644 --- a/src/backends/meta-screen-cast-window.c +++ b/src/backends/meta-screen-cast-window.c @@ -51,6 +51,22 @@ meta_screen_cast_window_transform_relative_position (MetaScreenCastWindow *scree y_out); } +gboolean +meta_screen_cast_window_transform_cursor_position (MetaScreenCastWindow *screen_cast_window, + MetaCursorSprite *cursor_sprite, + ClutterPoint *cursor_position, + float *out_cursor_scale, + ClutterPoint *out_relative_cursor_position) +{ + MetaScreenCastWindowInterface *iface = + META_SCREEN_CAST_WINDOW_GET_IFACE (screen_cast_window); + + return iface->transform_cursor_position (screen_cast_window, + cursor_sprite, + cursor_position, + out_cursor_scale, + out_relative_cursor_position); +} void meta_screen_cast_window_capture_into (MetaScreenCastWindow *screen_cast_window, diff --git a/src/backends/meta-screen-cast-window.h b/src/backends/meta-screen-cast-window.h index ba70f9b85b0..447fade7bd5 100644 --- a/src/backends/meta-screen-cast-window.h +++ b/src/backends/meta-screen-cast-window.h @@ -24,6 +24,7 @@ #include #include +#include "backends/meta-cursor.h" #include "meta/boxes.h" G_BEGIN_DECLS @@ -45,6 +46,12 @@ struct _MetaScreenCastWindowInterface double *x_out, double *y_out); + gboolean (*transform_cursor_position) (MetaScreenCastWindow *screen_cast_window, + MetaCursorSprite *cursor_sprite, + ClutterPoint *cursor_position, + float *out_cursor_scale, + ClutterPoint *out_relative_cursor_position); + void (*capture_into) (MetaScreenCastWindow *screen_cast_window, MetaRectangle *bounds, uint8_t *data); @@ -59,6 +66,12 @@ void meta_screen_cast_window_transform_relative_position (MetaScreenCastWindow * double *x_out, double *y_out); +gboolean meta_screen_cast_window_transform_cursor_position (MetaScreenCastWindow *screen_cast_window, + MetaCursorSprite *cursor_sprite, + ClutterPoint *cursor_position, + float *out_cursor_scale, + ClutterPoint *out_relative_cursor_position); + void meta_screen_cast_window_capture_into (MetaScreenCastWindow *screen_cast_window, MetaRectangle *bounds, uint8_t *data); diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index 0af96becaa4..616739223f3 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -1907,6 +1907,52 @@ meta_window_actor_transform_relative_position (MetaScreenCastWindow *screen_cast *y_out = (double) v2.y; } +static gboolean +meta_window_actor_transform_cursor_position (MetaScreenCastWindow *screen_cast_window, + MetaCursorSprite *cursor_sprite, + ClutterPoint *cursor_position, + float *out_cursor_scale, + ClutterPoint *out_relative_cursor_position) +{ + MetaWindowActor *window_actor = META_WINDOW_ACTOR (screen_cast_window); + MetaWindowActorPrivate *priv = + meta_window_actor_get_instance_private (window_actor); + MetaWindow *window; + + window = priv->window; + if (!meta_window_has_pointer (window)) + return FALSE; + + if (cursor_sprite && + meta_cursor_sprite_get_cogl_texture (cursor_sprite) && + out_cursor_scale) + { + MetaShapedTexture *stex; + double actor_scale; + float cursor_texture_scale; + + stex = meta_surface_actor_get_texture (priv->surface); + clutter_actor_get_scale (CLUTTER_ACTOR (stex), &actor_scale, NULL); + cursor_texture_scale = meta_cursor_sprite_get_texture_scale (cursor_sprite); + + *out_cursor_scale = actor_scale / cursor_texture_scale; + } + + if (out_relative_cursor_position) + { + MetaShapedTexture *stex; + + stex = meta_surface_actor_get_texture (priv->surface); + clutter_actor_transform_stage_point (CLUTTER_ACTOR (stex), + cursor_position->x, + cursor_position->y, + &out_relative_cursor_position->x, + &out_relative_cursor_position->y); + } + + return TRUE; +} + static void meta_window_actor_capture_into (MetaScreenCastWindow *screen_cast_window, MetaRectangle *bounds, @@ -1966,5 +2012,6 @@ screen_cast_window_iface_init (MetaScreenCastWindowInterface *iface) { iface->get_frame_bounds = meta_window_actor_get_frame_bounds; iface->transform_relative_position = meta_window_actor_transform_relative_position; + iface->transform_cursor_position = meta_window_actor_transform_cursor_position; iface->capture_into = meta_window_actor_capture_into; } -- GitLab From 2f01418d455b5c1880f9cb3dc25d6e5bd5270b05 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 23 Jan 2019 19:10:58 +0100 Subject: [PATCH 11/15] screen-cast-window: Add API to check if content has damage https://gitlab.gnome.org/GNOME/mutter/merge_requests/413 --- src/backends/meta-screen-cast-window.c | 9 +++++++++ src/backends/meta-screen-cast-window.h | 4 ++++ src/compositor/meta-window-actor.c | 7 +++++++ 3 files changed, 20 insertions(+) diff --git a/src/backends/meta-screen-cast-window.c b/src/backends/meta-screen-cast-window.c index 5df8a34165c..ce2bf82c966 100644 --- a/src/backends/meta-screen-cast-window.c +++ b/src/backends/meta-screen-cast-window.c @@ -77,3 +77,12 @@ meta_screen_cast_window_capture_into (MetaScreenCastWindow *screen_cast_window, bounds, data); } + +gboolean +meta_screen_cast_window_has_damage (MetaScreenCastWindow *screen_cast_window) +{ + MetaScreenCastWindowInterface *iface = + META_SCREEN_CAST_WINDOW_GET_IFACE (screen_cast_window); + + return iface->has_damage (screen_cast_window); +} diff --git a/src/backends/meta-screen-cast-window.h b/src/backends/meta-screen-cast-window.h index 447fade7bd5..badd8822484 100644 --- a/src/backends/meta-screen-cast-window.h +++ b/src/backends/meta-screen-cast-window.h @@ -55,6 +55,8 @@ struct _MetaScreenCastWindowInterface void (*capture_into) (MetaScreenCastWindow *screen_cast_window, MetaRectangle *bounds, uint8_t *data); + + gboolean (*has_damage) (MetaScreenCastWindow *screen_cast_window); }; void meta_screen_cast_window_get_frame_bounds (MetaScreenCastWindow *screen_cast_window, @@ -76,6 +78,8 @@ void meta_screen_cast_window_capture_into (MetaScreenCastWindow *screen_cast_win MetaRectangle *bounds, uint8_t *data); +gboolean meta_screen_cast_window_has_damage (MetaScreenCastWindow *screen_cast_window); + G_END_DECLS #endif /* META_SCREEN_CAST_WINDOW_H */ diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c index 616739223f3..adcba898c50 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c @@ -2007,6 +2007,12 @@ meta_window_actor_capture_into (MetaScreenCastWindow *screen_cast_window, cairo_surface_destroy (image); } +static gboolean +meta_window_actor_has_damage (MetaScreenCastWindow *screen_cast_window) +{ + return clutter_actor_has_damage (CLUTTER_ACTOR (screen_cast_window)); +} + static void screen_cast_window_iface_init (MetaScreenCastWindowInterface *iface) { @@ -2014,4 +2020,5 @@ screen_cast_window_iface_init (MetaScreenCastWindowInterface *iface) iface->transform_relative_position = meta_window_actor_transform_relative_position; iface->transform_cursor_position = meta_window_actor_transform_cursor_position; iface->capture_into = meta_window_actor_capture_into; + iface->has_damage = meta_window_actor_has_damage; } -- GitLab From 8c2b805d88f297d825d6be52438fe6793dc22430 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 24 Jan 2019 18:40:06 +0100 Subject: [PATCH 12/15] screen-cast-src: Add helper to draw cursor sprite into pixel buffer It makes sure the cursor sprite is correctly scaled and positioned in stream coordinate space. https://gitlab.gnome.org/GNOME/mutter/merge_requests/413 --- src/backends/meta-screen-cast-stream-src.c | 69 ++++++++++++++-------- src/backends/meta-screen-cast-stream-src.h | 6 ++ 2 files changed, 52 insertions(+), 23 deletions(-) diff --git a/src/backends/meta-screen-cast-stream-src.c b/src/backends/meta-screen-cast-stream-src.c index 3fc6084afbc..82c5cba4362 100644 --- a/src/backends/meta-screen-cast-stream-src.c +++ b/src/backends/meta-screen-cast-stream-src.c @@ -222,6 +222,43 @@ draw_cursor_sprite_via_offscreen (MetaScreenCastStreamSrc *src, return TRUE; } +gboolean +meta_screen_cast_stream_src_draw_cursor_into (MetaScreenCastStreamSrc *src, + CoglTexture *cursor_texture, + float scale, + uint8_t *data, + GError **error) +{ + int texture_width, texture_height; + int width, height; + + texture_width = cogl_texture_get_width (cursor_texture); + texture_height = cogl_texture_get_height (cursor_texture); + width = texture_width * scale; + height = texture_height * scale; + + if (texture_width == width && + texture_height == height) + { + cogl_texture_get_data (cursor_texture, + COGL_PIXEL_FORMAT_RGBA_8888_PRE, + texture_width * 4, + data); + } + else + { + if (!draw_cursor_sprite_via_offscreen (src, + cursor_texture, + width, + height, + data, + error)) + return FALSE; + } + + return TRUE; +} + void meta_screen_cast_stream_src_unset_cursor_metadata (MetaScreenCastStreamSrc *src, struct spa_meta_cursor *spa_meta_cursor) @@ -289,6 +326,7 @@ meta_screen_cast_stream_src_set_cursor_sprite_metadata (MetaScreenCastStreamSrc int texture_width, texture_height; int bitmap_width, bitmap_height; uint8_t *bitmap_data; + GError *error = NULL; cursor_texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); if (!cursor_texture) @@ -328,30 +366,15 @@ meta_screen_cast_stream_src_set_cursor_sprite_metadata (MetaScreenCastStreamSrc spa_meta_bitmap->offset, uint8_t); - if (texture_width == bitmap_width && - texture_height == bitmap_height) - { - cogl_texture_get_data (cursor_texture, - COGL_PIXEL_FORMAT_RGBA_8888_PRE, - texture_width * 4, - bitmap_data); - } - else + if (!meta_screen_cast_stream_src_draw_cursor_into (src, + cursor_texture, + scale, + bitmap_data, + &error)) { - GError *error = NULL; - - if (!draw_cursor_sprite_via_offscreen (src, - cursor_texture, - bitmap_width, - bitmap_height, - bitmap_data, - &error)) - { - g_warning ("Failed to draw cursor via offscreen: %s", - error->message); - g_error_free (error); - spa_meta_cursor->id = 0; - } + g_warning ("Failed to draw cursor: %s", error->message); + g_error_free (error); + spa_meta_cursor->id = 0; } } diff --git a/src/backends/meta-screen-cast-stream-src.h b/src/backends/meta-screen-cast-stream-src.h index 3f8c6fa27d0..fc0e5bc7714 100644 --- a/src/backends/meta-screen-cast-stream-src.h +++ b/src/backends/meta-screen-cast-stream-src.h @@ -65,6 +65,12 @@ void meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *sr MetaScreenCastStream * meta_screen_cast_stream_src_get_stream (MetaScreenCastStreamSrc *src); +gboolean meta_screen_cast_stream_src_draw_cursor_into (MetaScreenCastStreamSrc *src, + CoglTexture *cursor_texture, + float scale, + uint8_t *data, + GError **error); + void meta_screen_cast_stream_src_unset_cursor_metadata (MetaScreenCastStreamSrc *src, struct spa_meta_cursor *spa_meta_cursor); -- GitLab From 1760a6e56077eb3bd1c2e5902f73d93581770163 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 24 Jan 2019 19:22:24 +0100 Subject: [PATCH 13/15] screen-cast: Bump API version to 2 https://gitlab.gnome.org/GNOME/mutter/merge_requests/413 --- src/backends/meta-screen-cast.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/backends/meta-screen-cast.c b/src/backends/meta-screen-cast.c index ebf6c18b395..063fffd8ec2 100644 --- a/src/backends/meta-screen-cast.c +++ b/src/backends/meta-screen-cast.c @@ -32,7 +32,7 @@ #define META_SCREEN_CAST_DBUS_SERVICE "org.gnome.Mutter.ScreenCast" #define META_SCREEN_CAST_DBUS_PATH "/org/gnome/Mutter/ScreenCast" -#define META_SCREEN_CAST_API_VERSION 1 +#define META_SCREEN_CAST_API_VERSION 2 struct _MetaScreenCast { -- GitLab From 9a20271f900cfde225f5a2a98f9e93604ab89208 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Thu, 24 Jan 2019 18:43:27 +0100 Subject: [PATCH 14/15] screen-cast-window-stream: Add support for cursor modes Make the RecordWindow method also understand the 'cursor-mode' property. For 'embedded' the cursor is drawn onto the pixel buffer using cairo, otherwise it works similarly to how RecordMonitor deals with it. https://gitlab.gnome.org/GNOME/mutter/merge_requests/413 --- src/backends/meta-screen-cast-session.c | 17 ++ .../meta-screen-cast-window-stream-src.c | 286 +++++++++++++++++- src/backends/meta-screen-cast-window-stream.c | 10 +- src/backends/meta-screen-cast-window-stream.h | 9 +- src/org.gnome.Mutter.ScreenCast.xml | 1 + 5 files changed, 311 insertions(+), 12 deletions(-) diff --git a/src/backends/meta-screen-cast-session.c b/src/backends/meta-screen-cast-session.c index 130bd17c972..a9b861e8df9 100644 --- a/src/backends/meta-screen-cast-session.c +++ b/src/backends/meta-screen-cast-session.c @@ -383,6 +383,7 @@ handle_record_window (MetaDBusScreenCastSession *skeleton, GDBusInterfaceSkeleton *interface_skeleton; GDBusConnection *connection; MetaWindow *window; + MetaScreenCastCursorMode cursor_mode; GError *error = NULL; MetaDisplay *display; GVariant *window_id_variant = NULL; @@ -424,12 +425,28 @@ handle_record_window (MetaDBusScreenCastSession *skeleton, return TRUE; } + if (!g_variant_lookup (properties_variant, "cursor-mode", "u", &cursor_mode)) + { + cursor_mode = META_SCREEN_CAST_CURSOR_MODE_HIDDEN; + } + else + { + if (!is_valid_cursor_mode (cursor_mode)) + { + g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR, + G_DBUS_ERROR_FAILED, + "Unknown cursor mode"); + return TRUE; + } + } + interface_skeleton = G_DBUS_INTERFACE_SKELETON (skeleton); connection = g_dbus_interface_skeleton_get_connection (interface_skeleton); window_stream = meta_screen_cast_window_stream_new (session, connection, window, + cursor_mode, &error); if (!window_stream) { diff --git a/src/backends/meta-screen-cast-window-stream-src.c b/src/backends/meta-screen-cast-window-stream-src.c index 0448b443fa4..dbf330420e8 100644 --- a/src/backends/meta-screen-cast-window-stream-src.c +++ b/src/backends/meta-screen-cast-window-stream-src.c @@ -23,6 +23,7 @@ #include "backends/meta-screen-cast-window-stream-src.h" #include "backends/meta-backend-private.h" +#include "backends/meta-screen-cast-session.h" #include "backends/meta-screen-cast-window.h" #include "backends/meta-screen-cast-window-stream.h" #include "compositor/meta-window-actor-private.h" @@ -33,14 +34,32 @@ struct _MetaScreenCastWindowStreamSrc MetaScreenCastWindow *screen_cast_window; + unsigned long screen_cast_window_before_paint_handler_id; unsigned long screen_cast_window_after_paint_handler_id; unsigned long screen_cast_window_destroyed_handler_id; + unsigned long cursor_moved_handler_id; + unsigned long cursor_changed_handler_id; + + gboolean actor_was_dirty; + gboolean cursor_bitmap_invalid; }; G_DEFINE_TYPE (MetaScreenCastWindowStreamSrc, meta_screen_cast_window_stream_src, META_TYPE_SCREEN_CAST_STREAM_SRC) +static MetaBackend * +get_backend (MetaScreenCastWindowStreamSrc *window_src) +{ + MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src); + MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src); + MetaScreenCastSession *session = meta_screen_cast_stream_get_session (stream); + MetaScreenCast *screen_cast = + meta_screen_cast_session_get_screen_cast (session); + + return meta_screen_cast_get_backend (screen_cast); +} + static MetaScreenCastWindowStream * get_window_stream (MetaScreenCastWindowStreamSrc *window_src) { @@ -83,11 +102,91 @@ get_stream_height (MetaScreenCastWindowStreamSrc *window_src) return meta_screen_cast_window_stream_get_height (window_stream); } +static void +maybe_draw_cursor_sprite (MetaScreenCastWindowStreamSrc *window_src, + uint8_t *data, + MetaRectangle *stream_rect) +{ + MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src); + MetaBackend *backend = get_backend (window_src); + MetaCursorRenderer *cursor_renderer = + meta_backend_get_cursor_renderer (backend); + MetaCursorSprite *cursor_sprite; + CoglTexture *cursor_texture; + MetaScreenCastWindow *screen_cast_window; + ClutterPoint cursor_position; + ClutterPoint relative_cursor_position; + cairo_surface_t *cursor_surface; + uint8_t *cursor_surface_data; + GError *error = NULL; + cairo_surface_t *stream_surface; + int width, height; + float scale; + int hotspot_x, hotspot_y; + cairo_t *cr; + + cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer); + if (!cursor_sprite) + return; + + cursor_texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); + if (!cursor_texture) + return; + + screen_cast_window = window_src->screen_cast_window; + cursor_position = meta_cursor_renderer_get_position (cursor_renderer); + if (!meta_screen_cast_window_transform_cursor_position (screen_cast_window, + cursor_sprite, + &cursor_position, + &scale, + &relative_cursor_position)) + return; + + meta_cursor_sprite_get_hotspot (cursor_sprite, &hotspot_x, &hotspot_y); + + width = cogl_texture_get_width (cursor_texture) * scale; + height = cogl_texture_get_height (cursor_texture) * scale; + cursor_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + width, height); + + cursor_surface_data = cairo_image_surface_get_data (cursor_surface); + if (!meta_screen_cast_stream_src_draw_cursor_into (src, + cursor_texture, + scale, + cursor_surface_data, + &error)) + { + g_warning ("Failed to draw cursor: %s", error->message); + g_error_free (error); + cairo_surface_destroy (cursor_surface); + return; + } + + stream_surface = + cairo_image_surface_create_for_data (data, CAIRO_FORMAT_ARGB32, + stream_rect->width, + stream_rect->height, + stream_rect->width * 4); + + cr = cairo_create (stream_surface); + cairo_surface_mark_dirty (cursor_surface); + cairo_surface_flush (cursor_surface); + cairo_set_source_surface (cr, cursor_surface, + relative_cursor_position.x - hotspot_x * scale, + relative_cursor_position.y - hotspot_y * scale); + cairo_paint (cr); + cairo_destroy (cr); + cairo_surface_destroy (stream_surface); + cairo_surface_destroy (cursor_surface); +} + static gboolean capture_into (MetaScreenCastWindowStreamSrc *window_src, uint8_t *data) { + MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src); MetaRectangle stream_rect; + MetaScreenCastStream *stream; stream_rect.x = 0; stream_rect.y = 0; @@ -97,6 +196,17 @@ capture_into (MetaScreenCastWindowStreamSrc *window_src, meta_screen_cast_window_capture_into (window_src->screen_cast_window, &stream_rect, data); + stream = meta_screen_cast_stream_src_get_stream (src); + switch (meta_screen_cast_stream_get_cursor_mode (stream)) + { + case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: + maybe_draw_cursor_sprite (window_src, data, &stream_rect); + break; + case META_SCREEN_CAST_CURSOR_MODE_METADATA: + case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: + break; + } + return TRUE; } @@ -139,9 +249,16 @@ static void meta_screen_cast_window_stream_src_stop (MetaScreenCastWindowStreamSrc *window_src) { + MetaBackend *backend = get_backend (window_src); + MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); + if (!window_src->screen_cast_window) return; + if (window_src->screen_cast_window_before_paint_handler_id) + g_signal_handler_disconnect (window_src->screen_cast_window, + window_src->screen_cast_window_before_paint_handler_id); + window_src->screen_cast_window_before_paint_handler_id = 0; if (window_src->screen_cast_window_after_paint_handler_id) g_signal_handler_disconnect (window_src->screen_cast_window, @@ -152,31 +269,108 @@ meta_screen_cast_window_stream_src_stop (MetaScreenCastWindowStreamSrc *window_s g_signal_handler_disconnect (window_src->screen_cast_window, window_src->screen_cast_window_destroyed_handler_id); window_src->screen_cast_window_destroyed_handler_id = 0; + + if (window_src->cursor_moved_handler_id) + g_signal_handler_disconnect (cursor_tracker, + window_src->cursor_moved_handler_id); + window_src->cursor_moved_handler_id = 0; + + if (window_src->cursor_changed_handler_id) + g_signal_handler_disconnect (cursor_tracker, + window_src->cursor_changed_handler_id); + window_src->cursor_changed_handler_id = 0; } static void -screen_cast_window_after_paint (MetaScreenCastWindow *screen_cast_window, +screen_cast_window_before_paint (MetaScreenCastWindow *screen_cast_window, + MetaScreenCastWindowStreamSrc *window_src) +{ + window_src->actor_was_dirty = + meta_screen_cast_window_has_damage (screen_cast_window); +} + +static void +screen_cast_window_after_paint (MetaWindowActor *actor, MetaScreenCastWindowStreamSrc *window_src) { - MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src); + if (window_src->actor_was_dirty) + { + MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src); - meta_screen_cast_stream_src_maybe_record_frame (src); + meta_screen_cast_stream_src_maybe_record_frame (src); + } } static void -screen_cast_window_destroyed (MetaScreenCastWindow *screen_cast_window, +screen_cast_window_destroyed (MetaWindowActor *actor, MetaScreenCastWindowStreamSrc *window_src) { meta_screen_cast_window_stream_src_stop (window_src); window_src->screen_cast_window = NULL; } +static gboolean +is_cursor_in_stream (MetaScreenCastWindowStreamSrc *window_src) +{ + MetaBackend *backend = get_backend (window_src); + MetaCursorRenderer *cursor_renderer = + meta_backend_get_cursor_renderer (backend); + MetaCursorSprite *cursor_sprite; + ClutterPoint cursor_position; + MetaScreenCastWindow *screen_cast_window; + + cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer); + + cursor_position = meta_cursor_renderer_get_position (cursor_renderer); + + screen_cast_window = window_src->screen_cast_window; + return meta_screen_cast_window_transform_cursor_position (screen_cast_window, + cursor_sprite, + &cursor_position, + NULL, + NULL); +} + +static void +sync_cursor_state (MetaScreenCastWindowStreamSrc *window_src) +{ + MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src); + + if (!is_cursor_in_stream (window_src)) + return; + + if (meta_screen_cast_window_has_damage (window_src->screen_cast_window)) + return; + + meta_screen_cast_stream_src_maybe_record_frame (src); +} + +static void +cursor_moved (MetaCursorTracker *cursor_tracker, + float x, + float y, + MetaScreenCastWindowStreamSrc *window_src) +{ + sync_cursor_state (window_src); +} + +static void +cursor_changed (MetaCursorTracker *cursor_tracker, + MetaScreenCastWindowStreamSrc *window_src) +{ + window_src->cursor_bitmap_invalid = TRUE; + sync_cursor_state (window_src); +} + static void meta_screen_cast_window_stream_src_enable (MetaScreenCastStreamSrc *src) { MetaScreenCastWindowStreamSrc *window_src = META_SCREEN_CAST_WINDOW_STREAM_SRC (src); + MetaBackend *backend = get_backend (window_src); + MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); MetaWindowActor *window_actor; + MetaScreenCastStream *stream; window_actor = meta_window_actor_from_window (get_window (window_src)); if (!window_actor) @@ -184,6 +378,11 @@ meta_screen_cast_window_stream_src_enable (MetaScreenCastStreamSrc *src) window_src->screen_cast_window = META_SCREEN_CAST_WINDOW (window_actor); + window_src->screen_cast_window_before_paint_handler_id = + g_signal_connect (window_src->screen_cast_window, + "paint", + G_CALLBACK (screen_cast_window_before_paint), + window_src); window_src->screen_cast_window_after_paint_handler_id = g_signal_connect_after (window_src->screen_cast_window, "paint", @@ -195,6 +394,24 @@ meta_screen_cast_window_stream_src_enable (MetaScreenCastStreamSrc *src) "destroy", G_CALLBACK (screen_cast_window_destroyed), window_src); + + stream = meta_screen_cast_stream_src_get_stream (src); + switch (meta_screen_cast_stream_get_cursor_mode (stream)) + { + case META_SCREEN_CAST_CURSOR_MODE_METADATA: + case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED: + window_src->cursor_moved_handler_id = + g_signal_connect_after (cursor_tracker, "cursor-moved", + G_CALLBACK (cursor_moved), + window_src); + window_src->cursor_changed_handler_id = + g_signal_connect_after (cursor_tracker, "cursor-changed", + G_CALLBACK (cursor_changed), + window_src); + break; + case META_SCREEN_CAST_CURSOR_MODE_HIDDEN: + break; + } } static void @@ -218,6 +435,65 @@ meta_screen_cast_window_stream_src_record_frame (MetaScreenCastStreamSrc *src, return TRUE; } +static void +meta_screen_cast_window_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src, + struct spa_meta_cursor *spa_meta_cursor) +{ + MetaScreenCastWindowStreamSrc *window_src = + META_SCREEN_CAST_WINDOW_STREAM_SRC (src); + MetaBackend *backend = get_backend (window_src); + MetaCursorRenderer *cursor_renderer = + meta_backend_get_cursor_renderer (backend); + MetaScreenCastWindow *screen_cast_window = window_src->screen_cast_window; + MetaCursorSprite *cursor_sprite; + ClutterPoint cursor_position; + float scale; + ClutterPoint relative_cursor_position; + int x, y; + + cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer); + cursor_position = meta_cursor_renderer_get_position (cursor_renderer); + + if (!meta_screen_cast_window_transform_cursor_position (screen_cast_window, + cursor_sprite, + &cursor_position, + &scale, + &relative_cursor_position)) + { + meta_screen_cast_stream_src_unset_cursor_metadata (src, + spa_meta_cursor); + return; + } + + x = (int) roundf (relative_cursor_position.x); + y = (int) roundf (relative_cursor_position.y); + + if (window_src->cursor_bitmap_invalid) + { + if (cursor_sprite) + { + meta_screen_cast_stream_src_set_cursor_sprite_metadata (src, + spa_meta_cursor, + cursor_sprite, + x, y, + scale); + } + else + { + meta_screen_cast_stream_src_set_empty_cursor_sprite_metadata (src, + spa_meta_cursor, + x, y); + } + window_src->cursor_bitmap_invalid = FALSE; + } + else + { + meta_screen_cast_stream_src_set_cursor_position_metadata (src, + spa_meta_cursor, + x, y); + } +} + MetaScreenCastWindowStreamSrc * meta_screen_cast_window_stream_src_new (MetaScreenCastWindowStream *window_stream, GError **error) @@ -230,6 +506,7 @@ meta_screen_cast_window_stream_src_new (MetaScreenCastWindowStream *window_stre static void meta_screen_cast_window_stream_src_init (MetaScreenCastWindowStreamSrc *window_src) { + window_src->cursor_bitmap_invalid = TRUE; } static void @@ -243,4 +520,5 @@ meta_screen_cast_window_stream_src_class_init (MetaScreenCastWindowStreamSrcClas src_class->disable = meta_screen_cast_window_stream_src_disable; src_class->record_frame = meta_screen_cast_window_stream_src_record_frame; src_class->get_videocrop = meta_screen_cast_window_stream_src_get_videocrop; + src_class->set_cursor_metadata = meta_screen_cast_window_stream_src_set_cursor_metadata; } diff --git a/src/backends/meta-screen-cast-window-stream.c b/src/backends/meta-screen-cast-window-stream.c index 19645540c3d..50d1806cde0 100644 --- a/src/backends/meta-screen-cast-window-stream.c +++ b/src/backends/meta-screen-cast-window-stream.c @@ -80,16 +80,18 @@ meta_screen_cast_window_stream_get_height (MetaScreenCastWindowStream *window_st } MetaScreenCastWindowStream * -meta_screen_cast_window_stream_new (MetaScreenCastSession *session, - GDBusConnection *connection, - MetaWindow *window, - GError **error) +meta_screen_cast_window_stream_new (MetaScreenCastSession *session, + GDBusConnection *connection, + MetaWindow *window, + MetaScreenCastCursorMode cursor_mode, + GError **error) { return g_initable_new (META_TYPE_SCREEN_CAST_WINDOW_STREAM, NULL, error, "session", session, "connection", connection, + "cursor-mode", cursor_mode, "window", window, NULL); } diff --git a/src/backends/meta-screen-cast-window-stream.h b/src/backends/meta-screen-cast-window-stream.h index 3799be98a2c..6eae74f1cde 100644 --- a/src/backends/meta-screen-cast-window-stream.h +++ b/src/backends/meta-screen-cast-window-stream.h @@ -32,10 +32,11 @@ G_DECLARE_FINAL_TYPE (MetaScreenCastWindowStream, META, SCREEN_CAST_WINDOW_STREAM, MetaScreenCastStream) -MetaScreenCastWindowStream * meta_screen_cast_window_stream_new (MetaScreenCastSession *session, - GDBusConnection *connection, - MetaWindow *window, - GError **error); +MetaScreenCastWindowStream * meta_screen_cast_window_stream_new (MetaScreenCastSession *session, + GDBusConnection *connection, + MetaWindow *window, + MetaScreenCastCursorMode cursor_mode, + GError **error); MetaWindow * meta_screen_cast_window_stream_get_window (MetaScreenCastWindowStream *window_stream); int meta_screen_cast_window_stream_get_width (MetaScreenCastWindowStream *window_stream); diff --git a/src/org.gnome.Mutter.ScreenCast.xml b/src/org.gnome.Mutter.ScreenCast.xml index 953809727e0..8ec2a1919fd 100644 --- a/src/org.gnome.Mutter.ScreenCast.xml +++ b/src/org.gnome.Mutter.ScreenCast.xml @@ -97,6 +97,7 @@ Available @properties include: * "window-id" (t): Id of the window to record. + * "cursor-mode" (u): Cursor mode. Default: 'hidden' (see RecordMonitor) --> -- GitLab From 7c807c6e2ad2af62d0ded008808a756e4e789e34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jonas=20=C3=85dahl?= Date: Wed, 30 Jan 2019 15:16:19 +0100 Subject: [PATCH 15/15] org.gnome.Mutter.ScreenCast: Document what was added in API version 2 RecordWindow and the cursor-mode property are only available if the advertised version is at least 2. https://gitlab.gnome.org/GNOME/mutter/merge_requests/413 --- src/org.gnome.Mutter.ScreenCast.xml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/org.gnome.Mutter.ScreenCast.xml b/src/org.gnome.Mutter.ScreenCast.xml index 8ec2a1919fd..0e83747f53d 100644 --- a/src/org.gnome.Mutter.ScreenCast.xml +++ b/src/org.gnome.Mutter.ScreenCast.xml @@ -74,6 +74,7 @@ Available @properties include: * "cursor-mode" (u): Cursor mode. Default: 'hidden' (see below) + Available since API version 2. Available cursor mode values: @@ -92,12 +93,14 @@ @properties: Properties used determining what window to select @stream_path: Path to the new stream object + Supported since API version 2. + Record a single window. The cursor will not be included. Available @properties include: * "window-id" (t): Id of the window to record. - * "cursor-mode" (u): Cursor mode. Default: 'hidden' (see RecordMonitor) + * "cursor-mode" (u): Cursor mode. Default: 'hidden' (see RecordMonitor). --> -- GitLab