Skip to content
Commits on Source (21)
3.36.5
======
* Screencast fixes and improvements [Jonas; !1351, !1365]
* Fix glitches when subsurfaces extend outside the toplevel [Robert; #1316]
* Mipmap background texture rendering [Daniel; !1347]
* Fix wine copy & paste [Sebastian; !1369]
* Plugged memory leaks [Marco, Thomas; !1195]
Contributors:
Jonas Ådahl, Thomas Hindoe Paaboel Andersen, Sebastian Keller, Robert Mader,
Marco Trevisan (Treviño), Daniel van Vugt
Translators:
Rafael Fontenelle [pt_BR]
3.36.4
======
* Fix crash on area screenshots with fractional scaling [Sebastian; !1320]
......
......@@ -74,7 +74,7 @@ PangoFontMap *
cogl_pango_font_map_new (void)
{
PangoFontMap *fm = pango_cairo_font_map_new ();
CoglPangoFontMapPriv *priv = g_new0 (CoglPangoFontMapPriv, 1);
g_autofree CoglPangoFontMapPriv *priv = g_new0 (CoglPangoFontMapPriv, 1);
_COGL_GET_CONTEXT (context, NULL);
......@@ -85,7 +85,7 @@ cogl_pango_font_map_new (void)
* for now. */
g_object_set_qdata_full (G_OBJECT (fm),
cogl_pango_font_map_get_priv_key (),
priv,
g_steal_pointer (&priv),
free_priv);
return fm;
......
......@@ -93,10 +93,12 @@ _cogl_onscreen_init_from_template (CoglOnscreen *onscreen,
CoglOnscreen *
_cogl_onscreen_new (void)
{
CoglOnscreen *onscreen = g_new0 (CoglOnscreen, 1);
g_autofree CoglOnscreen *onscreen_ptr = g_new0 (CoglOnscreen, 1);
CoglOnscreen *onscreen;
_COGL_GET_CONTEXT (ctx, NULL);
onscreen = g_steal_pointer (&onscreen_ptr);
_cogl_framebuffer_init (COGL_FRAMEBUFFER (onscreen),
ctx,
COGL_FRAMEBUFFER_TYPE_ONSCREEN,
......
......@@ -50,7 +50,7 @@ struct _CoglPipelineCache
CoglPipelineCache *
_cogl_pipeline_cache_new (void)
{
CoglPipelineCache *cache = g_new (CoglPipelineCache, 1);
g_autofree CoglPipelineCache *cache = g_new (CoglPipelineCache, 1);
unsigned long vertex_state;
unsigned long layer_vertex_state;
unsigned int fragment_state;
......@@ -80,7 +80,7 @@ _cogl_pipeline_cache_new (void)
layer_vertex_state | layer_fragment_state,
"programs");
return cache;
return g_steal_pointer (&cache);
}
void
......
......@@ -402,6 +402,11 @@ _cogl_texture_2d_pre_paint (CoglTexture *tex, CoglTexturePrePaintFlags flags)
{
CoglContext *ctx = tex->context;
/* Since we are about to ask the GPU to generate mipmaps of tex, we
* better make sure tex is up-to-date.
*/
_cogl_texture_flush_journal_rendering (tex);
ctx->driver_vtable->texture_2d_generate_mipmap (tex_2d);
tex_2d->mipmaps_dirty = FALSE;
......
project('mutter', 'c',
version: '3.36.4',
version: '3.36.5',
meson_version: '>= 0.50.0',
license: 'GPLv2+'
)
......
......@@ -21,8 +21,8 @@ msgid ""
msgstr ""
"Project-Id-Version: mutter\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
"POT-Creation-Date: 2020-02-23 17:41+0000\n"
"PO-Revision-Date: 2020-02-24 06:39-0300\n"
"POT-Creation-Date: 2020-04-27 14:06+0000\n"
"PO-Revision-Date: 2020-07-17 17:56-0300\n"
"Last-Translator: Rafael Fontenelle <rafaelff@gnome.org>\n"
"Language-Team: Brazilian Portuguese <gnome-pt_br-list@gnome.org>\n"
"Language: pt_BR\n"
......@@ -30,7 +30,7 @@ msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
"X-Generator: Gtranslator 3.32.0\n"
"X-Generator: Gtranslator 3.36.0\n"
"X-Project-Style: gnome\n"
#: data/50-mutter-navigation.xml:6
......@@ -59,35 +59,35 @@ msgstr "Mover a janela para o último espaço de trabalho"
#: data/50-mutter-navigation.xml:24
msgid "Move window one workspace up"
msgstr "Mover a janela um espaço de trabalho acima"
msgstr "Mover a janela para um espaço de trabalho acima"
#: data/50-mutter-navigation.xml:27
msgid "Move window one workspace down"
msgstr "Mover a janela um espaço de trabalho abaixo"
msgstr "Mover a janela para um espaço de trabalho abaixo"
# Em conformidade com a tradução do gsettings-desktop-schemas --Enrico
#: data/50-mutter-navigation.xml:30
msgid "Move window one monitor to the left"
msgstr "Mover janela para o monitor da esquerda"
msgstr "Mover a janela para o monitor da esquerda"
# Em conformidade com a tradução do gsettings-desktop-schemas --Enrico
#: data/50-mutter-navigation.xml:33
msgid "Move window one monitor to the right"
msgstr "Mover janela para o monitor da direita"
msgstr "Mover a janela para o monitor da direita"
# Em conformidade com a tradução do gsettings-desktop-schemas --Enrico
#: data/50-mutter-navigation.xml:36
msgid "Move window one monitor up"
msgstr "Mover janela para o monitor acima"
msgstr "Mover a janela para o monitor acima"
# Em conformidade com a tradução do gsettings-desktop-schemas --Enrico
#: data/50-mutter-navigation.xml:39
msgid "Move window one monitor down"
msgstr "Mover janela para o monitor abaixo"
msgstr "Mover a janela para o monitor abaixo"
#: data/50-mutter-navigation.xml:43
msgid "Switch applications"
msgstr "Alternar aplicativos"
msgstr "Alternar entre aplicativos"
#: data/50-mutter-navigation.xml:48
msgid "Switch to previous application"
......@@ -95,7 +95,7 @@ msgstr "Alternar para o aplicativo anterior"
#: data/50-mutter-navigation.xml:52
msgid "Switch windows"
msgstr "Alternar janelas"
msgstr "Alternar entre janelas"
#: data/50-mutter-navigation.xml:57
msgid "Switch to previous window"
......@@ -111,7 +111,7 @@ msgstr "Alternar para a janela anterior de um aplicativo"
#: data/50-mutter-navigation.xml:70
msgid "Switch system controls"
msgstr "Alternar controles do sistema"
msgstr "Alternar os controles do sistema"
#: data/50-mutter-navigation.xml:75
msgid "Switch to previous system control"
......@@ -167,11 +167,11 @@ msgstr "Trocar para o último espaço de trabalho"
#: data/50-mutter-navigation.xml:123
msgid "Move to workspace above"
msgstr "Mover para o espaço de trabalho acima"
msgstr "Mover a visualização para o espaço de trabalho acima"
#: data/50-mutter-navigation.xml:126
msgid "Move to workspace below"
msgstr "Mover para o espaço de trabalho abaixo"
msgstr "Mover a visualização para o espaço de trabalho abaixo"
#: data/50-mutter-system.xml:6 data/50-mutter-wayland.xml:6
msgid "System"
......@@ -199,11 +199,11 @@ msgstr "Ativar o menu da janela"
#: data/50-mutter-windows.xml:10
msgid "Toggle fullscreen mode"
msgstr "Alternar modo de tela inteira"
msgstr "Alternar o modo de tela inteira"
#: data/50-mutter-windows.xml:12
msgid "Toggle maximization state"
msgstr "Alternar estado de maximização"
msgstr "Alternar o estado de maximização"
#: data/50-mutter-windows.xml:14
msgid "Maximize window"
......@@ -211,35 +211,35 @@ msgstr "Maximizar a janela"
#: data/50-mutter-windows.xml:16
msgid "Restore window"
msgstr "Restaurar janela"
msgstr "Restaurar a anela"
#: data/50-mutter-windows.xml:18
msgid "Close window"
msgstr "Fechar janela"
msgstr "Fechar a janela"
#: data/50-mutter-windows.xml:20
msgid "Hide window"
msgstr "Ocultar janela"
msgstr "Ocultar a janela"
#: data/50-mutter-windows.xml:22
msgid "Move window"
msgstr "Mover janela"
msgstr "Mover a janela"
#: data/50-mutter-windows.xml:24
msgid "Resize window"
msgstr "Redimensionar janela"
msgstr "Redimensionar a janela"
#: data/50-mutter-windows.xml:27
msgid "Toggle window on all workspaces or one"
msgstr "Alternar a janela em todos os espaços de trabalho ou em apenas um"
msgstr "Alternar a janela em todos os espaços de trabalho ou apenas em um"
#: data/50-mutter-windows.xml:29
msgid "Raise window if covered, otherwise lower it"
msgstr "Elevar a janela se estiver coberta; caso contrário, a abaixa"
msgstr "Trazer a janela se estiver coberta; caso contrário, coloca atrás"
#: data/50-mutter-windows.xml:31
msgid "Raise window above other windows"
msgstr "Elevar a janela para frente das outras"
msgstr "Trazer a janela para frente das outras"
#: data/50-mutter-windows.xml:33
msgid "Lower window below other windows"
......@@ -255,11 +255,11 @@ msgstr "Maximizar a janela horizontalmente"
#: data/50-mutter-windows.xml:41
msgid "View split on left"
msgstr "Visualizar divisão à esquerda"
msgstr "Visualizar a divisão à esquerda"
#: data/50-mutter-windows.xml:45
msgid "View split on right"
msgstr "Visualizar divisão à direita"
msgstr "Visualizar a divisão à direita"
#: data/mutter.desktop.in:4
msgid "Mutter"
......@@ -580,7 +580,7 @@ msgstr ""
#. TRANSLATORS: This string refers to a button that switches between
#. * different modes.
#.
#: src/backends/meta-input-settings.c:2567
#: src/backends/meta-input-settings.c:2631
#, c-format
msgid "Mode Switch (Group %d)"
msgstr "Alternador de modo (Grupo %d)"
......@@ -588,34 +588,34 @@ msgstr "Alternador de modo (Grupo %d)"
#. TRANSLATORS: This string refers to an action, cycles drawing tablets'
#. * mapping through the available outputs.
#.
#: src/backends/meta-input-settings.c:2590
#: src/backends/meta-input-settings.c:2654
msgid "Switch monitor"
msgstr "Trocar monitor"
#: src/backends/meta-input-settings.c:2592
#: src/backends/meta-input-settings.c:2656
msgid "Show on-screen help"
msgstr "Mostrar ajuda na tela"
#: src/backends/meta-monitor.c:223
#: src/backends/meta-monitor.c:226
msgid "Built-in display"
msgstr "Tela embutida"
#: src/backends/meta-monitor.c:252
#: src/backends/meta-monitor.c:255
msgid "Unknown"
msgstr "Desconhecido"
#: src/backends/meta-monitor.c:254
#: src/backends/meta-monitor.c:257
msgid "Unknown Display"
msgstr "Monitor desconhecido"
#: src/backends/meta-monitor.c:262
#: src/backends/meta-monitor.c:265
#, c-format
msgctxt ""
"This is a monitor vendor name, followed by a size in inches, like 'Dell 15\"'"
msgid "%s %s"
msgstr "%s %s"
#: src/backends/meta-monitor.c:270
#: src/backends/meta-monitor.c:273
#, c-format
msgctxt ""
"This is a monitor vendor name followed by product/model name where size in "
......
......@@ -121,8 +121,10 @@ stage_painted (MetaStage *stage,
gpointer user_data)
{
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (user_data);
MetaScreenCastRecordFlag flags;
meta_screen_cast_stream_src_maybe_record_frame (src);
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
meta_screen_cast_stream_src_maybe_record_frame (src, flags);
}
static MetaBackend *
......@@ -181,6 +183,7 @@ sync_cursor_state (MetaScreenCastMonitorStreamSrc *monitor_src)
{
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (monitor_src);
ClutterStage *stage = get_stage (monitor_src);
MetaScreenCastRecordFlag flags;
if (!is_cursor_in_stream (monitor_src))
return;
......@@ -188,7 +191,11 @@ sync_cursor_state (MetaScreenCastMonitorStreamSrc *monitor_src)
if (clutter_stage_is_redraw_queued (stage))
return;
meta_screen_cast_stream_src_maybe_record_frame (src);
if (meta_screen_cast_stream_src_pending_follow_up_frame (src))
return;
flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY;
meta_screen_cast_stream_src_maybe_record_frame (src, flags);
}
static void
......@@ -362,8 +369,9 @@ meta_screen_cast_monitor_stream_src_disable (MetaScreenCastStreamSrc *src)
}
static gboolean
meta_screen_cast_monitor_stream_src_record_frame (MetaScreenCastStreamSrc *src,
uint8_t *data)
meta_screen_cast_monitor_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src,
uint8_t *data,
GError **error)
{
MetaScreenCastMonitorStreamSrc *monitor_src =
META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
......@@ -372,9 +380,6 @@ meta_screen_cast_monitor_stream_src_record_frame (MetaScreenCastStreamSrc *src,
MetaLogicalMonitor *logical_monitor;
stage = get_stage (monitor_src);
if (!clutter_stage_is_redraw_queued (stage))
return FALSE;
monitor = get_monitor (monitor_src);
logical_monitor = meta_monitor_get_logical_monitor (monitor);
clutter_stage_capture_into (stage, FALSE, &logical_monitor->rect, data);
......@@ -383,8 +388,9 @@ meta_screen_cast_monitor_stream_src_record_frame (MetaScreenCastStreamSrc *src,
}
static gboolean
meta_screen_cast_monitor_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src,
CoglFramebuffer *framebuffer)
meta_screen_cast_monitor_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src,
CoglFramebuffer *framebuffer,
GError **error)
{
MetaScreenCastMonitorStreamSrc *monitor_src =
META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
......@@ -408,7 +414,6 @@ meta_screen_cast_monitor_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc
for (l = meta_renderer_get_views (renderer); l; l = l->next)
{
ClutterStageView *view = CLUTTER_STAGE_VIEW (l->data);
g_autoptr (GError) error = NULL;
CoglFramebuffer *view_framebuffer;
MetaRectangle view_layout;
int x, y;
......@@ -429,12 +434,8 @@ meta_screen_cast_monitor_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc
x, y,
cogl_framebuffer_get_width (view_framebuffer),
cogl_framebuffer_get_height (view_framebuffer),
&error))
{
g_warning ("Error blitting view into DMABuf framebuffer: %s",
error->message);
return FALSE;
}
error))
return FALSE;
}
cogl_framebuffer_finish (framebuffer);
......@@ -442,6 +443,44 @@ meta_screen_cast_monitor_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc
return TRUE;
}
static void
meta_screen_cast_monitor_stream_record_follow_up (MetaScreenCastStreamSrc *src)
{
MetaScreenCastMonitorStreamSrc *monitor_src =
META_SCREEN_CAST_MONITOR_STREAM_SRC (src);
MetaBackend *backend = get_backend (monitor_src);
MetaRenderer *renderer = meta_backend_get_renderer (backend);
ClutterStage *stage = get_stage (monitor_src);
MetaMonitor *monitor;
MetaLogicalMonitor *logical_monitor;
MetaRectangle logical_monitor_layout;
GList *l;
monitor = get_monitor (monitor_src);
logical_monitor = meta_monitor_get_logical_monitor (monitor);
logical_monitor_layout = meta_logical_monitor_get_layout (logical_monitor);
for (l = meta_renderer_get_views (renderer); l; l = l->next)
{
MetaRendererView *view = l->data;
MetaRectangle view_layout;
MetaRectangle damage;
clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view), &view_layout);
if (!meta_rectangle_overlap (&logical_monitor_layout, &view_layout))
continue;
damage = (cairo_rectangle_int_t) {
.x = view_layout.x,
.y = view_layout.y,
.width = 1,
.height = 1,
};
clutter_actor_queue_redraw_with_clip (CLUTTER_ACTOR (stage), &damage);
}
}
static void
meta_screen_cast_monitor_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src,
struct spa_meta_cursor *spa_meta_cursor)
......@@ -562,9 +601,12 @@ meta_screen_cast_monitor_stream_src_class_init (MetaScreenCastMonitorStreamSrcCl
src_class->get_specs = meta_screen_cast_monitor_stream_src_get_specs;
src_class->enable = meta_screen_cast_monitor_stream_src_enable;
src_class->disable = meta_screen_cast_monitor_stream_src_disable;
src_class->record_frame = meta_screen_cast_monitor_stream_src_record_frame;
src_class->blit_to_framebuffer =
meta_screen_cast_monitor_stream_src_blit_to_framebuffer;
src_class->record_to_buffer =
meta_screen_cast_monitor_stream_src_record_to_buffer;
src_class->record_to_framebuffer =
meta_screen_cast_monitor_stream_src_record_to_framebuffer;
src_class->record_follow_up =
meta_screen_cast_monitor_stream_record_follow_up;
src_class->set_cursor_metadata =
meta_screen_cast_monitor_stream_src_set_cursor_metadata;
}
......@@ -91,7 +91,8 @@ typedef struct _MetaScreenCastStreamSrcPrivate
struct spa_video_info_raw video_format;
int video_stride;
uint64_t last_frame_timestamp_us;
int64_t last_frame_timestamp_us;
guint follow_up_frame_source_id;
GHashTable *dmabuf_handles;
......@@ -109,6 +110,12 @@ G_DEFINE_TYPE_WITH_CODE (MetaScreenCastStreamSrc,
meta_screen_cast_stream_src_init_initable_iface)
G_ADD_PRIVATE (MetaScreenCastStreamSrc))
static inline uint32_t
us2ms (uint64_t us)
{
return (uint32_t) (us / 1000);
}
static void
meta_screen_cast_stream_src_get_specs (MetaScreenCastStreamSrc *src,
int *width,
......@@ -135,23 +142,34 @@ meta_screen_cast_stream_src_get_videocrop (MetaScreenCastStreamSrc *src,
}
static gboolean
meta_screen_cast_stream_src_record_frame (MetaScreenCastStreamSrc *src,
uint8_t *data)
meta_screen_cast_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src,
uint8_t *data,
GError **error)
{
MetaScreenCastStreamSrcClass *klass =
META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src);
return klass->record_frame (src, data);
return klass->record_to_buffer (src, data, error);
}
static gboolean
meta_screen_cast_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src,
CoglFramebuffer *framebuffer)
meta_screen_cast_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src,
CoglFramebuffer *framebuffer,
GError **error)
{
MetaScreenCastStreamSrcClass *klass =
META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src);
return klass->record_to_framebuffer (src, framebuffer, error);
}
static void
meta_screen_cast_stream_src_record_follow_up (MetaScreenCastStreamSrc *src)
{
MetaScreenCastStreamSrcClass *klass =
META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src);
return klass->blit_to_framebuffer (src, framebuffer);
klass->record_follow_up (src);
}
static void
......@@ -409,9 +427,10 @@ maybe_record_cursor (MetaScreenCastStreamSrc *src,
}
static gboolean
do_record_frame (MetaScreenCastStreamSrc *src,
struct spa_buffer *spa_buffer,
uint8_t *data)
do_record_frame (MetaScreenCastStreamSrc *src,
struct spa_buffer *spa_buffer,
uint8_t *data,
GError **error)
{
MetaScreenCastStreamSrcPrivate *priv =
meta_screen_cast_stream_src_get_instance_private (src);
......@@ -419,7 +438,7 @@ do_record_frame (MetaScreenCastStreamSrc *src,
if (spa_buffer->datas[0].data ||
spa_buffer->datas[0].type == SPA_DATA_MemFd)
{
return meta_screen_cast_stream_src_record_frame (src, data);
return meta_screen_cast_stream_src_record_to_buffer (src, data, error);
}
else if (spa_buffer->datas[0].type == SPA_DATA_DmaBuf)
{
......@@ -429,14 +448,56 @@ do_record_frame (MetaScreenCastStreamSrc *src,
CoglFramebuffer *dmabuf_fbo =
cogl_dma_buf_handle_get_framebuffer (dmabuf_handle);
return meta_screen_cast_stream_src_blit_to_framebuffer (src, dmabuf_fbo);
return meta_screen_cast_stream_src_record_to_framebuffer (src,
dmabuf_fbo,
error);
}
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Unknown SPA buffer type %u", spa_buffer->datas[0].type);
return FALSE;
}
gboolean
meta_screen_cast_stream_src_pending_follow_up_frame (MetaScreenCastStreamSrc *src)
{
MetaScreenCastStreamSrcPrivate *priv =
meta_screen_cast_stream_src_get_instance_private (src);
return priv->follow_up_frame_source_id != 0;
}
static gboolean
follow_up_frame_cb (gpointer user_data)
{
MetaScreenCastStreamSrc *src = user_data;
MetaScreenCastStreamSrcPrivate *priv =
meta_screen_cast_stream_src_get_instance_private (src);
priv->follow_up_frame_source_id = 0;
meta_screen_cast_stream_src_record_follow_up (src);
return G_SOURCE_REMOVE;
}
static void
maybe_schedule_follow_up_frame (MetaScreenCastStreamSrc *src,
int64_t timeout_us)
{
MetaScreenCastStreamSrcPrivate *priv =
meta_screen_cast_stream_src_get_instance_private (src);
if (priv->follow_up_frame_source_id)
return;
priv->follow_up_frame_source_id = g_timeout_add (us2ms (timeout_us),
follow_up_frame_cb,
src);
}
void
meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src,
MetaScreenCastRecordFlag flags)
{
MetaScreenCastStreamSrcPrivate *priv =
meta_screen_cast_stream_src_get_instance_private (src);
......@@ -445,14 +506,29 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
struct spa_buffer *spa_buffer;
uint8_t *data = NULL;
uint64_t now_us;
g_autoptr (GError) error = NULL;
now_us = g_get_monotonic_time ();
if (priv->video_format.max_framerate.num > 0 &&
priv->last_frame_timestamp_us != 0 &&
(now_us - priv->last_frame_timestamp_us <
((1000000 * priv->video_format.max_framerate.denom) /
priv->video_format.max_framerate.num)))
return;
priv->last_frame_timestamp_us != 0)
{
int64_t min_interval_us;
int64_t time_since_last_frame_us;
min_interval_us =
((G_USEC_PER_SEC * priv->video_format.max_framerate.denom) /
priv->video_format.max_framerate.num);
time_since_last_frame_us = now_us - priv->last_frame_timestamp_us;
if (time_since_last_frame_us < min_interval_us)
{
int64_t timeout_us;
timeout_us = min_interval_us - time_since_last_frame_us;
maybe_schedule_follow_up_frame (src, timeout_us);
return;
}
}
if (!priv->pipewire_stream)
return;
......@@ -470,34 +546,43 @@ meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src)
return;
}
if (do_record_frame (src, spa_buffer, data))
if (!(flags & META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY))
{
struct spa_meta_region *spa_meta_video_crop;
g_clear_handle_id (&priv->follow_up_frame_source_id, g_source_remove);
if (do_record_frame (src, spa_buffer, data, &error))
{
struct spa_meta_region *spa_meta_video_crop;
spa_buffer->datas[0].chunk->size = spa_buffer->datas[0].maxsize;
spa_buffer->datas[0].chunk->stride = priv->video_stride;
spa_buffer->datas[0].chunk->size = spa_buffer->datas[0].maxsize;
spa_buffer->datas[0].chunk->stride = priv->video_stride;
/* Update VideoCrop if needed */
spa_meta_video_crop =
spa_buffer_find_meta_data (spa_buffer, SPA_META_VideoCrop,
sizeof (*spa_meta_video_crop));
if (spa_meta_video_crop)
{
if (meta_screen_cast_stream_src_get_videocrop (src, &crop_rect))
{
spa_meta_video_crop->region.position.x = crop_rect.x;
spa_meta_video_crop->region.position.y = crop_rect.y;
spa_meta_video_crop->region.size.width = crop_rect.width;
spa_meta_video_crop->region.size.height = crop_rect.height;
}
else
/* Update VideoCrop if needed */
spa_meta_video_crop =
spa_buffer_find_meta_data (spa_buffer, SPA_META_VideoCrop,
sizeof (*spa_meta_video_crop));
if (spa_meta_video_crop)
{
spa_meta_video_crop->region.position.x = 0;
spa_meta_video_crop->region.position.y = 0;
spa_meta_video_crop->region.size.width = priv->stream_width;
spa_meta_video_crop->region.size.height = priv->stream_height;
if (meta_screen_cast_stream_src_get_videocrop (src, &crop_rect))
{
spa_meta_video_crop->region.position.x = crop_rect.x;
spa_meta_video_crop->region.position.y = crop_rect.y;
spa_meta_video_crop->region.size.width = crop_rect.width;
spa_meta_video_crop->region.size.height = crop_rect.height;
}
else
{
spa_meta_video_crop->region.position.x = 0;
spa_meta_video_crop->region.position.y = 0;
spa_meta_video_crop->region.size.width = priv->stream_width;
spa_meta_video_crop->region.size.height = priv->stream_height;
}
}
}
else
{
g_warning ("Failed to record screen cast frame: %s", error->message);
spa_buffer->datas[0].chunk->size = 0;
}
}
else
{
......@@ -539,6 +624,8 @@ meta_screen_cast_stream_src_disable (MetaScreenCastStreamSrc *src)
META_SCREEN_CAST_STREAM_SRC_GET_CLASS (src)->disable (src);
g_clear_handle_id (&priv->follow_up_frame_source_id, g_source_remove);
priv->is_enabled = FALSE;
}
......
......@@ -37,6 +37,12 @@
typedef struct _MetaScreenCastStream MetaScreenCastStream;
typedef enum _MetaScreenCastRecordFlag
{
META_SCREEN_CAST_RECORD_FLAG_NONE = 0,
META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY = 1 << 0,
} MetaScreenCastRecordFlag;
#define META_TYPE_SCREEN_CAST_STREAM_SRC (meta_screen_cast_stream_src_get_type ())
G_DECLARE_DERIVABLE_TYPE (MetaScreenCastStreamSrc,
meta_screen_cast_stream_src,
......@@ -53,17 +59,24 @@ struct _MetaScreenCastStreamSrcClass
float *frame_rate);
void (* enable) (MetaScreenCastStreamSrc *src);
void (* disable) (MetaScreenCastStreamSrc *src);
gboolean (* record_frame) (MetaScreenCastStreamSrc *src,
uint8_t *data);
gboolean (* blit_to_framebuffer) (MetaScreenCastStreamSrc *src,
CoglFramebuffer *framebuffer);
gboolean (* record_to_buffer) (MetaScreenCastStreamSrc *src,
uint8_t *data,
GError **error);
gboolean (* record_to_framebuffer) (MetaScreenCastStreamSrc *src,
CoglFramebuffer *framebuffer,
GError **error);
void (* record_follow_up) (MetaScreenCastStreamSrc *src);
gboolean (* get_videocrop) (MetaScreenCastStreamSrc *src,
MetaRectangle *crop_rect);
void (* set_cursor_metadata) (MetaScreenCastStreamSrc *src,
struct spa_meta_cursor *spa_meta_cursor);
};
void meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src);
void meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src,
MetaScreenCastRecordFlag flags);
gboolean meta_screen_cast_stream_src_pending_follow_up_frame (MetaScreenCastStreamSrc *src);
MetaScreenCastStream * meta_screen_cast_stream_src_get_stream (MetaScreenCastStreamSrc *src);
......
......@@ -327,8 +327,10 @@ screen_cast_window_damaged (MetaWindowActor *actor,
MetaScreenCastWindowStreamSrc *window_src)
{
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src);
MetaScreenCastRecordFlag flags;
meta_screen_cast_stream_src_maybe_record_frame (src);
flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY;
meta_screen_cast_stream_src_maybe_record_frame (src, flags);
}
static void
......@@ -365,6 +367,7 @@ static void
sync_cursor_state (MetaScreenCastWindowStreamSrc *window_src)
{
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (window_src);
MetaScreenCastRecordFlag flags;
if (!is_cursor_in_stream (window_src))
return;
......@@ -372,7 +375,8 @@ sync_cursor_state (MetaScreenCastWindowStreamSrc *window_src)
if (meta_screen_cast_window_has_damage (window_src->screen_cast_window))
return;
meta_screen_cast_stream_src_maybe_record_frame (src);
flags = META_SCREEN_CAST_RECORD_FLAG_CURSOR_ONLY;
meta_screen_cast_stream_src_maybe_record_frame (src, flags);
}
static void
......@@ -401,6 +405,7 @@ meta_screen_cast_window_stream_src_enable (MetaScreenCastStreamSrc *src)
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
MetaWindowActor *window_actor;
MetaScreenCastStream *stream;
MetaScreenCastRecordFlag flags;
window_actor = meta_window_actor_from_window (get_window (window_src));
if (!window_actor)
......@@ -438,7 +443,8 @@ meta_screen_cast_window_stream_src_enable (MetaScreenCastStreamSrc *src)
break;
}
meta_screen_cast_stream_src_maybe_record_frame (src);
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
meta_screen_cast_stream_src_maybe_record_frame (src, flags);
}
static void
......@@ -451,8 +457,9 @@ meta_screen_cast_window_stream_src_disable (MetaScreenCastStreamSrc *src)
}
static gboolean
meta_screen_cast_window_stream_src_record_frame (MetaScreenCastStreamSrc *src,
uint8_t *data)
meta_screen_cast_window_stream_src_record_to_buffer (MetaScreenCastStreamSrc *src,
uint8_t *data,
GError **error)
{
MetaScreenCastWindowStreamSrc *window_src =
META_SCREEN_CAST_WINDOW_STREAM_SRC (src);
......@@ -463,8 +470,9 @@ meta_screen_cast_window_stream_src_record_frame (MetaScreenCastStreamSrc *src,
}
static gboolean
meta_screen_cast_window_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src,
CoglFramebuffer *framebuffer)
meta_screen_cast_window_stream_src_record_to_framebuffer (MetaScreenCastStreamSrc *src,
CoglFramebuffer *framebuffer,
GError **error)
{
MetaScreenCastWindowStreamSrc *window_src =
META_SCREEN_CAST_WINDOW_STREAM_SRC (src);
......@@ -477,9 +485,13 @@ meta_screen_cast_window_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc
stream_rect.height = get_stream_height (window_src);
if (!meta_screen_cast_window_blit_to_framebuffer (window_src->screen_cast_window,
&stream_rect,
framebuffer))
return FALSE;
&stream_rect,
framebuffer))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Failed to blit window content to framebuffer");
return FALSE;
}
stream = meta_screen_cast_stream_src_get_stream (src);
switch (meta_screen_cast_stream_get_cursor_mode (stream))
......@@ -497,6 +509,15 @@ meta_screen_cast_window_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc
return TRUE;
}
static void
meta_screen_cast_window_stream_record_follow_up (MetaScreenCastStreamSrc *src)
{
MetaScreenCastRecordFlag flags;
flags = META_SCREEN_CAST_RECORD_FLAG_NONE;
meta_screen_cast_stream_src_maybe_record_frame (src, flags);
}
static void
meta_screen_cast_window_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src,
struct spa_meta_cursor *spa_meta_cursor)
......@@ -580,9 +601,12 @@ meta_screen_cast_window_stream_src_class_init (MetaScreenCastWindowStreamSrcClas
src_class->get_specs = meta_screen_cast_window_stream_src_get_specs;
src_class->enable = meta_screen_cast_window_stream_src_enable;
src_class->disable = meta_screen_cast_window_stream_src_disable;
src_class->record_frame = meta_screen_cast_window_stream_src_record_frame;
src_class->blit_to_framebuffer =
meta_screen_cast_window_stream_src_blit_to_framebuffer;
src_class->record_to_buffer =
meta_screen_cast_window_stream_src_record_to_buffer;
src_class->record_to_framebuffer =
meta_screen_cast_window_stream_src_record_to_framebuffer;
src_class->record_follow_up =
meta_screen_cast_window_stream_record_follow_up;
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;
}
......@@ -354,7 +354,7 @@ setup_pipeline (MetaBackgroundActor *self,
guint8 opacity;
float color_component;
CoglFramebuffer *fb;
CoglPipelineFilter filter;
CoglPipelineFilter min_filter, mag_filter;
opacity = clutter_actor_get_paint_opacity (CLUTTER_ACTOR (self));
if (opacity < 255)
......@@ -455,11 +455,17 @@ setup_pipeline (MetaBackgroundActor *self,
actor_pixel_rect->width,
actor_pixel_rect->height,
NULL, NULL))
filter = COGL_PIPELINE_FILTER_NEAREST;
{
min_filter = COGL_PIPELINE_FILTER_NEAREST;
mag_filter = COGL_PIPELINE_FILTER_NEAREST;
}
else
filter = COGL_PIPELINE_FILTER_LINEAR;
{
min_filter = COGL_PIPELINE_FILTER_LINEAR_MIPMAP_NEAREST;
mag_filter = COGL_PIPELINE_FILTER_LINEAR;
}
cogl_pipeline_set_layer_filters (self->pipeline, 0, filter, filter);
cogl_pipeline_set_layer_filters (self->pipeline, 0, min_filter, mag_filter);
}
static void
......
......@@ -139,29 +139,6 @@ meta_window_actor_wayland_set_frozen (MetaWindowActor *actor,
{
}
static gboolean
meta_window_actor_wayland_get_paint_volume (ClutterActor *actor,
ClutterPaintVolume *volume)
{
MetaSurfaceActor *surface;
surface = meta_window_actor_get_surface (META_WINDOW_ACTOR (actor));
if (surface)
{
ClutterActor *surface_actor = CLUTTER_ACTOR (surface);
const ClutterPaintVolume *child_volume;
child_volume = clutter_actor_get_transformed_paint_volume (surface_actor,
actor);
if (!child_volume)
return FALSE;
clutter_paint_volume_union (volume, child_volume);
}
return TRUE;
}
static void
meta_window_actor_wayland_update_regions (MetaWindowActor *actor)
{
......@@ -171,9 +148,6 @@ static void
meta_window_actor_wayland_class_init (MetaWindowActorWaylandClass *klass)
{
MetaWindowActorClass *window_actor_class = META_WINDOW_ACTOR_CLASS (klass);
ClutterActorClass *actor_class = CLUTTER_ACTOR_CLASS (klass);
actor_class->get_paint_volume = meta_window_actor_wayland_get_paint_volume;
window_actor_class->assign_surface_actor = meta_window_actor_wayland_assign_surface_actor;
window_actor_class->frame_complete = meta_window_actor_wayland_frame_complete;
......
......@@ -112,7 +112,7 @@ test_cogl_multitexture_main (int argc, char *argv[])
GError *error = NULL;
ClutterActor *stage;
ClutterColor stage_color = { 0x61, 0x56, 0x56, 0xff };
TestMultiLayerMaterialState *state = g_new0 (TestMultiLayerMaterialState, 1);
g_autofree TestMultiLayerMaterialState *state = g_new0 (TestMultiLayerMaterialState, 1);
gfloat stage_w, stage_h;
gchar **files;
gfloat tex_coords[] =
......
......@@ -427,7 +427,7 @@ test_client_new (const char *id,
MetaWindowClientType type,
GError **error)
{
TestClient *client = g_new0 (TestClient, 1);
TestClient *client;
GSubprocessLauncher *launcher;
GSubprocess *subprocess;
MetaWaylandCompositor *compositor;
......@@ -462,6 +462,7 @@ test_client_new (const char *id,
if (!subprocess)
return NULL;
client = g_new0 (TestClient, 1);
client->type = type;
client->id = g_strdup (id);
client->cancellable = g_cancellable_new ();
......
......@@ -41,7 +41,7 @@ static MetaGroup*
meta_group_new (MetaX11Display *x11_display,
Window group_leader)
{
MetaGroup *group;
g_autofree MetaGroup *group = NULL;
#define N_INITIAL_PROPS 3
Atom initial_props[N_INITIAL_PROPS];
int i;
......@@ -91,7 +91,7 @@ meta_group_new (MetaX11Display *x11_display,
"Created new group with leader 0x%lx\n",
group->group_leader);
return group;
return g_steal_pointer (&group);
}
static void
......
......@@ -127,6 +127,7 @@ struct _MetaX11Display
struct {
Window xwindow;
guint timeout_id;
MetaSelectionSource *owners[META_N_SELECTION_TYPES];
GCancellable *cancellables[META_N_SELECTION_TYPES];
......
......@@ -79,18 +79,49 @@ static GBytes *
mimetypes_to_bytes (GList *mimetypes,
Display *xdisplay)
{
gint i = 0, len = g_list_length (mimetypes) + 2;
Atom *atoms = g_new0 (Atom, len);
GArray *atoms = g_array_new (FALSE, FALSE, sizeof (Atom));
GList *l;
char *mimetype;
Atom atom;
gboolean utf8_string_found = FALSE, utf8_string_mimetype_found = FALSE;
gboolean string_found = FALSE, string_mimetype_found = FALSE;
GBytes *bytes;
for (l = mimetypes; l; l = l->next)
atoms[i++] = XInternAtom (xdisplay, l->data, False);
{
mimetype = l->data;
atom = XInternAtom (xdisplay, mimetype, False);
g_array_append_val (atoms, atom);
utf8_string_mimetype_found |= strcmp (mimetype, UTF8_STRING_MIMETYPE) == 0;
utf8_string_found |= strcmp (mimetype, "UTF8_STRING") == 0;
string_mimetype_found |= strcmp (mimetype, STRING_MIMETYPE) == 0;
string_found |= strcmp (mimetype, "STRING") == 0;
}
/* Some X11 clients can only handle STRING/UTF8_STRING but not the
* corresponding mimetypes. */
if (utf8_string_mimetype_found && !utf8_string_found)
{
atom = XInternAtom (xdisplay, "UTF8_STRING", False);
g_array_append_val (atoms, atom);
}
atoms[i++] = XInternAtom (xdisplay, "TARGETS", False);
atoms[i++] = XInternAtom (xdisplay, "TIMESTAMP", False);
g_assert (i == len);
if (string_mimetype_found && !string_found)
{
atom = XInternAtom (xdisplay, "STRING", False);
g_array_append_val (atoms, atom);
}
atom = XInternAtom (xdisplay, "TARGETS", False);
g_array_append_val (atoms, atom);
return g_bytes_new_take (atoms, len * sizeof (Atom));
atom = XInternAtom (xdisplay, "TIMESTAMP", False);
g_array_append_val (atoms, atom);
bytes = g_bytes_new_take (atoms->data, atoms->len * sizeof (Atom));
g_array_free (atoms, FALSE);
return bytes;
}
static void
......@@ -311,6 +342,22 @@ source_new_cb (GObject *object,
g_free (data);
}
static gboolean
unset_clipboard_owner (gpointer data)
{
MetaDisplay *display = meta_get_display ();
MetaSelection *selection = meta_display_get_selection (display);
MetaX11Display *x11_display = meta_display_get_x11_display (display);
meta_selection_unset_owner (selection, META_SELECTION_CLIPBOARD,
x11_display->selection.owners[META_SELECTION_CLIPBOARD]);
g_clear_object (&x11_display->selection.owners[META_SELECTION_CLIPBOARD]);
x11_display->selection.timeout_id = 0;
return G_SOURCE_REMOVE;
}
static gboolean
meta_x11_selection_handle_xfixes_selection_notify (MetaX11Display *x11_display,
XEvent *xevent)
......@@ -325,6 +372,9 @@ meta_x11_selection_handle_xfixes_selection_notify (MetaX11Display *x11_display,
selection = meta_display_get_selection (meta_get_display ());
if (selection_type == META_SELECTION_CLIPBOARD)
g_clear_handle_id (&x11_display->selection.timeout_id, g_source_remove);
if (x11_display->selection.cancellables[selection_type])
{
g_cancellable_cancel (x11_display->selection.cancellables[selection_type]);
......@@ -345,6 +395,19 @@ meta_x11_selection_handle_xfixes_selection_notify (MetaX11Display *x11_display,
meta_selection_set_owner (selection, selection_type, source);
g_object_unref (source);
}
else if (event->subtype == XFixesSelectionWindowDestroyNotify &&
selection_type == META_SELECTION_CLIPBOARD)
{
/* Selection window might have gotten destroyed as part of application
* shutdown. Trigger restoring clipboard, but wait a bit, because some
* clients, like wine, destroy the old window immediately before a new
* selection. Restoring the clipboard in this case would overwrite the
* new selection, so this will be cancelled when a new selection
* arrives. */
x11_display->selection.timeout_id = g_timeout_add (10,
unset_clipboard_owner,
NULL);
}
else
{
/* An X client went away, clear the selection */
......@@ -422,6 +485,7 @@ meta_x11_selection_init (MetaX11Display *x11_display)
attributes.event_mask = PropertyChangeMask | SubstructureNotifyMask;
attributes.override_redirect = True;
x11_display->selection.timeout_id = 0;
x11_display->selection.xwindow =
XCreateWindow (x11_display->xdisplay,
x11_display->xroot,
......@@ -482,4 +546,6 @@ meta_x11_selection_shutdown (MetaX11Display *x11_display)
XDestroyWindow (x11_display->xdisplay, x11_display->selection.xwindow);
x11_display->selection.xwindow = None;
}
g_clear_handle_id (&x11_display->selection.timeout_id, g_source_remove);
}