Compare commits

..

2 Commits

Author SHA1 Message Date
Carlos Garnacho
2cf9249d2b x11: Fix race conditions in XSetSelection
Some clients like X11 LibreOffice clear the selection prior to copying
some content there. This selection clear is correctly seen by our clipboard
manager as a hint to take ownership and preserve the last copied content,
all while LO is issuing other XSetSelection with the new clipboard content.

Our use of META_CURRENT_TIME turns this into a race condition, as there's
both LO and our clipboard manager trying to do XSetSelection(), from our
side it's all up to the order in which the requests arrive to the X server.

In order to break the tie, keep the selection timestamp from the XFixes
event (i.e. the timestamp set by the XSetSelection external call that is
unsetting the clipboard) and ensure it is used for our own XSetSelection
call replacing the selection. In this same situation, it will make the
X server deem the request too old, and let LO win.

If the compositor-side XSetSelection event does not happen in result to
a XFixes selection notify event, the current event time will be used, and
META_CURRENT_TIME as a last resort.

Closes: https://gitlab.gnome.org/GNOME/mutter/-/issues/1113

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1205
2020-04-17 14:37:33 +02:00
Carlos Garnacho
f988a9caaa x11: Clear X11 selection source after unsetting owner
The X11 selection source was being preserved after unsetting its
ownership. This is no leak as it would be eventually replaced by
another source, or destroyed on finalize. But it's pointless to
keep it.

https://gitlab.gnome.org/GNOME/mutter/-/merge_requests/1205
2020-04-17 14:37:30 +02:00
50 changed files with 193 additions and 2270 deletions

33
NEWS
View File

