Compare commits
22 Commits
3.36.4
...
gnome-3-36
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d2747a1288 | ||
|
|
32d130ddf0 | ||
|
|
7d061a06de | ||
|
|
e3b213f9d7 | ||
|
|
eea81807ee | ||
|
|
fdb76593d0 | ||
|
|
143771441f | ||
|
|
52a6b5df5f | ||
|
|
299569c3b8 | ||
|
|
3dab5120ed | ||
|
|
eae21f01dd | ||
|
|
4d8538d6a9 | ||
|
|
ef3dac7064 | ||
|
|
1fd53c480f | ||
|
|
0c6ac287e6 | ||
|
|
e8052f169b | ||
|
|
449fa7bf81 | ||
|
|
2d899596e2 | ||
|
|
cf88d64882 | ||
|
|
92db8902d9 | ||
|
|
b1d45820ef | ||
|
|
d07335cd4c |
15
NEWS
15
NEWS
@@ -1,3 +1,18 @@
|
||||
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;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
project('mutter', 'c',
|
||||
version: '3.36.4',
|
||||
version: '3.36.5',
|
||||
meson_version: '>= 0.50.0',
|
||||
license: 'GPLv2+'
|
||||
)
|
||||
|
||||
@@ -12,7 +12,7 @@ option('opengl_libname',
|
||||
|
||||
option('gles2_libname',
|
||||
type: 'string',
|
||||
value: 'libGLESv2.so',
|
||||
value: 'libGLESv2.so.2',
|
||||
description: 'GLESv2 library file name'
|
||||
)
|
||||
|
||||
|
||||
68
po/pt_BR.po
68
po/pt_BR.po
@@ -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->blit_to_framebuffer (src, framebuffer);
|
||||
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);
|
||||
|
||||
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;
|
||||
|
||||
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)
|
||||
g_clear_handle_id (&priv->follow_up_frame_source_id, g_source_remove);
|
||||
if (do_record_frame (src, spa_buffer, data, &error))
|
||||
{
|
||||
if (meta_screen_cast_stream_src_get_videocrop (src, &crop_rect))
|
||||
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;
|
||||
|
||||
/* 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 = 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;
|
||||
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 ();
|
||||
|
||||
@@ -275,7 +275,8 @@ meta_wayland_subsurface_notify_subsurface_state_changed (MetaWaylandSurfaceRole
|
||||
meta_wayland_surface_role_get_surface (surface_role);
|
||||
MetaWaylandSurface *parent = surface->sub.parent;
|
||||
|
||||
return meta_wayland_surface_notify_subsurface_state_changed (parent);
|
||||
if (parent)
|
||||
return meta_wayland_surface_notify_subsurface_state_changed (parent);
|
||||
}
|
||||
|
||||
static double
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
atoms[i++] = XInternAtom (xdisplay, "TARGETS", False);
|
||||
atoms[i++] = XInternAtom (xdisplay, "TIMESTAMP", False);
|
||||
g_assert (i == len);
|
||||
/* 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);
|
||||
}
|
||||
|
||||
return g_bytes_new_take (atoms, len * sizeof (Atom));
|
||||
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);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user