@@ -1,36 +1,3 @@
3.37.1
======
* Fix screencasting non-maximized windows [Jonas Å.; !1174]
* Make window-aliveness checks less aggressive [Jonas Å.; !1182]
* Fix stylus coordinates when using screen rotation [Jonas T.; #1118]
* Preserve keyboard state on VT switch [Olivier; !1185]
* Remove Clutter's drag and drop actions [Jonas D.; !789]
* Cancel clicks/gestures actions on disable [Georges; !1188]
* Fix various clipboard issues [Carlos; !1186, !1198, !1203, !1204, !1206]
* Fix trackball button scrolling [Phillip; #1120]
* Fix tiled monitor support [Jonas; !1199]
* Support unredirecting fullscreen wayland surfaces [Jonas Å.; !798]
* Support area screencasts [Jonas Å.; !1207]
* Synchronize shadows to server-side decorations [Olivier; !1214]
* Allow inhibiting remote access [Jonas Å.; !1212]
* Fix overview key on X11 when using multiple keyboard layouts [Olivier; !1219]
* Fixed crashes [Jonas, D., Carlos; !1173, !1183, !1012]
* Misc. bug fixes and cleanups [Andre, Georges, Christian, Jonas Å., Andre,
Simon, Florian, Carlos, Adam, Marco, Thomas, Elias, Pekka, Jonas D.,
Laurent; !1169, !1168, !1166, !1170, !1167, !1172, !1175, !1176, !1184,
!1126, !1187, !1191, !1195, !1179, !1200, !1193, !1209, !1213, !1208,
#1074, !1223]
Contributors:
Marco Trevisan (Treviño), Elias Aebi, Thomas Hindoe Paaboel Andersen,
Laurent Bigonville, Jonas Dreßler, Olivier Fourdan, Carlos Garnacho,
Adam Jackson, Andre Moreira Magalhaes, Simon McVittie, Florian Müllner,
Georges Basile Stavracas Neto, Pekka Paalanen, Christian Rauch, Jonas Troeger,
Phillip Wood, Jonas Ådahl
Translators:
Dušan Kazik [sk], Christian Kirbach [de]
3.36.0
======
* Fix placement of popup windows in multi-monitor setups [Jonas; !1110]

View File

@@ -36,9 +36,6 @@
#include "cogl/clutter-stage-cogl.h"
#include "clutter/x11/clutter-backend-x11.h"
CLUTTER_EXPORT
GList * clutter_stage_peek_stage_views (ClutterStage *stage);
CLUTTER_EXPORT
void clutter_set_custom_backend_func (ClutterBackend *(* func) (void));
@@ -51,23 +48,6 @@ void clutter_stage_capture_into (ClutterStage *stage,
cairo_rectangle_int_t *rect,
uint8_t *data);
CLUTTER_EXPORT
void clutter_stage_paint_to_framebuffer (ClutterStage *stage,
CoglFramebuffer *framebuffer,
const cairo_rectangle_int_t *rect,
float scale,
ClutterPaintFlag paint_flags);
CLUTTER_EXPORT
gboolean clutter_stage_paint_to_buffer (ClutterStage *stage,
const cairo_rectangle_int_t *rect,
float scale,
uint8_t *data,
int stride,
CoglPixelFormat format,
ClutterPaintFlag paint_flags,
GError **error);
CLUTTER_EXPORT
void clutter_stage_freeze_updates (ClutterStage *stage);

View File

@@ -21,8 +21,7 @@
#include "clutter-paint-context.h"
ClutterPaintContext * clutter_paint_context_new_for_view (ClutterStageView *view,
const cairo_region_t *redraw_clip,
ClutterPaintFlag paint_flags);
const cairo_region_t *redraw_clip);
gboolean clutter_paint_context_is_drawing_off_stage (ClutterPaintContext *paint_context);

View File

@@ -23,8 +23,6 @@ struct _ClutterPaintContext
{
grefcount ref_count;
ClutterPaintFlag paint_flags;
GList *framebuffers;
ClutterStageView *view;
@@ -38,8 +36,7 @@ G_DEFINE_BOXED_TYPE (ClutterPaintContext, clutter_paint_context,
ClutterPaintContext *
clutter_paint_context_new_for_view (ClutterStageView *view,
const cairo_region_t *redraw_clip,
ClutterPaintFlag paint_flags)
const cairo_region_t *redraw_clip)
{
ClutterPaintContext *paint_context;
CoglFramebuffer *framebuffer;
@@ -48,7 +45,6 @@ clutter_paint_context_new_for_view (ClutterStageView *view,
g_ref_count_init (&paint_context->ref_count);
paint_context->view = view;
paint_context->redraw_clip = cairo_region_copy (redraw_clip);
paint_context->paint_flags = paint_flags;
framebuffer = clutter_stage_view_get_framebuffer (view);
clutter_paint_context_push_framebuffer (paint_context, framebuffer);
@@ -60,16 +56,12 @@ clutter_paint_context_new_for_view (ClutterStageView *view,
* clutter_paint_context_new_for_framebuffer: (skip)
*/
ClutterPaintContext *
clutter_paint_context_new_for_framebuffer (CoglFramebuffer *framebuffer,
const cairo_region_t *redraw_clip,
ClutterPaintFlag paint_flags)
clutter_paint_context_new_for_framebuffer (CoglFramebuffer *framebuffer)
{
ClutterPaintContext *paint_context;
paint_context = g_new0 (ClutterPaintContext, 1);
g_ref_count_init (&paint_context->ref_count);
paint_context->redraw_clip = cairo_region_copy (redraw_clip);
paint_context->paint_flags = paint_flags;
clutter_paint_context_push_framebuffer (paint_context, framebuffer);
@@ -178,12 +170,3 @@ clutter_paint_context_is_drawing_off_stage (ClutterPaintContext *paint_context)
return !paint_context->view;
}
/**
* clutter_paint_context_get_paint_flags: (skip)
*/
ClutterPaintFlag
clutter_paint_context_get_paint_flags (ClutterPaintContext *paint_context)
{
return paint_context->paint_flags;
}

View File

@@ -29,21 +29,13 @@
typedef struct _ClutterPaintContext ClutterPaintContext;
typedef enum _ClutterPaintFlag
{
CLUTTER_PAINT_FLAG_NONE = 0,
CLUTTER_PAINT_FLAG_NO_CURSORS = 1 << 0,
} ClutterPaintFlag;
#define CLUTTER_TYPE_PAINT_CONTEXT (clutter_paint_context_get_type ())
CLUTTER_EXPORT
GType clutter_paint_context_get_type (void);
CLUTTER_EXPORT
ClutterPaintContext * clutter_paint_context_new_for_framebuffer (CoglFramebuffer *framebuffer,
const cairo_region_t *redraw_clip,
ClutterPaintFlag paint_flags);
ClutterPaintContext * clutter_paint_context_new_for_framebuffer (CoglFramebuffer *framebuffer);
CLUTTER_EXPORT
ClutterPaintContext * clutter_paint_context_ref (ClutterPaintContext *paint_context);
@@ -70,7 +62,4 @@ void clutter_paint_context_pop_framebuffer (ClutterPaintContext *paint_context);
CLUTTER_EXPORT
const cairo_region_t * clutter_paint_context_get_redraw_clip (ClutterPaintContext *paint_context);
CLUTTER_EXPORT
ClutterPaintFlag clutter_paint_context_get_paint_flags (ClutterPaintContext *paint_context);
#endif /* CLUTTER_PAINT_CONTEXT_H */

View File

@@ -139,6 +139,8 @@ void _clutter_stage_presented (ClutterStage *stag
CoglFrameEvent frame_event,
ClutterFrameInfo *frame_info);
GList * _clutter_stage_peek_stage_views (ClutterStage *stage);
void clutter_stage_queue_actor_relayout (ClutterStage *stage,
ClutterActor *actor);

View File

@@ -552,7 +552,7 @@ clutter_stage_add_redraw_clip (ClutterStage *stage,
{
GList *l;
for (l = clutter_stage_peek_stage_views (stage); l; l = l->next)
for (l = _clutter_stage_peek_stage_views (stage); l; l = l->next)
{
ClutterStageView *view = l->data;
@@ -924,8 +924,7 @@ clutter_stage_do_paint_view (ClutterStage *stage,
ClutterPaintContext *paint_context;
cairo_rectangle_int_t clip_rect;
paint_context = clutter_paint_context_new_for_view (view, redraw_clip,
CLUTTER_PAINT_FLAG_NONE);
paint_context = clutter_paint_context_new_for_view (view, redraw_clip);
cairo_region_get_extents (redraw_clip, &clip_rect);
setup_view_for_pick_or_paint (stage, view, &clip_rect);
@@ -1573,7 +1572,7 @@ is_full_stage_redraw_queued (ClutterStage *stage)
{
GList *l;
for (l = clutter_stage_peek_stage_views (stage); l; l = l->next)
for (l = _clutter_stage_peek_stage_views (stage); l; l = l->next)
{
ClutterStageView *view = l->data;
@@ -4164,97 +4163,6 @@ clutter_stage_get_capture_final_size (ClutterStage *stage,
return TRUE;
}
void
clutter_stage_paint_to_framebuffer (ClutterStage *stage,
CoglFramebuffer *framebuffer,
const cairo_rectangle_int_t *rect,
float scale,
ClutterPaintFlag paint_flags)
{
ClutterStagePrivate *priv = stage->priv;
ClutterPaintContext *paint_context;
cairo_region_t *redraw_clip;
redraw_clip = cairo_region_create_rectangle (rect);
paint_context =
clutter_paint_context_new_for_framebuffer (framebuffer,
redraw_clip,
paint_flags);
cairo_region_destroy (redraw_clip);
cogl_framebuffer_push_matrix (framebuffer);
cogl_framebuffer_set_projection_matrix (framebuffer, &priv->projection);
cogl_framebuffer_set_viewport (framebuffer,
-(rect->x * scale),
-(rect->y * scale),
priv->viewport[2] * scale,
priv->viewport[3] * scale);
clutter_actor_paint (CLUTTER_ACTOR (stage), paint_context);
cogl_framebuffer_pop_matrix (framebuffer);
clutter_paint_context_destroy (paint_context);
}
gboolean
clutter_stage_paint_to_buffer (ClutterStage *stage,
const cairo_rectangle_int_t *rect,
float scale,
uint8_t *data,
int stride,
CoglPixelFormat format,
ClutterPaintFlag paint_flags,
GError **error)
{
ClutterBackend *clutter_backend = clutter_get_default_backend ();
CoglContext *cogl_context =
clutter_backend_get_cogl_context (clutter_backend);
int texture_width, texture_height;
CoglTexture2D *texture;
CoglOffscreen *offscreen;
CoglFramebuffer *framebuffer;
CoglBitmap *bitmap;
texture_width = (int) ceilf (rect->width * scale);
texture_height = (int) ceilf (rect->height * scale);
texture = cogl_texture_2d_new_with_size (cogl_context,
texture_width,
texture_height);
if (!texture)
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Failed to create %dx%d texture",
texture_width, texture_height);
return FALSE;
}
offscreen = cogl_offscreen_new_with_texture (COGL_TEXTURE (texture));
framebuffer = COGL_FRAMEBUFFER (offscreen);
cogl_object_unref (texture);
if (!cogl_framebuffer_allocate (framebuffer, error))
return FALSE;
clutter_stage_paint_to_framebuffer (stage, framebuffer,
rect, scale, paint_flags);
bitmap = cogl_bitmap_new_for_data (cogl_context,
texture_width, texture_height,
format,
stride,
data);
cogl_framebuffer_read_pixels_into_bitmap (framebuffer,
0, 0,
COGL_READ_PIXELS_COLOR_BUFFER,
bitmap);
cogl_object_unref (bitmap);
cogl_object_unref (framebuffer);
return TRUE;
}
static void
capture_view_into (ClutterStage *stage,
gboolean paint,
@@ -4402,11 +4310,8 @@ clutter_stage_thaw_updates (ClutterStage *stage)
}
}
/**
* clutter_stage_peek_stage_views: (skip)
*/
GList *
clutter_stage_peek_stage_views (ClutterStage *stage)
_clutter_stage_peek_stage_views (ClutterStage *stage)
{
ClutterStagePrivate *priv = stage->priv;

View File

@@ -375,11 +375,15 @@ static gboolean
swap_framebuffer (ClutterStageWindow *stage_window,
ClutterStageView *view,
cairo_region_t *swap_region,
gboolean swap_with_damage)
gboolean swap_with_damage,
cairo_region_t *queued_redraw_clip)
{
CoglFramebuffer *framebuffer = clutter_stage_view_get_onscreen (view);
int *damage, n_rects, i;
if (G_UNLIKELY ((clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION)))
paint_damage_region (stage_window, view, swap_region, queued_redraw_clip);
n_rects = cairo_region_num_rectangles (swap_region);
damage = g_newa (int, n_rects * 4);
for (i = 0; i < n_rects; i++)
@@ -616,7 +620,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
gboolean swap_with_damage;
ClutterActor *wrapper;
cairo_region_t *redraw_clip;
cairo_region_t *queued_redraw_clip = NULL;
cairo_region_t *queued_redraw_clip;
cairo_region_t *fb_clip_region;
cairo_region_t *swap_region;
cairo_rectangle_int_t redraw_rect;
@@ -640,8 +644,6 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
has_buffer_age = cogl_is_onscreen (fb) && is_buffer_age_enabled ();
redraw_clip = clutter_stage_view_take_redraw_clip (view);
if (G_UNLIKELY (clutter_paint_debug_flags & CLUTTER_DEBUG_PAINT_DAMAGE_REGION))
queued_redraw_clip = cairo_region_copy (redraw_clip);
/* NB: a NULL redraw clip == full stage redraw */
if (!redraw_clip)
@@ -709,6 +711,8 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
redraw_clip = cairo_region_create_rectangle (&view_rect);
}
queued_redraw_clip = cairo_region_copy (redraw_clip);
if (may_use_clipped_redraw &&
G_LIKELY (!(clutter_paint_debug_flags & CLUTTER_DEBUG_DISABLE_CLIPPED_REDRAWS)))
use_clipped_redraw = TRUE;
@@ -918,6 +922,7 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
}
g_clear_pointer (&redraw_clip, cairo_region_destroy);
g_clear_pointer (&queued_redraw_clip, cairo_region_destroy);
g_clear_pointer (&fb_clip_region, cairo_region_destroy);
if (do_swap_buffer)
@@ -938,17 +943,11 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
swap_region = transformed_swap_region;
}
if (queued_redraw_clip)
{
paint_damage_region (stage_window, view,
swap_region, queued_redraw_clip);
cairo_region_destroy (queued_redraw_clip);
}
res = swap_framebuffer (stage_window,
view,
swap_region,
swap_with_damage);
swap_with_damage,
queued_redraw_clip);
cairo_region_destroy (swap_region);
@@ -956,7 +955,6 @@ clutter_stage_cogl_redraw_view (ClutterStageWindow *stage_window,
}
else
{
g_clear_pointer (&queued_redraw_clip, cairo_region_destroy);
return FALSE;
}
}

View File

@@ -70,12 +70,3 @@
/* Whether Xwayland has -initfd option */
#mesondefine HAVE_XWAYLAND_INITFD
/* Whether the mkostemp function exists */
#mesondefine HAVE_MKOSTEMP
/* Whether the posix_fallocate function exists */
#mesondefine HAVE_POSIX_FALLOCATE
/* Whether the memfd_create function exists */
#mesondefine HAVE_MEMFD_CREATE

View File

@@ -1,5 +1,5 @@
project('mutter', 'c',
version: '3.37.1',
version: '3.37.0',
meson_version: '>= 0.50.0',
license: 'GPLv2+'
)
@@ -408,20 +408,6 @@ if have_wayland
endif
endif
optional_functions = [
'mkostemp',
'posix_fallocate',
'memfd_create',
]
foreach function : optional_functions
if cc.has_function(function)
cdata.set('HAVE_' + function.to_upper(), 1)
else
message('Optional function ' + function + ' missing')
endif
endforeach
xwayland_grab_default_access_rules = get_option('xwayland_grab_default_access_rules')
cdata.set_quoted('XWAYLAND_GRAB_DEFAULT_ACCESS_RULES',
xwayland_grab_default_access_rules)

View File

@@ -13,8 +13,8 @@ msgid ""
msgstr ""
"Project-Id-Version: mutter master\n"
"Report-Msgid-Bugs-To: https://gitlab.gnome.org/GNOME/mutter/issues\n"
"POT-Creation-Date: 2020-03-30 20:11+0000\n"
"PO-Revision-Date: 2020-04-06 23:13+0200\n"
"POT-Creation-Date: 2019-08-06 00:49+0000\n"
"PO-Revision-Date: 2019-09-05 23:42+0200\n"
"Last-Translator: Christian Kirbach <christian.kirbach@gmail.com>\n"
"Language-Team: Deutsch <gnome-de@gnome.org>\n"
"Language: de\n"
@@ -22,7 +22,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: Poedit 2.3\n"
"X-Generator: Poedit 2.2.1\n"
#: data/50-mutter-navigation.xml:6
msgid "Navigation"
@@ -435,33 +435,20 @@ msgstr "Zusatztaste zum Finden des Zeigers"
msgid "This key will initiate the “locate pointer” action."
msgstr "Diese Taste wird die Aktion »Zeiger finden« auslösen."
#: data/org.gnome.mutter.gschema.xml.in:142
msgid "Timeout for check-alive ping"
msgstr "Reaktionsschwellwert bei Kontaktkontrolle"
#: data/org.gnome.mutter.gschema.xml.in:143
msgid ""
"Number of milliseconds a client has to respond to a ping request in order to "
"not be detected as frozen. Using 0 will disable the alive check completely."
msgstr ""
"Zeit in Millisekunden, innerhalb welcher ein Client auf eine "
"Kontaktkontrolle antworten muss, um nicht als abgestürzt zu gelten. »0« "
"bedeutet, dass die Kontaktkontrolle ausgeschaltet wird."
#: data/org.gnome.mutter.gschema.xml.in:165
#: data/org.gnome.mutter.gschema.xml.in:155
msgid "Select window from tab popup"
msgstr "Fenster aus Tab-Anzeige auswählen"
#: data/org.gnome.mutter.gschema.xml.in:170
#: data/org.gnome.mutter.gschema.xml.in:160
msgid "Cancel tab popup"
msgstr "Tab-Anzeige abbrechen"
#: data/org.gnome.mutter.gschema.xml.in:175
#: data/org.gnome.mutter.gschema.xml.in:165
msgid "Switch monitor configurations"
msgstr "Bildschirmkonfigurationen wechseln"
# Ich denke nicht, dass »rotate« hier die Bildschirmdrehung meint, sondern eher eine Liste aus Konfigurationen rotiert (d.h. umgewälzt) wird.
#: data/org.gnome.mutter.gschema.xml.in:180
#: data/org.gnome.mutter.gschema.xml.in:170
msgid "Rotates the built-in monitor configuration"
msgstr "Wechselt die Konfiguration des eingebauten Bildschirms"
@@ -582,7 +569,7 @@ msgstr ""
#. TRANSLATORS: This string refers to a button that switches between
#. * different modes.
#.
#: src/backends/meta-input-settings.c:2631
#: src/backends/meta-input-settings.c:2531
#, c-format
msgid "Mode Switch (Group %d)"
msgstr "Moduswechsel (Gruppe %d)"
@@ -590,34 +577,34 @@ msgstr "Moduswechsel (Gruppe %d)"
#. TRANSLATORS: This string refers to an action, cycles drawing tablets'
#. * mapping through the available outputs.
#.
#: src/backends/meta-input-settings.c:2654
#: src/backends/meta-input-settings.c:2554
msgid "Switch monitor"
msgstr "Bildschirm wechseln"
#: src/backends/meta-input-settings.c:2656
#: src/backends/meta-input-settings.c:2556
msgid "Show on-screen help"
msgstr "Bildschirmhilfe anzeigen"
#: src/backends/meta-monitor.c:226
#: src/backends/meta-monitor.c:223
msgid "Built-in display"
msgstr "Eingebaute Anzeige"
#: src/backends/meta-monitor.c:255
#: src/backends/meta-monitor.c:252
msgid "Unknown"
msgstr "Unbekannt"
#: src/backends/meta-monitor.c:257
#: src/backends/meta-monitor.c:254
msgid "Unknown Display"
msgstr "Unbekannte Anzeige"
#: src/backends/meta-monitor.c:265
#: src/backends/meta-monitor.c:262
#, 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:273
#: src/backends/meta-monitor.c:270
#, c-format
msgctxt ""
"This is a monitor vendor name followed by product/model name where size in "
@@ -627,13 +614,13 @@ msgstr "%s %s"
# https://de.wikipedia.org/wiki/Composition-Manager
#. Translators: this string will appear in Sysprof
#: src/backends/meta-profiler.c:79
#: src/backends/meta-profiler.c:82
msgid "Compositor"
msgstr "Compositor"
#. This probably means that a non-WM compositor like xcompmgr is running;
#. * we have no way to get it to exit
#: src/compositor/compositor.c:533
#: src/compositor/compositor.c:510
#, c-format
msgid ""
"Another compositing manager is already running on screen %i on display “%s”."
@@ -645,47 +632,47 @@ msgstr ""
msgid "Bell event"
msgstr "Klangereignis"
#: src/core/main.c:190
#: src/core/main.c:185
msgid "Disable connection to session manager"
msgstr "Verbindung zur Sitzungsverwaltung deaktivieren"
#: src/core/main.c:196
#: src/core/main.c:191
msgid "Replace the running window manager"
msgstr "Den aktuellen Fensterverwalter ersetzen"
#: src/core/main.c:202
#: src/core/main.c:197
msgid "Specify session management ID"
msgstr "Kennung der Sitzungsverwaltung angeben"
#: src/core/main.c:207
#: src/core/main.c:202
msgid "X Display to use"
msgstr "Zu verwendende X-Anzeige"
#: src/core/main.c:213
#: src/core/main.c:208
msgid "Initialize session from savefile"
msgstr "Sitzung anhand gespeicherter Datei starten"
#: src/core/main.c:219
#: src/core/main.c:214
msgid "Make X calls synchronous"
msgstr "X-Aufrufe abgleichen"
#: src/core/main.c:226
#: src/core/main.c:221
msgid "Run as a wayland compositor"
msgstr "Als Wayland-Compositor ausführen"
#: src/core/main.c:232
#: src/core/main.c:227
msgid "Run as a nested compositor"
msgstr "Als eingebetteten Compositor ausführen"
#: src/core/main.c:238
#: src/core/main.c:233
msgid "Run wayland compositor without starting Xwayland"
msgstr "Wayland-Compositor ausführen, ohne Xwayland zu starten"
#: src/core/main.c:246
#: src/core/main.c:241
msgid "Run as a full display server, rather than nested"
msgstr "Als vollwertigen Display-Server verwenden (nicht eingebettet)"
#: src/core/main.c:252
#: src/core/main.c:247
msgid "Run with X11 backend"
msgstr "Mit X11-Backend ausführen"
@@ -741,21 +728,21 @@ msgstr "Version ausgeben"
msgid "Mutter plugin to use"
msgstr "Zu benutzendes Mutter-Plugin"
#: src/core/prefs.c:1911
#: src/core/prefs.c:1849
#, c-format
msgid "Workspace %d"
msgstr "Arbeitsfläche %d"
#: src/core/util.c:122
#: src/core/util.c:121
msgid "Mutter was compiled without support for verbose mode\n"
msgstr "Mutter wurde ohne Unterstützung für den redseligen Modus kompiliert\n"
#: src/wayland/meta-wayland-tablet-pad.c:568
#: src/wayland/meta-wayland-tablet-pad.c:567
#, c-format
msgid "Mode Switch: Mode %d"
msgstr "Moduswechsel: Modus %d"
#: src/x11/meta-x11-display.c:676
#: src/x11/meta-x11-display.c:671
#, c-format
msgid ""
"Display “%s” already has a window manager; try using the --replace option to "
@@ -764,21 +751,21 @@ msgstr ""
"Bildschirm »%s« hat bereits einen Fensterverwalter. Versuchen Sie die Option "
"»--replace«, um den aktuellen Fensterverwalter zu ersetzen."
#: src/x11/meta-x11-display.c:1089
#: src/x11/meta-x11-display.c:1032
msgid "Failed to initialize GDK\n"
msgstr "GDK konnte nicht initialisiert werden\n"
#: src/x11/meta-x11-display.c:1113
#: src/x11/meta-x11-display.c:1056
#, c-format
msgid "Failed to open X Window System display “%s”\n"
msgstr "X-Window-Systemanzeige »%s« konnte nicht geöffnet werden\n"
#: src/x11/meta-x11-display.c:1196
#: src/x11/meta-x11-display.c:1140
#, c-format
msgid "Screen %d on display “%s” is invalid\n"
msgstr "Bildschirm %d auf Anzeige »%s« ist ungültig\n"
#: src/x11/meta-x11-selection-input-stream.c:460
#: src/x11/meta-x11-selection-input-stream.c:445
#, c-format
msgid "Format %s not supported"
msgstr "Format %s wird nicht unterstützt"

View File

@@ -49,7 +49,6 @@ typedef struct _MetaTileInfo MetaTileInfo;
typedef struct _MetaRenderer MetaRenderer;
typedef struct _MetaRendererView MetaRendererView;
typedef struct _MetaRemoteDesktop MetaRemoteDesktop;
typedef struct _MetaScreenCast MetaScreenCast;
typedef struct _MetaScreenCastSession MetaScreenCastSession;
typedef struct _MetaScreenCastStream MetaScreenCastStream;

View File

@@ -552,12 +552,12 @@ meta_backend_real_post_init (MetaBackend *backend)
}
#ifdef HAVE_REMOTE_DESKTOP
priv->remote_access_controller =
g_object_new (META_TYPE_REMOTE_ACCESS_CONTROLLER, NULL);
priv->dbus_session_watcher = g_object_new (META_TYPE_DBUS_SESSION_WATCHER, NULL);
priv->screen_cast = meta_screen_cast_new (backend,
priv->dbus_session_watcher);
priv->remote_desktop = meta_remote_desktop_new (priv->dbus_session_watcher);
priv->remote_access_controller =
meta_remote_access_controller_new (priv->remote_desktop, priv->screen_cast);
#endif /* HAVE_REMOTE_DESKTOP */
if (!meta_monitor_manager_is_headless (priv->monitor_manager))
@@ -809,6 +809,9 @@ static MetaMonitorManager *
meta_backend_create_monitor_manager (MetaBackend *backend,
GError **error)
{
if (g_getenv ("META_DUMMY_MONITORS"))
return g_object_new (META_TYPE_MONITOR_MANAGER_DUMMY, NULL);
return META_BACKEND_GET_CLASS (backend)->create_monitor_manager (backend,
error);
}

View File

@@ -54,8 +54,8 @@ meta_input_device_init (MetaInputDevice *input_device)
static void
meta_input_device_constructed (GObject *object)
{
MetaInputDevice *input_device = META_INPUT_DEVICE (object);
#ifdef HAVE_LIBWACOM
MetaInputDevice *input_device;
WacomDeviceDatabase *wacom_db;
MetaInputDevicePrivate *priv;
const char *node;
@@ -64,7 +64,6 @@ meta_input_device_constructed (GObject *object)
G_OBJECT_CLASS (meta_input_device_parent_class)->constructed (object);
#ifdef HAVE_LIBWACOM
input_device = META_INPUT_DEVICE (object);
priv = meta_input_device_get_instance_private (input_device);
wacom_db = meta_backend_get_wacom_database (meta_get_backend ());
node = clutter_input_device_get_device_node (CLUTTER_INPUT_DEVICE (input_device));

View File

@@ -21,12 +21,8 @@
#ifndef META_REMOTE_ACCESS_CONTROLLER_PRIVATE_H
#define META_REMOTE_ACCESS_CONTROLLER_PRIVATE_H
#include "backends/meta-backend-types.h"
#include "meta/meta-remote-access-controller.h"
MetaRemoteAccessController * meta_remote_access_controller_new (MetaRemoteDesktop *remote_desktop,
MetaScreenCast *screen_cast);
void meta_remote_access_controller_notify_new_handle (MetaRemoteAccessController *controller,
MetaRemoteAccessHandle *handle);

View File

@@ -22,11 +22,6 @@
#include "backends/meta-remote-access-controller-private.h"
#ifdef HAVE_REMOTE_DESKTOP
#include "backends/meta-remote-desktop.h"
#include "backends/meta-screen-cast.h"
#endif
enum
{
HANDLE_STOPPED,
@@ -59,9 +54,6 @@ G_DEFINE_TYPE_WITH_PRIVATE (MetaRemoteAccessHandle,
struct _MetaRemoteAccessController
{
GObject parent;
MetaRemoteDesktop *remote_desktop;
MetaScreenCast *screen_cast;
};
G_DEFINE_TYPE (MetaRemoteAccessController,
@@ -130,53 +122,6 @@ meta_remote_access_controller_notify_new_handle (MetaRemoteAccessController *con
handle);
}
/**
* meta_remote_access_controller_inhibit_remote_access:
* @controller: a #MetaRemoteAccessController
*
* Inhibits remote access sessions from being created and running. Any active
* remote access session will be terminated.
*/
void
meta_remote_access_controller_inhibit_remote_access (MetaRemoteAccessController *controller)
{
#ifdef HAVE_REMOTE_DESKTOP
meta_remote_desktop_inhibit (controller->remote_desktop);
meta_screen_cast_inhibit (controller->screen_cast);
#endif
}
/**
* meta_remote_access_controller_uninhibit_remote_access:
* @controller: a #MetaRemoteAccessController
*
* Uninhibits remote access sessions from being created and running. If this was
* the last inhibitation that was inhibited, new remote access sessions can now
* be created.
*/
void
meta_remote_access_controller_uninhibit_remote_access (MetaRemoteAccessController *controller)
{
#ifdef HAVE_REMOTE_DESKTOP
meta_screen_cast_uninhibit (controller->screen_cast);
meta_remote_desktop_uninhibit (controller->remote_desktop);
#endif
}
MetaRemoteAccessController *
meta_remote_access_controller_new (MetaRemoteDesktop *remote_desktop,
MetaScreenCast *screen_cast)
{
MetaRemoteAccessController *remote_access_controller;
remote_access_controller = g_object_new (META_TYPE_REMOTE_ACCESS_CONTROLLER,
NULL);
remote_access_controller->remote_desktop = remote_desktop;
remote_access_controller->screen_cast = screen_cast;
return remote_access_controller;
}
static void
meta_remote_access_handle_init (MetaRemoteAccessHandle *handle)
{

View File

@@ -56,8 +56,6 @@ struct _MetaRemoteDesktop
int dbus_name_id;
int inhibit_count;
GHashTable *sessions;
MetaDbusSessionWatcher *session_watcher;
@@ -72,34 +70,6 @@ G_DEFINE_TYPE_WITH_CODE (MetaRemoteDesktop,
G_IMPLEMENT_INTERFACE (META_DBUS_TYPE_REMOTE_DESKTOP,
meta_remote_desktop_init_iface));
void
meta_remote_desktop_inhibit (MetaRemoteDesktop *remote_desktop)
{
remote_desktop->inhibit_count++;
if (remote_desktop->inhibit_count == 1)
{
GHashTableIter iter;
gpointer key, value;
g_hash_table_iter_init (&iter, remote_desktop->sessions);
while (g_hash_table_iter_next (&iter, &key, &value))
{
MetaRemoteDesktopSession *session = value;
g_hash_table_iter_steal (&iter);
meta_remote_desktop_session_close (session);
}
}
}
void
meta_remote_desktop_uninhibit (MetaRemoteDesktop *remote_desktop)
{
g_return_if_fail (remote_desktop->inhibit_count > 0);
remote_desktop->inhibit_count--;
}
GDBusConnection *
meta_remote_desktop_get_connection (MetaRemoteDesktop *remote_desktop)
{
@@ -138,15 +108,6 @@ handle_create_session (MetaDBusRemoteDesktop *skeleton,
char *session_path;
const char *client_dbus_name;
if (remote_desktop->inhibit_count > 0)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Session creation inhibited");
return TRUE;
}
peer_name = g_dbus_method_invocation_get_sender (invocation);
session = meta_remote_desktop_session_new (remote_desktop,
peer_name,

View File

@@ -36,10 +36,6 @@ G_DECLARE_FINAL_TYPE (MetaRemoteDesktop, meta_remote_desktop,
META, REMOTE_DESKTOP,
MetaDBusRemoteDesktopSkeleton)
void meta_remote_desktop_inhibit (MetaRemoteDesktop *remote_desktop);
void meta_remote_desktop_uninhibit (MetaRemoteDesktop *remote_desktop);
MetaRemoteDesktopSession * meta_remote_desktop_get_session (MetaRemoteDesktop *remote_desktop,
const char *session_id);

View File

@@ -1,570 +0,0 @@
/*
* Copyright (C) 2020 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
*/
#include "config.h"
#include "backends/meta-screen-cast-area-stream-src.h"
#include <spa/buffer/meta.h>
#include "backends/meta-backend-private.h"
#include "backends/meta-cursor-tracker-private.h"
#include "backends/meta-screen-cast-area-stream.h"
#include "backends/meta-screen-cast-session.h"
#include "backends/meta-stage-private.h"
#include "clutter/clutter.h"
#include "clutter/clutter-mutter.h"
#include "core/boxes-private.h"
struct _MetaScreenCastAreaStreamSrc
{
MetaScreenCastStreamSrc parent;
gboolean cursor_bitmap_invalid;
gboolean hw_cursor_inhibited;
GList *watches;
gulong cursor_moved_handler_id;
gulong cursor_changed_handler_id;
guint maybe_record_idle_id;
};
static void
hw_cursor_inhibitor_iface_init (MetaHwCursorInhibitorInterface *iface);
G_DEFINE_TYPE_WITH_CODE (MetaScreenCastAreaStreamSrc,
meta_screen_cast_area_stream_src,
META_TYPE_SCREEN_CAST_STREAM_SRC,
G_IMPLEMENT_INTERFACE (META_TYPE_HW_CURSOR_INHIBITOR,
hw_cursor_inhibitor_iface_init))
static ClutterStage *
get_stage (MetaScreenCastAreaStreamSrc *area_src)
{
MetaScreenCastStreamSrc *src;
MetaScreenCastStream *stream;
MetaScreenCastAreaStream *area_stream;
src = META_SCREEN_CAST_STREAM_SRC (area_src);
stream = meta_screen_cast_stream_src_get_stream (src);
area_stream = META_SCREEN_CAST_AREA_STREAM (stream);
return meta_screen_cast_area_stream_get_stage (area_stream);
}
static MetaBackend *
get_backend (MetaScreenCastAreaStreamSrc *area_src)
{
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (area_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 MetaCursorRenderer *
get_cursor_renderer (MetaScreenCastAreaStreamSrc *area_src)
{
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (area_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);
MetaBackend *backend = meta_screen_cast_get_backend (screen_cast);
return meta_backend_get_cursor_renderer (backend);
}
static void
meta_screen_cast_area_stream_src_get_specs (MetaScreenCastStreamSrc *src,
int *width,
int *height,
float *frame_rate)
{
MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src);
MetaScreenCastAreaStream *area_stream = META_SCREEN_CAST_AREA_STREAM (stream);
MetaRectangle *area;
float scale;
area = meta_screen_cast_area_stream_get_area (area_stream);
scale = meta_screen_cast_area_stream_get_scale (area_stream);
*width = (int) roundf (area->width * scale);
*height = (int) roundf (area->height * scale);
*frame_rate = 60.0;
}
static gboolean
is_cursor_in_stream (MetaScreenCastAreaStreamSrc *area_src)
{
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (area_src);
MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src);
MetaScreenCastAreaStream *area_stream = META_SCREEN_CAST_AREA_STREAM (stream);
MetaBackend *backend = get_backend (area_src);
MetaCursorRenderer *cursor_renderer =
meta_backend_get_cursor_renderer (backend);
MetaRectangle *area;
graphene_rect_t area_rect;
MetaCursorSprite *cursor_sprite;
area = meta_screen_cast_area_stream_get_area (area_stream);
area_rect = meta_rectangle_to_graphene_rect (area);
cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer);
if (cursor_sprite)
{
graphene_rect_t cursor_rect;
cursor_rect = meta_cursor_renderer_calculate_rect (cursor_renderer,
cursor_sprite);
return graphene_rect_intersection (&cursor_rect, &area_rect, NULL);
}
else
{
graphene_point_t cursor_position;
cursor_position = meta_cursor_renderer_get_position (cursor_renderer);
return graphene_rect_contains_point (&area_rect, &cursor_position);
}
}
static void
sync_cursor_state (MetaScreenCastAreaStreamSrc *area_src)
{
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (area_src);
ClutterStage *stage = get_stage (area_src);
if (!is_cursor_in_stream (area_src))
return;
if (clutter_stage_is_redraw_queued (stage))
return;
meta_screen_cast_stream_src_maybe_record_frame (src);
}
static void
cursor_moved (MetaCursorTracker *cursor_tracker,
float x,
float y,
MetaScreenCastAreaStreamSrc *area_src)
{
sync_cursor_state (area_src);
}
static void
cursor_changed (MetaCursorTracker *cursor_tracker,
MetaScreenCastAreaStreamSrc *area_src)
{
area_src->cursor_bitmap_invalid = TRUE;
sync_cursor_state (area_src);
}
static void
inhibit_hw_cursor (MetaScreenCastAreaStreamSrc *area_src)
{
MetaCursorRenderer *cursor_renderer;
MetaHwCursorInhibitor *inhibitor;
g_return_if_fail (!area_src->hw_cursor_inhibited);
cursor_renderer = get_cursor_renderer (area_src);
inhibitor = META_HW_CURSOR_INHIBITOR (area_src);
meta_cursor_renderer_add_hw_cursor_inhibitor (cursor_renderer, inhibitor);
area_src->hw_cursor_inhibited = TRUE;
}
static void
uninhibit_hw_cursor (MetaScreenCastAreaStreamSrc *area_src)
{
MetaCursorRenderer *cursor_renderer;
MetaHwCursorInhibitor *inhibitor;
g_return_if_fail (area_src->hw_cursor_inhibited);
cursor_renderer = get_cursor_renderer (area_src);
inhibitor = META_HW_CURSOR_INHIBITOR (area_src);
meta_cursor_renderer_remove_hw_cursor_inhibitor (cursor_renderer, inhibitor);
area_src->hw_cursor_inhibited = FALSE;
}
static gboolean
maybe_record_frame_on_idle (gpointer user_data)
{
MetaScreenCastAreaStreamSrc *area_src =
META_SCREEN_CAST_AREA_STREAM_SRC (user_data);
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (area_src);
area_src->maybe_record_idle_id = 0;
meta_screen_cast_stream_src_maybe_record_frame (src);
return G_SOURCE_REMOVE;
}
static void
stage_painted (MetaStage *stage,
ClutterStageView *view,
ClutterPaintContext *paint_context,
gpointer user_data)
{
MetaScreenCastAreaStreamSrc *area_src =
META_SCREEN_CAST_AREA_STREAM_SRC (user_data);
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (area_src);
MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src);
MetaScreenCastAreaStream *area_stream = META_SCREEN_CAST_AREA_STREAM (stream);
const cairo_region_t *redraw_clip;
MetaRectangle *area;
if (area_src->maybe_record_idle_id)
return;
area = meta_screen_cast_area_stream_get_area (area_stream);
redraw_clip = clutter_paint_context_get_redraw_clip (paint_context);
if (redraw_clip)
{
switch (cairo_region_contains_rectangle (redraw_clip, area))
{
case CAIRO_REGION_OVERLAP_IN:
case CAIRO_REGION_OVERLAP_PART:
break;
case CAIRO_REGION_OVERLAP_OUT:
return;
}
}
area_src->maybe_record_idle_id = g_idle_add (maybe_record_frame_on_idle, src);
}
static void
add_view_painted_watches (MetaScreenCastAreaStreamSrc *area_src,
MetaStageWatchPhase watch_phase)
{
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (area_src);
MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src);
MetaScreenCastAreaStream *area_stream = META_SCREEN_CAST_AREA_STREAM (stream);
MetaBackend *backend = get_backend (area_src);
MetaRenderer *renderer = meta_backend_get_renderer (backend);
ClutterStage *stage;
MetaStage *meta_stage;
MetaRectangle *area;
GList *l;
stage = get_stage (area_src);
meta_stage = META_STAGE (stage);
area = meta_screen_cast_area_stream_get_area (area_stream);
for (l = meta_renderer_get_views (renderer); l; l = l->next)
{
MetaRendererView *view = l->data;
MetaRectangle view_layout;
clutter_stage_view_get_layout (CLUTTER_STAGE_VIEW (view), &view_layout);
if (meta_rectangle_overlap (area, &view_layout))
{
MetaStageWatch *watch;
watch = meta_stage_watch_view (meta_stage,
CLUTTER_STAGE_VIEW (view),
watch_phase,
stage_painted,
area_src);
area_src->watches = g_list_prepend (area_src->watches, watch);
}
}
}
static void
meta_screen_cast_area_stream_src_enable (MetaScreenCastStreamSrc *src)
{
MetaScreenCastAreaStreamSrc *area_src =
META_SCREEN_CAST_AREA_STREAM_SRC (src);
MetaBackend *backend = get_backend (area_src);
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
ClutterStage *stage;
MetaScreenCastStream *stream;
stream = meta_screen_cast_stream_src_get_stream (src);
stage = get_stage (area_src);
switch (meta_screen_cast_stream_get_cursor_mode (stream))
{
case META_SCREEN_CAST_CURSOR_MODE_METADATA:
area_src->cursor_moved_handler_id =
g_signal_connect_after (cursor_tracker, "cursor-moved",
G_CALLBACK (cursor_moved),
area_src);
area_src->cursor_changed_handler_id =
g_signal_connect_after (cursor_tracker, "cursor-changed",
G_CALLBACK (cursor_changed),
area_src);
G_GNUC_FALLTHROUGH;
case META_SCREEN_CAST_CURSOR_MODE_HIDDEN:
add_view_painted_watches (area_src,
META_STAGE_WATCH_AFTER_ACTOR_PAINT);
break;
case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED:
inhibit_hw_cursor (area_src);
add_view_painted_watches (area_src,
META_STAGE_WATCH_AFTER_ACTOR_PAINT);
break;
}
clutter_actor_queue_redraw (CLUTTER_ACTOR (stage));
}
static void
meta_screen_cast_area_stream_src_disable (MetaScreenCastStreamSrc *src)
{
MetaScreenCastAreaStreamSrc *area_src =
META_SCREEN_CAST_AREA_STREAM_SRC (src);
MetaBackend *backend = get_backend (area_src);
MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend);
ClutterStage *stage;
MetaStage *meta_stage;
GList *l;
stage = get_stage (area_src);
meta_stage = META_STAGE (stage);
for (l = area_src->watches; l; l = l->next)
{
MetaStageWatch *watch = l->data;
meta_stage_remove_watch (meta_stage, watch);
}
g_clear_pointer (&area_src->watches, g_list_free);
if (area_src->hw_cursor_inhibited)
uninhibit_hw_cursor (area_src);
g_clear_signal_handler (&area_src->cursor_moved_handler_id,
cursor_tracker);
g_clear_signal_handler (&area_src->cursor_changed_handler_id,
cursor_tracker);
g_clear_handle_id (&area_src->maybe_record_idle_id, g_source_remove);
}
static gboolean
meta_screen_cast_area_stream_src_record_frame (MetaScreenCastStreamSrc *src,
uint8_t *data)
{
MetaScreenCastAreaStreamSrc *area_src =
META_SCREEN_CAST_AREA_STREAM_SRC (src);
MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src);
MetaScreenCastAreaStream *area_stream = META_SCREEN_CAST_AREA_STREAM (stream);
ClutterStage *stage;
MetaRectangle *area;
float scale;
int stride;
ClutterPaintFlag paint_flags = CLUTTER_PAINT_FLAG_NONE;
g_autoptr (GError) error = NULL;
stage = get_stage (area_src);
area = meta_screen_cast_area_stream_get_area (area_stream);
scale = meta_screen_cast_area_stream_get_scale (area_stream);
stride = meta_screen_cast_stream_src_get_stride (src);
switch (meta_screen_cast_stream_get_cursor_mode (stream))
{
case META_SCREEN_CAST_CURSOR_MODE_METADATA:
case META_SCREEN_CAST_CURSOR_MODE_HIDDEN:
paint_flags |= CLUTTER_PAINT_FLAG_NO_CURSORS;
break;
case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED:
break;
}
if (!clutter_stage_paint_to_buffer (stage, area, scale,
data,
stride,
CLUTTER_CAIRO_FORMAT_ARGB32,
paint_flags,
&error))
{
g_warning ("Failed to record area: %s", error->message);
return FALSE;
}
return TRUE;
}
static gboolean
meta_screen_cast_area_stream_src_blit_to_framebuffer (MetaScreenCastStreamSrc *src,
CoglFramebuffer *framebuffer)
{
MetaScreenCastAreaStreamSrc *area_src =
META_SCREEN_CAST_AREA_STREAM_SRC (src);
MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src);
MetaScreenCastAreaStream *area_stream = META_SCREEN_CAST_AREA_STREAM (stream);
MetaBackend *backend = get_backend (area_src);
ClutterStage *stage;
MetaRectangle *area;
float scale;
ClutterPaintFlag paint_flags = CLUTTER_PAINT_FLAG_NONE;
stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
area = meta_screen_cast_area_stream_get_area (area_stream);
scale = meta_screen_cast_area_stream_get_scale (area_stream);
switch (meta_screen_cast_stream_get_cursor_mode (stream))
{
case META_SCREEN_CAST_CURSOR_MODE_METADATA:
case META_SCREEN_CAST_CURSOR_MODE_HIDDEN:
paint_flags |= CLUTTER_PAINT_FLAG_NO_CURSORS;
break;
case META_SCREEN_CAST_CURSOR_MODE_EMBEDDED:
break;
}
clutter_stage_paint_to_framebuffer (stage, framebuffer,
area, scale,
paint_flags);
cogl_framebuffer_finish (framebuffer);
return TRUE;
}
static void
meta_screen_cast_area_stream_src_set_cursor_metadata (MetaScreenCastStreamSrc *src,
struct spa_meta_cursor *spa_meta_cursor)
{
MetaScreenCastAreaStreamSrc *area_src =
META_SCREEN_CAST_AREA_STREAM_SRC (src);
MetaScreenCastStream *stream = meta_screen_cast_stream_src_get_stream (src);
MetaScreenCastAreaStream *area_stream = META_SCREEN_CAST_AREA_STREAM (stream);
MetaBackend *backend = get_backend (area_src);
MetaCursorRenderer *cursor_renderer =
meta_backend_get_cursor_renderer (backend);
MetaCursorSprite *cursor_sprite;
MetaRectangle *area;
float scale;
graphene_point_t cursor_position;
int x, y;
cursor_sprite = meta_cursor_renderer_get_cursor (cursor_renderer);
if (!is_cursor_in_stream (area_src))
{
meta_screen_cast_stream_src_unset_cursor_metadata (src,
spa_meta_cursor);
return;
}
area = meta_screen_cast_area_stream_get_area (area_stream);
scale = meta_screen_cast_area_stream_get_scale (area_stream);
cursor_position = meta_cursor_renderer_get_position (cursor_renderer);
cursor_position.x -= area->x;
cursor_position.y -= area->y;
cursor_position.x *= scale;
cursor_position.y *= scale;
x = (int) roundf (cursor_position.x);
y = (int) roundf (cursor_position.y);
if (area_src->cursor_bitmap_invalid)
{
if (cursor_sprite)
{
float cursor_scale;
float metadata_scale;
cursor_scale = meta_cursor_sprite_get_texture_scale (cursor_sprite);
metadata_scale = scale * cursor_scale;
meta_screen_cast_stream_src_set_cursor_sprite_metadata (src,
spa_meta_cursor,
cursor_sprite,
x, y,
metadata_scale);
}
else
{
meta_screen_cast_stream_src_set_empty_cursor_sprite_metadata (src,
spa_meta_cursor,
x, y);
}
area_src->cursor_bitmap_invalid = FALSE;
}
else
{
meta_screen_cast_stream_src_set_cursor_position_metadata (src,
spa_meta_cursor,
x, y);
}
}
static gboolean
meta_screen_cast_area_stream_src_is_cursor_sprite_inhibited (MetaHwCursorInhibitor *inhibitor,
MetaCursorSprite *cursor_sprite)
{
MetaScreenCastAreaStreamSrc *area_src =
META_SCREEN_CAST_AREA_STREAM_SRC (inhibitor);
return is_cursor_in_stream (area_src);
}
static void
hw_cursor_inhibitor_iface_init (MetaHwCursorInhibitorInterface *iface)
{
iface->is_cursor_sprite_inhibited =
meta_screen_cast_area_stream_src_is_cursor_sprite_inhibited;
}
MetaScreenCastAreaStreamSrc *
meta_screen_cast_area_stream_src_new (MetaScreenCastAreaStream *area_stream,
GError **error)
{
return g_initable_new (META_TYPE_SCREEN_CAST_AREA_STREAM_SRC, NULL, error,
"stream", area_stream,
NULL);
}
static void
meta_screen_cast_area_stream_src_init (MetaScreenCastAreaStreamSrc *area_src)
{
area_src->cursor_bitmap_invalid = TRUE;
}
static void
meta_screen_cast_area_stream_src_class_init (MetaScreenCastAreaStreamSrcClass *klass)
{
MetaScreenCastStreamSrcClass *src_class =
META_SCREEN_CAST_STREAM_SRC_CLASS (klass);
src_class->get_specs = meta_screen_cast_area_stream_src_get_specs;
src_class->enable = meta_screen_cast_area_stream_src_enable;
src_class->disable = meta_screen_cast_area_stream_src_disable;
src_class->record_frame = meta_screen_cast_area_stream_src_record_frame;
src_class->blit_to_framebuffer =
meta_screen_cast_area_stream_src_blit_to_framebuffer;
src_class->set_cursor_metadata =
meta_screen_cast_area_stream_src_set_cursor_metadata;
}

View File

@@ -1,37 +0,0 @@
/*
* Copyright (C) 2020 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
*/
#ifndef META_SCREEN_CAST_AREA_STREAM_SRC_H
#define META_SCREEN_CAST_AREA_STREAM_SRC_H
#include "backends/meta-screen-cast-stream-src.h"
typedef struct _MetaScreenCastAreaStream MetaScreenCastAreaStream;
#define META_TYPE_SCREEN_CAST_AREA_STREAM_SRC (meta_screen_cast_area_stream_src_get_type ())
G_DECLARE_FINAL_TYPE (MetaScreenCastAreaStreamSrc,
meta_screen_cast_area_stream_src,
META, SCREEN_CAST_AREA_STREAM_SRC,
MetaScreenCastStreamSrc)
MetaScreenCastAreaStreamSrc * meta_screen_cast_area_stream_src_new (MetaScreenCastAreaStream *area_stream,
GError **error);
#endif /* META_SCREEN_CAST_AREA_STREAM_SRC_H */

View File

@@ -1,177 +0,0 @@
/*
* Copyright (C) 2020 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
*/
#include "config.h"
#include "backends/meta-screen-cast-area-stream.h"
#include "backends/meta-screen-cast-area-stream-src.h"
struct _MetaScreenCastAreaStream
{
MetaScreenCastStream parent;
ClutterStage *stage;
MetaRectangle area;
float scale;
};
G_DEFINE_TYPE (MetaScreenCastAreaStream,
meta_screen_cast_area_stream,
META_TYPE_SCREEN_CAST_STREAM)
ClutterStage *
meta_screen_cast_area_stream_get_stage (MetaScreenCastAreaStream *area_stream)
{
return area_stream->stage;
}
MetaRectangle *
meta_screen_cast_area_stream_get_area (MetaScreenCastAreaStream *area_stream)
{
return &area_stream->area;
}
float
meta_screen_cast_area_stream_get_scale (MetaScreenCastAreaStream *area_stream)
{
return area_stream->scale;
}
static gboolean
calculate_scale (ClutterStage *stage,
MetaRectangle *area,
float *out_scale)
{
GList *l;
float scale = 0.0;
for (l = clutter_stage_peek_stage_views (stage); l; l = l->next)
{
ClutterStageView *stage_view = l->data;
MetaRectangle view_layout;
clutter_stage_view_get_layout (stage_view, &view_layout);
if (meta_rectangle_overlap (area, &view_layout))
scale = MAX (clutter_stage_view_get_scale (stage_view), scale);
}
if (scale == 0.0)
return FALSE;
*out_scale = scale;
return TRUE;
}
MetaScreenCastAreaStream *
meta_screen_cast_area_stream_new (MetaScreenCastSession *session,
GDBusConnection *connection,
MetaRectangle *area,
ClutterStage *stage,
MetaScreenCastCursorMode cursor_mode,
GError **error)
{
MetaScreenCastAreaStream *area_stream;
float scale;
if (!calculate_scale (stage, area, &scale))
{
g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED,
"Area is off-screen");
return NULL;
}
area_stream = g_initable_new (META_TYPE_SCREEN_CAST_AREA_STREAM,
NULL,
error,
"session", session,
"connection", connection,
"cursor-mode", cursor_mode,
NULL);
if (!area_stream)
return NULL;
area_stream->area = *area;
area_stream->scale = scale;
area_stream->stage = stage;
return area_stream;
}
static MetaScreenCastStreamSrc *
meta_screen_cast_area_stream_create_src (MetaScreenCastStream *stream,
GError **error)
{
MetaScreenCastAreaStream *area_stream =
META_SCREEN_CAST_AREA_STREAM (stream);
MetaScreenCastAreaStreamSrc *area_stream_src;
area_stream_src = meta_screen_cast_area_stream_src_new (area_stream,
error);
if (!area_stream_src)
return NULL;
return META_SCREEN_CAST_STREAM_SRC (area_stream_src);
}
static void
meta_screen_cast_area_stream_set_parameters (MetaScreenCastStream *stream,
GVariantBuilder *parameters_builder)
{
MetaScreenCastAreaStream *area_stream =
META_SCREEN_CAST_AREA_STREAM (stream);
g_variant_builder_add (parameters_builder, "{sv}",
"size",
g_variant_new ("(ii)",
area_stream->area.width,
area_stream->area.height));
}
static void
meta_screen_cast_area_stream_transform_position (MetaScreenCastStream *stream,
double stream_x,
double stream_y,
double *x,
double *y)
{
MetaScreenCastAreaStream *area_stream =
META_SCREEN_CAST_AREA_STREAM (stream);
*x = area_stream->area.x + (int) roundf (stream_x / area_stream->scale);
*y = area_stream->area.y + (int) roundf (stream_y / area_stream->scale);
}
static void
meta_screen_cast_area_stream_init (MetaScreenCastAreaStream *area_stream)
{
}
static void
meta_screen_cast_area_stream_class_init (MetaScreenCastAreaStreamClass *klass)
{
MetaScreenCastStreamClass *stream_class =
META_SCREEN_CAST_STREAM_CLASS (klass);
stream_class->create_src = meta_screen_cast_area_stream_create_src;
stream_class->set_parameters = meta_screen_cast_area_stream_set_parameters;
stream_class->transform_position = meta_screen_cast_area_stream_transform_position;
}

View File

@@ -1,48 +0,0 @@
/*
* Copyright (C) 2020 Red Hat Inc.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
*/
#ifndef META_SCREEN_CAST_AREA_STREAM_H
#define META_SCREEN_CAST_AREA_STREAM_H
#include <glib-object.h>
#include "backends/meta-screen-cast-stream.h"
#include "backends/meta-screen-cast.h"
#define META_TYPE_SCREEN_CAST_AREA_STREAM (meta_screen_cast_area_stream_get_type ())
G_DECLARE_FINAL_TYPE (MetaScreenCastAreaStream,
meta_screen_cast_area_stream,
META, SCREEN_CAST_AREA_STREAM,
MetaScreenCastStream)
MetaScreenCastAreaStream * meta_screen_cast_area_stream_new (MetaScreenCastSession *session,
GDBusConnection *connection,
MetaRectangle *area,
ClutterStage *stage,
MetaScreenCastCursorMode cursor_mode,
GError **error);
ClutterStage * meta_screen_cast_area_stream_get_stage (MetaScreenCastAreaStream *area_stream);
MetaRectangle * meta_screen_cast_area_stream_get_area (MetaScreenCastAreaStream *area_stream);
float meta_screen_cast_area_stream_get_scale (MetaScreenCastAreaStream *area_stream);
#endif /* META_SCREEN_CAST_AREA_STREAM_H */

View File

@@ -115,10 +115,9 @@ meta_screen_cast_monitor_stream_src_get_specs (MetaScreenCastStreamSrc *src,
}
static void
stage_painted (MetaStage *stage,
ClutterStageView *view,
ClutterPaintContext *paint_context,
gpointer user_data)
stage_painted (MetaStage *stage,
ClutterStageView *view,
gpointer user_data)
{
MetaScreenCastStreamSrc *src = META_SCREEN_CAST_STREAM_SRC (user_data);

View File

@@ -27,7 +27,6 @@
#include "backends/meta-backend-private.h"
#include "backends/meta-dbus-session-watcher.h"
#include "backends/meta-remote-access-controller-private.h"
#include "backends/meta-screen-cast-area-stream.h"
#include "backends/meta-screen-cast-monitor-stream.h"
#include "backends/meta-screen-cast-stream.h"
#include "backends/meta-screen-cast-window-stream.h"
@@ -486,90 +485,6 @@ handle_record_window (MetaDBusScreenCastSession *skeleton,
return TRUE;
}
static gboolean
handle_record_area (MetaDBusScreenCastSession *skeleton,
GDBusMethodInvocation *invocation,
int x,
int y,
int width,
int height,
GVariant *properties_variant)
{
MetaScreenCastSession *session = META_SCREEN_CAST_SESSION (skeleton);
GDBusInterfaceSkeleton *interface_skeleton;
GDBusConnection *connection;
MetaBackend *backend;
ClutterStage *stage;
MetaScreenCastCursorMode cursor_mode;
g_autoptr (GError) error = NULL;
MetaRectangle rect;
MetaScreenCastAreaStream *area_stream;
MetaScreenCastStream *stream;
char *stream_path;
if (!check_permission (session, invocation))
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Permission denied");
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);
backend = meta_screen_cast_get_backend (session->screen_cast);
stage = CLUTTER_STAGE (meta_backend_get_stage (backend));
rect = (MetaRectangle) {
.x = x,
.y = y,
.width = width,
.height = height
};
area_stream = meta_screen_cast_area_stream_new (session,
connection,
&rect,
stage,
cursor_mode,
&error);
if (!area_stream)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_FAILED,
"Failed to record area: %s",
error->message);
return TRUE;
}
stream = META_SCREEN_CAST_STREAM (area_stream);
stream_path = meta_screen_cast_stream_get_object_path (stream);
session->streams = g_list_append (session->streams, stream);
g_signal_connect (stream, "closed", G_CALLBACK (on_stream_closed), session);
meta_dbus_screen_cast_session_complete_record_area (skeleton,
invocation,
stream_path);
return TRUE;
}
static void
meta_screen_cast_session_init_iface (MetaDBusScreenCastSessionIface *iface)
{
@@ -577,7 +492,6 @@ meta_screen_cast_session_init_iface (MetaDBusScreenCastSessionIface *iface)
iface->handle_stop = handle_stop;
iface->handle_record_monitor = handle_record_monitor;
iface->handle_record_window = handle_record_window;
iface->handle_record_area = handle_record_area;
}
static void

View File

@@ -956,15 +956,6 @@ meta_screen_cast_stream_src_init_initable_iface (GInitableIface *iface)
iface->init = meta_screen_cast_stream_src_initable_init;
}
int
meta_screen_cast_stream_src_get_stride (MetaScreenCastStreamSrc *src)
{
MetaScreenCastStreamSrcPrivate *priv =
meta_screen_cast_stream_src_get_instance_private (src);
return priv->video_stride;
}
MetaScreenCastStream *
meta_screen_cast_stream_src_get_stream (MetaScreenCastStreamSrc *src)
{

View File

@@ -65,8 +65,6 @@ struct _MetaScreenCastStreamSrcClass
void meta_screen_cast_stream_src_maybe_record_frame (MetaScreenCastStreamSrc *src);
int meta_screen_cast_stream_src_get_stride (MetaScreenCastStreamSrc *src);
MetaScreenCastStream * meta_screen_cast_stream_src_get_stream (MetaScreenCastStreamSrc *src);
gboolean meta_screen_cast_stream_src_draw_cursor_into (MetaScreenCastStreamSrc *src,

View File

@@ -40,8 +40,6 @@ struct _MetaScreenCast
int dbus_name_id;
int inhibit_count;
GList *sessions;
MetaDbusSessionWatcher *session_watcher;
@@ -56,29 +54,6 @@ G_DEFINE_TYPE_WITH_CODE (MetaScreenCast, meta_screen_cast,
G_IMPLEMENT_INTERFACE (META_DBUS_TYPE_SCREEN_CAST,
meta_screen_cast_init_iface))
void
meta_screen_cast_inhibit (MetaScreenCast *screen_cast)
{
screen_cast->inhibit_count++;
if (screen_cast->inhibit_count == 1)
{
while (screen_cast->sessions)
{
MetaScreenCastSession *session = screen_cast->sessions->data;
meta_screen_cast_session_close (session);
}
}
}
void
meta_screen_cast_uninhibit (MetaScreenCast *screen_cast)
{
g_return_if_fail (screen_cast->inhibit_count > 0);
screen_cast->inhibit_count--;
}
GDBusConnection *
meta_screen_cast_get_connection (MetaScreenCast *screen_cast)
{
@@ -144,15 +119,6 @@ handle_create_session (MetaDBusScreenCast *skeleton,
gboolean disable_animations;
MetaScreenCastSessionType session_type;
if (screen_cast->inhibit_count > 0)
{
g_dbus_method_invocation_return_error (invocation, G_DBUS_ERROR,
G_DBUS_ERROR_ACCESS_DENIED,
"Session creation inhibited");
return TRUE;
}
g_variant_lookup (properties, "remote-desktop-session-id", "s",
&remote_desktop_session_id);

View File

@@ -42,10 +42,6 @@ G_DECLARE_FINAL_TYPE (MetaScreenCast, meta_screen_cast,
META, SCREEN_CAST,
MetaDBusScreenCastSkeleton)
void meta_screen_cast_inhibit (MetaScreenCast *screen_cast);
void meta_screen_cast_uninhibit (MetaScreenCast *screen_cast);
GDBusConnection * meta_screen_cast_get_connection (MetaScreenCast *screen_cast);
MetaBackend * meta_screen_cast_get_backend (MetaScreenCast *screen_cast);

View File

@@ -38,10 +38,9 @@ typedef enum
META_STAGE_WATCH_AFTER_PAINT,
} MetaStageWatchPhase;
typedef void (* MetaStageWatchFunc) (MetaStage *stage,
ClutterStageView *view,
ClutterPaintContext *paint_context,
gpointer user_data);
typedef void (* MetaStageWatchFunc) (MetaStage *stage,
ClutterStageView *view,
gpointer user_data);
ClutterActor *meta_stage_new (MetaBackend *backend);

View File

@@ -65,6 +65,7 @@ struct _MetaStage
ClutterStage parent;
GPtrArray *watchers[N_WATCH_MODES];
ClutterStageView *current_view;
GList *overlays;
gboolean is_active;
@@ -168,7 +169,6 @@ meta_stage_finalize (GObject *object)
static void
notify_watchers_for_mode (MetaStage *stage,
ClutterStageView *view,
ClutterPaintContext *paint_context,
MetaStageWatchPhase watch_phase)
{
GPtrArray *watchers;
@@ -183,7 +183,7 @@ notify_watchers_for_mode (MetaStage *stage,
if (watch->view && view != watch->view)
continue;
watch->callback (stage, view, paint_context, watch->user_data);
watch->callback (stage, view, watch->user_data);
}
}
@@ -192,32 +192,20 @@ meta_stage_paint (ClutterActor *actor,
ClutterPaintContext *paint_context)
{
MetaStage *stage = META_STAGE (actor);
ClutterStageView *view;
GList *l;
CLUTTER_ACTOR_CLASS (meta_stage_parent_class)->paint (actor, paint_context);
view = clutter_paint_context_get_stage_view (paint_context);
if (view)
{
notify_watchers_for_mode (stage, view, paint_context,
META_STAGE_WATCH_AFTER_ACTOR_PAINT);
}
notify_watchers_for_mode (stage, stage->current_view,
META_STAGE_WATCH_AFTER_ACTOR_PAINT);
g_signal_emit (stage, signals[ACTORS_PAINTED], 0);
if (!(clutter_paint_context_get_paint_flags (paint_context) &
CLUTTER_PAINT_FLAG_NO_CURSORS))
{
for (l = stage->overlays; l; l = l->next)
meta_overlay_paint (l->data, paint_context);
}
for (l = stage->overlays; l; l = l->next)
meta_overlay_paint (l->data, paint_context);
if (view)
{
notify_watchers_for_mode (stage, view, paint_context,
META_STAGE_WATCH_AFTER_OVERLAY_PAINT);
}
notify_watchers_for_mode (stage, stage->current_view,
META_STAGE_WATCH_AFTER_OVERLAY_PAINT);
}
static void
@@ -227,14 +215,13 @@ meta_stage_paint_view (ClutterStage *stage,
{
MetaStage *meta_stage = META_STAGE (stage);
notify_watchers_for_mode (meta_stage, view, NULL,
META_STAGE_WATCH_BEFORE_PAINT);
notify_watchers_for_mode (meta_stage, view, META_STAGE_WATCH_BEFORE_PAINT);
meta_stage->current_view = view;
CLUTTER_STAGE_CLASS (meta_stage_parent_class)->paint_view (stage, view,
redraw_clip);
notify_watchers_for_mode (meta_stage, view, NULL,
META_STAGE_WATCH_AFTER_PAINT);
notify_watchers_for_mode (meta_stage, view, META_STAGE_WATCH_AFTER_PAINT);
}
static void

View File

@@ -1,6 +1,6 @@
/*
* Copyright (C) 2018-2019 Red Hat
* Copyright (C) 2019-2020 DisplayLink (UK) Ltd.
* Copyright (C) 2019 DisplayLink (UK) Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -660,9 +660,6 @@ process_page_flip (MetaKmsImpl *impl,
meta_kms_page_flip_data_ref (page_flip_data));
}
if (ret != 0)
meta_kms_page_flip_data_unref (page_flip_data);
if (ret == -EBUSY)
{
CachedModeSet *cached_mode_set;

View File

@@ -1,6 +1,5 @@
/*
* Copyright (C) 2018 Red Hat
* Copyright 2020 DisplayLink (UK) Ltd.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
@@ -384,7 +383,6 @@ meta_kms_add_source_in_impl (MetaKms *kms,
simple_impl_source->kms = kms;
g_source_set_callback (source, func, user_data, user_data_destroy);
g_source_set_ready_time (source, 0);
g_source_attach (source, g_main_context_get_thread_default ());
return source;

View File

@@ -64,6 +64,7 @@
#include "cogl/cogl.h"
#include "compositor/meta-later-private.h"
#include "compositor/meta-window-actor-x11.h"
#include "compositor/meta-window-actor-wayland.h"
#include "compositor/meta-window-actor-private.h"
#include "compositor/meta-window-group-private.h"
#include "core/display-private.h"
@@ -82,7 +83,6 @@
#include "x11/meta-x11-display-private.h"
#ifdef HAVE_WAYLAND
#include "compositor/meta-window-actor-wayland.h"
#include "wayland/meta-wayland-private.h"
#endif

View File

@@ -1270,9 +1270,7 @@ get_image_via_offscreen (MetaShapedTexture *stex,
root_node = clutter_root_node_new (fb, &clear_color, COGL_BUFFER_BIT_COLOR);
clutter_paint_node_set_static_name (root_node, "MetaShapedTexture.offscreen");
paint_context =
clutter_paint_context_new_for_framebuffer (fb, NULL,
CLUTTER_PAINT_FLAG_NONE);
paint_context = clutter_paint_context_new_for_framebuffer (fb);
do_paint_content (stex, root_node, paint_context,
stex->texture,

View File

@@ -86,8 +86,6 @@ struct _MetaWindowActorX11
cairo_region_t *shape_region;
/* The region we should clip to when painting the shadow */
cairo_region_t *shadow_clip;
/* The frame region */
cairo_region_t *frame_bounds;
/* Extracted size-invariant shape used for shadows */
MetaWindowShape *shadow_shape;
@@ -711,8 +709,11 @@ set_clip_region_beneath (MetaWindowActorX11 *actor_x11,
if (clip_shadow_under_window (actor_x11))
{
if (actor_x11->frame_bounds)
cairo_region_subtract (actor_x11->shadow_clip, actor_x11->frame_bounds);
cairo_region_t *frame_bounds;
frame_bounds = meta_window_get_frame_bounds (window);
if (frame_bounds)
cairo_region_subtract (actor_x11->shadow_clip, frame_bounds);
}
}
else
@@ -1132,17 +1133,6 @@ update_opaque_region (MetaWindowActorX11 *actor_x11)
cairo_region_destroy (opaque_region);
}
static void
update_frame_bounds (MetaWindowActorX11 *actor_x11)
{
MetaWindow *window =
meta_window_actor_get_meta_window (META_WINDOW_ACTOR (actor_x11));
g_clear_pointer (&actor_x11->frame_bounds, cairo_region_destroy);
actor_x11->frame_bounds =
cairo_region_copy (meta_window_get_frame_bounds (window));
}
static void
update_regions (MetaWindowActorX11 *actor_x11)
{
@@ -1214,7 +1204,6 @@ handle_updates (MetaWindowActorX11 *actor_x11)
if (!meta_surface_actor_is_visible (surface))
return;
update_frame_bounds (actor_x11);
check_needs_reshape (actor_x11);
check_needs_shadow (actor_x11);
}
@@ -1268,13 +1257,15 @@ meta_window_actor_x11_paint (ClutterActor *actor,
*/
if (!clip && clip_shadow_under_window (actor_x11))
{
cairo_region_t *frame_bounds;
cairo_rectangle_int_t bounds;
get_shadow_bounds (actor_x11, appears_focused, &bounds);
clip = cairo_region_create_rectangle (&bounds);
if (actor_x11->frame_bounds)
cairo_region_subtract (clip, actor_x11->frame_bounds);
frame_bounds = meta_window_get_frame_bounds (window);
if (frame_bounds)
cairo_region_subtract (clip, frame_bounds);
}
framebuffer = clutter_paint_context_get_framebuffer (paint_context);
@@ -1561,7 +1552,6 @@ meta_window_actor_x11_dispose (GObject *object)
g_clear_pointer (&actor_x11->shape_region, cairo_region_destroy);
g_clear_pointer (&actor_x11->shadow_clip, cairo_region_destroy);
g_clear_pointer (&actor_x11->frame_bounds, cairo_region_destroy);
g_clear_pointer (&actor_x11->shadow_class, g_free);
g_clear_pointer (&actor_x11->focused_shadow, meta_shadow_unref);

View File

@@ -1321,9 +1321,7 @@ meta_window_actor_blit_to_framebuffer (MetaScreenCastWindow *screen_cast_window,
cogl_framebuffer_scale (framebuffer, resource_scale, resource_scale, 1);
cogl_framebuffer_translate (framebuffer, -x, -y, 0);
paint_context =
clutter_paint_context_new_for_framebuffer (framebuffer, NULL,
CLUTTER_PAINT_FLAG_NONE);
paint_context = clutter_paint_context_new_for_framebuffer (framebuffer);
clutter_actor_paint (actor, paint_context);
clutter_paint_context_destroy (paint_context);
@@ -1481,9 +1479,7 @@ meta_window_actor_get_image (MetaWindowActor *self,
cogl_framebuffer_scale (framebuffer, resource_scale, resource_scale, 1);
cogl_framebuffer_translate (framebuffer, -x, -y, 0);
paint_context =
clutter_paint_context_new_for_framebuffer (framebuffer, NULL,
CLUTTER_PAINT_FLAG_NONE);
paint_context = clutter_paint_context_new_for_framebuffer (framebuffer);
clutter_actor_paint (actor, paint_context);
clutter_paint_context_destroy (paint_context);

View File

@@ -2129,7 +2129,7 @@ process_special_modifier_key (MetaDisplay *display,
return TRUE;
}
else if (event->type == CLUTTER_KEY_PRESS &&
((event->modifier_state & ~(IGNORED_MODIFIERS)) & CLUTTER_MODIFIER_MASK) == 0 &&
(event->modifier_state & ~(IGNORED_MODIFIERS)) == 0 &&
resolved_key_combo_has_keycode (resolved_key_combo,
event->hardware_keycode))
{

View File

@@ -1,368 +0,0 @@
/*
* Copyright (C) 2020 Sebastian Wick
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Sebastian Wick <sebastian@sebastianwick.net>
*/
#include "config.h"
#include <errno.h>
#include <fcntl.h>
#include <sys/mman.h>
#include "core/meta-anonymous-file.h"
struct _MetaAnonymousFile
{
int fd;
size_t size;
};
#define READONLY_SEALS (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE)
static int
create_tmpfile_cloexec (char *tmpname)
{
int fd;
#if defined(HAVE_MKOSTEMP)
fd = mkostemp (tmpname, O_CLOEXEC);
if (fd >= 0)
unlink (tmpname);
#else
fd = mkstemp (tmpname);
if (fd >= 0)
{
long flags;
unlink (tmpname);
flags = fcntl (fd, F_GETFD);
if (flags == -1 ||
fcntl (fd, F_SETFD, flags | FD_CLOEXEC) == -1)
{
close (fd);
return -1;
}
}
#endif
return fd;
}
/*
* Create a new, unique, anonymous file of the given size, and
* return the file descriptor for it. The file descriptor is set
* CLOEXEC. The file is immediately suitable for mmap()'ing
* the given size at offset zero.
*
* The file should not have a permanent backing store like a disk,
* but may have if XDG_RUNTIME_DIR is not properly implemented in OS.
*
* The file name is deleted from the file system.
*
* The file is suitable for buffer sharing between processes by
* transmitting the file descriptor over Unix sockets using the
* SCM_RIGHTS methods.
*
* If the C library implements posix_fallocate(), it is used to
* guarantee that disk space is available for the file at the
* given size. If disk space is insufficient, errno is set to ENOSPC.
* If posix_fallocate() is not supported, program may receive
* SIGBUS on accessing mmap()'ed file contents instead.
*
* If the C library implements memfd_create(), it is used to create the
* file purely in memory, without any backing file name on the file
* system, and then sealing off the possibility of shrinking it. This
* can then be checked before accessing mmap()'ed file contents, to make
* sure SIGBUS can't happen. It also avoids requiring XDG_RUNTIME_DIR.
*/
static int
create_anonymous_file (off_t size)
{
int fd, ret;
#if defined(HAVE_MEMFD_CREATE)
fd = memfd_create ("mutter-shared", MFD_CLOEXEC | MFD_ALLOW_SEALING);
if (fd >= 0)
{
/* We can add this seal before calling posix_fallocate(), as
* the file is currently zero-sized anyway.
*
* There is also no need to check for the return value, we
* couldn't do anything with it anyway.
*/
fcntl (fd, F_ADD_SEALS, F_SEAL_SHRINK);
}
else
#endif
{
static const char template[] = "/mutter-shared-XXXXXX";
const char *path;
char *name;
path = getenv ("XDG_RUNTIME_DIR");
if (!path)
{
errno = ENOENT;
return -1;
}
name = g_malloc (strlen (path) + sizeof (template));
if (!name)
return -1;
strcpy (name, path);
strcat (name, template);
fd = create_tmpfile_cloexec (name);
g_free (name);
if (fd < 0)
return -1;
}
#if defined(HAVE_POSIX_FALLOCATE)
do
{
ret = posix_fallocate (fd, 0, size);
}
while (ret == EINTR);
if (ret != 0)
{
close (fd);
errno = ret;
return -1;
}
#else
do
{
ret = ftruncate (fd, size);
}
while (ret < 0 && errno == EINTR);
if (ret < 0)
{
close (fd);
return -1;
}
#endif
return fd;
}
/**
* meta_anonymous_file_new: (skip)
* @size: The size of @data
* @data: The data of the file with the size @size
*
* Create a new anonymous read-only file of the given size and the given data
* The intended use-case is for sending mid-sized data from the compositor
* to clients.
*
* When done, free the data using meta_anonymous_file_free().
*
* If this function fails errno is set.
*
* Returns: The newly created #MetaAnonymousFile, or NULL on failure. Use
* meta_anonymous_file_free() to free the resources when done.
*/
MetaAnonymousFile *
meta_anonymous_file_new (size_t size,
const uint8_t *data)
{
MetaAnonymousFile *file;
void *map;
file = g_malloc0 (sizeof *file);
if (!file)
{
errno = ENOMEM;
return NULL;
}
file->size = size;
file->fd = create_anonymous_file (size);
if (file->fd == -1)
goto err_free;
map = mmap (NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, file->fd, 0);
if (map == MAP_FAILED)
goto err_close;
memcpy (map, data, size);
munmap (map, size);
#if defined(HAVE_MEMFD_CREATE)
/* try to put seals on the file to make it read-only so that we can
* return the fd later directly when MAPMODE_SHARED is not set.
* meta_anonymous_file_open_fd can handle the fd even if it is not
* sealed read-only and will instead create a new anonymous file on
* each invocation.
*/
fcntl (file->fd, F_ADD_SEALS, READONLY_SEALS);
#endif
return file;
err_close:
close (file->fd);
err_free:
g_free (file);
return NULL;
}
/**
* meta_anonymous_file_free: (skip)
* @file: the #MetaAnonymousFile
*
* Free the resources used by an anonymous read-only file.
*/
void
meta_anonymous_file_free (MetaAnonymousFile *file)
{
close (file->fd);
g_free (file);
}
/**
* meta_anonymous_file_size: (skip)
* @file: the #MetaAnonymousFile
*
* Get the size of an anonymous read-only file.
*
* Returns: The size of the anonymous read-only file.
*/
size_t
meta_anonymous_file_size (MetaAnonymousFile *file)
{
return file->size;
}
/**
* meta_anonymous_file_open_fd: (skip)
* @file: the #MetaAnonymousFile to get a file descriptor for
* @mapmode: describes the ways in which the returned file descriptor can
* be used with mmap
*
* Returns a file descriptor for the given file, ready to be sent to a client.
* The returned file descriptor must not be shared between multiple clients.
* If @mapmode is %META_ANONYMOUS_FILE_MAPMODE_PRIVATE the file descriptor is
* only guaranteed to be mmapable with MAP_PRIVATE. If @mapmode is
* %META_ANONYMOUS_FILE_MAPMODE_SHARED the file descriptor can be mmaped with
* either MAP_PRIVATE or MAP_SHARED.
*
* In case %META_ANONYMOUS_FILE_MAPMODE_PRIVATE is used, it is important to
* only read the returned fd using mmap() since using read() will move the
* read cursor of the fd and thus may cause read() calls on other returned
* fds to fail.
*
* When done using the fd, it is required to call meta_anonymous_file_close_fd()
* instead of close().
*
* If this function fails errno is set.
*
* Returns: A file descriptor for the given file that can be sent to a client
* or -1 on failure. Use meta_anonymous_file_close_fd() to release the fd
* when done.
*/
int
meta_anonymous_file_open_fd (MetaAnonymousFile *file,
MetaAnonymousFileMapmode mapmode)
{
void *src, *dst;
int fd;
#if defined(HAVE_MEMFD_CREATE)
int seals;
seals = fcntl (file->fd, F_GET_SEALS);
/* file was sealed for read-only and we don't have to support MAP_SHARED
* so we can simply pass the memfd fd
*/
if (seals != -1 && mapmode == META_ANONYMOUS_FILE_MAPMODE_PRIVATE &&
(seals & READONLY_SEALS) == READONLY_SEALS)
return file->fd;
#endif
/* for all other cases we create a new anonymous file that can be mapped
* with MAP_SHARED and copy the contents to it and return that instead
*/
fd = create_anonymous_file (file->size);
if (fd == -1)
return fd;
src = mmap (NULL, file->size, PROT_READ, MAP_PRIVATE, file->fd, 0);
if (src == MAP_FAILED)
{
close (fd);
return -1;
}
dst = mmap (NULL, file->size, PROT_WRITE, MAP_SHARED, fd, 0);
if (dst == MAP_FAILED)
{
close (fd);
munmap (src, file->size);
return -1;
}
memcpy (dst, src, file->size);
munmap (src, file->size);
munmap (dst, file->size);
return fd;
}
/**
* meta_anonymous_file_close_fd: (skip)
* @fd: A file descriptor obtained using meta_anonymous_file_open_fd()
*
* Release a file descriptor returned by meta_anonymous_file_open_fd().
* This function must be called for every file descriptor created with
* meta_anonymous_file_open_fd() to not leak any resources.
*
* If this function fails errno is set.
*/
void
meta_anonymous_file_close_fd (int fd)
{
#if defined(HAVE_MEMFD_CREATE)
int seals;
seals = fcntl (fd, F_GET_SEALS);
if (seals == -1 && errno != EINVAL)
{
g_warning ("Reading seals of anonymous file %d failed", fd);
return;
}
/* The only case in which we do NOT have to close the file is when the file
* was sealed for read-only
*/
if (seals != -1 && (seals & READONLY_SEALS) == READONLY_SEALS)
return;
#endif
close (fd);
}

View File

@@ -1,53 +0,0 @@
/*
* Copyright (C) 2020 Sebastian Wick
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
* 02111-1307, USA.
*
* Author: Sebastian Wick <sebastian@sebastianwick.net>
*/
#ifndef META_ANONYMOUS_FILE_H
#define META_ANONYMOUS_FILE_H
#include "meta/common.h"
#include "core/util-private.h"
typedef struct _MetaAnonymousFile MetaAnonymousFile;
typedef enum _MetaAnonymousFileMapmode
{
META_ANONYMOUS_FILE_MAPMODE_PRIVATE,
META_ANONYMOUS_FILE_MAPMODE_SHARED,
} MetaAnonymousFileMapmode;
META_EXPORT_TEST
MetaAnonymousFile * meta_anonymous_file_new (size_t size,
const uint8_t *data);
META_EXPORT_TEST
void meta_anonymous_file_free (MetaAnonymousFile *file);
META_EXPORT_TEST
size_t meta_anonymous_file_size (MetaAnonymousFile *file);
META_EXPORT_TEST
int meta_anonymous_file_open_fd (MetaAnonymousFile *file,
MetaAnonymousFileMapmode mapmode);
META_EXPORT_TEST
void meta_anonymous_file_close_fd (int fd);
#endif /* META_ANONYMOUS_FILE_H */

View File

@@ -349,8 +349,6 @@ mutter_sources = [
'core/main-private.h',
'core/meta-accel-parse.c',
'core/meta-accel-parse.h',
'core/meta-anonymous-file.c',
'core/meta-anonymous-file.h',
'core/meta-border.c',
'core/meta-border.h',
'core/meta-clipboard-manager.c',
@@ -458,10 +456,6 @@ if have_remote_desktop
'backends/meta-remote-desktop-session.h',
'backends/meta-screen-cast.c',
'backends/meta-screen-cast.h',
'backends/meta-screen-cast-area-stream.c',
'backends/meta-screen-cast-area-stream.h',
'backends/meta-screen-cast-area-stream-src.c',
'backends/meta-screen-cast-area-stream-src.h',
'backends/meta-screen-cast-monitor-stream.c',
'backends/meta-screen-cast-monitor-stream.h',
'backends/meta-screen-cast-monitor-stream-src.c',

View File

@@ -54,10 +54,4 @@ G_DECLARE_FINAL_TYPE (MetaRemoteAccessController,
META, REMOTE_ACCESS_CONTROLLER,
GObject)
META_EXPORT
void meta_remote_access_controller_inhibit_remote_access (MetaRemoteAccessController *controller);
META_EXPORT
void meta_remote_access_controller_uninhibit_remote_access (MetaRemoteAccessController *controller);
#endif /* META_REMOTE_ACCESS_CONTROLLER_H */

View File

@@ -111,39 +111,6 @@
<arg name="properties" type="a{sv}" direction="in" />
<arg name="stream_path" type="o" direction="out" />
</method>
<!--
RecordArea:
@x: X position of the recorded area
@y: Y position of the recorded area
@width: width of the recorded area
@height: height of the recorded area
@properties: Properties
@stream_path: Path to the new stream object
Record an area of the stage. The coordinates are in stage coordinates.
The size of the stream does not necessarily match the size of the
recorded area, and will depend on DPI scale of the affected monitors.
Available @properties include:
* "cursor-mode" (u): Cursor mode. Default: 'hidden' (see below)
Available since API version 2.
Available cursor mode values:
0: hidden - cursor is not included in the stream
1: embedded - cursor is included in the framebuffer
2: metadata - cursor is included as metadata in the PipeWire stream
-->
<method name="RecordArea">
<arg name="x" type="i" direction="in" />
<arg name="y" type="i" direction="in" />
<arg name="width" type="i" direction="in" />
<arg name="height" type="i" direction="in" />
<arg name="properties" type="a{sv}" direction="in" />
<arg name="stream_path" type="o" direction="out" />
</method>
</interface>
<!--

View File

@@ -59,19 +59,3 @@ executable('subsurface-remap-toplevel',
install: have_installed_tests,
install_dir: wayland_test_client_installed_tests_libexecdir,
)
executable('meta-anonymous-file',
sources: [
'meta-anonymous-file.c',
common_sources,
],
include_directories: tests_includepath,
c_args: tests_c_args,
dependencies: [
glib_dep,
wayland_client_dep,
libmutter_dep,
],
install: have_installed_tests,
install_dir: wayland_test_client_installed_tests_libexecdir,
)

View File

@@ -1,278 +0,0 @@
/*
* Copyright (C) 2020 Jonas Dreßler.
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
#include "config.h"
#include <glib.h>
#include <sys/resource.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>
#include <core/meta-anonymous-file.h>
#include "wayland-test-client-utils.h"
#define READONLY_SEALS (F_SEAL_SHRINK | F_SEAL_GROW | F_SEAL_WRITE)
static const char *teststring = "test string 1234567890";
static int
test_read_fd_mmap (int fd,
const char *expected_string)
{
void *mem;
int string_size;
string_size = strlen (expected_string) + 1;
mem = mmap (NULL, string_size, PROT_READ, MAP_PRIVATE, fd, 0);
g_assert (mem != MAP_FAILED);
if (strcmp (expected_string, mem) != 0)
{
munmap (mem, string_size);
return FALSE;
}
munmap (mem, string_size);
return TRUE;
}
static int
test_write_fd (int fd,
const char *string)
{
int written_size, string_size;
string_size = strlen (string) + 1;
written_size = write (fd, string, string_size);
if (written_size != string_size)
return FALSE;
return TRUE;
}
static int
test_readonly_seals (int fd)
{
unsigned int seals;
seals = fcntl (fd, F_GET_SEALS);
if (seals == -1)
return FALSE;
if (seals != READONLY_SEALS)
return FALSE;
return TRUE;
}
static int
test_write_read (int fd)
{
g_autofree char *new_string = g_uuid_string_random ();
if (!test_write_fd (fd, new_string))
return FALSE;
if (!test_read_fd_mmap (fd, new_string))
return FALSE;
return TRUE;
}
#if defined(HAVE_MEMFD_CREATE)
static int
test_open_write_read (const char *path)
{
int fd;
fd = open (path, O_RDWR);
g_assert (fd != -1);
if (!test_write_read (fd))
{
close (fd);
return FALSE;
}
close (fd);
return TRUE;
}
#endif
int
main (int argc,
char **argv)
{
MetaAnonymousFile *file;
int fd = -1, other_fd = -1;
g_autofree char *fd_path = NULL;
file = meta_anonymous_file_new (strlen (teststring) + 1,
(const uint8_t *) teststring);
if (!file)
{
g_critical ("%s: Creating file failed", __func__);
return EXIT_FAILURE;
}
#if defined(HAVE_MEMFD_CREATE)
fd = meta_anonymous_file_open_fd (file, META_ANONYMOUS_FILE_MAPMODE_PRIVATE);
g_assert (fd != -1);
other_fd = meta_anonymous_file_open_fd (file, META_ANONYMOUS_FILE_MAPMODE_PRIVATE);
g_assert (other_fd != -1);
/* When MAPMODE_PRIVATE was used, meta_anonymous_file_open_fd() should always
* return the same fd. */
if (other_fd != fd)
goto fail;
/* If memfd_create was used and we request a MAPMODE_PRIVATE file, all the
* readonly seals should be set. */
if (!test_readonly_seals (fd))
goto fail;
if (!test_read_fd_mmap (fd, teststring))
goto fail;
/* Writing and reading the written data should fail */
if (test_write_read (fd))
goto fail;
/* Instead we should still be reading the teststring */
if (!test_read_fd_mmap (fd, teststring))
goto fail;
/* Opening the fd manually in RW mode and writing to it should fail */
fd_path = g_strdup_printf ("/proc/%d/fd/%d", getpid (), fd);
if (test_open_write_read (fd_path))
goto fail;
/* Instead we should still be reading the teststring */
if (!test_read_fd_mmap (fd, teststring))
goto fail;
/* Just to be sure test the other fd, too */
if (!test_read_fd_mmap (other_fd, teststring))
goto fail;
meta_anonymous_file_close_fd (fd);
meta_anonymous_file_close_fd (fd);
fd = meta_anonymous_file_open_fd (file, META_ANONYMOUS_FILE_MAPMODE_SHARED);
g_assert (fd != -1);
other_fd = meta_anonymous_file_open_fd (file, META_ANONYMOUS_FILE_MAPMODE_SHARED);
g_assert (other_fd != -1);
/* The MAPMODE_SHARED fd should not have readonly seals applied */
if (test_readonly_seals (fd))
goto fail;
if (!test_read_fd_mmap (fd, teststring))
goto fail;
if (!test_read_fd_mmap (other_fd, teststring))
goto fail;
/* Writing and reading the written data should succeed */
if (!test_write_read (fd))
goto fail;
/* The other fd should still read the teststring though */
if (!test_read_fd_mmap (other_fd, teststring))
goto fail;
meta_anonymous_file_close_fd (fd);
meta_anonymous_file_close_fd (other_fd);
/* Test an artificial out-of-space situation by setting the maximium file
* size this process may create to 2 bytes, if memfd_create with
* MAPMODE_PRIVATE is used, everything should still work (the existing FD
* should be used). */
struct rlimit limit = {2, 2};
if (setrlimit (RLIMIT_FSIZE, &limit) == -1)
goto fail;
fd = meta_anonymous_file_open_fd (file, META_ANONYMOUS_FILE_MAPMODE_PRIVATE);
g_assert (fd != -1);
if (!test_read_fd_mmap (fd, teststring))
goto fail;
meta_anonymous_file_close_fd (fd);
#else
fd = meta_anonymous_file_open_fd (file, META_ANONYMOUS_FILE_MAPMODE_PRIVATE);
g_assert (fd != -1);
other_fd = meta_anonymous_file_open_fd (file, META_ANONYMOUS_FILE_MAPMODE_PRIVATE);
g_assert (other_fd != -1);
if (test_readonly_seals (fd))
goto fail;
/* Writing and reading the written data should succeed */
if (!test_write_read (fd))
goto fail;
/* The other fd should still read the teststring though */
if (!test_read_fd_mmap (other_fd, teststring))
goto fail;
meta_anonymous_file_close_fd (fd);
meta_anonymous_file_close_fd (other_fd);
fd = meta_anonymous_file_open_fd (file, META_ANONYMOUS_FILE_MAPMODE_SHARED);
g_assert (fd != -1);
other_fd = meta_anonymous_file_open_fd (file, META_ANONYMOUS_FILE_MAPMODE_SHARED);
g_assert (other_fd != -1);
if (test_readonly_seals (fd))
goto fail;
if (!test_read_fd_mmap (fd, teststring))
goto fail;
if (!test_read_fd_mmap (other_fd, teststring))
goto fail;
/* Writing and reading the written data should succeed */
if (!test_write_read (fd))
goto fail;
/* The other fd should still read the teststring though */
if (!test_read_fd_mmap (other_fd, teststring))
goto fail;
meta_anonymous_file_close_fd (fd);
meta_anonymous_file_close_fd (other_fd);
#endif
meta_anonymous_file_free (file);
return EXIT_SUCCESS;
fail:
if (fd > 0)
meta_anonymous_file_close_fd (fd);
if (other_fd > 0)
meta_anonymous_file_close_fd (other_fd);
meta_anonymous_file_free (file);
return EXIT_FAILURE;
}

View File

@@ -48,14 +48,15 @@
#include "config.h"
#include <errno.h>
#include <fcntl.h>
#include <glib.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <unistd.h>
#include "backends/meta-backend-private.h"
#include "core/display-private.h"
#include "core/meta-anonymous-file.h"
#include "wayland/meta-wayland-private.h"
#ifdef HAVE_NATIVE_BACKEND
@@ -78,34 +79,86 @@ unbind_resource (struct wl_resource *resource)
wl_list_remove (wl_resource_get_link (resource));
}
static int
create_anonymous_file (off_t size,
GError **error)
{
static const char template[] = "mutter-shared-XXXXXX";
char *path;
int fd, flags;
fd = g_file_open_tmp (template, &path, error);
if (fd == -1)
return -1;
unlink (path);
g_free (path);
flags = fcntl (fd, F_GETFD);
if (flags == -1)
goto err;
if (fcntl (fd, F_SETFD, flags | FD_CLOEXEC) == -1)
goto err;
if (ftruncate (fd, size) < 0)
goto err;
return fd;
err:
g_set_error_literal (error,
G_FILE_ERROR,
g_file_error_from_errno (errno),
strerror (errno));
close (fd);
return -1;
}
static void
send_keymap (MetaWaylandKeyboard *keyboard,
struct wl_resource *resource)
{
MetaWaylandXkbInfo *xkb_info = &keyboard->xkb_info;
GError *error = NULL;
int fd;
size_t size;
MetaAnonymousFileMapmode mapmode;
char *keymap_area;
if (wl_resource_get_version (resource) < 7)
mapmode = META_ANONYMOUS_FILE_MAPMODE_SHARED;
else
mapmode = META_ANONYMOUS_FILE_MAPMODE_PRIVATE;
if (!xkb_info->keymap_string)
return;
fd = meta_anonymous_file_open_fd (xkb_info->keymap_rofile, mapmode);
size = meta_anonymous_file_size (xkb_info->keymap_rofile);
if (fd == -1)
fd = create_anonymous_file (xkb_info->keymap_size, &error);
if (fd < 0)
{
g_warning ("Creating a keymap file failed: %s", strerror (errno));
g_warning ("Creating a keymap file for %lu bytes failed: %s",
(unsigned long) xkb_info->keymap_size,
error->message);
g_clear_error (&error);
return;
}
keymap_area = mmap (NULL, xkb_info->keymap_size,
PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
if (keymap_area == MAP_FAILED)
{
g_warning ("Failed to mmap() %lu bytes\n",
(unsigned long) xkb_info->keymap_size);
close (fd);
return;
}
strcpy (keymap_area, xkb_info->keymap_string);
munmap (keymap_area, xkb_info->keymap_size);
wl_keyboard_send_keymap (resource,
WL_KEYBOARD_KEYMAP_FORMAT_XKB_V1,
fd, size);
meta_anonymous_file_close_fd (fd);
fd,
keyboard->xkb_info.keymap_size);
close (fd);
}
static void
@@ -124,8 +177,6 @@ meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard,
struct xkb_keymap *keymap)
{
MetaWaylandXkbInfo *xkb_info = &keyboard->xkb_info;
char *keymap_string;
size_t keymap_size;
if (keymap == NULL)
{
@@ -133,30 +184,20 @@ meta_wayland_keyboard_take_keymap (MetaWaylandKeyboard *keyboard,
return;
}
g_clear_pointer (&xkb_info->keymap_string, g_free);
xkb_keymap_unref (xkb_info->keymap);
xkb_info->keymap = xkb_keymap_ref (keymap);
meta_wayland_keyboard_update_xkb_state (keyboard);
keymap_string =
xkb_info->keymap_string =
xkb_keymap_get_as_string (xkb_info->keymap, XKB_KEYMAP_FORMAT_TEXT_V1);
if (!keymap_string)
if (!xkb_info->keymap_string)
{
g_warning ("Failed to get string version of keymap");
return;
}
keymap_size = strlen (keymap_string) + 1;
xkb_info->keymap_rofile =
meta_anonymous_file_new (keymap_size, (const uint8_t *) keymap_string);
free (keymap_string);
if (!xkb_info->keymap_rofile)
{
g_warning ("Failed to create anonymous file for keymap");
return;
}
xkb_info->keymap_size = strlen (xkb_info->keymap_string) + 1;
inform_clients_of_new_keymap (keyboard);
@@ -549,7 +590,7 @@ meta_wayland_xkb_info_destroy (MetaWaylandXkbInfo *xkb_info)
{
g_clear_pointer (&xkb_info->keymap, xkb_keymap_unref);
g_clear_pointer (&xkb_info->state, xkb_state_unref);
meta_anonymous_file_free (xkb_info->keymap_rofile);
g_clear_pointer (&xkb_info->keymap_string, g_free);
}
void

View File

@@ -49,7 +49,6 @@
#include <xkbcommon/xkbcommon.h>
#include "clutter/clutter.h"
#include "core/meta-anonymous-file.h"
#include "wayland/meta-wayland-types.h"
#define META_TYPE_WAYLAND_KEYBOARD (meta_wayland_keyboard_get_type ())
@@ -75,7 +74,8 @@ typedef struct
{
struct xkb_keymap *keymap;
struct xkb_state *state;
MetaAnonymousFile *keymap_rofile;
size_t keymap_size;
char *keymap_string;
} MetaWaylandXkbInfo;
struct _MetaWaylandKeyboard

View File

@@ -46,9 +46,7 @@ typedef struct
{
int display_index;
char *lock_file;
#ifdef __linux__
int abstract_fd;
#endif
int unix_fd;
char *name;
} MetaXWaylandConnection;

View File

@@ -235,7 +235,6 @@ create_lock_file (int display, int *display_out)
return filename;
}
#ifdef __linux__
static int
bind_to_abstract_socket (int display,
gboolean *fatal)
@@ -275,7 +274,6 @@ bind_to_abstract_socket (int display,
return fd;
}
#endif
static int
bind_to_unix_socket (int display)
@@ -383,37 +381,26 @@ meta_xwayland_override_display_number (int number)
static gboolean
open_display_sockets (MetaXWaylandManager *manager,
int display_index,
#ifdef __linux__
int *abstract_fd_out,
#endif
int *unix_fd_out,
gboolean *fatal)
{
#ifdef __linux__
int abstract_fd;
#endif
int unix_fd;
int abstract_fd, unix_fd;
#ifdef __linux__
abstract_fd = bind_to_abstract_socket (display_index,
fatal);
if (abstract_fd < 0)
return FALSE;
#endif
unix_fd = bind_to_unix_socket (display_index);
if (unix_fd < 0)
{
*fatal = FALSE;
#ifdef __linux__
close (abstract_fd);
#endif
return FALSE;
}
#ifdef __linux__
*abstract_fd_out = abstract_fd;
#endif
*unix_fd_out = unix_fd;
return TRUE;
@@ -442,9 +429,7 @@ choose_xdisplay (MetaXWaylandManager *manager,
}
if (!open_display_sockets (manager, display,
#ifdef __linux__
&connection->abstract_fd,
#endif
&connection->unix_fd,
&fatal))
{
@@ -632,14 +617,10 @@ meta_xwayland_start_xserver (MetaXWaylandManager *manager,
launcher = g_subprocess_launcher_new (flags);
g_subprocess_launcher_take_fd (launcher, xwayland_client_fd[1], 3);
g_subprocess_launcher_take_fd (launcher, displayfd[1], 4);
g_subprocess_launcher_take_fd (launcher, manager->public_connection.abstract_fd, 4);
g_subprocess_launcher_take_fd (launcher, manager->public_connection.unix_fd, 5);
#ifdef __linux__
g_subprocess_launcher_take_fd (launcher, manager->private_connection.abstract_fd, 6);
g_subprocess_launcher_take_fd (launcher, manager->public_connection.abstract_fd, 7);
#else
g_subprocess_launcher_take_fd (launcher, manager->private_connection.unix_fd, 6);
#endif
g_subprocess_launcher_take_fd (launcher, displayfd[1], 6);
g_subprocess_launcher_take_fd (launcher, manager->private_connection.abstract_fd, 7);
g_subprocess_launcher_setenv (launcher, "WAYLAND_SOCKET", "3", TRUE);
@@ -651,14 +632,12 @@ meta_xwayland_start_xserver (MetaXWaylandManager *manager,
"-accessx",
"-core",
"-auth", manager->auth_file,
"-displayfd", "4",
"-listen", "4",
"-listen", "5",
"-displayfd", "6",
#ifdef HAVE_XWAYLAND_INITFD
"-initfd", "6",
"-initfd", "7",
#else
"-listen", "6",
#endif
#ifdef __linux__
"-listen", "7",
#endif
NULL);
@@ -777,18 +756,14 @@ meta_xwayland_init (MetaXWaylandManager *manager,
{
if (!open_display_sockets (manager,
manager->public_connection.display_index,
#ifdef __linux__
&manager->public_connection.abstract_fd,
#endif
&manager->public_connection.unix_fd,
&fatal))
return FALSE;
if (!open_display_sockets (manager,
manager->private_connection.display_index,
#ifdef __linux__
&manager->private_connection.abstract_fd,
#endif
&manager->private_connection.unix_fd,
&fatal))
return FALSE;
@@ -799,13 +774,8 @@ meta_xwayland_init (MetaXWaylandManager *manager,
if (policy == META_DISPLAY_POLICY_ON_DEMAND)
{
#ifdef __linux__
g_unix_fd_add (manager->public_connection.abstract_fd, G_IO_IN,
xdisplay_connection_activity_cb, manager);
#else
g_unix_fd_add (manager->public_connection.unix_fd, G_IO_IN,
xdisplay_connection_activity_cb, manager);
#endif
}
return TRUE;

View File

@@ -127,6 +127,7 @@ struct _MetaX11Display
struct {
Window xwindow;
uint32_t ownership_timestamp;
MetaSelectionSource *owners[META_N_SELECTION_TYPES];
GCancellable *cancellables[META_N_SELECTION_TYPES];

View File

@@ -24,7 +24,6 @@
#include <gdk/gdkx.h>
#include "core/meta-selection-private.h"
#include "meta/meta-selection-source-memory.h"
#include "x11/meta-selection-source-x11-private.h"
#include "x11/meta-x11-selection-output-stream-private.h"
#include "x11/meta-x11-selection-private.h"
@@ -32,13 +31,6 @@
#define UTF8_STRING_MIMETYPE "text/plain;charset=utf-8"
#define STRING_MIMETYPE "text/plain"
/* Set an arbitrary (although generous) threshold to determine whether a
* XFixesSelectionNotify corresponds to a XSetSelectionOwner from another
* client. The selection timestamp is not updated if the owner client is
* closed.
*/
#define SELECTION_CLEARED_BY_CLIENT(e) (e->timestamp - e->selection_timestamp < 50)
static gboolean
atom_to_selection_type (Display *xdisplay,
Atom selection,
@@ -305,8 +297,8 @@ source_new_cb (GObject *object,
source = meta_selection_source_x11_new_finish (res, &error);
if (source)
{
g_set_object (&x11_display->selection.owners[selection_type], source);
meta_selection_set_owner (selection, selection_type, source);
g_set_object (&x11_display->selection.owners[selection_type], source);
g_object_unref (source);
}
else if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
@@ -330,6 +322,7 @@ meta_x11_selection_handle_xfixes_selection_notify (MetaX11Display *x11_display,
if (!atom_to_selection_type (xdisplay, event->selection, &selection_type))
return FALSE;
x11_display->selection.ownership_timestamp = event->selection_timestamp;
selection = meta_display_get_selection (meta_get_display ());
if (x11_display->selection.cancellables[selection_type])
@@ -340,19 +333,9 @@ meta_x11_selection_handle_xfixes_selection_notify (MetaX11Display *x11_display,
x11_display->selection.cancellables[selection_type] = g_cancellable_new ();
if (event->owner == None && x11_display->selection.owners[selection_type])
if (event->owner == None)
{
if (SELECTION_CLEARED_BY_CLIENT (event))
{
MetaSelectionSource *source;
/* Replace with an empty owner */
source = g_object_new (META_TYPE_SELECTION_SOURCE_MEMORY, NULL);
g_set_object (&x11_display->selection.owners[selection_type], source);
meta_selection_set_owner (selection, selection_type, source);
g_object_unref (source);
}
else
if (x11_display->selection.owners[selection_type])
{
/* An X client went away, clear the selection */
meta_selection_unset_owner (selection, selection_type,
@@ -360,7 +343,7 @@ meta_x11_selection_handle_xfixes_selection_notify (MetaX11Display *x11_display,
g_clear_object (&x11_display->selection.owners[selection_type]);
}
}
else if (event->owner != None && event->owner != x11_display->selection.xwindow)
else if (event->owner != x11_display->selection.xwindow)
{
SourceNewData *data;
@@ -378,6 +361,8 @@ meta_x11_selection_handle_xfixes_selection_notify (MetaX11Display *x11_display,
data);
}
x11_display->selection.ownership_timestamp = 0;
return TRUE;
}
@@ -399,8 +384,9 @@ notify_selection_owner (MetaX11Display *x11_display,
MetaSelectionSource *new_owner)
{
Display *xdisplay = x11_display->xdisplay;
uint32_t timestamp;
if (new_owner && new_owner != x11_display->selection.owners[selection_type])
if (new_owner && !META_IS_SELECTION_SOURCE_X11 (new_owner))
{
if (x11_display->selection.cancellables[selection_type])
{
@@ -408,13 +394,17 @@ notify_selection_owner (MetaX11Display *x11_display,
g_clear_object (&x11_display->selection.cancellables[selection_type]);
}
timestamp = x11_display->selection.ownership_timestamp ?
x11_display->selection.ownership_timestamp :
meta_display_get_current_time (x11_display->display);
/* If the owner is non-X11, claim the selection on our selection
* window, so X11 apps can interface with it.
*/
XSetSelectionOwner (xdisplay,
selection_to_atom (selection_type, xdisplay),
x11_display->selection.xwindow,
META_CURRENT_TIME);
timestamp);
}
}