diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d71c898 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/mutter-3.32.2.tar.xz diff --git a/.mutter.metadata b/.mutter.metadata new file mode 100644 index 0000000..9e3c1a4 --- /dev/null +++ b/.mutter.metadata @@ -0,0 +1 @@ +5068f43514a6212e4b5b5f7f856b7713cbc3d420 SOURCES/mutter-3.32.2.tar.xz diff --git a/SOURCES/0001-Add-support-for-quad-buffer-stereo.patch b/SOURCES/0001-Add-support-for-quad-buffer-stereo.patch new file mode 100644 index 0000000..397dc41 --- /dev/null +++ b/SOURCES/0001-Add-support-for-quad-buffer-stereo.patch @@ -0,0 +1,907 @@ +From d0ad5ea18bb02112837bcdf7270d58d8ad235a4d Mon Sep 17 00:00:00 2001 +From: "Owen W. Taylor" +Date: Thu, 8 May 2014 18:44:15 -0400 +Subject: [PATCH] Add support for quad-buffer stereo + +Track the stereo status of windows using the new EXT_stereo_tree +GLX extension. + +When stereo is enabled or disabled, a restart is triggered via +meta_restart() after a timeout, setting a _META_ENABLE_STEREO +property on the root window to indicate whether we should +turn on a stereo stage for clutter. The property avoids a loop, +since we need to enable stereo *before* initializing Clutter and GL, +but we need GL to figure out whether we have stereo windows. + +Stereo windows are drawn to the stage using new functionality +in Cogl to setup a stereo context, select which buffer to draw +to, and draw either the left or right buffer of a stereo +texture_from_pixmap. +--- + src/compositor/compositor-private.h | 9 ++ + src/compositor/compositor.c | 125 +++++++++++++++ + src/compositor/meta-shaped-texture-private.h | 5 +- + src/compositor/meta-shaped-texture.c | 84 +++++++++- + src/compositor/meta-surface-actor-wayland.c | 2 +- + src/compositor/meta-surface-actor-x11.c | 54 ++++++- + src/compositor/meta-surface-actor-x11.h | 5 + + src/compositor/meta-window-actor-private.h | 5 + + src/compositor/meta-window-actor.c | 22 +++ + src/core/main.c | 4 + + src/core/stereo.c | 154 +++++++++++++++++++ + src/core/stereo.h | 28 ++++ + src/meson.build | 2 + + src/wayland/meta-wayland-surface.c | 2 +- + 14 files changed, 481 insertions(+), 20 deletions(-) + create mode 100644 src/core/stereo.c + create mode 100644 src/core/stereo.h + +diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h +index 6ab33416c..f70087512 100644 +--- a/src/compositor/compositor-private.h ++++ b/src/compositor/compositor-private.h +@@ -24,6 +24,10 @@ struct _MetaCompositor + gint64 server_time_query_time; + gint64 server_time_offset; + ++ int glx_opcode; ++ guint stereo_tree_ext : 1; ++ guint have_stereo_windows : 1; ++ + guint server_time_is_monotonic_time : 1; + + ClutterActor *stage, *window_group, *top_window_group, *feedback_group; +@@ -63,6 +67,11 @@ void meta_end_modal_for_plugin (MetaCompositor *compositor, + gint64 meta_compositor_monotonic_time_to_server_time (MetaDisplay *display, + gint64 monotonic_time); + ++gboolean meta_compositor_window_is_stereo (MetaDisplay *display, ++ Window xwindow); ++void meta_compositor_select_stereo_notify (MetaDisplay *display, ++ Window xwindow); ++ + void meta_compositor_flash_window (MetaCompositor *compositor, + MetaWindow *window); + +diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c +index 2a2c8fb3b..6c08c8fe4 100644 +--- a/src/compositor/compositor.c ++++ b/src/compositor/compositor.c +@@ -69,6 +69,8 @@ + #include "core/core.h" + #include "core/display-private.h" + #include "core/frame.h" ++#include "core/stack-tracker.h" ++#include "core/stereo.h" + #include "core/util-private.h" + #include "core/window-private.h" + #include "meta/compositor-mutter.h" +@@ -514,6 +516,94 @@ redirect_windows (MetaX11Display *x11_display) + } + } + ++#define GLX_STEREO_TREE_EXT 0x20F5 ++#define GLX_STEREO_NOTIFY_MASK_EXT 0x00000001 ++#define GLX_STEREO_NOTIFY_EXT 0x00000000 ++ ++typedef struct { ++ int type; ++ unsigned long serial; ++ Bool send_event; ++ Display *display; ++ int extension; ++ int evtype; ++ Drawable window; ++ Bool stereo_tree; ++} StereoNotifyEvent; ++ ++static gboolean ++display_has_stereo_tree_ext (MetaX11Display *x11_display) ++{ ++ Display *xdisplay = x11_display->xdisplay; ++ const char *extensions_string; ++ ++ static const char * (*query_extensions_string) (Display *display, ++ int screen); ++ ++ if (query_extensions_string == NULL) ++ query_extensions_string = ++ (const char * (*) (Display *, int)) ++ cogl_get_proc_address ("glXQueryExtensionsString"); ++ ++ extensions_string = query_extensions_string (xdisplay, ++ meta_x11_display_get_screen_number (x11_display)); ++ ++ return extensions_string && strstr (extensions_string, "EXT_stereo_tree") != 0; ++} ++ ++#include ++ ++gboolean ++meta_compositor_window_is_stereo (MetaDisplay *display, ++ Window xwindow) ++{ ++ MetaCompositor *compositor = get_compositor_for_display (display); ++ Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display); ++ ++ static int (*query_drawable) (Display *dpy, ++ Drawable draw, ++ int attribute, ++ unsigned int *value); ++ ++ if (compositor->stereo_tree_ext) ++ { ++ unsigned int stereo_tree = 0; ++ ++ if (query_drawable == NULL) ++ query_drawable = ++ (int (*) (Display *, Drawable, int, unsigned int *)) ++ cogl_get_proc_address ("glXQueryDrawable"); ++ ++ query_drawable (xdisplay, xwindow, GLX_STEREO_TREE_EXT, &stereo_tree); ++ ++ return stereo_tree != 0; ++ } ++ else ++ return FALSE; ++} ++ ++void ++meta_compositor_select_stereo_notify (MetaDisplay *display, ++ Window xwindow) ++{ ++ MetaCompositor *compositor = get_compositor_for_display (display); ++ Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display); ++ ++ static void (*select_event) (Display *dpy, ++ Drawable draw, ++ unsigned long event_mask); ++ ++ if (compositor->stereo_tree_ext) ++ { ++ if (select_event == NULL) ++ select_event = ++ (void (*) (Display *, Drawable, unsigned long)) ++ cogl_get_proc_address ("glXSelectEvent"); ++ ++ select_event (xdisplay, xwindow, GLX_STEREO_NOTIFY_MASK_EXT); ++ } ++} ++ + void + meta_compositor_manage (MetaCompositor *compositor) + { +@@ -525,6 +615,8 @@ meta_compositor_manage (MetaCompositor *compositor) + { + xdisplay = display->x11_display->xdisplay; + meta_x11_display_set_cm_selection (display->x11_display); ++ ++ compositor->stereo_tree_ext = display_has_stereo_tree_ext (display->x11_display); + } + + compositor->stage = meta_backend_get_stage (backend); +@@ -822,6 +914,23 @@ meta_compositor_process_event (MetaCompositor *compositor, + if (window) + process_damage (compositor, (XDamageNotifyEvent *) event, window); + } ++ else if (!meta_is_wayland_compositor () && ++ event->type == GenericEvent && ++ event->xcookie.extension == compositor->glx_opcode) ++ { ++ if (event->xcookie.evtype == GLX_STEREO_NOTIFY_EXT) ++ { ++ StereoNotifyEvent *stereo_event = (StereoNotifyEvent *)(event->xcookie.data); ++ window = meta_x11_display_lookup_x_window (x11_display, stereo_event->window); ++ ++ if (window != NULL) ++ { ++ MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window)); ++ meta_window_actor_stereo_notify (window_actor, stereo_event->stereo_tree); ++ meta_stack_tracker_queue_sync_stack (window->display->stack_tracker); ++ } ++ } ++ } + + if (compositor->have_x11_sync_object) + meta_sync_ring_handle_event (event); +@@ -1038,6 +1147,7 @@ meta_compositor_sync_stack (MetaCompositor *compositor, + GList *stack) + { + GList *old_stack; ++ int stereo_window_count = 0; + + /* This is painful because hidden windows that we are in the process + * of animating out of existence. They'll be at the bottom of the +@@ -1113,6 +1223,8 @@ meta_compositor_sync_stack (MetaCompositor *compositor, + * near the front of the other.) + */ + compositor->windows = g_list_prepend (compositor->windows, actor); ++ if (meta_window_actor_is_stereo (actor)) ++ stereo_window_count++; + + stack = g_list_remove (stack, window); + old_stack = g_list_remove (old_stack, actor); +@@ -1120,6 +1232,8 @@ meta_compositor_sync_stack (MetaCompositor *compositor, + + sync_actor_stacking (compositor); + ++ meta_stereo_set_have_stereo_windows (stereo_window_count > 0); ++ + if (compositor->top_window_actor) + g_signal_handlers_disconnect_by_func (compositor->top_window_actor, + on_top_window_actor_destroyed, +@@ -1325,6 +1439,17 @@ meta_compositor_new (MetaDisplay *display) + meta_post_paint_func, + compositor, + NULL); ++ if (!meta_is_wayland_compositor ()) ++ { ++ Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display); ++ int glx_major_opcode, glx_first_event, glx_first_error; ++ ++ if (XQueryExtension (xdisplay, ++ "GLX", ++ &glx_major_opcode, &glx_first_event, &glx_first_error)) ++ compositor->glx_opcode = glx_major_opcode; ++ } ++ + return compositor; + } + +diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h +index a86a2bff0..d0efdd4dc 100644 +--- a/src/compositor/meta-shaped-texture-private.h ++++ b/src/compositor/meta-shaped-texture-private.h +@@ -31,8 +31,9 @@ + #include "meta/meta-shaped-texture.h" + + ClutterActor *meta_shaped_texture_new (void); +-void meta_shaped_texture_set_texture (MetaShapedTexture *stex, +- CoglTexture *texture); ++void meta_shaped_texture_set_textures (MetaShapedTexture *stex, ++ CoglTexture *texture, ++ CoglTexture *texture_right); + void meta_shaped_texture_set_is_y_inverted (MetaShapedTexture *stex, + gboolean is_y_inverted); + void meta_shaped_texture_set_snippet (MetaShapedTexture *stex, +diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c +index ea8daa03d..9a00ccd6d 100644 +--- a/src/compositor/meta-shaped-texture.c ++++ b/src/compositor/meta-shaped-texture.c +@@ -102,8 +102,10 @@ struct _MetaShapedTexture + ClutterActor parent; + + MetaTextureTower *paint_tower; ++ MetaTextureTower *paint_tower_right; + + CoglTexture *texture; ++ CoglTexture *texture_right; + CoglTexture *mask_texture; + CoglSnippet *snippet; + +@@ -192,6 +194,7 @@ meta_shaped_texture_init (MetaShapedTexture *stex) + clutter_backend_get_cogl_context (clutter_backend); + + stex->paint_tower = meta_texture_tower_new (); ++ stex->paint_tower_right = NULL; /* demand create */ + + stex->texture = NULL; + stex->mask_texture = NULL; +@@ -335,6 +338,9 @@ meta_shaped_texture_dispose (GObject *object) + meta_texture_tower_free (stex->paint_tower); + stex->paint_tower = NULL; + ++ g_clear_pointer (&stex->paint_tower, meta_texture_tower_free); ++ g_clear_pointer (&stex->paint_tower_right, meta_texture_tower_free); ++ + g_clear_pointer (&stex->texture, cogl_object_unref); + g_clear_pointer (&stex->opaque_region, cairo_region_destroy); + +@@ -611,8 +617,9 @@ paint_clipped_rectangle (MetaShapedTexture *stex, + } + + static void +-set_cogl_texture (MetaShapedTexture *stex, +- CoglTexture *cogl_tex) ++set_cogl_textures (MetaShapedTexture *stex, ++ CoglTexture *cogl_tex, ++ CoglTexture *cogl_tex_right) + { + int width, height; + +@@ -620,10 +627,13 @@ set_cogl_texture (MetaShapedTexture *stex, + + if (stex->texture) + cogl_object_unref (stex->texture); ++ if (stex->texture_right) ++ cogl_object_unref (stex->texture_right); + + g_clear_pointer (&stex->saved_base_surface, cairo_surface_destroy); + + stex->texture = cogl_tex; ++ stex->texture_right = cogl_tex_right; + + if (cogl_tex != NULL) + { +@@ -637,6 +647,9 @@ set_cogl_texture (MetaShapedTexture *stex, + height = 0; + } + ++ if (cogl_tex_right != NULL) ++ cogl_object_ref (cogl_tex_right); ++ + if (stex->tex_width != width || + stex->tex_height != height) + { +@@ -650,8 +663,23 @@ set_cogl_texture (MetaShapedTexture *stex, + * previous buffer. We only queue a redraw in response to surface + * damage. */ + ++ if (cogl_tex_right != NULL) ++ { ++ if (stex->paint_tower_right == NULL) ++ stex->paint_tower_right = meta_texture_tower_new (); ++ } ++ else ++ { ++ g_clear_pointer (&stex->paint_tower_right, meta_texture_tower_free); ++ } ++ + if (stex->create_mipmaps) +- meta_texture_tower_set_base_texture (stex->paint_tower, cogl_tex); ++ { ++ meta_texture_tower_set_base_texture (stex->paint_tower, cogl_tex); ++ ++ if (stex->paint_tower_right) ++ meta_texture_tower_set_base_texture (stex->paint_tower_right, cogl_tex_right); ++ } + } + + static gboolean +@@ -927,7 +955,9 @@ meta_shaped_texture_paint (ClutterActor *actor) + { + MetaShapedTexture *stex = META_SHAPED_TEXTURE (actor); + CoglTexture *paint_tex; ++ CoglTexture *paint_tex_right = NULL; + CoglFramebuffer *fb; ++ gboolean stereo; + + if (!stex->texture) + return; +@@ -989,7 +1019,32 @@ meta_shaped_texture_paint (ClutterActor *actor) + return; + + fb = cogl_get_draw_framebuffer (); +- do_paint (META_SHAPED_TEXTURE (actor), fb, paint_tex, stex->clip_region); ++ ++ stereo = stex->texture_right && cogl_framebuffer_get_is_stereo (fb); ++ ++ if (stereo) ++ { ++ if (stex->create_mipmaps) ++ paint_tex_right = meta_texture_tower_get_paint_texture (stex->paint_tower_right); ++ ++ if (!paint_tex_right) ++ paint_tex_right = COGL_TEXTURE (stex->texture_right); ++ } ++ else ++ paint_tex_right = NULL; ++ ++ if (stereo) ++ cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_LEFT); ++ do_paint (stex, fb, paint_tex, stex->clip_region); ++ if (stereo) ++ cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_BOTH); ++ ++ if (paint_tex_right != NULL) ++ { ++ cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_RIGHT); ++ do_paint (stex, fb, paint_tex_right, stex->clip_region); ++ cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_BOTH); ++ } + } + + static void +@@ -1063,6 +1118,12 @@ meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex, + stex->create_mipmaps = create_mipmaps; + base_texture = create_mipmaps ? stex->texture : NULL; + meta_texture_tower_set_base_texture (stex->paint_tower, base_texture); ++ ++ if (stex->paint_tower_right) ++ { ++ base_texture = create_mipmaps ? stex->texture_right : NULL; ++ meta_texture_tower_set_base_texture (stex->paint_tower_right, base_texture); ++ } + } + } + +@@ -1256,6 +1317,12 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, + clip.y, + clip.width, + clip.height); ++ if (stex->paint_tower_right) ++ meta_texture_tower_update_area (stex->paint_tower_right, ++ clip.x, ++ clip.y, ++ clip.width, ++ clip.height); + + stex->prev_invalidation = stex->last_invalidation; + stex->last_invalidation = g_get_monotonic_time (); +@@ -1302,17 +1369,18 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, + } + + /** +- * meta_shaped_texture_set_texture: ++ * meta_shaped_texture_set_textures: + * @stex: The #MetaShapedTexture + * @pixmap: The #CoglTexture to display + */ + void +-meta_shaped_texture_set_texture (MetaShapedTexture *stex, +- CoglTexture *texture) ++meta_shaped_texture_set_textures (MetaShapedTexture *stex, ++ CoglTexture *texture, ++ CoglTexture *texture_right) + { + g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); + +- set_cogl_texture (stex, texture); ++ set_cogl_textures (stex, texture, texture_right); + } + + /** +diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c +index f8d6c32b7..a75c4dd09 100644 +--- a/src/compositor/meta-surface-actor-wayland.c ++++ b/src/compositor/meta-surface-actor-wayland.c +@@ -182,7 +182,7 @@ meta_surface_actor_wayland_dispose (GObject *object) + MetaShapedTexture *stex = + meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); + +- meta_shaped_texture_set_texture (stex, NULL); ++ meta_shaped_texture_set_textures (stex, NULL, NULL); + if (self->surface) + { + g_object_remove_weak_pointer (G_OBJECT (self->surface), +diff --git a/src/compositor/meta-surface-actor-x11.c b/src/compositor/meta-surface-actor-x11.c +index 244b1e885..3cd164d77 100644 +--- a/src/compositor/meta-surface-actor-x11.c ++++ b/src/compositor/meta-surface-actor-x11.c +@@ -32,6 +32,7 @@ + #include "cogl/winsys/cogl-texture-pixmap-x11.h" + #include "compositor/meta-cullable.h" + #include "compositor/meta-shaped-texture-private.h" ++#include "compositor-private.h" + #include "core/window-private.h" + #include "meta/meta-x11-errors.h" + #include "x11/meta-x11-display-private.h" +@@ -46,6 +47,7 @@ struct _MetaSurfaceActorX11 + MetaDisplay *display; + + CoglTexture *texture; ++ CoglTexture *texture_right; + Pixmap pixmap; + Damage damage; + +@@ -61,6 +63,8 @@ struct _MetaSurfaceActorX11 + guint size_changed : 1; + + guint unredirected : 1; ++ ++ guint stereo : 1; + }; + + G_DEFINE_TYPE (MetaSurfaceActorX11, +@@ -96,7 +100,7 @@ detach_pixmap (MetaSurfaceActorX11 *self) + * you are supposed to be able to free a GLXPixmap after freeing the underlying + * pixmap, but it certainly doesn't work with current DRI/Mesa + */ +- meta_shaped_texture_set_texture (stex, NULL); ++ meta_shaped_texture_set_textures (stex, NULL, NULL); + cogl_flush (); + + meta_x11_error_trap_push (display->x11_display); +@@ -105,6 +109,7 @@ detach_pixmap (MetaSurfaceActorX11 *self) + meta_x11_error_trap_pop (display->x11_display); + + g_clear_pointer (&self->texture, cogl_object_unref); ++ g_clear_pointer (&self->texture_right, cogl_object_unref); + } + + static void +@@ -114,23 +119,37 @@ set_pixmap (MetaSurfaceActorX11 *self, + CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); + MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); + CoglError *error = NULL; +- CoglTexture *texture; ++ CoglTexturePixmapX11 *texture; ++ CoglTexturePixmapX11 *texture_right; + + g_assert (self->pixmap == None); + self->pixmap = pixmap; + +- texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, self->pixmap, FALSE, &error)); ++ if (self->stereo) ++ texture = cogl_texture_pixmap_x11_new_left (ctx, pixmap, FALSE, &error); ++ else ++ texture = cogl_texture_pixmap_x11_new (ctx, pixmap, FALSE, &error); ++ ++ if (self->stereo) ++ texture_right = cogl_texture_pixmap_x11_new_right (texture); ++ else ++ texture_right = NULL; + + if (error != NULL) + { + g_warning ("Failed to allocate stex texture: %s", error->message); + cogl_error_free (error); + } +- else if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture)))) ++ else if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (texture))) + g_warning ("NOTE: Not using GLX TFP!\n"); + +- self->texture = texture; +- meta_shaped_texture_set_texture (stex, texture); ++ self->texture = COGL_TEXTURE (texture); ++ if (self->stereo) ++ self->texture_right = COGL_TEXTURE (texture_right); ++ ++ meta_shaped_texture_set_textures (stex, ++ COGL_TEXTURE (texture), ++ COGL_TEXTURE (texture_right));; + } + + static void +@@ -419,8 +438,8 @@ reset_texture (MetaSurfaceActorX11 *self) + /* Setting the texture to NULL will cause all the FBO's cached by the + * shaped texture's MetaTextureTower to be discarded and recreated. + */ +- meta_shaped_texture_set_texture (stex, NULL); +- meta_shaped_texture_set_texture (stex, self->texture); ++ meta_shaped_texture_set_textures (stex, NULL, NULL); ++ meta_shaped_texture_set_textures (stex, self->texture, self->texture_right); + } + + MetaSurfaceActor * +@@ -428,12 +447,17 @@ meta_surface_actor_x11_new (MetaWindow *window) + { + MetaSurfaceActorX11 *self = g_object_new (META_TYPE_SURFACE_ACTOR_X11, NULL); + MetaDisplay *display = meta_window_get_display (window); ++ Window xwindow; + + g_assert (!meta_is_wayland_compositor ()); + + self->window = window; + self->display = display; + ++ xwindow = meta_window_x11_get_toplevel_xwindow (window); ++ self->stereo = meta_compositor_window_is_stereo (display, xwindow); ++ meta_compositor_select_stereo_notify (display, xwindow); ++ + g_signal_connect_object (self->display, "gl-video-memory-purged", + G_CALLBACK (reset_texture), self, G_CONNECT_SWAPPED); + +@@ -463,3 +487,17 @@ meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self, + self->last_height = height; + meta_shaped_texture_set_fallback_size (stex, width, height); + } ++ ++void ++meta_surface_actor_x11_stereo_notify (MetaSurfaceActorX11 *self, ++ gboolean stereo_tree) ++{ ++ self->stereo = stereo_tree != FALSE; ++ detach_pixmap (self); ++} ++ ++gboolean ++meta_surface_actor_x11_is_stereo (MetaSurfaceActorX11 *self) ++{ ++ return self->stereo; ++} +diff --git a/src/compositor/meta-surface-actor-x11.h b/src/compositor/meta-surface-actor-x11.h +index 2c4ed4dd6..3bdd5fdb0 100644 +--- a/src/compositor/meta-surface-actor-x11.h ++++ b/src/compositor/meta-surface-actor-x11.h +@@ -47,6 +47,11 @@ MetaSurfaceActor * meta_surface_actor_x11_new (MetaWindow *window); + void meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self, + int width, int height); + ++void meta_surface_actor_x11_stereo_notify (MetaSurfaceActorX11 *self, ++ gboolean stereo_tree); ++ ++gboolean meta_surface_actor_x11_is_stereo (MetaSurfaceActorX11 *self); ++ + G_END_DECLS + + #endif /* __META_SURFACE_ACTOR_X11_H__ */ +diff --git a/src/compositor/meta-window-actor-private.h b/src/compositor/meta-window-actor-private.h +index 6333f43db..9c1c12d09 100644 +--- a/src/compositor/meta-window-actor-private.h ++++ b/src/compositor/meta-window-actor-private.h +@@ -76,4 +76,9 @@ MetaSurfaceActor *meta_window_actor_get_surface (MetaWindowActor *self); + void meta_window_actor_update_surface (MetaWindowActor *self); + MetaWindowActor *meta_window_actor_from_window (MetaWindow *window); + ++void meta_window_actor_stereo_notify (MetaWindowActor *actor, ++ gboolean stereo_tree); ++ ++gboolean meta_window_actor_is_stereo (MetaWindowActor *actor); ++ + #endif /* META_WINDOW_ACTOR_PRIVATE_H */ +diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c +index 1c8dc8fe5..11686d00b 100644 +--- a/src/compositor/meta-window-actor.c ++++ b/src/compositor/meta-window-actor.c +@@ -2031,3 +2031,25 @@ screen_cast_window_iface_init (MetaScreenCastWindowInterface *iface) + iface->capture_into = meta_window_actor_capture_into; + iface->has_damage = meta_window_actor_has_damage; + } ++ ++void ++meta_window_actor_stereo_notify (MetaWindowActor *self, ++ gboolean stereo_tree) ++{ ++ MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private (self); ++ ++ if (META_IS_SURFACE_ACTOR_X11 (priv->surface)) ++ meta_surface_actor_x11_stereo_notify (META_SURFACE_ACTOR_X11 (priv->surface), ++ stereo_tree); ++} ++ ++gboolean ++meta_window_actor_is_stereo (MetaWindowActor *self) ++{ ++ MetaWindowActorPrivate *priv = meta_window_actor_get_instance_private (self); ++ ++ if (META_IS_SURFACE_ACTOR_X11 (priv->surface)) ++ return meta_surface_actor_x11_is_stereo (META_SURFACE_ACTOR_X11 (priv->surface)); ++ else ++ return FALSE; ++} +diff --git a/src/core/main.c b/src/core/main.c +index e8464720f..629f8e94e 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -81,6 +81,7 @@ + #include "meta/meta-backend.h" + #include "meta/meta-x11-errors.h" + #include "meta/prefs.h" ++#include "stereo.h" + #include "ui/ui.h" + #include "x11/session.h" + +@@ -589,6 +590,9 @@ meta_init (void) + + meta_init_backend (backend_gtype); + ++ if (!meta_is_wayland_compositor ()) ++ meta_stereo_init (); ++ + meta_clutter_init (); + + #ifdef HAVE_WAYLAND +diff --git a/src/core/stereo.c b/src/core/stereo.c +new file mode 100644 +index 000000000..817056527 +--- /dev/null ++++ b/src/core/stereo.c +@@ -0,0 +1,154 @@ ++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ ++ ++/* ++ * Copyright (C) 2014 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, see . ++ */ ++ ++/* ++ * SECTION:stereo ++ * @short_description: Keep track of whether we are a stereo compositor ++ * ++ * With GLX, we need to use a different GL context for stereo and ++ * non-stereo support. Support for multiple GL contexts is unfinished ++ * in Cogl and entirely lacking in Clutter, so it's by far easier ++ * to just restart Mutter when we detect a stereo window. ++ * ++ * A property _MUTTER_ENABLE_STEREO is maintained on the root window ++ * to know whether we should initialize clutter for stereo or not. ++ * When the presence or absence of stereo windows mismatches the ++ * stereo-enabled state for a sufficiently long period of time, ++ * we restart Mutter. ++ */ ++ ++#include ++ ++#include ++#include ++#include ++ ++#include "display-private.h" ++#include ++#include ++#include ++#include "stereo.h" ++#include "ui/ui.h" ++#include "util-private.h" ++ ++static guint stereo_switch_id = 0; ++static gboolean stereo_enabled = FALSE; ++/* -1 so the first time meta_stereo_set_have_stereo_windows() is called ++ * we avoid the short-circuit and set up a timeout to restart ++ * if necessary */ ++static gboolean stereo_have_windows = (gboolean)-1; ++static gboolean stereo_restart = FALSE; ++ ++#define STEREO_ENABLE_WAIT 1000 ++#define STEREO_DISABLE_WAIT 5000 ++ ++void ++meta_stereo_init (void) ++{ ++ Display *xdisplay; ++ Window root; ++ Atom atom_enable_stereo; ++ Atom type; ++ int format; ++ unsigned long n_items, bytes_after; ++ guchar *data; ++ ++ xdisplay = XOpenDisplay (NULL); ++ if (xdisplay == NULL) ++ meta_fatal ("Unable to open X display %s\n", XDisplayName (NULL)); ++ ++ root = DefaultRootWindow (xdisplay); ++ atom_enable_stereo = XInternAtom (xdisplay, "_MUTTER_ENABLE_STEREO", False); ++ ++ XGetWindowProperty (xdisplay, root, atom_enable_stereo, ++ 0, 1, False, XA_INTEGER, ++ &type, &format, &n_items, &bytes_after, &data); ++ if (type == XA_INTEGER) ++ { ++ if (format == 32 && n_items == 1 && bytes_after == 0) ++ { ++ stereo_enabled = *(long *)data; ++ } ++ else ++ { ++ meta_warning ("Bad value for _MUTTER_ENABLE_STEREO property\n"); ++ } ++ ++ XFree (data); ++ } ++ else if (type != None) ++ { ++ meta_warning ("Bad type for _MUTTER_ENABLE_STEREO property\n"); ++ } ++ ++ meta_verbose ("On startup, _MUTTER_ENABLE_STEREO=%s", ++ stereo_enabled ? "yes" : "no"); ++ clutter_x11_set_use_stereo_stage (stereo_enabled); ++ XCloseDisplay (xdisplay); ++} ++ ++static gboolean ++meta_stereo_switch (gpointer data) ++{ ++ stereo_switch_id = 0; ++ stereo_restart = TRUE; ++ ++ meta_restart (stereo_have_windows ? ++ _("Enabling stereo...") : ++ _("Disabling stereo...")); ++ ++ return FALSE; ++} ++ ++void ++meta_stereo_set_have_stereo_windows (gboolean have_windows) ++{ ++ have_windows = have_windows != FALSE; ++ ++ if (!stereo_restart && have_windows != stereo_have_windows) ++ { ++ MetaDisplay *display = meta_get_display (); ++ Display *xdisplay = meta_x11_display_get_xdisplay (display->x11_display); ++ Window root = DefaultRootWindow (xdisplay); ++ Atom atom_enable_stereo = XInternAtom (xdisplay, "_MUTTER_ENABLE_STEREO", False); ++ long value; ++ ++ stereo_have_windows = have_windows; ++ ++ if (stereo_have_windows) ++ meta_verbose ("Detected stereo windows\n"); ++ else ++ meta_verbose ("No stereo windows detected\n"); ++ ++ value = stereo_have_windows; ++ XChangeProperty (xdisplay, root, ++ atom_enable_stereo, XA_INTEGER, 32, ++ PropModeReplace, (guchar *)&value, 1); ++ ++ if (stereo_switch_id != 0) ++ { ++ g_source_remove (stereo_switch_id); ++ stereo_switch_id = 0; ++ } ++ ++ if (stereo_have_windows != stereo_enabled) ++ stereo_switch_id = g_timeout_add (stereo_have_windows ? STEREO_ENABLE_WAIT : STEREO_DISABLE_WAIT, ++ meta_stereo_switch, NULL); ++ } ++} +diff --git a/src/core/stereo.h b/src/core/stereo.h +new file mode 100644 +index 000000000..ccd1d702a +--- /dev/null ++++ b/src/core/stereo.h +@@ -0,0 +1,28 @@ ++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ ++ ++/* ++ * Copyright (C) 2014 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, see . ++ */ ++ ++#ifndef META_STEREO_H ++#define META_STEREO_H ++ ++void meta_stereo_init (void); ++void meta_stereo_set_have_stereo_windows (gboolean have_windows); ++gboolean meta_stereo_is_restart (void); ++void meta_stereo_finish_restart (void); ++ ++#endif +diff --git a/src/meson.build b/src/meson.build +index 9919b5cfb..7cced8f53 100644 +--- a/src/meson.build ++++ b/src/meson.build +@@ -353,6 +353,8 @@ mutter_sources = [ + 'core/stack.h', + 'core/stack-tracker.c', + 'core/stack-tracker.h', ++ 'core/stereo.c', ++ 'core/stereo.h', + 'core/startup-notification.c', + 'core/startup-notification-private.h', + 'core/util.c', +diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c +index da0acfcbb..ddad1a45c 100644 +--- a/src/wayland/meta-wayland-surface.c ++++ b/src/wayland/meta-wayland-surface.c +@@ -731,7 +731,7 @@ meta_wayland_surface_apply_pending_state (MetaWaylandSurface *surface, + snippet = meta_wayland_buffer_create_snippet (pending->buffer); + is_y_inverted = meta_wayland_buffer_is_y_inverted (pending->buffer); + +- meta_shaped_texture_set_texture (stex, texture); ++ meta_shaped_texture_set_textures (stex, texture, NULL); + meta_shaped_texture_set_snippet (stex, snippet); + meta_shaped_texture_set_is_y_inverted (stex, is_y_inverted); + g_clear_pointer (&snippet, cogl_object_unref); +-- +2.23.0 + diff --git a/SOURCES/0001-Create-explicit-WacomDevices-for-tablet-touchpad-dev.patch b/SOURCES/0001-Create-explicit-WacomDevices-for-tablet-touchpad-dev.patch new file mode 100644 index 0000000..732b754 --- /dev/null +++ b/SOURCES/0001-Create-explicit-WacomDevices-for-tablet-touchpad-dev.patch @@ -0,0 +1,55 @@ +From 38d88d4e4286c3ada041561426873e44fdba3c40 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Fri, 17 Jan 2020 14:45:00 +0100 +Subject: [PATCH] Create explicit WacomDevices for tablet "touchpad" devices + +--- + src/backends/meta-input-settings.c | 15 +++++++++++---- + 1 file changed, 11 insertions(+), 4 deletions(-) + +diff --git a/src/backends/meta-input-settings.c b/src/backends/meta-input-settings.c +index 28dc387ef9..820a3b201e 100644 +--- a/src/backends/meta-input-settings.c ++++ b/src/backends/meta-input-settings.c +@@ -521,27 +521,34 @@ static gboolean + device_is_tablet_touchpad (MetaInputSettings *input_settings, + ClutterInputDevice *device) + { ++ gboolean is_tablet = FALSE; + #ifdef HAVE_LIBWACOM ++ MetaInputSettingsPrivate *priv; + WacomIntegrationFlags flags = 0; + WacomDevice *wacom_device; + ++ priv = meta_input_settings_get_instance_private (input_settings); ++ + if (clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE) + return FALSE; + + wacom_device = +- meta_input_settings_get_tablet_wacom_device (input_settings, +- device); ++ libwacom_new_from_path (priv->wacom_db, ++ clutter_input_device_get_device_node (device), ++ WFALLBACK_NONE, NULL); + if (wacom_device) + { + flags = libwacom_get_integration_flags (wacom_device); + + if ((flags & (WACOM_DEVICE_INTEGRATED_SYSTEM | + WACOM_DEVICE_INTEGRATED_DISPLAY)) == 0) +- return TRUE; ++ is_tablet = TRUE; ++ ++ libwacom_destroy (wacom_device); + } + #endif + +- return FALSE; ++ return is_tablet; + } + + static void +-- +2.25.0.rc2 + diff --git a/SOURCES/0001-EGL-Include-EGL-eglmesaext.h.patch b/SOURCES/0001-EGL-Include-EGL-eglmesaext.h.patch new file mode 100644 index 0000000..ae7ff46 --- /dev/null +++ b/SOURCES/0001-EGL-Include-EGL-eglmesaext.h.patch @@ -0,0 +1,68 @@ +From abfc64268d4135663fb46c5f3529cd5f082a5c20 Mon Sep 17 00:00:00 2001 +From: "Jan Alexander Steffens (heftig)" +Date: Sun, 20 Oct 2019 12:04:31 +0200 +Subject: [PATCH] EGL: Include EGL/eglmesaext.h + +The eglext.h shipped by libglvnd does not include the Mesa extensions, +unlike the header shipped in Mesa. + +Fixes https://gitlab.gnome.org/GNOME/mutter/issues/876 +--- + cogl/cogl/meson.build | 2 +- + src/backends/meta-egl-ext.h | 1 + + src/backends/meta-egl.c | 1 + + src/backends/meta-egl.h | 1 + + 4 files changed, 4 insertions(+), 1 deletion(-) + +diff --git a/cogl/cogl/meson.build b/cogl/cogl/meson.build +index cb940420a..8032669e4 100644 +--- a/cogl/cogl/meson.build ++++ b/cogl/cogl/meson.build +@@ -48,7 +48,7 @@ cogl_gl_header_h = configure_file( + built_headers += [cogl_gl_header_h] + + if have_egl +- cogl_egl_includes_string = '#include \n#include ' ++ cogl_egl_includes_string = '#include \n#include \n#include ' + else + cogl_egl_includes_string = '' + endif +diff --git a/src/backends/meta-egl-ext.h b/src/backends/meta-egl-ext.h +index 8705e7d5b..db0b74f76 100644 +--- a/src/backends/meta-egl-ext.h ++++ b/src/backends/meta-egl-ext.h +@@ -29,6 +29,7 @@ + + #include + #include ++#include + + /* + * This is a little different to the tests shipped with EGL implementations, +diff --git a/src/backends/meta-egl.c b/src/backends/meta-egl.c +index 8b953449a..a28eef4ca 100644 +--- a/src/backends/meta-egl.c ++++ b/src/backends/meta-egl.c +@@ -26,6 +26,7 @@ + + #include + #include ++#include + #include + #include + #include +diff --git a/src/backends/meta-egl.h b/src/backends/meta-egl.h +index ff37f124f..81b53b32d 100644 +--- a/src/backends/meta-egl.h ++++ b/src/backends/meta-egl.h +@@ -27,6 +27,7 @@ + + #include + #include ++#include + #include + + #define META_EGL_ERROR meta_egl_error_quark () +-- +2.23.0 + diff --git a/SOURCES/0001-Revert-MetaMonitorManager-ignore-hotplug_mode_update.patch b/SOURCES/0001-Revert-MetaMonitorManager-ignore-hotplug_mode_update.patch new file mode 100644 index 0000000..f61ecf6 --- /dev/null +++ b/SOURCES/0001-Revert-MetaMonitorManager-ignore-hotplug_mode_update.patch @@ -0,0 +1,28 @@ +From d9d355bfd8ecfb7dcf65a3810ec30e12f12673ab Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Mon, 24 Feb 2020 16:09:59 +0100 +Subject: [PATCH] Revert "MetaMonitorManager: ignore hotplug_mode_update at + startup" + +This reverts commit 183f4b0c13f3dc9565bf5f693f2e5d61ca0199c9. +--- + src/backends/meta-monitor-manager.c | 3 +-- + 1 file changed, 1 insertion(+), 2 deletions(-) + +diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c +index 076dca8cb..0adf2100d 100644 +--- a/src/backends/meta-monitor-manager.c ++++ b/src/backends/meta-monitor-manager.c +@@ -527,8 +527,7 @@ meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager) + static gboolean + should_use_stored_config (MetaMonitorManager *manager) + { +- return (manager->in_init || +- !meta_monitor_manager_has_hotplug_mode_update (manager)); ++ return !meta_monitor_manager_has_hotplug_mode_update (manager); + } + + static gboolean +-- +2.24.1 + diff --git a/SOURCES/0001-Skip-wacom-touchpads-when-updating-setting.patch b/SOURCES/0001-Skip-wacom-touchpads-when-updating-setting.patch new file mode 100644 index 0000000..ba10e5e --- /dev/null +++ b/SOURCES/0001-Skip-wacom-touchpads-when-updating-setting.patch @@ -0,0 +1,94 @@ +From dafc9cb414fd47112b972d34c205e73797a3c1c1 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Fri, 21 Feb 2020 16:45:35 +0100 +Subject: [PATCH] Skip wacom touchpads when updating setting + +--- + src/backends/meta-input-settings.c | 46 +++++++++++++++++++++++------- + 1 file changed, 36 insertions(+), 10 deletions(-) + +diff --git a/src/backends/meta-input-settings.c b/src/backends/meta-input-settings.c +index cdff7b346..7d866594a 100644 +--- a/src/backends/meta-input-settings.c ++++ b/src/backends/meta-input-settings.c +@@ -569,20 +569,33 @@ update_touchpad_tap_enabled (MetaInputSettings *input_settings, + + priv = meta_input_settings_get_instance_private (input_settings); + input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); +- enabled = device_is_tablet_touchpad (input_settings, device) || +- g_settings_get_boolean (priv->touchpad_settings, "tap-to-click"); + + if (device) + { ++ enabled = device_is_tablet_touchpad (input_settings, device) || ++ g_settings_get_boolean (priv->touchpad_settings, "tap-to-click"); + settings_device_set_bool_setting (input_settings, device, + input_settings_class->set_tap_enabled, + enabled); + } + else + { +- settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, +- input_settings_class->set_tap_enabled, +- enabled); ++ const GSList *devices, *l; ++ ++ devices = clutter_device_manager_peek_devices (priv->device_manager); ++ for (l = devices; l; l = l->next) ++ { ++ device = l->data; ++ ++ if (clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE) ++ continue; ++ ++ enabled = device_is_tablet_touchpad (input_settings, device) || ++ g_settings_get_boolean (priv->touchpad_settings, "tap-to-click"); ++ settings_device_set_bool_setting (input_settings, device, ++ input_settings_class->set_tap_enabled, ++ enabled); ++ } + } + } + +@@ -600,20 +613,33 @@ update_touchpad_tap_and_drag_enabled (MetaInputSettings *input_settings, + + priv = meta_input_settings_get_instance_private (input_settings); + input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); +- enabled = device_is_tablet_touchpad (input_settings, device) || +- g_settings_get_boolean (priv->touchpad_settings, "tap-and-drag"); + + if (device) + { ++ enabled = device_is_tablet_touchpad (input_settings, device) || ++ g_settings_get_boolean (priv->touchpad_settings, "tap-and-drag"); + settings_device_set_bool_setting (input_settings, device, + input_settings_class->set_tap_and_drag_enabled, + enabled); + } + else + { +- settings_set_bool_setting (input_settings, CLUTTER_TOUCHPAD_DEVICE, +- input_settings_class->set_tap_and_drag_enabled, +- enabled); ++ const GSList *devices, *l; ++ ++ devices = clutter_device_manager_peek_devices (priv->device_manager); ++ for (l = devices; l; l = l->next) ++ { ++ device = l->data; ++ ++ if (clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE) ++ continue; ++ ++ enabled = device_is_tablet_touchpad (input_settings, device) || ++ g_settings_get_boolean (priv->touchpad_settings, "tap-and-drag"); ++ settings_device_set_bool_setting (input_settings, device, ++ input_settings_class->set_tap_and_drag_enabled, ++ enabled); ++ } + } + } + +-- +2.24.1 + diff --git a/SOURCES/0001-backends-Always-enable-tap-to-click-drag-on-opaque-W.patch b/SOURCES/0001-backends-Always-enable-tap-to-click-drag-on-opaque-W.patch new file mode 100644 index 0000000..0420251 --- /dev/null +++ b/SOURCES/0001-backends-Always-enable-tap-to-click-drag-on-opaque-W.patch @@ -0,0 +1,80 @@ +From eeff82f534f81b086d10d53124362d9e316e2cf9 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Thu, 12 Dec 2019 18:05:08 +0100 +Subject: [PATCH] backends: Always enable tap-to-click/drag on opaque Wacom + tablets + +Touch-wise, those are essentially giant touchpads, but have no buttons +associated to the "touchpad" device (There may be pad buttons, but +those are not mouse buttons). + +Without tap-to-click/drag, touch in those devices is somewhat useless +out of the box. Have them always enable these features, despite the +setting. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/968 +--- + src/backends/meta-input-settings.c | 33 ++++++++++++++++++++++++++++-- + 1 file changed, 31 insertions(+), 2 deletions(-) + +diff --git a/src/backends/meta-input-settings.c b/src/backends/meta-input-settings.c +index 2e6672d9c..28dc387ef 100644 +--- a/src/backends/meta-input-settings.c ++++ b/src/backends/meta-input-settings.c +@@ -517,6 +517,33 @@ update_touchpad_disable_while_typing (MetaInputSettings *input_settings, + } + } + ++static gboolean ++device_is_tablet_touchpad (MetaInputSettings *input_settings, ++ ClutterInputDevice *device) ++{ ++#ifdef HAVE_LIBWACOM ++ WacomIntegrationFlags flags = 0; ++ WacomDevice *wacom_device; ++ ++ if (clutter_input_device_get_device_type (device) != CLUTTER_TOUCHPAD_DEVICE) ++ return FALSE; ++ ++ wacom_device = ++ meta_input_settings_get_tablet_wacom_device (input_settings, ++ device); ++ if (wacom_device) ++ { ++ flags = libwacom_get_integration_flags (wacom_device); ++ ++ if ((flags & (WACOM_DEVICE_INTEGRATED_SYSTEM | ++ WACOM_DEVICE_INTEGRATED_DISPLAY)) == 0) ++ return TRUE; ++ } ++#endif ++ ++ return FALSE; ++} ++ + static void + update_touchpad_tap_enabled (MetaInputSettings *input_settings, + ClutterInputDevice *device) +@@ -531,7 +558,8 @@ update_touchpad_tap_enabled (MetaInputSettings *input_settings, + + priv = meta_input_settings_get_instance_private (input_settings); + input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); +- enabled = g_settings_get_boolean (priv->touchpad_settings, "tap-to-click"); ++ enabled = device_is_tablet_touchpad (input_settings, device) || ++ g_settings_get_boolean (priv->touchpad_settings, "tap-to-click"); + + if (device) + { +@@ -561,7 +589,8 @@ update_touchpad_tap_and_drag_enabled (MetaInputSettings *input_settings, + + priv = meta_input_settings_get_instance_private (input_settings); + input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); +- enabled = g_settings_get_boolean (priv->touchpad_settings, "tap-and-drag"); ++ enabled = device_is_tablet_touchpad (input_settings, device) || ++ g_settings_get_boolean (priv->touchpad_settings, "tap-and-drag"); + + if (device) + { +-- +2.23.0 + diff --git a/SOURCES/0001-backends-Check-both-input-settings-and-mapper-for-ta.patch b/SOURCES/0001-backends-Check-both-input-settings-and-mapper-for-ta.patch new file mode 100644 index 0000000..9880a83 --- /dev/null +++ b/SOURCES/0001-backends-Check-both-input-settings-and-mapper-for-ta.patch @@ -0,0 +1,205 @@ +From 20fcc3e045287c1ca591f3e795b19e120479a89a Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Wed, 12 Feb 2020 20:26:56 +0100 +Subject: [PATCH 1/2] backends/x11: Implement is_grouped for X11 + +If the devices have a wacom description, compare those. Otherwise, +look up the devices' VID:PID, if they match they should also be +grouped. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/971 +--- + .../clutter/x11/clutter-input-device-xi2.c | 25 +++++++++++++++++++ + 1 file changed, 25 insertions(+) + +diff --git a/clutter/clutter/x11/clutter-input-device-xi2.c b/clutter/clutter/x11/clutter-input-device-xi2.c +index ae2fa27..9eca34d 100644 +--- a/clutter/clutter/x11/clutter-input-device-xi2.c ++++ b/clutter/clutter/x11/clutter-input-device-xi2.c +@@ -98,6 +98,31 @@ static gboolean + clutter_input_device_xi2_is_grouped (ClutterInputDevice *device, + ClutterInputDevice *other_device) + { ++#ifdef HAVE_LIBWACOM ++ ClutterInputDeviceXI2 *device_x11 = CLUTTER_INPUT_DEVICE_XI2 (device); ++ ClutterInputDeviceXI2 *other_device_x11 = CLUTTER_INPUT_DEVICE_XI2 (other_device); ++ ++ if (device_x11->wacom_device && ++ other_device_x11->wacom_device && ++ libwacom_compare (device_x11->wacom_device, ++ other_device_x11->wacom_device, ++ WCOMPARE_NORMAL) == 0) ++ return TRUE; ++#endif ++ ++ /* Devices with the same VID:PID get grouped together */ ++ if (clutter_input_device_get_vendor_id (device) && ++ clutter_input_device_get_product_id (device) && ++ clutter_input_device_get_vendor_id (other_device) && ++ clutter_input_device_get_product_id (other_device)) ++ { ++ if (strcmp (clutter_input_device_get_vendor_id (device), ++ clutter_input_device_get_vendor_id (other_device)) == 0 && ++ strcmp (clutter_input_device_get_product_id (device), ++ clutter_input_device_get_product_id (other_device)) == 0) ++ return TRUE; ++ } ++ + return FALSE; + } + +-- +2.24.1 + + +From 5914ab9ac79ce42da054036c4a8f118a3a868cc0 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Fri, 13 Dec 2019 15:26:05 +0100 +Subject: [PATCH 2/2] backends: Check both input settings and mapper for tablet + monitors + +The upper layers (OSDs basically) want to know the monitor that a +tablet is currently assigned to, not the monitor just as configured +through settings. + +This broke proper OSD positioning for display-attached tablets since +commit 87858a4e01d9, as the MetaInputMapper kicks in precisely when +there is no configured monitor for the given device. + +Consulting both about the assigned output will make OSDs pop up +again in the right place. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/971 +--- + src/backends/meta-input-mapper-private.h | 3 ++ + src/backends/meta-input-mapper.c | 26 ++++++++++++ + src/backends/meta-input-settings.c | 54 +++++++++++++++++++++++- + 3 files changed, 81 insertions(+), 2 deletions(-) + +diff --git a/src/backends/meta-input-mapper-private.h b/src/backends/meta-input-mapper-private.h +index 3431457..cdfdccd 100644 +--- a/src/backends/meta-input-mapper-private.h ++++ b/src/backends/meta-input-mapper-private.h +@@ -42,5 +42,8 @@ ClutterInputDevice * + meta_input_mapper_get_logical_monitor_device (MetaInputMapper *mapper, + MetaLogicalMonitor *logical_monitor, + ClutterInputDeviceType device_type); ++MetaLogicalMonitor * ++meta_input_mapper_get_device_logical_monitor (MetaInputMapper *mapper, ++ ClutterInputDevice *device); + + #endif /* META_INPUT_MAPPER_H */ +diff --git a/src/backends/meta-input-mapper.c b/src/backends/meta-input-mapper.c +index fc4f3bd..fe02ab8 100644 +--- a/src/backends/meta-input-mapper.c ++++ b/src/backends/meta-input-mapper.c +@@ -675,3 +675,29 @@ meta_input_mapper_get_logical_monitor_device (MetaInputMapper *mapper, + + return NULL; + } ++ ++MetaLogicalMonitor * ++meta_input_mapper_get_device_logical_monitor (MetaInputMapper *mapper, ++ ClutterInputDevice *device) ++{ ++ MetaMapperOutputInfo *output; ++ MetaLogicalMonitor *logical_monitor; ++ GHashTableIter iter; ++ GList *l; ++ ++ g_hash_table_iter_init (&iter, mapper->output_devices); ++ ++ while (g_hash_table_iter_next (&iter, (gpointer *) &logical_monitor, ++ (gpointer *) &output)) ++ { ++ for (l = output->input_devices; l; l = l->next) ++ { ++ MetaMapperInputInfo *input = l->data; ++ ++ if (input->device == device) ++ return logical_monitor; ++ } ++ } ++ ++ return NULL; ++} +diff --git a/src/backends/meta-input-settings.c b/src/backends/meta-input-settings.c +index b84595e..ab80bee 100644 +--- a/src/backends/meta-input-settings.c ++++ b/src/backends/meta-input-settings.c +@@ -1937,6 +1937,42 @@ meta_input_settings_get_tablet_settings (MetaInputSettings *settings, + return info ? g_object_ref (info->settings) : NULL; + } + ++static ClutterInputDevice * ++find_grouped_pen (MetaInputSettings *settings, ++ ClutterInputDevice *device) ++{ ++ MetaInputSettingsPrivate *priv; ++ GSList *l, *devices; ++ ClutterInputDeviceType device_type; ++ ClutterInputDevice *pen = NULL; ++ ++ device_type = clutter_input_device_get_device_type (device); ++ ++ if (device_type == CLUTTER_TABLET_DEVICE || ++ device_type == CLUTTER_PEN_DEVICE) ++ return device; ++ ++ priv = meta_input_settings_get_instance_private (settings); ++ devices = clutter_device_manager_peek_devices (priv->device_manager); ++ ++ for (l = devices; l; l = l->next) ++ { ++ ClutterInputDevice *device = l->data; ++ ++ device_type = clutter_input_device_get_device_type (l->data); ++ ++ if ((device_type == CLUTTER_TABLET_DEVICE || ++ device_type == CLUTTER_PEN_DEVICE) && ++ clutter_input_device_is_grouped (device, l->data)) ++ { ++ pen = l->data; ++ break; ++ } ++ } ++ ++ return pen; ++} ++ + MetaLogicalMonitor * + meta_input_settings_get_tablet_logical_monitor (MetaInputSettings *settings, + ClutterInputDevice *device) +@@ -1948,13 +1984,27 @@ meta_input_settings_get_tablet_logical_monitor (MetaInputSettings *settings, + g_return_val_if_fail (META_IS_INPUT_SETTINGS (settings), NULL); + g_return_val_if_fail (CLUTTER_IS_INPUT_DEVICE (device), NULL); + ++ if (clutter_input_device_get_device_type (device) == CLUTTER_PAD_DEVICE) ++ { ++ device = find_grouped_pen (settings, device); ++ if (!device) ++ return NULL; ++ } ++ + priv = meta_input_settings_get_instance_private (settings); + info = g_hash_table_lookup (priv->mappable_devices, device); + if (!info) + return NULL; + +- meta_input_settings_find_monitor (settings, info->settings, device, +- NULL, &logical_monitor); ++ logical_monitor = ++ meta_input_mapper_get_device_logical_monitor (priv->input_mapper, device); ++ ++ if (!logical_monitor) ++ { ++ meta_input_settings_find_monitor (settings, info->settings, device, ++ NULL, &logical_monitor); ++ } ++ + return logical_monitor; + } + +-- +2.24.1 + diff --git a/SOURCES/0001-backends-Consider-pen-eraser-devices-when-looking-fo.patch b/SOURCES/0001-backends-Consider-pen-eraser-devices-when-looking-fo.patch new file mode 100644 index 0000000..f7fa3b2 --- /dev/null +++ b/SOURCES/0001-backends-Consider-pen-eraser-devices-when-looking-fo.patch @@ -0,0 +1,30 @@ +From e512c397a640994807f239c570333e9942717ef5 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Fri, 13 Dec 2019 17:01:44 +0100 +Subject: [PATCH] backends: Consider pen/eraser devices when looking for + matching WacomDevice + +Those device types are still in use through the X11 backend, breaking some +checks around on that backend... + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/972 +--- + src/backends/meta-input-settings.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/backends/meta-input-settings.c b/src/backends/meta-input-settings.c +index 2e6672d9c..18ae52dd7 100644 +--- a/src/backends/meta-input-settings.c ++++ b/src/backends/meta-input-settings.c +@@ -1589,6 +1589,8 @@ check_add_mappable_device (MetaInputSettings *input_settings, + + #ifdef HAVE_LIBWACOM + if (device_type == CLUTTER_TABLET_DEVICE || ++ device_type == CLUTTER_PEN_DEVICE || ++ device_type == CLUTTER_ERASER_DEVICE || + device_type == CLUTTER_PAD_DEVICE) + { + WacomError *error = libwacom_error_new (); +-- +2.23.0 + diff --git a/SOURCES/0001-backends-x11-Observe-multiple-pad-mode-switch-button.patch b/SOURCES/0001-backends-x11-Observe-multiple-pad-mode-switch-button.patch new file mode 100644 index 0000000..ac6986f --- /dev/null +++ b/SOURCES/0001-backends-x11-Observe-multiple-pad-mode-switch-button.patch @@ -0,0 +1,118 @@ +From a8f12e7afdb35ebda581cee6a32b295cb6e643ec Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Fri, 13 Dec 2019 14:22:12 +0100 +Subject: [PATCH] backends/x11: Observe multiple pad mode switch buttons in a + group + +Some tablets like the Cintiq 24HDT have several mode switch buttons +per group. Those are meant to jump straight to a given mode, however +we just handle cycling across modes (as most other tablets have a +single mode switch button per group). + +So spice up the mode switch handling so we handle multiple mode +switch buttons, assigning each of them a mode. If the device only +has one mode switch button, we do the old-fashioned cycling. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/970 +--- + .../clutter/x11/clutter-input-device-xi2.c | 71 ++++++++++++++++--- + 1 file changed, 60 insertions(+), 11 deletions(-) + +diff --git a/clutter/clutter/x11/clutter-input-device-xi2.c b/clutter/clutter/x11/clutter-input-device-xi2.c +index 1254aca3a..c33adffc2 100644 +--- a/clutter/clutter/x11/clutter-input-device-xi2.c ++++ b/clutter/clutter/x11/clutter-input-device-xi2.c +@@ -318,6 +318,57 @@ clutter_input_device_xi2_get_pad_group_mode (ClutterInputDevice *device, + return g_array_index (device_xi2->group_modes, guint, group); + } + ++static gboolean ++pad_switch_mode (ClutterInputDevice *device, ++ uint32_t button, ++ uint32_t group, ++ uint32_t *mode) ++{ ++ ClutterInputDeviceXI2 *device_x11 = CLUTTER_INPUT_DEVICE_XI2 (device); ++ uint32_t n_buttons, n_modes, button_group, next_mode, i; ++ GList *switch_buttons = NULL; ++ ++ n_buttons = libwacom_get_num_buttons (device_x11->wacom_device); ++ ++ for (i = 0; i < n_buttons; i++) ++ { ++ button_group = clutter_input_device_xi2_get_button_group (device, i); ++ if (button_group == group) ++ switch_buttons = g_list_prepend (switch_buttons, GINT_TO_POINTER (i)); ++ } ++ ++ switch_buttons = g_list_reverse (switch_buttons); ++ n_modes = clutter_input_device_get_group_n_modes (device, group); ++ ++ if (g_list_length (switch_buttons) > 1) ++ { ++ /* If there's multiple switch buttons, we don't toggle but assign a mode ++ * to each of those buttons. ++ */ ++ next_mode = g_list_index (switch_buttons, GINT_TO_POINTER (button)); ++ } ++ else if (switch_buttons) ++ { ++ uint32_t cur_mode; ++ ++ /* If there is a single button, have it toggle across modes */ ++ cur_mode = g_array_index (device_x11->group_modes, uint32_t, group); ++ next_mode = (cur_mode + 1) % n_modes; ++ } ++ else ++ { ++ return FALSE; ++ } ++ ++ g_list_free (switch_buttons); ++ ++ if (next_mode < 0 || next_mode > n_modes) ++ return FALSE; ++ ++ *mode = next_mode; ++ return TRUE; ++} ++ + void + clutter_input_device_xi2_update_pad_state (ClutterInputDevice *device, + guint button, +@@ -330,23 +381,21 @@ clutter_input_device_xi2_update_pad_state (ClutterInputDevice *device, + gboolean is_mode_switch = FALSE; + + button_group = clutter_input_device_xi2_get_button_group (device, button); +- is_mode_switch = button_group >= 0; + +- /* Assign all non-mode-switch buttons to group 0 so far */ +- button_group = MAX (0, button_group); +- +- if (button_group >= device_xi2->group_modes->len) +- return; ++ if (button_group < 0 || button_group >= device_xi2->group_modes->len) ++ { ++ *group = *mode = 0; ++ return; ++ } + + group_mode = &g_array_index (device_xi2->group_modes, guint, button_group); + +- if (is_mode_switch && state) ++ if (state) + { +- guint next, n_modes; ++ uint32_t next_mode; + +- n_modes = clutter_input_device_get_group_n_modes (device, button_group); +- next = (*group_mode + 1) % n_modes; +- *group_mode = next; ++ if (pad_switch_mode (device, button, button_group, &next_mode)) ++ *group_mode = next_mode; + } + + if (group) +-- +2.23.0 + diff --git a/SOURCES/0001-backends-x11-Support-synaptics-configuration.patch b/SOURCES/0001-backends-x11-Support-synaptics-configuration.patch new file mode 100644 index 0000000..2dd5bb9 --- /dev/null +++ b/SOURCES/0001-backends-x11-Support-synaptics-configuration.patch @@ -0,0 +1,349 @@ +From 471174ba6cf517baf8ff73e903202e1c73b6ec74 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Thu, 19 Jan 2017 15:03:41 +0100 +Subject: [PATCH] backends/x11: Support synaptics configuration + +The code is taken mostly as-is from g-s-d, so we can drag the +dead horse a bit longer. +--- + src/backends/x11/meta-input-settings-x11.c | 268 +++++++++++++++++++++ + 1 file changed, 268 insertions(+) + +diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c +index 89f07ee1f..051a1c605 100644 +--- a/src/backends/x11/meta-input-settings-x11.c ++++ b/src/backends/x11/meta-input-settings-x11.c +@@ -26,6 +26,7 @@ + #include "backends/x11/meta-input-settings-x11.h" + + #include ++#include + #include + #include + #include +@@ -162,6 +163,180 @@ change_property (ClutterInputDevice *device, + meta_XFree (data_ret); + } + ++static gboolean ++is_device_synaptics (ClutterInputDevice *device) ++{ ++ guchar *has_setting; ++ ++ /* We just need looking for a synaptics-specific property */ ++ has_setting = get_property (device, "Synaptics Off", XA_INTEGER, 8, 1); ++ if (!has_setting) ++ return FALSE; ++ ++ meta_XFree (has_setting); ++ return TRUE; ++} ++ ++static void ++change_synaptics_tap_left_handed (ClutterInputDevice *device, ++ gboolean tap_enabled, ++ gboolean left_handed) ++{ ++ MetaDisplay *display = meta_get_display (); ++ MetaX11Display *x11_display = display ? display->x11_display : NULL; ++ MetaBackend *backend = meta_get_backend (); ++ Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); ++ XDevice *xdevice; ++ guchar *tap_action, *buttons; ++ guint buttons_capacity = 16, n_buttons; ++ ++ xdevice = XOpenDevice(xdisplay, clutter_input_device_get_device_id (device)); ++ if (!xdevice) ++ return; ++ ++ tap_action = get_property (device, "Synaptics Tap Action", ++ XA_INTEGER, 8, 7); ++ if (!tap_action) ++ goto out; ++ ++ tap_action[4] = tap_enabled ? (left_handed ? 3 : 1) : 0; ++ tap_action[5] = tap_enabled ? (left_handed ? 1 : 3) : 0; ++ tap_action[6] = tap_enabled ? 2 : 0; ++ ++ change_property (device, "Synaptics Tap Action", ++ XA_INTEGER, 8, tap_action, 7); ++ meta_XFree (tap_action); ++ ++ if (x11_display) ++ meta_x11_error_trap_push (x11_display); ++ buttons = g_new (guchar, buttons_capacity); ++ n_buttons = XGetDeviceButtonMapping (xdisplay, xdevice, ++ buttons, buttons_capacity); ++ ++ while (n_buttons > buttons_capacity) ++ { ++ buttons_capacity = n_buttons; ++ buttons = (guchar *) g_realloc (buttons, ++ buttons_capacity * sizeof (guchar)); ++ ++ n_buttons = XGetDeviceButtonMapping (xdisplay, xdevice, ++ buttons, buttons_capacity); ++ } ++ ++ buttons[0] = left_handed ? 3 : 1; ++ buttons[2] = left_handed ? 1 : 3; ++ XSetDeviceButtonMapping (xdisplay, xdevice, buttons, n_buttons); ++ g_free (buttons); ++ ++ if (x11_display && meta_x11_error_trap_pop_with_return (x11_display)) ++ { ++ g_warning ("Could not set synaptics touchpad left-handed for %s", ++ clutter_input_device_get_device_name (device)); ++ } ++ ++ out: ++ XCloseDevice (xdisplay, xdevice); ++} ++ ++static void ++change_synaptics_speed (ClutterInputDevice *device, ++ gdouble speed) ++{ ++ MetaDisplay *display = meta_get_display (); ++ MetaX11Display *x11_display = display ? display->x11_display : NULL; ++ MetaBackend *backend = meta_get_backend (); ++ Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); ++ XDevice *xdevice; ++ XPtrFeedbackControl feedback; ++ XFeedbackState *states, *state; ++ int i, num_feedbacks, motion_threshold, numerator, denominator; ++ gfloat motion_acceleration; ++ ++ xdevice = XOpenDevice(xdisplay, clutter_input_device_get_device_id (device)); ++ if (!xdevice) ++ return; ++ /* Get the list of feedbacks for the device */ ++ states = XGetFeedbackControl (xdisplay, xdevice, &num_feedbacks); ++ if (!states) ++ return; ++ ++ /* Calculate acceleration and threshold */ ++ motion_acceleration = (speed + 1) * 5; /* speed is [-1..1], map to [0..10] */ ++ motion_threshold = CLAMP (10 - floor (motion_acceleration), 1, 10); ++ ++ if (motion_acceleration >= 1.0) ++ { ++ /* we want to get the acceleration, with a resolution of 0.5 ++ */ ++ if ((motion_acceleration - floor (motion_acceleration)) < 0.25) ++ { ++ numerator = floor (motion_acceleration); ++ denominator = 1; ++ } ++ else if ((motion_acceleration - floor (motion_acceleration)) < 0.5) ++ { ++ numerator = ceil (2.0 * motion_acceleration); ++ denominator = 2; ++ } ++ else if ((motion_acceleration - floor (motion_acceleration)) < 0.75) ++ { ++ numerator = floor (2.0 *motion_acceleration); ++ denominator = 2; ++ } ++ else ++ { ++ numerator = ceil (motion_acceleration); ++ denominator = 1; ++ } ++ } ++ else if (motion_acceleration < 1.0 && motion_acceleration > 0) ++ { ++ /* This we do to 1/10ths */ ++ numerator = floor (motion_acceleration * 10) + 1; ++ denominator= 10; ++ } ++ else ++ { ++ numerator = -1; ++ denominator = -1; ++ } ++ ++ if (x11_display) ++ meta_x11_error_trap_push (x11_display); ++ ++ state = (XFeedbackState *) states; ++ ++ for (i = 0; i < num_feedbacks; i++) ++ { ++ if (state->class == PtrFeedbackClass) ++ { ++ /* And tell the device */ ++ feedback.class = PtrFeedbackClass; ++ feedback.length = sizeof (XPtrFeedbackControl); ++ feedback.id = state->id; ++ feedback.threshold = motion_threshold; ++ feedback.accelNum = numerator; ++ feedback.accelDenom = denominator; ++ ++ XChangeFeedbackControl (xdisplay, xdevice, ++ DvAccelNum | DvAccelDenom | DvThreshold, ++ (XFeedbackControl *) &feedback); ++ break; ++ } ++ ++ state = (XFeedbackState *) ((char *) state + state->length); ++ } ++ ++ if (x11_display && meta_x11_error_trap_pop_with_return (x11_display)) ++ { ++ g_warning ("Could not set synaptics touchpad acceleration for %s", ++ clutter_input_device_get_device_name (device)); ++ } ++ ++ XFreeFeedbackList (states); ++ XCloseDevice (xdisplay, xdevice); ++} ++ + static void + meta_input_settings_x11_set_send_events (MetaInputSettings *settings, + ClutterInputDevice *device, +@@ -170,6 +345,13 @@ meta_input_settings_x11_set_send_events (MetaInputSettings *settings, + guchar values[2] = { 0 }; /* disabled, disabled-on-external-mouse */ + guchar *available; + ++ if (is_device_synaptics (device)) ++ { ++ values[0] = mode != G_DESKTOP_DEVICE_SEND_EVENTS_ENABLED; ++ change_property (device, "Synaptics Off", XA_INTEGER, 8, &values, 1); ++ return; ++ } ++ + available = get_property (device, "libinput Send Events Modes Available", + XA_INTEGER, 8, 2); + if (!available) +@@ -222,6 +404,12 @@ meta_input_settings_x11_set_speed (MetaInputSettings *settings, + Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); + gfloat value = speed; + ++ if (is_device_synaptics (device)) ++ { ++ change_synaptics_speed (device, speed); ++ return; ++ } ++ + change_property (device, "libinput Accel Speed", + XInternAtom (xdisplay, "FLOAT", False), + 32, &value, 1); +@@ -248,6 +436,19 @@ meta_input_settings_x11_set_left_handed (MetaInputSettings *settings, + else + { + value = enabled ? 1 : 0; ++ ++ if (is_device_synaptics (device)) ++ { ++ GSettings *settings; ++ ++ settings = g_settings_new ("org.gnome.desktop.peripherals.touchpad"); ++ change_synaptics_tap_left_handed (device, ++ g_settings_get_boolean (settings, "tap-to-click"), ++ enabled); ++ g_object_unref (settings); ++ return; ++ } ++ + change_property (device, "libinput Left Handed Enabled", + XA_INTEGER, 8, &value, 1); + } +@@ -271,6 +472,20 @@ meta_input_settings_x11_set_tap_enabled (MetaInputSettings *settings, + { + guchar value = (enabled) ? 1 : 0; + ++ if (is_device_synaptics (device)) ++ { ++ GDesktopTouchpadHandedness handedness; ++ GSettings *settings; ++ ++ settings = g_settings_new ("org.gnome.desktop.peripherals.touchpad"); ++ handedness = g_settings_get_enum (settings, "left-handed"); ++ g_object_unref (settings); ++ ++ change_synaptics_tap_left_handed (device, enabled, ++ handedness == G_DESKTOP_TOUCHPAD_HANDEDNESS_LEFT); ++ return; ++ } ++ + change_property (device, "libinput Tapping Enabled", + XA_INTEGER, 8, &value, 1); + } +@@ -293,6 +508,27 @@ meta_input_settings_x11_set_invert_scroll (MetaInputSettings *settings, + { + guchar value = (inverted) ? 1 : 0; + ++ if (is_device_synaptics (device)) ++ { ++ gint32 *scrolling_distance; ++ ++ scrolling_distance = get_property (device, "Synaptics Scrolling Distance", ++ XA_INTEGER, 32, 2); ++ if (scrolling_distance) ++ { ++ scrolling_distance[0] = inverted ? ++ -abs (scrolling_distance[0]) : abs (scrolling_distance[0]); ++ scrolling_distance[1] = inverted ? ++ -abs (scrolling_distance[1]) : abs (scrolling_distance[1]); ++ ++ change_property (device, "Synaptics Scrolling Distance", ++ XA_INTEGER, 32, scrolling_distance, 2); ++ meta_XFree (scrolling_distance); ++ } ++ ++ return; ++ } ++ + change_property (device, "libinput Natural Scrolling Enabled", + XA_INTEGER, 8, &value, 1); + } +@@ -306,6 +542,22 @@ meta_input_settings_x11_set_edge_scroll (MetaInputSettings *settings, + guchar *current = NULL; + guchar *available = NULL; + ++ if (is_device_synaptics (device)) ++ { ++ current = get_property (device, "Synaptics Edge Scrolling", ++ XA_INTEGER, 8, 3); ++ if (current) ++ { ++ current[0] = !!edge_scroll_enabled; ++ current[1] = !!edge_scroll_enabled; ++ change_property (device, "Synaptics Edge Scrolling", ++ XA_INTEGER, 8, current, 3); ++ meta_XFree (current); ++ } ++ ++ return; ++ } ++ + available = get_property (device, "libinput Scroll Methods Available", + XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS); + if (!available || !available[SCROLL_METHOD_FIELD_EDGE]) +@@ -335,6 +587,22 @@ meta_input_settings_x11_set_two_finger_scroll (MetaInputSettings *set + guchar *current = NULL; + guchar *available = NULL; + ++ if (is_device_synaptics (device)) ++ { ++ current = get_property (device, "Synaptics Two-Finger Scrolling", ++ XA_INTEGER, 8, 2); ++ if (current) ++ { ++ current[0] = !!two_finger_scroll_enabled; ++ current[1] = !!two_finger_scroll_enabled; ++ change_property (device, "Synaptics Two-Finger Scrolling", ++ XA_INTEGER, 8, current, 2); ++ meta_XFree (current); ++ } ++ ++ return; ++ } ++ + available = get_property (device, "libinput Scroll Methods Available", + XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS); + if (!available || !available[SCROLL_METHOD_FIELD_2FG]) +-- +2.21.0 + diff --git a/SOURCES/0001-clutter-Extend-touchpad-device-property-check-for-Sy.patch b/SOURCES/0001-clutter-Extend-touchpad-device-property-check-for-Sy.patch new file mode 100644 index 0000000..96fe26b --- /dev/null +++ b/SOURCES/0001-clutter-Extend-touchpad-device-property-check-for-Sy.patch @@ -0,0 +1,61 @@ +From 368fdebe8f4f4e0c0e41f5be9961a748f328cb57 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Tue, 13 Feb 2018 11:44:40 +0100 +Subject: [PATCH] clutter: Extend touchpad device property check for Synaptics + +So we reliably get CLUTTER_TOUCHPAD_DEVICE for those. The other heuristics +to get the device type may fall short. +--- + .../clutter/x11/clutter-device-manager-xi2.c | 22 ++++++++++++++++--- + 1 file changed, 19 insertions(+), 3 deletions(-) + +diff --git a/clutter/clutter/x11/clutter-device-manager-xi2.c b/clutter/clutter/x11/clutter-device-manager-xi2.c +index 87da4b050..297d3acfe 100644 +--- a/clutter/clutter/x11/clutter-device-manager-xi2.c ++++ b/clutter/clutter/x11/clutter-device-manager-xi2.c +@@ -282,8 +282,9 @@ is_touch_device (XIAnyClassInfo **classes, + } + + static gboolean +-is_touchpad_device (ClutterBackendX11 *backend_x11, +- XIDeviceInfo *info) ++query_exists_device_property (ClutterBackendX11 *backend_x11, ++ XIDeviceInfo *info, ++ const gchar *property) + { + gulong nitems, bytes_after; + guint32 *data = NULL; +@@ -291,7 +292,7 @@ is_touchpad_device (ClutterBackendX11 *backend_x11, + Atom type; + Atom prop; + +- prop = XInternAtom (backend_x11->xdpy, "libinput Tapping Enabled", True); ++ prop = XInternAtom (backend_x11->xdpy, property, True); + if (prop == None) + return FALSE; + +@@ -312,6 +313,21 @@ is_touchpad_device (ClutterBackendX11 *backend_x11, + return TRUE; + } + ++static gboolean ++is_touchpad_device (ClutterBackendX11 *backend_x11, ++ XIDeviceInfo *info) ++{ ++ if (query_exists_device_property (backend_x11, info, ++ "libinput Tapping Enabled")) ++ return TRUE; ++ ++ if (query_exists_device_property (backend_x11, info, ++ "Synaptics Off")) ++ return TRUE; ++ ++ return FALSE; ++} ++ + static gboolean + get_device_ids (ClutterBackendX11 *backend_x11, + XIDeviceInfo *info, +-- +2.21.0 + diff --git a/SOURCES/0001-clutter-Only-reset-scroll-axes-on-slave-devices.patch b/SOURCES/0001-clutter-Only-reset-scroll-axes-on-slave-devices.patch new file mode 100644 index 0000000..dd9eeb5 --- /dev/null +++ b/SOURCES/0001-clutter-Only-reset-scroll-axes-on-slave-devices.patch @@ -0,0 +1,27 @@ +From 2259241e4e6f03bea4e9d746582a9e6a82b3c755 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Wed, 13 Jun 2018 13:48:24 +0200 +Subject: [PATCH] clutter: Only reset scroll axes on slave devices + +As a plus, unknown source device IDs will just warn instead of crash. +--- + clutter/clutter/x11/clutter-device-manager-xi2.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/clutter/clutter/x11/clutter-device-manager-xi2.c b/clutter/clutter/x11/clutter-device-manager-xi2.c +index 297d3acfe..76ef420ed 100644 +--- a/clutter/clutter/x11/clutter-device-manager-xi2.c ++++ b/clutter/clutter/x11/clutter-device-manager-xi2.c +@@ -1899,7 +1899,8 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator, + _clutter_input_device_set_stage (device, NULL); + } + +- _clutter_input_device_reset_scroll_info (source_device); ++ if (clutter_input_device_get_device_mode (source_device) == CLUTTER_INPUT_MODE_SLAVE) ++ _clutter_input_device_reset_scroll_info (source_device); + + clutter_event_set_device (event, device); + clutter_event_set_source_device (event, source_device); +-- +2.21.0 + diff --git a/SOURCES/0001-cogl-Remove-unused-OFFSCREEN_BLIT-feature-flag.patch b/SOURCES/0001-cogl-Remove-unused-OFFSCREEN_BLIT-feature-flag.patch new file mode 100644 index 0000000..b2965a3 --- /dev/null +++ b/SOURCES/0001-cogl-Remove-unused-OFFSCREEN_BLIT-feature-flag.patch @@ -0,0 +1,37 @@ +From 251ef4ff4bacefac211e21873e10da7fa067dd68 Mon Sep 17 00:00:00 2001 +From: Pekka Paalanen +Date: Fri, 26 Apr 2019 12:23:18 +0300 +Subject: [PATCH 01/12] cogl: Remove unused OFFSCREEN_BLIT feature flag + +This named constant is never used anywhere. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/615 + +(cherry picked from commit c08a24bb40ad7aa7746e86251c9dbe6c264b4d7c) +--- + cogl/cogl/cogl-types.h | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/cogl/cogl/cogl-types.h b/cogl/cogl/cogl-types.h +index 690daa16a..69d304cf0 100644 +--- a/cogl/cogl/cogl-types.h ++++ b/cogl/cogl/cogl-types.h +@@ -325,7 +325,6 @@ typedef enum /*< prefix=COGL_PIXEL_FORMAT >*/ + * @COGL_FEATURE_SHADERS_GLSL: GLSL support + * @COGL_FEATURE_OFFSCREEN: FBO support + * @COGL_FEATURE_OFFSCREEN_MULTISAMPLE: Multisample support on FBOs +- * @COGL_FEATURE_OFFSCREEN_BLIT: Blit support on FBOs + * @COGL_FEATURE_FOUR_CLIP_PLANES: At least 4 clip planes available + * @COGL_FEATURE_STENCIL_BUFFER: Stencil buffer support + * @COGL_FEATURE_VBOS: VBO support +@@ -368,7 +367,6 @@ typedef enum + COGL_FEATURE_SHADERS_GLSL = (1 << 5), + COGL_FEATURE_OFFSCREEN = (1 << 6), + COGL_FEATURE_OFFSCREEN_MULTISAMPLE = (1 << 7), +- COGL_FEATURE_OFFSCREEN_BLIT = (1 << 8), + COGL_FEATURE_FOUR_CLIP_PLANES = (1 << 9), + COGL_FEATURE_STENCIL_BUFFER = (1 << 10), + COGL_FEATURE_VBOS = (1 << 11), +-- +2.21.0 + diff --git a/SOURCES/0001-cogl-add-new-UNSTABLE_TEXTURES-feature.patch b/SOURCES/0001-cogl-add-new-UNSTABLE_TEXTURES-feature.patch new file mode 100644 index 0000000..673608d --- /dev/null +++ b/SOURCES/0001-cogl-add-new-UNSTABLE_TEXTURES-feature.patch @@ -0,0 +1,136 @@ +From 78bb1fff1155462638b0d6037ccddf1328482842 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 15 Jan 2019 11:01:38 -0500 +Subject: [PATCH 1/9] cogl: add new UNSTABLE_TEXTURES feature + +The proprietary nvidia driver garbles texture memory on suspend. + +Before we can address that, we need to be able to detect it. + +This commit adds a new UNSTABLE_TEXTURES feature that gets set if +the proprietary nvidia driver is in use. +--- + cogl/cogl/cogl-context.h | 1 + + cogl/cogl/cogl-types.h | 5 ++++- + cogl/cogl/winsys/cogl-winsys-egl.c | 11 +++++++++++ + cogl/cogl/winsys/cogl-winsys-glx.c | 13 +++++++++++-- + 4 files changed, 27 insertions(+), 3 deletions(-) + +diff --git a/cogl/cogl/cogl-context.h b/cogl/cogl/cogl-context.h +index d4104625e..a20c54549 100644 +--- a/cogl/cogl/cogl-context.h ++++ b/cogl/cogl/cogl-context.h +@@ -261,6 +261,7 @@ typedef enum _CoglFeatureID + COGL_FEATURE_ID_TEXTURE_RG, + COGL_FEATURE_ID_BUFFER_AGE, + COGL_FEATURE_ID_TEXTURE_EGL_IMAGE_EXTERNAL, ++ COGL_FEATURE_ID_UNSTABLE_TEXTURES, + + /*< private >*/ + _COGL_N_FEATURE_IDS /*< skip >*/ +diff --git a/cogl/cogl/cogl-types.h b/cogl/cogl/cogl-types.h +index 690daa16a..5b980a43c 100644 +--- a/cogl/cogl/cogl-types.h ++++ b/cogl/cogl/cogl-types.h +@@ -354,6 +354,8 @@ typedef enum /*< prefix=COGL_PIXEL_FORMAT >*/ + * supported with CoglBufferAccess including write support. + * @COGL_FEATURE_DEPTH_TEXTURE: Whether #CoglFramebuffer support rendering the + * depth buffer to a texture. ++ * @COGL_FEATURE_UNSTABLE_TEXTURES: Whether textures require redrawing on ++ * resume or not. + * + * Flags for the supported features. + * +@@ -383,7 +385,8 @@ typedef enum + COGL_FEATURE_MAP_BUFFER_FOR_READ = (1 << 21), + COGL_FEATURE_MAP_BUFFER_FOR_WRITE = (1 << 22), + COGL_FEATURE_ONSCREEN_MULTIPLE = (1 << 23), +- COGL_FEATURE_DEPTH_TEXTURE = (1 << 24) ++ COGL_FEATURE_DEPTH_TEXTURE = (1 << 24), ++ COGL_FEATURE_UNSTABLE_TEXTURES = (1 << 25) + } CoglFeatureFlags; + + /** +diff --git a/cogl/cogl/winsys/cogl-winsys-egl.c b/cogl/cogl/winsys/cogl-winsys-egl.c +index 903c6492d..dd450d4f3 100644 +--- a/cogl/cogl/winsys/cogl-winsys-egl.c ++++ b/cogl/cogl/winsys/cogl-winsys-egl.c +@@ -499,6 +499,7 @@ _cogl_winsys_context_init (CoglContext *context, CoglError **error) + CoglRenderer *renderer = context->display->renderer; + CoglDisplayEGL *egl_display = context->display->winsys; + CoglRendererEGL *egl_renderer = renderer->winsys; ++ CoglGpuInfo *info; + + context->winsys = g_new0 (CoglContextEGL, 1); + +@@ -511,6 +512,16 @@ _cogl_winsys_context_init (CoglContext *context, CoglError **error) + if (!_cogl_context_update_features (context, error)) + return FALSE; + ++ info = &context->gpu; ++ ++ if (info->vendor == COGL_GPU_INFO_VENDOR_NVIDIA) ++ { ++ context->feature_flags |= COGL_FEATURE_UNSTABLE_TEXTURES; ++ COGL_FLAGS_SET (context->features, ++ COGL_FEATURE_ID_UNSTABLE_TEXTURES, ++ TRUE); ++ } ++ + if (egl_renderer->private_features & COGL_EGL_WINSYS_FEATURE_SWAP_REGION) + { + COGL_FLAGS_SET (context->winsys_features, +diff --git a/cogl/cogl/winsys/cogl-winsys-glx.c b/cogl/cogl/winsys/cogl-winsys-glx.c +index 235cfe81f..7e87dc15f 100644 +--- a/cogl/cogl/winsys/cogl-winsys-glx.c ++++ b/cogl/cogl/winsys/cogl-winsys-glx.c +@@ -830,12 +830,15 @@ update_winsys_features (CoglContext *context, CoglError **error) + { + CoglGLXDisplay *glx_display = context->display->winsys; + CoglGLXRenderer *glx_renderer = context->display->renderer->winsys; ++ CoglGpuInfo *info; + + _COGL_RETURN_VAL_IF_FAIL (glx_display->glx_context, FALSE); + + if (!_cogl_context_update_features (context, error)) + return FALSE; + ++ info = &context->gpu; ++ + memcpy (context->winsys_features, + glx_renderer->base_winsys_features, + sizeof (context->winsys_features)); +@@ -848,7 +851,6 @@ update_winsys_features (CoglContext *context, CoglError **error) + + if (glx_renderer->glXCopySubBuffer || context->glBlitFramebuffer) + { +- CoglGpuInfo *info = &context->gpu; + CoglGpuInfoArchitecture arch = info->architecture; + + COGL_FLAGS_SET (context->winsys_features, COGL_WINSYS_FEATURE_SWAP_REGION, TRUE); +@@ -897,7 +899,6 @@ update_winsys_features (CoglContext *context, CoglError **error) + } + else + { +- CoglGpuInfo *info = &context->gpu; + if (glx_display->have_vblank_counter && + context->display->renderer->xlib_enable_threaded_swap_wait && + info->vendor == COGL_GPU_INFO_VENDOR_NVIDIA) +@@ -919,6 +920,14 @@ update_winsys_features (CoglContext *context, CoglError **error) + } + } + ++ if (info->vendor == COGL_GPU_INFO_VENDOR_NVIDIA) ++ { ++ context->feature_flags |= COGL_FEATURE_UNSTABLE_TEXTURES; ++ COGL_FLAGS_SET (context->features, ++ COGL_FEATURE_ID_UNSTABLE_TEXTURES, ++ TRUE); ++ } ++ + /* We'll manually handle queueing dirty events in response to + * Expose events from X */ + COGL_FLAGS_SET (context->private_features, +-- +2.21.0 + diff --git a/SOURCES/0001-core-Let-pad-mode-switch-events-always-go-through-Me.patch b/SOURCES/0001-core-Let-pad-mode-switch-events-always-go-through-Me.patch new file mode 100644 index 0000000..5ee31d1 --- /dev/null +++ b/SOURCES/0001-core-Let-pad-mode-switch-events-always-go-through-Me.patch @@ -0,0 +1,64 @@ +From 5cab6bac4d4fb06e60d3198dc654a5d70fa6240e Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Mon, 16 Dec 2019 13:53:26 +0100 +Subject: [PATCH] core: Let pad mode switch events always go through + MetaInputSettings + +We used to inhibit all pad actions while the OSD is shown, but one we +would actually want to handle are mode switches while the OSD is open. +So it has an opportunity to catch up to the mode switch. + +This lets MetaInputSettings reflect the mode switch (eg. when querying +action labels), so the OSD has an opportunity to update the current +actions. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/975 +--- + src/core/events.c | 30 ++++++++++++++++++++++++------ + 1 file changed, 24 insertions(+), 6 deletions(-) + +diff --git a/src/core/events.c b/src/core/events.c +index d383778629..44f28d0b97 100644 +--- a/src/core/events.c ++++ b/src/core/events.c +@@ -256,13 +256,31 @@ meta_display_handle_event (MetaDisplay *display, + } + #endif + +- if (!display->current_pad_osd && +- (event->type == CLUTTER_PAD_BUTTON_PRESS || +- event->type == CLUTTER_PAD_BUTTON_RELEASE || +- event->type == CLUTTER_PAD_RING || +- event->type == CLUTTER_PAD_STRIP)) ++ if (event->type == CLUTTER_PAD_BUTTON_PRESS || ++ event->type == CLUTTER_PAD_BUTTON_RELEASE || ++ event->type == CLUTTER_PAD_RING || ++ event->type == CLUTTER_PAD_STRIP) + { +- if (meta_input_settings_handle_pad_event (meta_backend_get_input_settings (backend), ++ gboolean handle_pad_event = TRUE; ++ gboolean is_mode_switch = FALSE; ++ ++ if (event->type == CLUTTER_PAD_BUTTON_PRESS || ++ event->type == CLUTTER_PAD_BUTTON_RELEASE) ++ { ++ ClutterInputDevice *pad; ++ uint32_t button; ++ ++ pad = clutter_event_get_source_device (event); ++ button = clutter_event_get_button (event); ++ ++ is_mode_switch = ++ clutter_input_device_get_mode_switch_button_group (pad, button) >= 0; ++ } ++ ++ handle_pad_event = !display->current_pad_osd || is_mode_switch; ++ ++ if (handle_pad_event && ++ meta_input_settings_handle_pad_event (meta_backend_get_input_settings (backend), + event)) + { + bypass_wayland = bypass_clutter = TRUE; +-- +2.24.0 + diff --git a/SOURCES/0001-crtc-xrandr-Respect-configured-RANDR-panning.patch b/SOURCES/0001-crtc-xrandr-Respect-configured-RANDR-panning.patch new file mode 100644 index 0000000..29e6b88 --- /dev/null +++ b/SOURCES/0001-crtc-xrandr-Respect-configured-RANDR-panning.patch @@ -0,0 +1,73 @@ +From bac090f571e6f413ba2a362ed2d70146b7701d16 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Mon, 24 Feb 2020 17:37:34 +0100 +Subject: [PATCH] crtc-xrandr: Respect configured RANDR panning + +A user may have configured an output to be panning, e.g. using xrandr +--output --mode --panning . Respect this by making +the logical monitor use the panning size, instead of the mode. This +makes e.g. makes the background cover the whole panning size, and panels +etc will cover the whole top of the panned area, instead of just the top +left part covering the monitor if having panned to (0, 0). + +No support is added to configuring panning, i.e. a panned monitor +configuration cannot be stored in monitors.xml. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/1085 +--- + src/backends/x11/meta-crtc-xrandr.c | 31 +++++++++++++++++++++++++---- + 1 file changed, 27 insertions(+), 4 deletions(-) + +diff --git a/src/backends/x11/meta-crtc-xrandr.c b/src/backends/x11/meta-crtc-xrandr.c +index d201b8581..dc3f931e3 100644 +--- a/src/backends/x11/meta-crtc-xrandr.c ++++ b/src/backends/x11/meta-crtc-xrandr.c +@@ -177,7 +177,14 @@ meta_create_xrandr_crtc (MetaGpuXrandr *gpu_xrandr, + RRCrtc crtc_id, + XRRScreenResources *resources) + { ++ MetaGpu *gpu = META_GPU (gpu_xrandr); ++ MetaMonitorManager *monitor_manager = meta_gpu_get_monitor_manager (gpu); ++ MetaMonitorManagerXrandr *monitor_manager_xrandr = ++ META_MONITOR_MANAGER_XRANDR (monitor_manager); ++ Display *xdisplay = ++ meta_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr); + MetaCrtc *crtc; ++ XRRPanning *panning; + unsigned int i; + GList *modes; + +@@ -185,10 +192,26 @@ meta_create_xrandr_crtc (MetaGpuXrandr *gpu_xrandr, + + crtc->gpu = META_GPU (gpu_xrandr); + crtc->crtc_id = crtc_id; +- crtc->rect.x = xrandr_crtc->x; +- crtc->rect.y = xrandr_crtc->y; +- crtc->rect.width = xrandr_crtc->width; +- crtc->rect.height = xrandr_crtc->height; ++ ++ panning = XRRGetPanning (xdisplay, resources, crtc_id); ++ if (panning && panning->width > 0 && panning->height > 0) ++ { ++ crtc->rect = (MetaRectangle) { ++ .x = panning->left, ++ .y = panning->top, ++ .width = panning->width, ++ .height = panning->height, ++ }; ++ } ++ else ++ { ++ crtc->rect = (MetaRectangle) { ++ .x = xrandr_crtc->x, ++ .y = xrandr_crtc->y, ++ .width = xrandr_crtc->width, ++ .height = xrandr_crtc->height, ++ }; ++ } + crtc->is_dirty = FALSE; + crtc->transform = + meta_monitor_transform_from_xrandr (xrandr_crtc->rotation); +-- +2.24.1 + diff --git a/SOURCES/0001-enum-types-Use-basename-in-header-comment.patch b/SOURCES/0001-enum-types-Use-basename-in-header-comment.patch new file mode 100644 index 0000000..88b3a4f --- /dev/null +++ b/SOURCES/0001-enum-types-Use-basename-in-header-comment.patch @@ -0,0 +1,55 @@ +From 62387eb649b7b33d923d5382f85c9210a3bedbe8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Thu, 30 May 2019 16:32:35 +0200 +Subject: [PATCH] enum-types: Use @basename@ in header comment + +@filename@ may contain arch-specific bits that introduce unnecessary +multi-lib issues. +--- + clutter/clutter/clutter-enum-types.h.in | 2 +- + cogl/cogl-path/cogl-path-enum-types.h.in | 2 +- + src/meta/meta-enum-types.h.in | 2 +- + 3 files changed, 3 insertions(+), 3 deletions(-) + +diff --git a/clutter/clutter/clutter-enum-types.h.in b/clutter/clutter/clutter-enum-types.h.in +index 2e5b6707e..17f9ee644 100644 +--- a/clutter/clutter/clutter-enum-types.h.in ++++ b/clutter/clutter/clutter-enum-types.h.in +@@ -13,7 +13,7 @@ G_BEGIN_DECLS + /*** END file-header ***/ + + /*** BEGIN file-production ***/ +-/* enumerations from "@filename@" */ ++/* enumerations from "@basename@" */ + /*** END file-production ***/ + + /*** BEGIN value-header ***/ +diff --git a/cogl/cogl-path/cogl-path-enum-types.h.in b/cogl/cogl-path/cogl-path-enum-types.h.in +index 071686acd..2b377ed18 100644 +--- a/cogl/cogl-path/cogl-path-enum-types.h.in ++++ b/cogl/cogl-path/cogl-path-enum-types.h.in +@@ -9,7 +9,7 @@ G_BEGIN_DECLS + /*** END file-header ***/ + + /*** BEGIN file-production ***/ +-/* enumerations from "@filename@" */ ++/* enumerations from "@basename@" */ + /*** END file-production ***/ + + /*** BEGIN file-tail ***/ +diff --git a/src/meta/meta-enum-types.h.in b/src/meta/meta-enum-types.h.in +index 6e3b67b26..bee0196de 100644 +--- a/src/meta/meta-enum-types.h.in ++++ b/src/meta/meta-enum-types.h.in +@@ -10,7 +10,7 @@ G_BEGIN_DECLS + /*** END file-header ***/ + + /*** BEGIN file-production ***/ +-/* enumerations from "@filename@" */ ++/* enumerations from "@basename@" */ + /*** END file-production ***/ + + /*** BEGIN file-tail ***/ +-- +2.21.0 + diff --git a/SOURCES/0001-events-Don-t-move-sloppy-focus-while-buttons-are-pre.patch b/SOURCES/0001-events-Don-t-move-sloppy-focus-while-buttons-are-pre.patch new file mode 100644 index 0000000..69fc6ef --- /dev/null +++ b/SOURCES/0001-events-Don-t-move-sloppy-focus-while-buttons-are-pre.patch @@ -0,0 +1,42 @@ +From f735f345ad8390a7fb09ef54ca3e0e419d395d1b Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Thu, 21 Jul 2016 15:43:12 +0200 +Subject: [PATCH] events: Don't move (sloppy) focus while buttons are pressed + +(https://bugzilla.redhat.com/show_bug.cgi?id=1358535) +--- + src/x11/events.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/src/x11/events.c b/src/x11/events.c +index e363fdbb6..905b5bf9d 100644 +--- a/src/x11/events.c ++++ b/src/x11/events.c +@@ -832,6 +832,16 @@ crossing_serial_is_ignored (MetaX11Display *x11_display, + return FALSE; + } + ++static gboolean ++event_has_button_mask (XIEnterEvent *enter_event) ++{ ++ int i; ++ for (i = 0; i < enter_event->buttons.mask_len; i++) ++ if (enter_event->buttons.mask[i] != '\0') ++ return TRUE; ++ return FALSE; ++} ++ + static gboolean + handle_input_xevent (MetaX11Display *x11_display, + XIEvent *input_event, +@@ -876,6 +886,7 @@ handle_input_xevent (MetaX11Display *x11_display, + * avoid races. + */ + if (window && !crossing_serial_is_ignored (x11_display, serial) && ++ !event_has_button_mask (enter_event) && + enter_event->mode != XINotifyGrab && + enter_event->mode != XINotifyUngrab && + enter_event->detail != XINotifyInferior && +-- +2.21.0 + diff --git a/SOURCES/0001-events-Sync-pending-pointer-events-without-a-window.patch b/SOURCES/0001-events-Sync-pending-pointer-events-without-a-window.patch new file mode 100644 index 0000000..3ba3963 --- /dev/null +++ b/SOURCES/0001-events-Sync-pending-pointer-events-without-a-window.patch @@ -0,0 +1,122 @@ +From f108395c32351cda8722130e0e2970827b18e5a9 Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Wed, 2 Oct 2019 16:49:28 +0200 +Subject: [PATCH] events: Sync pending pointer events without a window + +Mutter issues a synchronous grab on the pointer for unfocused client +windows to be able to catch the button events first and raise/focus +client windows accordingly. + +When there is a synchronous grab in effect, all events are queued until +the grabbing client releases the event queue as it processes the events. + +Mutter does release the events in its event handler function but does so +only if it is able to find the window matching the event. If the window +is a shell widget, that matching may fail and therefore Mutter will not +release the events, hence causing a freeze in pointer events delivery. + +To avoid the issue, make sure we sync the pointer events in case we +can't find a matching window. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/821 +--- + src/core/events.c | 62 ++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 51 insertions(+), 11 deletions(-) + +diff --git a/src/core/events.c b/src/core/events.c +index 5b8e49fc7..831cb007b 100644 +--- a/src/core/events.c ++++ b/src/core/events.c +@@ -50,6 +50,12 @@ + #define IS_KEY_EVENT(e) ((e)->type == CLUTTER_KEY_PRESS || \ + (e)->type == CLUTTER_KEY_RELEASE) + ++typedef enum ++{ ++ EVENTS_UNFREEZE_SYNC, ++ EVENTS_UNFREEZE_REPLAY, ++} EventsUnfreezeMethod; ++ + static gboolean + stage_has_key_focus (void) + { +@@ -167,6 +173,43 @@ sequence_is_pointer_emulated (MetaDisplay *display, + return FALSE; + } + ++static void ++maybe_unfreeze_pointer_events (MetaBackend *backend, ++ const ClutterEvent *event, ++ EventsUnfreezeMethod unfreeze_method) ++{ ++ Display *xdisplay; ++ int event_mode; ++ int device_id; ++ ++ if (event->type != CLUTTER_BUTTON_PRESS) ++ return; ++ ++ if (!META_IS_BACKEND_X11 (backend)) ++ return; ++ ++ device_id = clutter_event_get_device_id (event); ++ switch (unfreeze_method) ++ { ++ case EVENTS_UNFREEZE_SYNC: ++ event_mode = XISyncDevice; ++ meta_verbose ("Syncing events time %u device %i\n", ++ (unsigned int) event->button.time, device_id); ++ break; ++ case EVENTS_UNFREEZE_REPLAY: ++ event_mode = XIReplayDevice; ++ meta_verbose ("Replaying events time %u device %i\n", ++ (unsigned int) event->button.time, device_id); ++ break; ++ default: ++ g_assert_not_reached (); ++ return; ++ } ++ ++ xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); ++ XIAllowEvents (xdisplay, device_id, event_mode, event->button.time); ++} ++ + static gboolean + meta_display_handle_event (MetaDisplay *display, + const ClutterEvent *event) +@@ -366,17 +409,7 @@ meta_display_handle_event (MetaDisplay *display, + { + /* Only replay button press events, since that's where we + * have the synchronous grab. */ +- if (event->type == CLUTTER_BUTTON_PRESS) +- { +- if (META_IS_BACKEND_X11 (backend)) +- { +- Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); +- meta_verbose ("Allowing events time %u\n", +- (unsigned int)event->button.time); +- XIAllowEvents (xdisplay, clutter_event_get_device_id (event), +- XIReplayDevice, event->button.time); +- } +- } ++ maybe_unfreeze_pointer_events (backend, event, EVENTS_UNFREEZE_REPLAY); + + /* If the focus window has an active close dialog let clutter + * events go through, so fancy clutter dialogs can get to handle +@@ -392,6 +425,13 @@ meta_display_handle_event (MetaDisplay *display, + + goto out; + } ++ else ++ { ++ /* We could not match the event with a window, make sure we sync ++ * the pointer to discard the sequence and don't keep events frozen. ++ */ ++ maybe_unfreeze_pointer_events (backend, event, EVENTS_UNFREEZE_SYNC); ++ } + + out: + /* If the compositor has a grab, don't pass that through to Wayland */ +-- +2.23.0 + diff --git a/SOURCES/0001-iconcache-Avoid-xrender-picture-formats-when-creatin.patch b/SOURCES/0001-iconcache-Avoid-xrender-picture-formats-when-creatin.patch new file mode 100644 index 0000000..0ed0857 --- /dev/null +++ b/SOURCES/0001-iconcache-Avoid-xrender-picture-formats-when-creatin.patch @@ -0,0 +1,136 @@ +From 80f79e0cc7509b79b38193a006b0d98d03432044 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 5 Aug 2019 14:39:21 -0400 +Subject: [PATCH] iconcache: Avoid xrender picture formats when creating cairo + surface + +If an application provides its window icon via wmhints, then mutter +loads the pixmap specified by the application into a cairo xlib surface. When +creating the surface it specifies the visual, indirectly, via an XRender +picture format. + +This is suboptimal, since XRender picture formats don't have a way to specify +16bpp depth, which an application may be using. + +In particular, applications are likely to use 16bpp depth pixmaps for their +icons, if the video card offers a 16bpp framebuffer/root window. + +This commit drops the XRender middleman, and just tells cairo a visual to use +directly. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/715 +--- + src/x11/iconcache.c | 31 ++++++------------------------- + 1 file changed, 6 insertions(+), 25 deletions(-) + +diff --git a/src/x11/iconcache.c b/src/x11/iconcache.c +index 15d72da65..521c77b8d 100644 +--- a/src/x11/iconcache.c ++++ b/src/x11/iconcache.c +@@ -261,97 +261,78 @@ get_pixmap_geometry (MetaX11Display *x11_display, + Pixmap pixmap, + int *w, + int *h, + int *d) + { + Window root_ignored; + int x_ignored, y_ignored; + guint width, height; + guint border_width_ignored; + guint depth; + + if (w) + *w = 1; + if (h) + *h = 1; + if (d) + *d = 1; + + XGetGeometry (x11_display->xdisplay, + pixmap, &root_ignored, &x_ignored, &y_ignored, + &width, &height, &border_width_ignored, &depth); + + if (w) + *w = width; + if (h) + *h = height; + if (d) + *d = depth; + } + +-static int +-standard_pict_format_for_depth (int depth) +-{ +- switch (depth) +- { +- case 1: +- return PictStandardA1; +- case 24: +- return PictStandardRGB24; +- case 32: +- return PictStandardARGB32; +- default: +- g_assert_not_reached (); +- } +- return 0; +-} +- +-static XRenderPictFormat * +-pict_format_for_depth (Display *xdisplay, int depth) +-{ +- return XRenderFindStandardFormat (xdisplay, standard_pict_format_for_depth (depth)); +-} +- + static cairo_surface_t * + surface_from_pixmap (Display *xdisplay, Pixmap xpixmap, + int width, int height) + { + Window root_return; ++ XVisualInfo visual_info; + int x_ret, y_ret; + unsigned int w_ret, h_ret, bw_ret, depth_ret; + + if (!XGetGeometry (xdisplay, xpixmap, &root_return, + &x_ret, &y_ret, &w_ret, &h_ret, &bw_ret, &depth_ret)) + return NULL; + +- return cairo_xlib_surface_create_with_xrender_format (xdisplay, xpixmap, DefaultScreenOfDisplay (xdisplay), +- pict_format_for_depth (xdisplay, depth_ret), w_ret, h_ret); ++ if (!XMatchVisualInfo (xdisplay, DefaultScreen (xdisplay), ++ depth_ret, TrueColor, &visual_info)) ++ return NULL; ++ ++ return cairo_xlib_surface_create (xdisplay, xpixmap, visual_info.visual, w_ret, h_ret); + } + + static gboolean + try_pixmap_and_mask (MetaX11Display *x11_display, + Pixmap src_pixmap, + Pixmap src_mask, + cairo_surface_t **iconp) + { + Display *xdisplay = x11_display->xdisplay; + cairo_surface_t *icon, *mask = NULL; + int w, h, d; + + if (src_pixmap == None) + return FALSE; + + meta_x11_error_trap_push (x11_display); + + get_pixmap_geometry (x11_display, src_pixmap, &w, &h, &d); + icon = surface_from_pixmap (xdisplay, src_pixmap, w, h); + + if (icon && src_mask != None) + { + get_pixmap_geometry (x11_display, src_mask, &w, &h, &d); + + if (d == 1) + mask = surface_from_pixmap (xdisplay, src_mask, w, h); + } + + meta_x11_error_trap_pop (x11_display); + +-- +2.21.0 + diff --git a/SOURCES/0001-main-be-more-aggressive-in-assuming-X11-backend.patch b/SOURCES/0001-main-be-more-aggressive-in-assuming-X11-backend.patch new file mode 100644 index 0000000..495d859 --- /dev/null +++ b/SOURCES/0001-main-be-more-aggressive-in-assuming-X11-backend.patch @@ -0,0 +1,49 @@ +From 18d4fbb1fb641e2b507b3adcd13d231145a01cd6 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 13 Feb 2018 09:44:50 -0500 +Subject: [PATCH] main: be more aggressive in assuming X11 backend + +If the session is started by vncserver right now, the +XDG_SESSION_TYPE won't be X11. Ideally that would be +fixed, but for backward compatibility we should default +to X11 if the session type isn't set to wayland explicitly. +--- + src/core/main.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/src/core/main.c b/src/core/main.c +index 629f8e94e..1e1e13367 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -333,7 +333,6 @@ find_session_type (void) + char *session_id; + char *session_type; + const char *session_type_env; +- gboolean is_tty = FALSE; + int ret, i; + + ret = sd_pid_get_session (0, &session_id); +@@ -346,8 +345,7 @@ find_session_type (void) + { + if (session_type_is_supported (session_type)) + goto out; +- else +- is_tty = g_strcmp0 (session_type, "tty") == 0; ++ + free (session_type); + } + } +@@ -379,8 +377,8 @@ find_session_type (void) + goto out; + } + +- /* Legacy support for starting through xinit */ +- if (is_tty && (g_getenv ("MUTTER_DISPLAY") || g_getenv ("DISPLAY"))) ++ /* Legacy support for starting through xinit or vncserver */ ++ if (g_getenv ("MUTTER_DISPLAY") || g_getenv ("DISPLAY")) + { + session_type = strdup ("x11"); + goto out; +-- +2.21.0 + diff --git a/SOURCES/0001-monitor-manager-Consider-external-layout-before-defa.patch b/SOURCES/0001-monitor-manager-Consider-external-layout-before-defa.patch new file mode 100644 index 0000000..d204242 --- /dev/null +++ b/SOURCES/0001-monitor-manager-Consider-external-layout-before-defa.patch @@ -0,0 +1,152 @@ +From 4904f1a1e5b881dfd5a051c15acecb3232dc8207 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Thu, 28 Jan 2016 15:26:33 +0100 +Subject: [PATCH] monitor-manager: Consider external layout before default + linear config + +In case of no existing configuration, we use a default layout of +aligning attached displays horizontally. This sidesteps any layout +configuration that is done externally, for instance via xorg.conf, +which is not desirable. Instead, base the initial configuration on +the existing layout if it passes some sanity checks before falling +back to the default linear config. +--- + src/backends/meta-monitor-config-manager.c | 77 ++++++++++++++++++++++ + src/backends/meta-monitor-config-manager.h | 2 + + src/backends/meta-monitor-manager.c | 19 ++++++ + 3 files changed, 98 insertions(+) + +diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c +index 9a54ce50f..d64ca1f79 100644 +--- a/src/backends/meta-monitor-config-manager.c ++++ b/src/backends/meta-monitor-config-manager.c +@@ -643,6 +643,83 @@ create_preferred_logical_monitor_config (MetaMonitorManager *monitor_ma + return logical_monitor_config; + } + ++static MetaLogicalMonitorConfig * ++create_logical_monitor_config_from_output (MetaMonitorManager *monitor_manager, ++ MetaMonitor *monitor, ++ MetaLogicalMonitorConfig *primary_logical_monitor_config, ++ MetaLogicalMonitorLayoutMode layout_mode) ++{ ++ MetaOutput *output; ++ MetaCrtc *crtc; ++ ++ output = meta_monitor_get_main_output (monitor); ++ crtc = meta_output_get_assigned_crtc (output); ++ return create_preferred_logical_monitor_config (monitor_manager, ++ monitor, ++ crtc->rect.x, ++ crtc->rect.y, ++ primary_logical_monitor_config, ++ layout_mode); ++} ++ ++MetaMonitorsConfig * ++meta_monitor_config_manager_create_current (MetaMonitorConfigManager *config_manager) ++{ ++ MetaMonitorManager *monitor_manager = config_manager->monitor_manager; ++ GList *logical_monitor_configs; ++ MetaMonitor *primary_monitor; ++ MetaLogicalMonitorLayoutMode layout_mode; ++ MetaLogicalMonitorConfig *primary_logical_monitor_config; ++ GList *monitors; ++ GList *l; ++ ++ if (meta_monitor_config_store_get_config_count (config_manager->config_store) > 0) ++ return NULL; ++ ++ primary_monitor = find_primary_monitor (monitor_manager); ++ if (!primary_monitor || !meta_monitor_is_active (primary_monitor)) ++ return NULL; ++ ++ layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager); ++ ++ primary_logical_monitor_config = ++ create_logical_monitor_config_from_output (monitor_manager, ++ primary_monitor, ++ NULL, ++ layout_mode); ++ ++ primary_logical_monitor_config->is_primary = TRUE; ++ logical_monitor_configs = g_list_append (NULL, ++ primary_logical_monitor_config); ++ ++ monitors = meta_monitor_manager_get_monitors (monitor_manager); ++ for (l = monitors; l; l = l->next) ++ { ++ MetaMonitor *monitor = l->data; ++ MetaLogicalMonitorConfig *logical_monitor_config; ++ ++ if (monitor == primary_monitor) ++ continue; ++ ++ if (!meta_monitor_is_active (monitor)) ++ continue; ++ ++ logical_monitor_config = ++ create_logical_monitor_config_from_output (monitor_manager, ++ monitor, ++ primary_logical_monitor_config, ++ layout_mode); ++ ++ logical_monitor_configs = g_list_append (logical_monitor_configs, ++ logical_monitor_config); ++ } ++ ++ return meta_monitors_config_new (monitor_manager, ++ logical_monitor_configs, ++ layout_mode, ++ META_MONITORS_CONFIG_FLAG_NONE); ++} ++ + MetaMonitorsConfig * + meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_manager) + { +diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h +index 3875e04e9..364a2b36b 100644 +--- a/src/backends/meta-monitor-config-manager.h ++++ b/src/backends/meta-monitor-config-manager.h +@@ -94,6 +94,8 @@ gboolean meta_monitor_config_manager_assign (MetaMonitorManager *manager, + META_EXPORT_TEST + MetaMonitorsConfig * meta_monitor_config_manager_get_stored (MetaMonitorConfigManager *config_manager); + ++META_EXPORT_TEST ++MetaMonitorsConfig * meta_monitor_config_manager_create_current (MetaMonitorConfigManager *config_manager); + META_EXPORT_TEST + MetaMonitorsConfig * meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_manager); + +diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c +index 2d898c757..05b27c6be 100644 +--- a/src/backends/meta-monitor-manager.c ++++ b/src/backends/meta-monitor-manager.c +@@ -614,6 +614,25 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager) + g_clear_object (&config); + } + ++ config = meta_monitor_config_manager_create_current (manager->config_manager); ++ if (config) ++ { ++ if (!meta_monitor_manager_apply_monitors_config (manager, ++ config, ++ method, ++ &error)) ++ { ++ g_clear_object (&config); ++ g_warning ("Failed to use current monitor configuration: %s", ++ error->message); ++ g_clear_error (&error); ++ } ++ else ++ { ++ goto done; ++ } ++ } ++ + config = meta_monitor_config_manager_create_linear (manager->config_manager); + if (config) + { +-- +2.21.0 + diff --git a/SOURCES/0001-monitor-manager-only-reuse-initial-config-if-monitor.patch b/SOURCES/0001-monitor-manager-only-reuse-initial-config-if-monitor.patch new file mode 100644 index 0000000..dc34cee --- /dev/null +++ b/SOURCES/0001-monitor-manager-only-reuse-initial-config-if-monitor.patch @@ -0,0 +1,144 @@ +From 4ad8fd80355189ecbde6c38961335ae4be4db8b3 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Tue, 11 Sep 2018 10:19:44 -0400 +Subject: [PATCH] monitor-manager: only reuse initial-config if monitor + topology matches startup + +Right now we try to apply the current monitor config when a new +monitor is attached. The current config obviously doesn't include the +new monitor, so the new monitor isn't lit up. + +The only reason we apply the current config at all is to handle the +startup case: We want to reuse the config set in Xorg when first +logging in. + +This commit changes the code to look at the *initial config* instead +of the current config, and only if the new monitor topology matches +the start up topology. +--- + src/backends/meta-monitor-config-manager.c | 20 +++++++++++++++----- + src/backends/meta-monitor-config-manager.h | 2 +- + src/backends/meta-monitor-manager.c | 16 +++++++++++++++- + 3 files changed, 31 insertions(+), 7 deletions(-) + +diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c +index d64ca1f79..c09edbe00 100644 +--- a/src/backends/meta-monitor-config-manager.c ++++ b/src/backends/meta-monitor-config-manager.c +@@ -42,6 +42,7 @@ struct _MetaMonitorConfigManager + MetaMonitorConfigStore *config_store; + + MetaMonitorsConfig *current_config; ++ MetaMonitorsConfig *initial_config; + GQueue config_history; + }; + +@@ -663,9 +664,10 @@ create_logical_monitor_config_from_output (MetaMonitorManager *monitor + } + + MetaMonitorsConfig * +-meta_monitor_config_manager_create_current (MetaMonitorConfigManager *config_manager) ++meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_manager) + { + MetaMonitorManager *monitor_manager = config_manager->monitor_manager; ++ MetaMonitorsConfig *initial_config; + GList *logical_monitor_configs; + MetaMonitor *primary_monitor; + MetaLogicalMonitorLayoutMode layout_mode; +@@ -673,6 +675,9 @@ meta_monitor_config_manager_create_current (MetaMonitorConfigManager *config_man + GList *monitors; + GList *l; + ++ if (config_manager->initial_config != NULL) ++ return g_object_ref (config_manager->initial_config); ++ + if (meta_monitor_config_store_get_config_count (config_manager->config_store) > 0) + return NULL; + +@@ -714,10 +719,14 @@ meta_monitor_config_manager_create_current (MetaMonitorConfigManager *config_man + logical_monitor_config); + } + +- return meta_monitors_config_new (monitor_manager, +- logical_monitor_configs, +- layout_mode, +- META_MONITORS_CONFIG_FLAG_NONE); ++ initial_config = meta_monitors_config_new (monitor_manager, ++ logical_monitor_configs, ++ layout_mode, ++ META_MONITORS_CONFIG_FLAG_NONE); ++ ++ config_manager->initial_config = g_object_ref (initial_config); ++ ++ return initial_config; + } + + MetaMonitorsConfig * +@@ -1256,6 +1265,7 @@ meta_monitor_config_manager_dispose (GObject *object) + META_MONITOR_CONFIG_MANAGER (object); + + g_clear_object (&config_manager->current_config); ++ g_clear_object (&config_manager->initial_config); + meta_monitor_config_manager_clear_history (config_manager); + + G_OBJECT_CLASS (meta_monitor_config_manager_parent_class)->dispose (object); +diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h +index 364a2b36b..409611bb0 100644 +--- a/src/backends/meta-monitor-config-manager.h ++++ b/src/backends/meta-monitor-config-manager.h +@@ -95,7 +95,7 @@ META_EXPORT_TEST + MetaMonitorsConfig * meta_monitor_config_manager_get_stored (MetaMonitorConfigManager *config_manager); + + META_EXPORT_TEST +-MetaMonitorsConfig * meta_monitor_config_manager_create_current (MetaMonitorConfigManager *config_manager); ++MetaMonitorsConfig * meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_manager); + META_EXPORT_TEST + MetaMonitorsConfig * meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_manager); + +diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c +index 05b27c6be..bb4b44188 100644 +--- a/src/backends/meta-monitor-manager.c ++++ b/src/backends/meta-monitor-manager.c +@@ -534,9 +534,11 @@ should_use_stored_config (MetaMonitorManager *manager) + MetaMonitorsConfig * + meta_monitor_manager_ensure_configured (MetaMonitorManager *manager) + { ++ g_autoptr (MetaMonitorsConfig) initial_config = NULL; + MetaMonitorsConfig *config = NULL; + GError *error = NULL; + gboolean use_stored_config; ++ MetaMonitorsConfigKey *current_state_key; + MetaMonitorsConfigMethod method; + MetaMonitorsConfigMethod fallback_method = + META_MONITORS_CONFIG_METHOD_TEMPORARY; +@@ -547,6 +549,18 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager) + else + method = META_MONITORS_CONFIG_METHOD_TEMPORARY; + ++ initial_config = meta_monitor_config_manager_create_initial (manager->config_manager); ++ ++ if (initial_config) ++ { ++ current_state_key = meta_create_monitors_config_key_for_current_state (manager); ++ ++ /* don't ever reuse initial configuration, if the monitor topology changed ++ */ ++ if (current_state_key && !meta_monitors_config_key_equal (current_state_key, initial_config->key)) ++ g_clear_object (&initial_config); ++ } ++ + if (use_stored_config) + { + config = meta_monitor_config_manager_get_stored (manager->config_manager); +@@ -614,7 +628,7 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager) + g_clear_object (&config); + } + +- config = meta_monitor_config_manager_create_current (manager->config_manager); ++ config = g_steal_pointer (&initial_config); + if (config) + { + if (!meta_monitor_manager_apply_monitors_config (manager, +-- +2.21.0 + diff --git a/SOURCES/0001-monitor-manager-xrandr-Force-an-update-when-resuming.patch b/SOURCES/0001-monitor-manager-xrandr-Force-an-update-when-resuming.patch new file mode 100644 index 0000000..2242c67 --- /dev/null +++ b/SOURCES/0001-monitor-manager-xrandr-Force-an-update-when-resuming.patch @@ -0,0 +1,272 @@ +From 849902beff553de41dd3940b17672ef98f687be5 Mon Sep 17 00:00:00 2001 +From: Rui Matos +Date: Mon, 4 Jun 2018 16:35:04 -0400 +Subject: [PATCH] monitor-manager-xrandr: Force an update when resuming from + suspend + +The stack below us isn't as reliable as we'd like and in some cases +doesn't generate RRScreenChangeNotify events when e.g. resuming a +laptop on a dock, meaning that we'd miss newly attached outputs. +--- + src/backends/meta-gpu.c | 7 ++ + src/backends/meta-gpu.h | 4 + + src/backends/x11/meta-gpu-xrandr.c | 26 ++++- + .../x11/meta-monitor-manager-xrandr.c | 96 +++++++++++++++++-- + 4 files changed, 123 insertions(+), 10 deletions(-) + +diff --git a/src/backends/meta-gpu.c b/src/backends/meta-gpu.c +index 3577391e5..946f72387 100644 +--- a/src/backends/meta-gpu.c ++++ b/src/backends/meta-gpu.c +@@ -64,6 +64,13 @@ meta_gpu_has_hotplug_mode_update (MetaGpu *gpu) + return FALSE; + } + ++void ++meta_gpu_poll_hardware (MetaGpu *gpu) ++{ ++ if (META_GPU_GET_CLASS (gpu)->poll_hardware) ++ META_GPU_GET_CLASS (gpu)->poll_hardware (gpu); ++} ++ + gboolean + meta_gpu_read_current (MetaGpu *gpu, + GError **error) +diff --git a/src/backends/meta-gpu.h b/src/backends/meta-gpu.h +index 701acdc97..a2fd061f7 100644 +--- a/src/backends/meta-gpu.h ++++ b/src/backends/meta-gpu.h +@@ -36,8 +36,12 @@ struct _MetaGpuClass + + gboolean (* read_current) (MetaGpu *gpu, + GError **error); ++ void (* poll_hardware) (MetaGpu *gpu); + }; + ++META_EXPORT_TEST ++void meta_gpu_poll_hardware (MetaGpu *gpu); ++ + META_EXPORT_TEST + gboolean meta_gpu_read_current (MetaGpu *gpu, + GError **error); +diff --git a/src/backends/x11/meta-gpu-xrandr.c b/src/backends/x11/meta-gpu-xrandr.c +index 3e8a7318d..90b33d486 100644 +--- a/src/backends/x11/meta-gpu-xrandr.c ++++ b/src/backends/x11/meta-gpu-xrandr.c +@@ -44,6 +44,8 @@ struct _MetaGpuXrandr + + int max_screen_width; + int max_screen_height; ++ ++ gboolean need_hardware_poll; + }; + + G_DEFINE_TYPE (MetaGpuXrandr, meta_gpu_xrandr, META_TYPE_GPU) +@@ -81,6 +83,14 @@ get_xmode_name (XRRModeInfo *xmode) + return g_strdup_printf ("%dx%d", width, height); + } + ++static void ++meta_gpu_xrandr_poll_hardware (MetaGpu *gpu) ++{ ++ MetaGpuXrandr *gpu_xrandr = META_GPU_XRANDR (gpu); ++ ++ gpu_xrandr->need_hardware_poll = TRUE; ++} ++ + static gboolean + meta_gpu_xrandr_read_current (MetaGpu *gpu, + GError **error) +@@ -116,8 +126,18 @@ meta_gpu_xrandr_read_current (MetaGpu *gpu, + monitor_manager->screen_width = WidthOfScreen (screen); + monitor_manager->screen_height = HeightOfScreen (screen); + +- resources = XRRGetScreenResourcesCurrent (xdisplay, +- DefaultRootWindow (xdisplay)); ++ if (gpu_xrandr->need_hardware_poll) ++ { ++ resources = XRRGetScreenResources (xdisplay, ++ DefaultRootWindow (xdisplay)); ++ gpu_xrandr->need_hardware_poll = FALSE; ++ } ++ else ++ { ++ resources = XRRGetScreenResourcesCurrent (xdisplay, ++ DefaultRootWindow (xdisplay)); ++ } ++ + if (!resources) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, +@@ -250,6 +270,7 @@ meta_gpu_xrandr_finalize (GObject *object) + static void + meta_gpu_xrandr_init (MetaGpuXrandr *gpu_xrandr) + { ++ gpu_xrandr->need_hardware_poll = TRUE; + } + + static void +@@ -261,4 +282,5 @@ meta_gpu_xrandr_class_init (MetaGpuXrandrClass *klass) + object_class->finalize = meta_gpu_xrandr_finalize; + + gpu_class->read_current = meta_gpu_xrandr_read_current; ++ gpu_class->poll_hardware = meta_gpu_xrandr_poll_hardware; + } +diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c +index 448e51fae..d60f00325 100644 +--- a/src/backends/x11/meta-monitor-manager-xrandr.c ++++ b/src/backends/x11/meta-monitor-manager-xrandr.c +@@ -71,6 +71,10 @@ struct _MetaMonitorManagerXrandr + Display *xdisplay; + int rr_event_base; + int rr_error_base; ++ ++ guint logind_watch_id; ++ guint logind_signal_sub_id; ++ + gboolean has_randr15; + + /* +@@ -102,6 +106,8 @@ typedef struct _MetaMonitorXrandrData + + GQuark quark_meta_monitor_xrandr_data; + ++static void meta_monitor_manager_xrandr_update (MetaMonitorManagerXrandr *manager_xrandr); ++ + Display * + meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *manager_xrandr) + { +@@ -1016,6 +1022,62 @@ meta_monitor_manager_xrandr_get_default_layout_mode (MetaMonitorManager *manager + return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL; + } + ++static void ++logind_signal_handler (GDBusConnection *connection, ++ const gchar *sender_name, ++ const gchar *object_path, ++ const gchar *interface_name, ++ const gchar *signal_name, ++ GVariant *parameters, ++ gpointer user_data) ++{ ++ MetaMonitorManagerXrandr *manager_xrandr = user_data; ++ gboolean suspending; ++ ++ if (!g_str_equal (signal_name, "PrepareForSleep")) ++ return; ++ ++ g_variant_get (parameters, "(b)", &suspending); ++ if (!suspending) ++ { ++ meta_gpu_poll_hardware (manager_xrandr->gpu); ++ meta_monitor_manager_xrandr_update (manager_xrandr); ++ } ++} ++ ++static void ++logind_appeared (GDBusConnection *connection, ++ const gchar *name, ++ const gchar *name_owner, ++ gpointer user_data) ++{ ++ MetaMonitorManagerXrandr *manager_xrandr = user_data; ++ ++ manager_xrandr->logind_signal_sub_id = g_dbus_connection_signal_subscribe (connection, ++ "org.freedesktop.login1", ++ "org.freedesktop.login1.Manager", ++ "PrepareForSleep", ++ "/org/freedesktop/login1", ++ NULL, ++ G_DBUS_SIGNAL_FLAGS_NONE, ++ logind_signal_handler, ++ manager_xrandr, ++ NULL); ++} ++ ++static void ++logind_vanished (GDBusConnection *connection, ++ const gchar *name, ++ gpointer user_data) ++{ ++ MetaMonitorManagerXrandr *manager_xrandr = user_data; ++ ++ if (connection && manager_xrandr->logind_signal_sub_id > 0) ++ g_dbus_connection_signal_unsubscribe (connection, manager_xrandr->logind_signal_sub_id); ++ ++ manager_xrandr->logind_signal_sub_id = 0; ++} ++ + static void + meta_monitor_manager_xrandr_constructed (GObject *object) + { +@@ -1072,12 +1134,23 @@ meta_monitor_manager_xrandr_finalize (GObject *object) + g_hash_table_destroy (manager_xrandr->tiled_monitor_atoms); + g_free (manager_xrandr->supported_scales); + ++ if (manager_xrandr->logind_watch_id > 0) ++ g_bus_unwatch_name (manager_xrandr->logind_watch_id); ++ manager_xrandr->logind_watch_id = 0; ++ + G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object); + } + + static void + meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr) + { ++ manager_xrandr->logind_watch_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM, ++ "org.freedesktop.login1", ++ G_BUS_NAME_WATCHER_FLAGS_NONE, ++ logind_appeared, ++ logind_vanished, ++ manager_xrandr, ++ NULL); + } + + static void +@@ -1123,9 +1196,8 @@ is_xvnc (MetaMonitorManager *manager) + return FALSE; + } + +-gboolean +-meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr, +- XEvent *event) ++static void ++meta_monitor_manager_xrandr_update (MetaMonitorManagerXrandr *manager_xrandr) + { + MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr); + MetaGpuXrandr *gpu_xrandr; +@@ -1134,11 +1206,6 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra + gboolean is_our_configuration; + unsigned int timestamp; + +- if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify) +- return FALSE; +- +- XRRUpdateConfiguration (event); +- + meta_monitor_manager_read_current_state (manager); + + gpu_xrandr = META_GPU_XRANDR (manager_xrandr->gpu); +@@ -1173,6 +1240,19 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra + + meta_monitor_manager_xrandr_rebuild_derived (manager, config); + } ++} ++ ++gboolean ++meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr, ++ XEvent *event) ++{ ++ ++ if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify) ++ return FALSE; ++ ++ XRRUpdateConfiguration (event); ++ ++ meta_monitor_manager_xrandr_update (manager_xrandr); + + return TRUE; + } +-- +2.21.0 + diff --git a/SOURCES/0001-monitor-manager-xrandr-Move-dpms-state-and-screen-si.patch b/SOURCES/0001-monitor-manager-xrandr-Move-dpms-state-and-screen-si.patch new file mode 100644 index 0000000..8a0242c --- /dev/null +++ b/SOURCES/0001-monitor-manager-xrandr-Move-dpms-state-and-screen-si.patch @@ -0,0 +1,114 @@ +From 078547521dd709d41ac3791322f711030ccc50e9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Wed, 27 Nov 2019 19:03:50 +0100 +Subject: [PATCH 1/2] monitor-manager-xrandr: Move dpms state and screen size + updating into helpers + +To be used by no-Xrandr fallback path. +--- + src/backends/x11/meta-gpu-xrandr.c | 37 +++++++++++++------ + .../x11/meta-monitor-manager-xrandr.c | 18 ++++++--- + 2 files changed, 38 insertions(+), 17 deletions(-) + +diff --git a/src/backends/x11/meta-gpu-xrandr.c b/src/backends/x11/meta-gpu-xrandr.c +index 90b33d486..1884278ca 100644 +--- a/src/backends/x11/meta-gpu-xrandr.c ++++ b/src/backends/x11/meta-gpu-xrandr.c +@@ -91,6 +91,30 @@ meta_gpu_xrandr_poll_hardware (MetaGpu *gpu) + gpu_xrandr->need_hardware_poll = TRUE; + } + ++static void ++update_screen_size (MetaGpuXrandr *gpu_xrandr) ++{ ++ MetaGpu *gpu = META_GPU (gpu_xrandr); ++ MetaMonitorManager *monitor_manager = meta_gpu_get_monitor_manager (gpu); ++ MetaMonitorManagerXrandr *monitor_manager_xrandr = ++ META_MONITOR_MANAGER_XRANDR (monitor_manager); ++ Display *xdisplay = ++ meta_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr); ++ int min_width, min_height; ++ Screen *screen; ++ ++ XRRGetScreenSizeRange (xdisplay, DefaultRootWindow (xdisplay), ++ &min_width, ++ &min_height, ++ &gpu_xrandr->max_screen_width, ++ &gpu_xrandr->max_screen_height); ++ ++ screen = ScreenOfDisplay (xdisplay, DefaultScreen (xdisplay)); ++ /* This is updated because we called XRRUpdateConfiguration. */ ++ monitor_manager->screen_width = WidthOfScreen (screen); ++ monitor_manager->screen_height = HeightOfScreen (screen); ++} ++ + static gboolean + meta_gpu_xrandr_read_current (MetaGpu *gpu, + GError **error) +@@ -105,8 +129,6 @@ meta_gpu_xrandr_read_current (MetaGpu *gpu, + RROutput primary_output; + unsigned int i, j; + GList *l; +- int min_width, min_height; +- Screen *screen; + GList *outputs = NULL; + GList *modes = NULL; + GList *crtcs = NULL; +@@ -115,16 +137,7 @@ meta_gpu_xrandr_read_current (MetaGpu *gpu, + XRRFreeScreenResources (gpu_xrandr->resources); + gpu_xrandr->resources = NULL; + +- XRRGetScreenSizeRange (xdisplay, DefaultRootWindow (xdisplay), +- &min_width, +- &min_height, +- &gpu_xrandr->max_screen_width, +- &gpu_xrandr->max_screen_height); +- +- screen = ScreenOfDisplay (xdisplay, DefaultScreen (xdisplay)); +- /* This is updated because we called XRRUpdateConfiguration. */ +- monitor_manager->screen_width = WidthOfScreen (screen); +- monitor_manager->screen_height = HeightOfScreen (screen); ++ update_screen_size (gpu_xrandr); + + if (gpu_xrandr->need_hardware_poll) + { +diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c +index b8d6342b6..7a0b43ac4 100644 +--- a/src/backends/x11/meta-monitor-manager-xrandr.c ++++ b/src/backends/x11/meta-monitor-manager-xrandr.c +@@ -146,12 +146,9 @@ x11_dpms_state_to_power_save (CARD16 dpms_state) + } + + static void +-meta_monitor_manager_xrandr_read_current_state (MetaMonitorManager *manager) ++meta_monitor_manager_xrandr_update_dpms_state (MetaMonitorManagerXrandr *manager_xrandr) + { +- MetaMonitorManagerXrandr *manager_xrandr = +- META_MONITOR_MANAGER_XRANDR (manager); +- MetaMonitorManagerClass *parent_class = +- META_MONITOR_MANAGER_CLASS (meta_monitor_manager_xrandr_parent_class); ++ MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr); + Display *xdisplay = meta_monitor_manager_xrandr_get_xdisplay (manager_xrandr); + BOOL dpms_capable, dpms_enabled; + CARD16 dpms_state; +@@ -167,6 +164,17 @@ meta_monitor_manager_xrandr_read_current_state (MetaMonitorManager *manager) + power_save_mode = META_POWER_SAVE_UNSUPPORTED; + + meta_monitor_manager_power_save_mode_changed (manager, power_save_mode); ++} ++ ++static void ++meta_monitor_manager_xrandr_read_current_state (MetaMonitorManager *manager) ++{ ++ MetaMonitorManagerXrandr *manager_xrandr = ++ META_MONITOR_MANAGER_XRANDR (manager); ++ MetaMonitorManagerClass *parent_class = ++ META_MONITOR_MANAGER_CLASS (meta_monitor_manager_xrandr_parent_class); ++ ++ meta_monitor_manager_xrandr_update_dpms_state (manager_xrandr); + + parent_class->read_current_state (manager); + } +-- +2.23.0 + diff --git a/SOURCES/0001-monitor-manager-xrandr-Work-around-spurious-hotplugs.patch b/SOURCES/0001-monitor-manager-xrandr-Work-around-spurious-hotplugs.patch new file mode 100644 index 0000000..c487119 --- /dev/null +++ b/SOURCES/0001-monitor-manager-xrandr-Work-around-spurious-hotplugs.patch @@ -0,0 +1,62 @@ +From 7e21503dc7c3b8321475eb5ccfdb23e71f86c0a0 Mon Sep 17 00:00:00 2001 +From: Rui Matos +Date: Tue, 6 Oct 2015 21:16:18 +0200 +Subject: [PATCH] monitor-manager-xrandr: Work around spurious hotplugs on Xvnc + +Xvnc turns its outputs off/on on every mode set which makes us believe +there was an hotplug when there actually wasn't. Work around this by +requiring new randr configuration timestamps to be ahead of the last +set timestamp by at least 100 ms for us to consider them an actual +hotplug. +--- + .../x11/meta-monitor-manager-xrandr.c | 20 ++++++++++++++++++- + 1 file changed, 19 insertions(+), 1 deletion(-) + +diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c +index 45c81f4eb..448e51fae 100644 +--- a/src/backends/x11/meta-monitor-manager-xrandr.c ++++ b/src/backends/x11/meta-monitor-manager-xrandr.c +@@ -1110,6 +1110,19 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass) + g_quark_from_static_string ("-meta-monitor-xrandr-data"); + } + ++static gboolean ++is_xvnc (MetaMonitorManager *manager) ++{ ++ MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); ++ GList *l; ++ ++ for (l = meta_gpu_get_outputs (manager_xrandr->gpu); l; l = l->next) ++ if (g_str_has_prefix (((MetaOutput *)l->data)->name, "VNC-")) ++ return TRUE; ++ ++ return FALSE; ++} ++ + gboolean + meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr, + XEvent *event) +@@ -1119,6 +1132,7 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra + XRRScreenResources *resources; + gboolean is_hotplug; + gboolean is_our_configuration; ++ unsigned int timestamp; + + if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify) + return FALSE; +@@ -1130,7 +1144,11 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra + gpu_xrandr = META_GPU_XRANDR (manager_xrandr->gpu); + resources = meta_gpu_xrandr_get_resources (gpu_xrandr); + +- is_hotplug = resources->timestamp < resources->configTimestamp; ++ timestamp = resources->timestamp; ++ if (is_xvnc (manager)) ++ timestamp += 100; ++ ++ is_hotplug = (timestamp < resources->configTimestamp); + is_our_configuration = (resources->timestamp == + manager_xrandr->last_xrandr_set_timestamp); + if (is_hotplug) +-- +2.21.0 + diff --git a/SOURCES/0001-wayland-Allow-Xwayland-grabs-on-selected-apps.patch b/SOURCES/0001-wayland-Allow-Xwayland-grabs-on-selected-apps.patch new file mode 100644 index 0000000..83f42ff --- /dev/null +++ b/SOURCES/0001-wayland-Allow-Xwayland-grabs-on-selected-apps.patch @@ -0,0 +1,35 @@ +From 9dfe362f41b8811450cb563c39899fafe8ec2b63 Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Fri, 26 Oct 2018 08:49:39 +0200 +Subject: [PATCH] wayland: Allow Xwayland grabs on selected apps + +Allow Xwayland grabs on a selected set of X11 applications. +--- + data/org.gnome.mutter.wayland.gschema.xml.in | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/data/org.gnome.mutter.wayland.gschema.xml.in b/data/org.gnome.mutter.wayland.gschema.xml.in +index 48241296e..7a6ab9288 100644 +--- a/data/org.gnome.mutter.wayland.gschema.xml.in ++++ b/data/org.gnome.mutter.wayland.gschema.xml.in +@@ -60,7 +60,7 @@ + gettext-domain="@GETTEXT_DOMAIN@"> + + +- false ++ true + Allow grabs with Xwayland + + Allow keyboard grabs issued by X11 applications running in Xwayland +@@ -73,7 +73,7 @@ + + + +- [] ++ ['@XWAYLAND_GRAB_DEFAULT_ACCESS_RULES@'] + Xwayland applications allowed to issue keyboard grabs + + List the resource names or resource class of X11 windows either +-- +2.21.0 + diff --git a/SOURCES/0001-wayland-Check-stylus-serials-on-meta_wayland_seat_ca.patch b/SOURCES/0001-wayland-Check-stylus-serials-on-meta_wayland_seat_ca.patch new file mode 100644 index 0000000..486df56 --- /dev/null +++ b/SOURCES/0001-wayland-Check-stylus-serials-on-meta_wayland_seat_ca.patch @@ -0,0 +1,109 @@ +From f2b3dd318f1165849b45a86251724939b100ef7d Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Mon, 28 Oct 2019 18:07:31 +0100 +Subject: [PATCH] wayland: Check stylus serials on + meta_wayland_seat_can_popup() + +This allows xdg_popup.grab() to work with styli. Without this check +we would bail out and emit xdg_popup.popup_done, leaving stylus users +unable to interact with popup menus, comboboxes, etc... + +Closes: https://gitlab.gnome.org/GNOME/mutter/issues/886 +--- + src/wayland/meta-wayland-seat.c | 10 +++++++++- + src/wayland/meta-wayland-tablet-seat.c | 17 +++++++++++++++++ + src/wayland/meta-wayland-tablet-seat.h | 2 ++ + src/wayland/meta-wayland-tablet-tool.c | 7 +++++++ + src/wayland/meta-wayland-tablet-tool.h | 2 ++ + 5 files changed, 37 insertions(+), 1 deletion(-) + +diff --git a/src/wayland/meta-wayland-seat.c b/src/wayland/meta-wayland-seat.c +index 91fe376ff..cf41d6eb8 100644 +--- a/src/wayland/meta-wayland-seat.c ++++ b/src/wayland/meta-wayland-seat.c +@@ -504,9 +504,17 @@ gboolean + meta_wayland_seat_can_popup (MetaWaylandSeat *seat, + uint32_t serial) + { ++ MetaWaylandCompositor *compositor; ++ MetaWaylandTabletSeat *tablet_seat; ++ ++ compositor = meta_wayland_compositor_get_default (); ++ tablet_seat = ++ meta_wayland_tablet_manager_ensure_seat (compositor->tablet_manager, seat); ++ + return (meta_wayland_pointer_can_popup (seat->pointer, serial) || + meta_wayland_keyboard_can_popup (seat->keyboard, serial) || +- meta_wayland_touch_can_popup (seat->touch, serial)); ++ meta_wayland_touch_can_popup (seat->touch, serial) || ++ meta_wayland_tablet_seat_can_popup (tablet_seat, serial)); + } + + gboolean +diff --git a/src/wayland/meta-wayland-tablet-seat.c b/src/wayland/meta-wayland-tablet-seat.c +index b4bc4aa58..b1964714a 100644 +--- a/src/wayland/meta-wayland-tablet-seat.c ++++ b/src/wayland/meta-wayland-tablet-seat.c +@@ -552,3 +552,20 @@ meta_wayland_tablet_seat_set_pad_focus (MetaWaylandTabletSeat *tablet_seat, + while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &pad)) + meta_wayland_tablet_pad_set_focus (pad, surface); + } ++ ++gboolean ++meta_wayland_tablet_seat_can_popup (MetaWaylandTabletSeat *tablet_seat, ++ uint32_t serial) ++{ ++ MetaWaylandTabletTool *tool; ++ GHashTableIter iter; ++ ++ g_hash_table_iter_init (&iter, tablet_seat->tools); ++ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &tool)) ++ { ++ if (meta_wayland_tablet_tool_can_popup (tool, serial)) ++ return TRUE; ++ } ++ ++ return FALSE; ++} +diff --git a/src/wayland/meta-wayland-tablet-seat.h b/src/wayland/meta-wayland-tablet-seat.h +index c083dec5f..e3be5f264 100644 +--- a/src/wayland/meta-wayland-tablet-seat.h ++++ b/src/wayland/meta-wayland-tablet-seat.h +@@ -75,5 +75,7 @@ MetaWaylandTablet *meta_wayland_tablet_seat_lookup_paired_tablet (MetaWaylan + MetaWaylandTabletPad *pad); + GList *meta_wayland_tablet_seat_lookup_paired_pads (MetaWaylandTabletSeat *tablet_seat, + MetaWaylandTablet *tablet); ++gboolean meta_wayland_tablet_seat_can_popup (MetaWaylandTabletSeat *tablet_seat, ++ uint32_t serial); + + #endif /* META_WAYLAND_TABLET_SEAT_H */ +diff --git a/src/wayland/meta-wayland-tablet-tool.c b/src/wayland/meta-wayland-tablet-tool.c +index c02831d73..065c834bb 100644 +--- a/src/wayland/meta-wayland-tablet-tool.c ++++ b/src/wayland/meta-wayland-tablet-tool.c +@@ -1018,3 +1018,10 @@ meta_wayland_tablet_tool_can_grab_surface (MetaWaylandTabletTool *tool, + return ((tool->down_serial == serial || tool->button_serial == serial) && + tablet_tool_can_grab_surface (tool, surface)); + } ++ ++gboolean ++meta_wayland_tablet_tool_can_popup (MetaWaylandTabletTool *tool, ++ uint32_t serial) ++{ ++ return tool->down_serial == serial || tool->button_serial == serial; ++} +diff --git a/src/wayland/meta-wayland-tablet-tool.h b/src/wayland/meta-wayland-tablet-tool.h +index 71bc86643..315e26bde 100644 +--- a/src/wayland/meta-wayland-tablet-tool.h ++++ b/src/wayland/meta-wayland-tablet-tool.h +@@ -85,5 +85,7 @@ void meta_wayland_tablet_tool_set_cursor_position (MetaWaylandTabletTool *t + gboolean meta_wayland_tablet_tool_can_grab_surface (MetaWaylandTabletTool *tool, + MetaWaylandSurface *surface, + uint32_t serial); ++gboolean meta_wayland_tablet_tool_can_popup (MetaWaylandTabletTool *tool, ++ uint32_t serial); + + #endif /* META_WAYLAND_TABLET_TOOL_H */ +-- +2.23.0 + diff --git a/SOURCES/0001-window-actor-Special-case-shaped-Java-windows.patch b/SOURCES/0001-window-actor-Special-case-shaped-Java-windows.patch new file mode 100644 index 0000000..3cf01de --- /dev/null +++ b/SOURCES/0001-window-actor-Special-case-shaped-Java-windows.patch @@ -0,0 +1,35 @@ +From 6bca5f001338d4647e4e21d549c8cdea4bcad669 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Fri, 12 May 2017 13:40:31 +0200 +Subject: [PATCH] window-actor: Special-case shaped Java windows + +OpenJDK wrongly assumes that shaping a window implies no shadows. +They got lucky until commit b975676c changed the fallback case, +but now their compliance tests are broken. Make them happy again +by special-casing shaped Java windows. +--- + src/compositor/meta-window-actor.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c +index f850cb222..1c8dc8fe5 100644 +--- a/src/compositor/meta-window-actor.c ++++ b/src/compositor/meta-window-actor.c +@@ -798,6 +798,14 @@ meta_window_actor_has_shadow (MetaWindowActor *self) + if (priv->window->has_custom_frame_extents) + return FALSE; + ++ /* ++ * OpenJDK wrongly assumes that shaping a window implies no compositor ++ * shadows; make its compliance tests happy to give it what it wants ... ++ */ ++ if (g_strcmp0 (priv->window->res_name, "sun-awt-X11-XWindowPeer") == 0 && ++ priv->window->shape_region != NULL) ++ return FALSE; ++ + /* + * Generate shadows for all other windows. + */ +-- +2.21.0 + diff --git a/SOURCES/0001-workspace-Focus-only-ancestors-that-are-focusable.patch b/SOURCES/0001-workspace-Focus-only-ancestors-that-are-focusable.patch new file mode 100644 index 0000000..94a73d8 --- /dev/null +++ b/SOURCES/0001-workspace-Focus-only-ancestors-that-are-focusable.patch @@ -0,0 +1,83 @@ +From eca25ab6a12770a2a767458d9b0129d4fde3995c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= +Date: Tue, 13 Nov 2018 08:31:52 +0100 +Subject: [PATCH 1/2] workspace: Focus only ancestors that are focusable + +When destroying a window that has a parent, we initially try to focus one of +its ancestors. However if no ancestor can be focused, then we should instead +focus the default focus window instead of trying to request focus for a window +that can't get focus anyways. + +Fixes https://gitlab.gnome.org/GNOME/mutter/issues/308 +(cherry picked from commit eccc791f3b3451216f957e67fec47a73b65ed2b2) +--- + src/core/workspace.c | 37 +++++++++++++++++++++++++++---------- + 1 file changed, 27 insertions(+), 10 deletions(-) + +diff --git a/src/core/workspace.c b/src/core/workspace.c +index f2b2c2c48..58fcfa78c 100644 +--- a/src/core/workspace.c ++++ b/src/core/workspace.c +@@ -85,6 +85,12 @@ typedef struct _MetaWorkspaceLogicalMonitorData + MetaRectangle logical_monitor_work_area; + } MetaWorkspaceLogicalMonitorData; + ++typedef struct _MetaWorkspaceFocusableAncestorData ++{ ++ MetaWorkspace *workspace; ++ MetaWindow *out_window; ++} MetaWorkspaceFocusableAncestorData; ++ + static MetaWorkspaceLogicalMonitorData * + meta_workspace_get_logical_monitor_data (MetaWorkspace *workspace, + MetaLogicalMonitor *logical_monitor) +@@ -1322,13 +1328,20 @@ meta_workspace_focus_default_window (MetaWorkspace *workspace, + } + + static gboolean +-record_ancestor (MetaWindow *window, +- void *data) ++find_focusable_ancestor (MetaWindow *window, ++ gpointer user_data) + { +- MetaWindow **result = data; ++ MetaWorkspaceFocusableAncestorData *data = user_data; ++ ++ if (!window->unmanaging && meta_window_is_focusable (window) && ++ meta_window_located_on_workspace (window, data->workspace) && ++ meta_window_showing_on_its_workspace (window)) ++ { ++ data->out_window = window; ++ return FALSE; ++ } + +- *result = window; +- return FALSE; /* quit with the first ancestor we find */ ++ return TRUE; + } + + /* Focus ancestor of not_this_one if there is one */ +@@ -1350,11 +1363,15 @@ focus_ancestor_or_top_window (MetaWorkspace *workspace, + if (not_this_one) + { + MetaWindow *ancestor; +- ancestor = NULL; +- meta_window_foreach_ancestor (not_this_one, record_ancestor, &ancestor); +- if (ancestor != NULL && +- meta_window_located_on_workspace (ancestor, workspace) && +- meta_window_showing_on_its_workspace (ancestor)) ++ MetaWorkspaceFocusableAncestorData data; ++ ++ data = (MetaWorkspaceFocusableAncestorData) { ++ .workspace = workspace, ++ }; ++ meta_window_foreach_ancestor (not_this_one, find_focusable_ancestor, &data); ++ ancestor = data.out_window; ++ ++ if (ancestor) + { + meta_topic (META_DEBUG_FOCUS, + "Focusing %s, ancestor of %s\n", +-- +2.21.0 + diff --git a/SOURCES/0001-workspace-manager-Expose-layout-properties.patch b/SOURCES/0001-workspace-manager-Expose-layout-properties.patch new file mode 100644 index 0000000..908fe67 --- /dev/null +++ b/SOURCES/0001-workspace-manager-Expose-layout-properties.patch @@ -0,0 +1,80 @@ +From 52536a44e96aa34d3ec3b9332adaa15a6399fc3e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Tue, 4 Jun 2019 21:21:37 +0200 +Subject: [PATCH] workspace-manager: Expose layout properties + +gnome-shell hardcodes a vertical one-column workspace layout, and +while not supporting arbitrary grids is very much by design, it +currently doesn't have a choice: We simply don't expose the workspace +layout we use. + +Change that to allow gnome-shell to be a bit more flexible with the +workspace layouts it supports. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/618 +--- + src/core/meta-workspace-manager.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/src/core/meta-workspace-manager.c b/src/core/meta-workspace-manager.c +index 8e1f03fe8..fbae34c73 100644 +--- a/src/core/meta-workspace-manager.c ++++ b/src/core/meta-workspace-manager.c +@@ -50,6 +50,9 @@ enum + { + PROP_0, + ++ PROP_LAYOUT_COLUMNS, ++ PROP_LAYOUT_ROWS, ++ + PROP_N_WORKSPACES + }; + +@@ -68,6 +71,12 @@ meta_workspace_manager_get_property (GObject *object, + + switch (prop_id) + { ++ case PROP_LAYOUT_COLUMNS: ++ g_value_set_int (value, workspace_manager->columns_of_workspaces); ++ break; ++ case PROP_LAYOUT_ROWS: ++ g_value_set_int (value, workspace_manager->rows_of_workspaces); ++ break; + case PROP_N_WORKSPACES: + g_value_set_int (value, meta_workspace_manager_get_n_workspaces (workspace_manager)); + break; +@@ -154,6 +163,22 @@ meta_workspace_manager_class_init (MetaWorkspaceManagerClass *klass) + 0, NULL, NULL, NULL, + G_TYPE_NONE, 0); + ++ g_object_class_install_property (object_class, ++ PROP_LAYOUT_COLUMNS, ++ g_param_spec_int ("layout-columns", ++ "Layout columns", ++ "Number of columns in layout", ++ -1, G_MAXINT, 1, ++ G_PARAM_READABLE)); ++ ++ g_object_class_install_property (object_class, ++ PROP_LAYOUT_ROWS, ++ g_param_spec_int ("layout-rows", ++ "Layout rows", ++ "Number of rows in layout", ++ -1, G_MAXINT, -1, ++ G_PARAM_READABLE)); ++ + g_object_class_install_property (object_class, + PROP_N_WORKSPACES, + g_param_spec_int ("n-workspaces", +@@ -474,6 +499,8 @@ meta_workspace_manager_update_workspace_layout (MetaWorkspaceManager *workspace_ + workspace_manager->columns_of_workspaces, + workspace_manager->vertical_workspaces, + workspace_manager->starting_corner); ++ g_object_notify (G_OBJECT (workspace_manager), "layout-columns"); ++ g_object_notify (G_OBJECT (workspace_manager), "layout-rows"); + } + + /** +-- +2.21.0 + diff --git a/SOURCES/0001-x11-Check-wacom-button-flags-to-determine-whether-bu.patch b/SOURCES/0001-x11-Check-wacom-button-flags-to-determine-whether-bu.patch new file mode 100644 index 0000000..5303bbc --- /dev/null +++ b/SOURCES/0001-x11-Check-wacom-button-flags-to-determine-whether-bu.patch @@ -0,0 +1,53 @@ +From 57b3a2ea620f754cfd38f1ed4851dd8223efbcab Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Thu, 28 Nov 2019 22:50:36 +0100 +Subject: [PATCH] x11: Check wacom button flags to determine whether button is + mode switch + +Checking the leds is not really accurate, since some devices have mode +switch buttons without leds. Check in the button flags whether they are +mode switch buttons for any of ring/ring2/strip/strip2, and return the +appropriate group. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/952 +--- + .../clutter/x11/clutter-input-device-xi2.c | 19 +++++++++++++++---- + 1 file changed, 15 insertions(+), 4 deletions(-) + +diff --git a/clutter/clutter/x11/clutter-input-device-xi2.c b/clutter/clutter/x11/clutter-input-device-xi2.c +index 1254aca3ae..4e5e2fd12c 100644 +--- a/clutter/clutter/x11/clutter-input-device-xi2.c ++++ b/clutter/clutter/x11/clutter-input-device-xi2.c +@@ -155,14 +155,25 @@ clutter_input_device_xi2_get_button_group (ClutterInputDevice *device, + + if (device_xi2->wacom_device) + { ++ WacomButtonFlags flags; ++ + if (button >= libwacom_get_num_buttons (device_xi2->wacom_device)) + return -1; + +- return libwacom_get_button_led_group (device_xi2->wacom_device, +- 'A' + button); ++ flags = libwacom_get_button_flag (device_xi2->wacom_device, ++ 'A' + button); ++ ++ if (flags & ++ (WACOM_BUTTON_RING_MODESWITCH | ++ WACOM_BUTTON_TOUCHSTRIP_MODESWITCH)) ++ return 0; ++ if (flags & ++ (WACOM_BUTTON_RING2_MODESWITCH | ++ WACOM_BUTTON_TOUCHSTRIP2_MODESWITCH)) ++ return 1; + } +- else +- return -1; ++ ++ return -1; + } + #endif + +-- +2.24.0 + diff --git a/SOURCES/0002-backend-switch-to-using-generated-logind-proxy.patch b/SOURCES/0002-backend-switch-to-using-generated-logind-proxy.patch new file mode 100644 index 0000000..3cb0623 --- /dev/null +++ b/SOURCES/0002-backend-switch-to-using-generated-logind-proxy.patch @@ -0,0 +1,163 @@ +From 063db6c9a7504a4d7baae28f7899bd661c459c41 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Mon, 14 Jan 2019 11:11:01 -0500 +Subject: [PATCH 2/9] backend: switch to using generated logind proxy + +Right now we listen to prepare-for-sleep using +raw gdbus calls. + +This commit switches it over to use a generated +proxy, which will become useful in a future commit, +for adding suspending inhibitors. +--- + src/backends/meta-backend.c | 60 ++++++++++++++++++++++------------ + src/org.freedesktop.login1.xml | 13 ++++++++ + 2 files changed, 52 insertions(+), 21 deletions(-) + +diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c +index 23ab2faec..5d71977c6 100644 +--- a/src/backends/meta-backend.c ++++ b/src/backends/meta-backend.c +@@ -65,6 +65,7 @@ + #include "meta/main.h" + #include "meta/meta-backend.h" + #include "meta/util.h" ++#include "meta-dbus-login1.h" + + #ifdef HAVE_REMOTE_DESKTOP + #include "backends/meta-dbus-session-watcher.h" +@@ -145,10 +146,12 @@ struct _MetaBackendPrivate + GDBusProxy *upower_proxy; + gboolean lid_is_closed; + +- guint sleep_signal_id; + GCancellable *cancellable; + GDBusConnection *system_bus; + ++ Login1Manager *logind_proxy; ++ int inhibit_sleep_fd; ++ + gboolean was_headless; + }; + typedef struct _MetaBackendPrivate MetaBackendPrivate; +@@ -156,6 +159,10 @@ typedef struct _MetaBackendPrivate MetaBackendPrivate; + static void + initable_iface_init (GInitableIface *initable_iface); + ++ ++static void prepare_for_sleep_cb (MetaBackend *backend, ++ gboolean suspending); ++ + G_DEFINE_ABSTRACT_TYPE_WITH_CODE (MetaBackend, meta_backend, G_TYPE_OBJECT, + G_ADD_PRIVATE (MetaBackend) + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, +@@ -177,8 +184,6 @@ meta_backend_finalize (GObject *object) + g_clear_object (&priv->remote_access_controller); + #endif + +- if (priv->sleep_signal_id) +- g_dbus_connection_signal_unsubscribe (priv->system_bus, priv->sleep_signal_id); + if (priv->upower_watch_id) + g_bus_unwatch_name (priv->upower_watch_id); + g_cancellable_cancel (priv->cancellable); +@@ -764,13 +769,8 @@ meta_backend_create_renderer (MetaBackend *backend, + } + + static void +-prepare_for_sleep_cb (GDBusConnection *connection, +- const gchar *sender_name, +- const gchar *object_path, +- const gchar *interface_name, +- const gchar *signal_name, +- GVariant *parameters, +- gpointer user_data) ++prepare_for_sleep_cb (MetaBackend *backend, ++ gboolean suspending) + { + gboolean suspending; + +@@ -780,12 +780,31 @@ prepare_for_sleep_cb (GDBusConnection *connection, + meta_idle_monitor_reset_idletime (meta_idle_monitor_get_core ()); + } + ++static Login1Manager * ++get_logind_proxy (GCancellable *cancellable, ++ GError **error) ++{ ++ Login1Manager *proxy; ++ ++ proxy = ++ login1_manager_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM, ++ G_DBUS_PROXY_FLAGS_DO_NOT_AUTO_START, ++ "org.freedesktop.login1", ++ "/org/freedesktop/login1", ++ cancellable, error); ++ if (!proxy) ++ g_prefix_error (error, "Could not get logind proxy: "); ++ ++ return proxy; ++} ++ + static void + system_bus_gotten_cb (GObject *object, + GAsyncResult *res, + gpointer user_data) + { + MetaBackendPrivate *priv; ++ g_autoptr (GError) error = NULL; + GDBusConnection *bus; + + bus = g_bus_get_finish (res, NULL); +@@ -794,17 +813,16 @@ system_bus_gotten_cb (GObject *object, + + priv = meta_backend_get_instance_private (user_data); + priv->system_bus = bus; +- priv->sleep_signal_id = +- g_dbus_connection_signal_subscribe (priv->system_bus, +- "org.freedesktop.login1", +- "org.freedesktop.login1.Manager", +- "PrepareForSleep", +- "/org/freedesktop/login1", +- NULL, +- G_DBUS_SIGNAL_FLAGS_NONE, +- prepare_for_sleep_cb, +- NULL, +- NULL); ++ priv->logind_proxy = get_logind_proxy (priv->cancellable, &error); ++ ++ if (!priv->logind_proxy) ++ g_warning ("Failed to get logind proxy: %s", error->message); ++ ++ g_signal_connect_object (priv->logind_proxy, ++ "prepare-for-sleep", ++ G_CALLBACK (prepare_for_sleep_cb), ++ user_data, ++ G_CONNECT_SWAPPED); + } + + static gboolean +diff --git a/src/org.freedesktop.login1.xml b/src/org.freedesktop.login1.xml +index 765475132..1ecfd976f 100644 +--- a/src/org.freedesktop.login1.xml ++++ b/src/org.freedesktop.login1.xml +@@ -43,4 +43,17 @@ + + + ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ ++ + +-- +2.21.0 + diff --git a/SOURCES/0002-cogl-Fix-doc-for-_cogl_blit_framebuffer.patch b/SOURCES/0002-cogl-Fix-doc-for-_cogl_blit_framebuffer.patch new file mode 100644 index 0000000..510b926 --- /dev/null +++ b/SOURCES/0002-cogl-Fix-doc-for-_cogl_blit_framebuffer.patch @@ -0,0 +1,42 @@ +From 801da0dab1d2928578e9b191ee1684bcc7154081 Mon Sep 17 00:00:00 2001 +From: Pekka Paalanen +Date: Tue, 30 Apr 2019 17:01:04 +0300 +Subject: [PATCH 02/12] cogl: Fix doc for _cogl_blit_framebuffer + +Commit 38921701e533b7fda38a236cc45aec2ed3afef8a added explicit source and +destination parameters. Fix the documentation to match. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/615 + +(cherry picked from commit fc0ce11fcd997af12fc2253eeb37e03cebb5964f) +--- + cogl/cogl/cogl-framebuffer-private.h | 6 +++--- + 1 file changed, 3 insertions(+), 3 deletions(-) + +diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h +index 296788c2b..de886b64f 100644 +--- a/cogl/cogl/cogl-framebuffer-private.h ++++ b/cogl/cogl/cogl-framebuffer-private.h +@@ -4,6 +4,7 @@ + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009 Intel Corporation. ++ * Copyright (C) 2019 DisplayLink (UK) Ltd. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation +@@ -377,9 +378,8 @@ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer, + * @width: Width of region to copy + * @height: Height of region to copy + * +- * This blits a region of the color buffer of the current draw buffer +- * to the current read buffer. The draw and read buffers can be set up +- * using _cogl_push_framebuffers(). This function should only be ++ * This blits a region of the color buffer of the source buffer ++ * to the destination buffer. This function should only be + * called if the COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT feature is + * advertised. The two buffers must both be offscreen and have the + * same format. +-- +2.21.0 + diff --git a/SOURCES/0002-monitor-manager-xrandr-Create-dummy-screen-sized-mon.patch b/SOURCES/0002-monitor-manager-xrandr-Create-dummy-screen-sized-mon.patch new file mode 100644 index 0000000..93756e4 --- /dev/null +++ b/SOURCES/0002-monitor-manager-xrandr-Create-dummy-screen-sized-mon.patch @@ -0,0 +1,185 @@ +From 85484d8f5d75764ab74308da7b21411c3fe4a2da Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Wed, 3 Oct 2018 10:50:47 +0200 +Subject: [PATCH 2/2] monitor-manager/xrandr: Create dummy screen sized monitor + if no RANDR + +When there is no RANDR support enabled in the X server, we wont get +notified of any monitors, resulting in mutter believing we're being +headless. To get at least something working, although with no way +configuration ability, lets pretend the whole screen is just a single +monitor with a single output, crtc and mode. +--- + src/backends/x11/meta-gpu-xrandr.c | 60 +++++++++++++++++++ + .../x11/meta-monitor-manager-xrandr.c | 22 ++++++- + .../x11/meta-monitor-manager-xrandr.h | 4 ++ + 3 files changed, 85 insertions(+), 1 deletion(-) + +diff --git a/src/backends/x11/meta-gpu-xrandr.c b/src/backends/x11/meta-gpu-xrandr.c +index 1884278ca..22e7e70e0 100644 +--- a/src/backends/x11/meta-gpu-xrandr.c ++++ b/src/backends/x11/meta-gpu-xrandr.c +@@ -115,6 +115,63 @@ update_screen_size (MetaGpuXrandr *gpu_xrandr) + monitor_manager->screen_height = HeightOfScreen (screen); + } + ++static gboolean ++read_current_fallback (MetaGpuXrandr *gpu_xrandr, ++ MetaMonitorManagerXrandr *monitor_manager_xrandr) ++{ ++ MetaGpu *gpu = META_GPU (gpu_xrandr); ++ MetaMonitorManager *monitor_manager = ++ META_MONITOR_MANAGER (monitor_manager_xrandr); ++ MetaCrtcMode *mode; ++ MetaCrtc *crtc; ++ MetaOutput *output; ++ ++ meta_monitor_manager_xrandr_update_dpms_state (monitor_manager_xrandr); ++ update_screen_size (gpu_xrandr); ++ ++ mode = g_object_new (META_TYPE_CRTC_MODE, NULL); ++ mode->mode_id = 0; ++ mode->width = monitor_manager->screen_width; ++ mode->height = monitor_manager->screen_height; ++ mode->refresh_rate = 60.0; ++ mode->name = g_strdup_printf ("%dx%d", mode->width, mode->height); ++ ++ meta_gpu_take_modes (gpu, g_list_prepend (NULL, mode)); ++ ++ crtc = g_object_new (META_TYPE_CRTC, NULL); ++ crtc->gpu = gpu; ++ crtc->crtc_id = 0; ++ crtc->rect = (MetaRectangle) { .width = mode->width, .height = mode->height }; ++ crtc->current_mode = mode; ++ ++ meta_gpu_take_crtcs (gpu, g_list_prepend (NULL, crtc)); ++ ++ output = g_object_new (META_TYPE_OUTPUT, NULL); ++ output->gpu = gpu; ++ output->winsys_id = 0; ++ output->name = g_strdup ("X11 Screen"); ++ output->vendor = g_strdup ("unknown"); ++ output->product = g_strdup ("unknown"); ++ output->serial = g_strdup ("unknown"); ++ output->hotplug_mode_update = TRUE; ++ output->suggested_x = -1; ++ output->suggested_y = -1; ++ output->connector_type = META_CONNECTOR_TYPE_Unknown; ++ output->modes = g_new0 (MetaCrtcMode *, 1); ++ output->modes[0] = mode; ++ output->n_modes = 1; ++ output->preferred_mode = mode; ++ output->possible_crtcs = g_new0 (MetaCrtc *, 1); ++ output->possible_crtcs[0] = crtc; ++ output->n_possible_crtcs = 1; ++ meta_output_assign_crtc (output, crtc); ++ output->is_primary = TRUE; ++ ++ meta_gpu_take_outputs (gpu, g_list_prepend (NULL, output)); ++ ++ return TRUE; ++} ++ + static gboolean + meta_gpu_xrandr_read_current (MetaGpu *gpu, + GError **error) +@@ -133,6 +190,9 @@ meta_gpu_xrandr_read_current (MetaGpu *gpu, + GList *modes = NULL; + GList *crtcs = NULL; + ++ if (!meta_monitor_manager_xrandr_has_randr (monitor_manager_xrandr)) ++ return read_current_fallback (gpu_xrandr, monitor_manager_xrandr); ++ + if (gpu_xrandr->resources) + XRRFreeScreenResources (gpu_xrandr->resources); + gpu_xrandr->resources = NULL; +diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c +index 7a0b43ac4..d6306faeb 100644 +--- a/src/backends/x11/meta-monitor-manager-xrandr.c ++++ b/src/backends/x11/meta-monitor-manager-xrandr.c +@@ -75,6 +75,7 @@ struct _MetaMonitorManagerXrandr + guint logind_watch_id; + guint logind_signal_sub_id; + ++ gboolean has_randr; + gboolean has_randr15; + + /* +@@ -114,6 +115,12 @@ meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *manager_xran + return manager_xrandr->xdisplay; + } + ++gboolean ++meta_monitor_manager_xrandr_has_randr (MetaMonitorManagerXrandr *manager_xrandr) ++{ ++ return manager_xrandr->has_randr; ++} ++ + gboolean + meta_monitor_manager_xrandr_has_randr15 (MetaMonitorManagerXrandr *manager_xrandr) + { +@@ -145,7 +152,7 @@ x11_dpms_state_to_power_save (CARD16 dpms_state) + } + } + +-static void ++void + meta_monitor_manager_xrandr_update_dpms_state (MetaMonitorManagerXrandr *manager_xrandr) + { + MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr); +@@ -637,9 +644,18 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *mana + MetaMonitorsConfigMethod method, + GError **error) + { ++ MetaMonitorManagerXrandr *manager_xrandr = ++ META_MONITOR_MANAGER_XRANDR (manager); + GPtrArray *crtc_infos; + GPtrArray *output_infos; + ++ if (!manager_xrandr->has_randr) ++ { ++ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, ++ "Tried to change configuration without XRANDR support"); ++ return FALSE; ++ } ++ + if (!config) + { + meta_monitor_manager_xrandr_rebuild_derived (manager, NULL); +@@ -1105,11 +1121,15 @@ meta_monitor_manager_xrandr_constructed (GObject *object) + &manager_xrandr->rr_event_base, + &manager_xrandr->rr_error_base)) + { ++ g_warning ("No RANDR support, monitor configuration disabled"); + return; + } + else + { + int major_version, minor_version; ++ ++ manager_xrandr->has_randr = TRUE; ++ + /* We only use ScreenChangeNotify, but GDK uses the others, + and we don't want to step on its toes */ + XRRSelectInput (manager_xrandr->xdisplay, +diff --git a/src/backends/x11/meta-monitor-manager-xrandr.h b/src/backends/x11/meta-monitor-manager-xrandr.h +index d55b3d2b8..dc75134a5 100644 +--- a/src/backends/x11/meta-monitor-manager-xrandr.h ++++ b/src/backends/x11/meta-monitor-manager-xrandr.h +@@ -33,9 +33,13 @@ G_DECLARE_FINAL_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, + + Display * meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *manager_xrandr); + ++gboolean meta_monitor_manager_xrandr_has_randr (MetaMonitorManagerXrandr *manager_xrandr); ++ + gboolean meta_monitor_manager_xrandr_has_randr15 (MetaMonitorManagerXrandr *manager_xrandr); + + gboolean meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager, + XEvent *event); + ++void meta_monitor_manager_xrandr_update_dpms_state (MetaMonitorManagerXrandr *manager_xrandr); ++ + #endif /* META_MONITOR_MANAGER_XRANDR_H */ +-- +2.23.0 + diff --git a/SOURCES/0002-window-Emit-an-error-and-return-when-trying-to-activ.patch b/SOURCES/0002-window-Emit-an-error-and-return-when-trying-to-activ.patch new file mode 100644 index 0000000..fedf5ce --- /dev/null +++ b/SOURCES/0002-window-Emit-an-error-and-return-when-trying-to-activ.patch @@ -0,0 +1,42 @@ +From 9a8bb8a205656ca1089444a041c99c5591477642 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= +Date: Fri, 3 May 2019 18:10:47 +0000 +Subject: [PATCH 2/2] window: Emit an error and return when trying to activate + an unmanaged + +If something (i.e. gnome-shell or an extension) tries to activate an unmanaged +window, we should warn about this and avoid to perform further actions as this +could lead to a crash of mutter, since the window has not valid flags (like +workspace) set anymore at this stage. + +Fixes https://gitlab.gnome.org/GNOME/mutter/issues/580 + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/564 + + +(cherry picked from commit a6fc656e917fd48b8708b8d9f4bf9f8b15581313) +--- + src/core/window.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/src/core/window.c b/src/core/window.c +index d2c24506b..725cca7ce 100644 +--- a/src/core/window.c ++++ b/src/core/window.c +@@ -3683,6 +3683,13 @@ meta_window_activate_full (MetaWindow *window, + { + MetaWorkspaceManager *workspace_manager = window->display->workspace_manager; + gboolean allow_workspace_switch; ++ ++ if (window->unmanaging) ++ { ++ g_warning ("Trying to activate unmanaged window '%s'", window->desc); ++ return; ++ } ++ + meta_topic (META_DEBUG_FOCUS, + "_NET_ACTIVE_WINDOW message sent for %s at time %u " + "by client type %u.\n", +-- +2.21.0 + diff --git a/SOURCES/0003-backend-add-signals-for-reporting-suspend-and-resume.patch b/SOURCES/0003-backend-add-signals-for-reporting-suspend-and-resume.patch new file mode 100644 index 0000000..03adc3a --- /dev/null +++ b/SOURCES/0003-backend-add-signals-for-reporting-suspend-and-resume.patch @@ -0,0 +1,181 @@ +From c5020c3d303ab211a970d88638e7d723034688db Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 10 Jan 2019 10:47:19 -0500 +Subject: [PATCH 3/9] backend: add signals for reporting suspend and resume + +This commit adds "suspending" and "resuming" signals +to MetaBackend. + +It's preliminary work needed for tracking when to purge +and recreate all textures (needed by nvidia). +--- + src/backends/meta-backend.c | 98 ++++++++++++++++++++++++++++++---- + src/org.freedesktop.login1.xml | 1 + + 2 files changed, 88 insertions(+), 11 deletions(-) + +diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c +index 5d71977c6..f59b899b7 100644 +--- a/src/backends/meta-backend.c ++++ b/src/backends/meta-backend.c +@@ -53,6 +53,8 @@ + + #include + ++#include ++ + #include "backends/meta-cursor-tracker-private.h" + #include "backends/meta-idle-monitor-private.h" + #include "backends/meta-input-settings-private.h" +@@ -87,6 +89,8 @@ enum + LAST_DEVICE_CHANGED, + LID_IS_CLOSED_CHANGED, + ++ SUSPENDING, ++ RESUMING, + N_SIGNALS + }; + +@@ -745,6 +749,20 @@ meta_backend_class_init (MetaBackendClass *klass) + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 1, G_TYPE_BOOLEAN); ++ signals[SUSPENDING] = ++ g_signal_new ("suspending", ++ G_TYPE_FROM_CLASS (object_class), ++ G_SIGNAL_RUN_LAST, ++ 0, ++ NULL, NULL, NULL, ++ G_TYPE_NONE, 0); ++ signals[RESUMING] = ++ g_signal_new ("resuming", ++ G_TYPE_FROM_CLASS (object_class), ++ G_SIGNAL_RUN_LAST, ++ 0, ++ NULL, NULL, NULL, ++ G_TYPE_NONE, 0); + + mutter_stage_views = g_getenv ("MUTTER_STAGE_VIEWS"); + stage_views_disabled = g_strcmp0 (mutter_stage_views, "0") == 0; +@@ -768,15 +786,66 @@ meta_backend_create_renderer (MetaBackend *backend, + return META_BACKEND_GET_CLASS (backend)->create_renderer (backend, error); + } + ++static void ++inhibit_sleep (MetaBackend *backend) ++{ ++ MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); ++ g_autoptr (GVariant) fd_variant = NULL; ++ g_autoptr (GUnixFDList) fd_list = NULL; ++ g_autoptr (GError) error = NULL; ++ int handle, fd; ++ ++ if (priv->inhibit_sleep_fd >= 0) ++ return; ++ ++ if (!login1_manager_call_inhibit_sync (priv->logind_proxy, ++ "sleep", ++ "Display Server", ++ "Prepare for suspend", ++ "delay", ++ NULL, ++ &fd_variant, ++ &fd_list, ++ priv->cancellable, ++ &error)) ++ { ++ g_warning ("Failed to inhibit sleep: %s", error->message); ++ return; ++ } ++ ++ handle = g_variant_get_handle (fd_variant); ++ fd = g_unix_fd_list_get (fd_list, handle, &error); ++ ++ if (fd < 0) ++ { ++ g_warning ("Failed to fetch sleep inhibitor fd: %s", error->message); ++ return; ++ } ++ ++ priv->inhibit_sleep_fd = fd; ++} ++ ++static void ++uninhibit_sleep (MetaBackend *backend) ++{ ++ MetaBackendPrivate *priv = meta_backend_get_instance_private (backend); ++ ++ close (priv->inhibit_sleep_fd); ++ priv->inhibit_sleep_fd = -1; ++} ++ + static void + prepare_for_sleep_cb (MetaBackend *backend, + gboolean suspending) + { +- gboolean suspending; +- +- g_variant_get (parameters, "(b)", &suspending); +- if (suspending) ++ if (suspending) { ++ g_signal_emit (backend, signals[SUSPENDING], 0); ++ uninhibit_sleep (backend); + return; ++ } ++ ++ inhibit_sleep (backend); ++ g_signal_emit (backend, signals[RESUMING], 0); + meta_idle_monitor_reset_idletime (meta_idle_monitor_get_core ()); + } + +@@ -803,6 +872,7 @@ system_bus_gotten_cb (GObject *object, + GAsyncResult *res, + gpointer user_data) + { ++ MetaBackend *backend = META_BACKEND (user_data); + MetaBackendPrivate *priv; + g_autoptr (GError) error = NULL; + GDBusConnection *bus; +@@ -814,15 +884,21 @@ system_bus_gotten_cb (GObject *object, + priv = meta_backend_get_instance_private (user_data); + priv->system_bus = bus; + priv->logind_proxy = get_logind_proxy (priv->cancellable, &error); ++ priv->inhibit_sleep_fd = -1; + + if (!priv->logind_proxy) +- g_warning ("Failed to get logind proxy: %s", error->message); +- +- g_signal_connect_object (priv->logind_proxy, +- "prepare-for-sleep", +- G_CALLBACK (prepare_for_sleep_cb), +- user_data, +- G_CONNECT_SWAPPED); ++ { ++ g_warning ("Failed to get logind proxy: %s", error->message); ++ } ++ else ++ { ++ inhibit_sleep (backend); ++ g_signal_connect_object (priv->logind_proxy, ++ "prepare-for-sleep", ++ G_CALLBACK (prepare_for_sleep_cb), ++ user_data, ++ G_CONNECT_SWAPPED); ++ } + } + + static gboolean +diff --git a/src/org.freedesktop.login1.xml b/src/org.freedesktop.login1.xml +index 1ecfd976f..7db8f373c 100644 +--- a/src/org.freedesktop.login1.xml ++++ b/src/org.freedesktop.login1.xml +@@ -46,6 +46,7 @@ + + + ++ + + + +-- +2.21.0 + diff --git a/SOURCES/0003-cogl-Replace-ANGLE-with-GLES3-and-NV-framebuffer_bli.patch b/SOURCES/0003-cogl-Replace-ANGLE-with-GLES3-and-NV-framebuffer_bli.patch new file mode 100644 index 0000000..b41fa93 --- /dev/null +++ b/SOURCES/0003-cogl-Replace-ANGLE-with-GLES3-and-NV-framebuffer_bli.patch @@ -0,0 +1,77 @@ +From 04d921c2c1da571c8c61a4ca12a380bc3b9623fe Mon Sep 17 00:00:00 2001 +From: Pekka Paalanen +Date: Mon, 6 May 2019 13:40:31 +0300 +Subject: [PATCH 03/12] cogl: Replace ANGLE with GLES3 and NV framebuffer_blit + +ANGLE extensions are only provided by Google's Almost Native Graphics Layer +Engine (ANGLE) implementation. Therefore they do not seem too useful for +Mutter. + +The reason to drop GL_ANGLE_framebuffer_blit support is that it has more +limitations compared to the glBlitFramebuffer in GL_EXT_framebuffer_blit, +GL_NV_framebuffer_bit, OpenGL 3.0 and OpenGL ES 3.0. Most importantly, the +ANGLE version cannot flip the image while copying, which limits +_cogl_blit_framebuffer to only off-screen <-> off-screen copies. Follow-up work +will need off-screen <-> on-screen copies. + +Instead of adding yet more capability flags to Cogl, dropping ANGLE support +seems appropriate. + +The NV extension is added to the list of glBlitFramebuffer providers because it +provides the same support as ANGLE and more. + +Likewise OpenGL ES 3.0 is added to the list of glBlitFramebuffer providers +because e.g. Mesa GLES implementation usually provides it and that makes it +widely available, again surpassing the ANGLE supported features. + +Follow-up patches will lift some of the Cogl assumptions of what +glBlitFramebuffer cannot do. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/615 + +(cherry picked from commit 3e68c9e8faa78298039fa3583898f18550740812) +--- + cogl/cogl/cogl-framebuffer-private.h | 3 +-- + cogl/cogl/gl-prototypes/cogl-all-functions.h | 5 +++-- + 2 files changed, 4 insertions(+), 4 deletions(-) + +diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h +index de886b64f..3aab852c4 100644 +--- a/cogl/cogl/cogl-framebuffer-private.h ++++ b/cogl/cogl/cogl-framebuffer-private.h +@@ -387,8 +387,7 @@ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer, + * Note that this function differs a lot from the glBlitFramebuffer + * function provided by the GL_EXT_framebuffer_blit extension. Notably + * it doesn't support having different sizes for the source and +- * destination rectangle. This isn't supported by the corresponding +- * GL_ANGLE_framebuffer_blit extension on GLES2.0 and it doesn't seem ++ * destination rectangle. This doesn't seem + * like a particularly useful feature. If the application wanted to + * scale the results it may make more sense to draw a primitive + * instead. +diff --git a/cogl/cogl/gl-prototypes/cogl-all-functions.h b/cogl/cogl/gl-prototypes/cogl-all-functions.h +index 924ee349d..0af126059 100644 +--- a/cogl/cogl/gl-prototypes/cogl-all-functions.h ++++ b/cogl/cogl/gl-prototypes/cogl-all-functions.h +@@ -4,6 +4,7 @@ + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2009, 2011 Intel Corporation. ++ * Copyright (C) 2019 DisplayLink (UK) Ltd. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation +@@ -132,8 +133,8 @@ COGL_EXT_END () + + + COGL_EXT_BEGIN (offscreen_blit, 3, 0, +- 0, /* not in either GLES */ +- "EXT\0ANGLE\0", ++ COGL_EXT_IN_GLES3, ++ "EXT\0NV\0", + "framebuffer_blit\0") + COGL_EXT_FUNCTION (void, glBlitFramebuffer, + (GLint srcX0, +-- +2.21.0 + diff --git a/SOURCES/0004-cogl-Relax-formats-on-glBlitFramebuffer.patch b/SOURCES/0004-cogl-Relax-formats-on-glBlitFramebuffer.patch new file mode 100644 index 0000000..751e0cb --- /dev/null +++ b/SOURCES/0004-cogl-Relax-formats-on-glBlitFramebuffer.patch @@ -0,0 +1,100 @@ +From 6c6c6ad5412f5bb13592630d7cb3b7aed25d159b Mon Sep 17 00:00:00 2001 +From: Pekka Paalanen +Date: Mon, 6 May 2019 14:09:16 +0300 +Subject: [PATCH 04/12] cogl: Relax formats on glBlitFramebuffer + +Depends on: "cogl: Replace ANGLE with GLES3 and NV framebuffer_blit" + +As a possible ANGLE implementation is not longer limiting the pixel format +matching, lift the requirement of having the same pixel format. + +We still cannot do a premult <-> non-premult conversion during a blit, so guard +against that. + +This will be useful in follow-up work to copy from onscreen primary GPU +framebuffer to an offscreen secondary GPU framebuffer if the formats do not +match exactly. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/615 + +(cherry picked from commit 6df34eb4b7c65210f4066f7eb9bd462278b7279b) +--- + cogl/cogl/cogl-blit.c | 10 ++++++---- + cogl/cogl/cogl-framebuffer-private.h | 8 ++++++-- + cogl/cogl/cogl-framebuffer.c | 6 ++++-- + 3 files changed, 16 insertions(+), 8 deletions(-) + +diff --git a/cogl/cogl/cogl-blit.c b/cogl/cogl/cogl-blit.c +index 74f404f3d..a61eb66d2 100644 +--- a/cogl/cogl/cogl-blit.c ++++ b/cogl/cogl/cogl-blit.c +@@ -4,6 +4,7 @@ + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2011 Intel Corporation. ++ * Copyright (C) 2019 DisplayLink (UK) Ltd. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation +@@ -152,10 +153,11 @@ _cogl_blit_framebuffer_begin (CoglBlitData *data) + CoglFramebuffer *dst_fb, *src_fb; + CoglError *ignore_error = NULL; + +- /* We can only blit between FBOs if both textures are the same +- format and the blit framebuffer extension is supported */ +- if ((_cogl_texture_get_format (data->src_tex) & ~COGL_A_BIT) != +- (_cogl_texture_get_format (data->dst_tex) & ~COGL_A_BIT) || ++ /* We can only blit between FBOs if both textures have the same ++ premult convention and the blit framebuffer extension is ++ supported. */ ++ if ((_cogl_texture_get_format (data->src_tex) & COGL_PREMULT_BIT) != ++ (_cogl_texture_get_format (data->dst_tex) & COGL_PREMULT_BIT) || + !_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT)) + return FALSE; + +diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h +index 3aab852c4..b06fbaee1 100644 +--- a/cogl/cogl/cogl-framebuffer-private.h ++++ b/cogl/cogl/cogl-framebuffer-private.h +@@ -381,8 +381,12 @@ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer, + * This blits a region of the color buffer of the source buffer + * to the destination buffer. This function should only be + * called if the COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT feature is +- * advertised. The two buffers must both be offscreen and have the +- * same format. ++ * advertised. The two buffers must both be offscreen. ++ * ++ * The two buffers must have the same value types (e.g. floating-point, ++ * unsigned int, signed int, or fixed-point), but color formats do not ++ * need to match. This limitation comes from OpenGL ES 3.0 definition ++ * of glBlitFramebuffer. + * + * Note that this function differs a lot from the glBlitFramebuffer + * function provided by the GL_EXT_framebuffer_blit extension. Notably +diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c +index bd8a7fa42..0bc225945 100644 +--- a/cogl/cogl/cogl-framebuffer.c ++++ b/cogl/cogl/cogl-framebuffer.c +@@ -4,6 +4,7 @@ + * A Low Level GPU Graphics and Utilities API + * + * Copyright (C) 2007,2008,2009,2012 Intel Corporation. ++ * Copyright (C) 2019 DisplayLink (UK) Ltd. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation +@@ -1468,8 +1469,9 @@ _cogl_blit_framebuffer (CoglFramebuffer *src, + support this */ + _COGL_RETURN_IF_FAIL (cogl_is_offscreen (src)); + _COGL_RETURN_IF_FAIL (cogl_is_offscreen (dest)); +- /* The buffers must be the same format */ +- _COGL_RETURN_IF_FAIL (src->internal_format == dest->internal_format); ++ /* The buffers must use the same premult convention */ ++ _COGL_RETURN_IF_FAIL ((src->internal_format & COGL_PREMULT_BIT) == ++ (dest->internal_format & COGL_PREMULT_BIT)); + + /* Make sure the current framebuffers are bound. We explicitly avoid + flushing the clip state so we can bind our own empty state */ +-- +2.21.0 + diff --git a/SOURCES/0004-wayland-force-X-clients-to-redraw-on-resume.patch b/SOURCES/0004-wayland-force-X-clients-to-redraw-on-resume.patch new file mode 100644 index 0000000..d5a0e9f --- /dev/null +++ b/SOURCES/0004-wayland-force-X-clients-to-redraw-on-resume.patch @@ -0,0 +1,118 @@ +From a4a703c75e208badf78c81558994a249797dbb0a Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Sat, 12 Jan 2019 12:38:01 -0500 +Subject: [PATCH 4/9] wayland: force X clients to redraw on resume + +On nvidia, the textures backing Xwayland client window contents get +corrupted on suspend. Xwayland currently doesn't handle this situation +itself. + +For now, in order to work around this issue, send an empty output +change event to Xwayland. This will cause it to force Expose events +to get sent to all clients and get them to redraw. +--- + .../native/meta-monitor-manager-kms.c | 7 +++ + src/wayland/meta-wayland-outputs.c | 47 +++++++++++++++++++ + src/wayland/meta-wayland-outputs.h | 1 + + 3 files changed, 55 insertions(+) + +diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c +index 9a0364441..7bcceee97 100644 +--- a/src/backends/native/meta-monitor-manager-kms.c ++++ b/src/backends/native/meta-monitor-manager-kms.c +@@ -60,6 +60,7 @@ + #include "clutter/clutter.h" + #include "meta/main.h" + #include "meta/meta-x11-errors.h" ++#include "wayland/meta-wayland-outputs.h" + + #define DRM_CARD_UDEV_DEVICE_TYPE "drm_minor" + +@@ -505,9 +506,15 @@ void + meta_monitor_manager_kms_resume (MetaMonitorManagerKms *manager_kms) + { + MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_kms); ++ ClutterBackend *clutter_backend = clutter_get_default_backend (); ++ CoglContext *cogl_context = ++ clutter_backend_get_cogl_context (clutter_backend); + + meta_monitor_manager_kms_connect_uevent_handler (manager_kms); + handle_hotplug_event (manager); ++ ++ if (cogl_has_feature (cogl_context, COGL_FEATURE_ID_UNSTABLE_TEXTURES)) ++ meta_wayland_outputs_redraw (meta_wayland_compositor_get_default ()); + } + + static gboolean +diff --git a/src/wayland/meta-wayland-outputs.c b/src/wayland/meta-wayland-outputs.c +index 099e87ab9..bc69d699d 100644 +--- a/src/wayland/meta-wayland-outputs.c ++++ b/src/wayland/meta-wayland-outputs.c +@@ -496,6 +496,53 @@ meta_wayland_compositor_update_outputs (MetaWaylandCompositor *compositor, + return new_table; + } + ++void ++meta_wayland_outputs_redraw (MetaWaylandCompositor *compositor) ++{ ++ MetaMonitorManager *monitor_manager; ++ GList *logical_monitors, *l; ++ ++ monitor_manager = meta_monitor_manager_get (); ++ ++ logical_monitors = ++ meta_monitor_manager_get_logical_monitors (monitor_manager); ++ ++ for (l = logical_monitors; l; l = l->next) ++ { ++ MetaLogicalMonitor *logical_monitor = l->data; ++ MetaWaylandOutput *wayland_output; ++ GList *iter; ++ ++ if (logical_monitor->winsys_id == 0) ++ continue; ++ ++ wayland_output = ++ g_hash_table_lookup (compositor->outputs, ++ GSIZE_TO_POINTER (logical_monitor->winsys_id)); ++ ++ if (wayland_output == NULL) ++ continue; ++ ++ /* Just output a "changes done" event for one of the outputs, with no actual changes. ++ * xwayland takes this as a cue to send expose events to all X clients. ++ */ ++ for (iter = wayland_output->resources; iter; iter = iter->next) ++ { ++ struct wl_resource *resource = iter->data; ++ if (wl_resource_get_version (resource) >= WL_OUTPUT_DONE_SINCE_VERSION) ++ wl_output_send_done (resource); ++ } ++ ++ for (iter = wayland_output->xdg_output_resources; iter; iter = iter->next) ++ { ++ struct wl_resource *xdg_output = iter->data; ++ zxdg_output_v1_send_done (xdg_output); ++ } ++ ++ break; ++ } ++} ++ + static void + on_monitors_changed (MetaMonitorManager *monitors, + MetaWaylandCompositor *compositor) +diff --git a/src/wayland/meta-wayland-outputs.h b/src/wayland/meta-wayland-outputs.h +index ff15a81bd..d649e0fa1 100644 +--- a/src/wayland/meta-wayland-outputs.h ++++ b/src/wayland/meta-wayland-outputs.h +@@ -49,5 +49,6 @@ struct _MetaWaylandOutput + }; + + void meta_wayland_outputs_init (MetaWaylandCompositor *compositor); ++void meta_wayland_outputs_redraw (MetaWaylandCompositor *compositor); + + #endif /* META_WAYLAND_OUTPUTS_H */ +-- +2.21.0 + diff --git a/SOURCES/0005-backends-native-emit-gl-video-memory-purged-when-bec.patch b/SOURCES/0005-backends-native-emit-gl-video-memory-purged-when-bec.patch new file mode 100644 index 0000000..0567862 --- /dev/null +++ b/SOURCES/0005-backends-native-emit-gl-video-memory-purged-when-bec.patch @@ -0,0 +1,40 @@ +From 122d7726e450712b8b2fc85db41e3c8ab7b6ad56 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 15 Jan 2019 10:29:55 -0500 +Subject: [PATCH 5/9] backends/native: emit gl-video-memory-purged when + becoming active + +The proprietary NVIDIA driver garbles memory on suspend. In order +to work around that limitation, mutter needs to refresh all its +textures on resuem. + +This commit lays the way toward doing that by emitting the +"gl-video-memory-purged" signal when the compositor becomes active +by logind (which happens on VT switch and on resume). +--- + src/backends/native/meta-backend-native.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c +index c473681cb..f593197e7 100644 +--- a/src/backends/native/meta-backend-native.c ++++ b/src/backends/native/meta-backend-native.c +@@ -653,8 +653,15 @@ void meta_backend_native_resume (MetaBackendNative *native) + meta_backend_get_monitor_manager (backend); + MetaMonitorManagerKms *monitor_manager_kms = + META_MONITOR_MANAGER_KMS (monitor_manager); ++ MetaDisplay *display = meta_get_display (); ++ ClutterBackend *clutter_backend = clutter_get_default_backend (); ++ CoglContext *cogl_context = ++ clutter_backend_get_cogl_context (clutter_backend); + MetaIdleMonitor *idle_monitor; + ++ if (cogl_has_feature (cogl_context, COGL_FEATURE_ID_UNSTABLE_TEXTURES)) ++ g_signal_emit_by_name (display, "gl-video-memory-purged"); ++ + meta_monitor_manager_kms_resume (monitor_manager_kms); + + clutter_evdev_reclaim_devices (); +-- +2.21.0 + diff --git a/SOURCES/0005-cogl-Allow-glBlitFramebuffer-between-onscreen-offscr.patch b/SOURCES/0005-cogl-Allow-glBlitFramebuffer-between-onscreen-offscr.patch new file mode 100644 index 0000000..81d49d6 --- /dev/null +++ b/SOURCES/0005-cogl-Allow-glBlitFramebuffer-between-onscreen-offscr.patch @@ -0,0 +1,145 @@ +From e4b2234d9918e9d3357ac3c7ca3898599725d3da Mon Sep 17 00:00:00 2001 +From: Pekka Paalanen +Date: Mon, 6 May 2019 15:08:29 +0300 +Subject: [PATCH 05/12] cogl: Allow glBlitFramebuffer between + onscreen/offscreen + +Depends on "cogl: Replace ANGLE with GLES3 and NV framebuffer_blit" + +Allow blitting between onscreen and offscreen framebuffers by doing the y-flip +as necessary. This was not possible with ANGLE, but now with ANGLE gone, +glBlitFramebuffer supports flipping the copied image. + +This will be useful in follow-up work to copy from onscreen primary GPU +framebuffer to an offscreen secondary GPU framebuffer. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/615 + +(cherry picked from commit 45289b3d65e308117f1bc8fe6a4c88c1baaacca7) +--- + cogl/cogl/cogl-framebuffer-private.h | 14 +++---- + cogl/cogl/cogl-framebuffer.c | 46 ++++++++++++++++++----- + cogl/cogl/driver/gl/cogl-framebuffer-gl.c | 5 +-- + 3 files changed, 43 insertions(+), 22 deletions(-) + +diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h +index b06fbaee1..f68153d8b 100644 +--- a/cogl/cogl/cogl-framebuffer-private.h ++++ b/cogl/cogl/cogl-framebuffer-private.h +@@ -381,7 +381,11 @@ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer, + * This blits a region of the color buffer of the source buffer + * to the destination buffer. This function should only be + * called if the COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT feature is +- * advertised. The two buffers must both be offscreen. ++ * advertised. ++ * ++ * The source and destination rectangles are defined in offscreen ++ * framebuffer orientation. When copying between an offscreen and ++ * onscreen framebuffers, the image is y-flipped accordingly. + * + * The two buffers must have the same value types (e.g. floating-point, + * unsigned int, signed int, or fixed-point), but color formats do not +@@ -396,14 +400,6 @@ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer, + * scale the results it may make more sense to draw a primitive + * instead. + * +- * We can only really support blitting between two offscreen buffers +- * for this function on GLES2.0. This is because we effectively render +- * upside down to offscreen buffers to maintain Cogl's representation +- * of the texture coordinate system where 0,0 is the top left of the +- * texture. If we were to blit from an offscreen to an onscreen buffer +- * then we would need to mirror the blit along the x-axis but the GLES +- * extension does not support this. +- * + * The GL function is documented to be affected by the scissor. This + * function therefore ensure that an empty clip stack is flushed + * before performing the blit which means the scissor is effectively +diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c +index 0bc225945..90976a611 100644 +--- a/cogl/cogl/cogl-framebuffer.c ++++ b/cogl/cogl/cogl-framebuffer.c +@@ -1460,15 +1460,12 @@ _cogl_blit_framebuffer (CoglFramebuffer *src, + int height) + { + CoglContext *ctx = src->context; ++ int src_x1, src_y1, src_x2, src_y2; ++ int dst_x1, dst_y1, dst_x2, dst_y2; + + _COGL_RETURN_IF_FAIL (_cogl_has_private_feature + (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT)); + +- /* We can only support blitting between offscreen buffers because +- otherwise we would need to mirror the image and GLES2.0 doesn't +- support this */ +- _COGL_RETURN_IF_FAIL (cogl_is_offscreen (src)); +- _COGL_RETURN_IF_FAIL (cogl_is_offscreen (dest)); + /* The buffers must use the same premult convention */ + _COGL_RETURN_IF_FAIL ((src->internal_format & COGL_PREMULT_BIT) == + (dest->internal_format & COGL_PREMULT_BIT)); +@@ -1492,10 +1489,41 @@ _cogl_blit_framebuffer (CoglFramebuffer *src, + * as changed */ + ctx->current_draw_buffer_changes |= COGL_FRAMEBUFFER_STATE_CLIP; + +- ctx->glBlitFramebuffer (src_x, src_y, +- src_x + width, src_y + height, +- dst_x, dst_y, +- dst_x + width, dst_y + height, ++ /* Offscreens we do the normal way, onscreens need an y-flip. Even if ++ * we consider offscreens to be rendered upside-down, the offscreen ++ * orientation is in this function's API. */ ++ if (cogl_is_offscreen (src)) ++ { ++ src_x1 = src_x; ++ src_y1 = src_y; ++ src_x2 = src_x + width; ++ src_y2 = src_y + height; ++ } ++ else ++ { ++ src_x1 = src_x; ++ src_y1 = cogl_framebuffer_get_height (src) - src_y; ++ src_x2 = src_x + width; ++ src_y2 = src_y1 - height; ++ } ++ ++ if (cogl_is_offscreen (dest)) ++ { ++ dst_x1 = dst_x; ++ dst_y1 = dst_y; ++ dst_x2 = dst_x + width; ++ dst_y2 = dst_y + height; ++ } ++ else ++ { ++ dst_x1 = dst_x; ++ dst_y1 = cogl_framebuffer_get_height (dest) - dst_y; ++ dst_x2 = dst_x + width; ++ dst_y2 = dst_y1 - height; ++ } ++ ++ ctx->glBlitFramebuffer (src_x1, src_y1, src_x2, src_y2, ++ dst_x1, dst_y1, dst_x2, dst_y2, + GL_COLOR_BUFFER_BIT, + GL_NEAREST); + } +diff --git a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c +index 5402a7075..83e1d263a 100644 +--- a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c ++++ b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c +@@ -400,12 +400,9 @@ _cogl_framebuffer_gl_flush_state (CoglFramebuffer *draw_buffer, + else + { + /* NB: Currently we only take advantage of binding separate +- * read/write buffers for offscreen framebuffer blit +- * purposes. */ ++ * read/write buffers for framebuffer blit purposes. */ + _COGL_RETURN_IF_FAIL (_cogl_has_private_feature + (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT)); +- _COGL_RETURN_IF_FAIL (draw_buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN); +- _COGL_RETURN_IF_FAIL (read_buffer->type == COGL_FRAMEBUFFER_TYPE_OFFSCREEN); + + _cogl_framebuffer_gl_bind (draw_buffer, GL_DRAW_FRAMEBUFFER); + _cogl_framebuffer_gl_bind (read_buffer, GL_READ_FRAMEBUFFER); +-- +2.21.0 + diff --git a/SOURCES/0006-backends-native-update-glyph-cache-on-resume.patch b/SOURCES/0006-backends-native-update-glyph-cache-on-resume.patch new file mode 100644 index 0000000..3f4193b --- /dev/null +++ b/SOURCES/0006-backends-native-update-glyph-cache-on-resume.patch @@ -0,0 +1,35 @@ +From 762ffddfa6157fe50bfa394ecbe4ba707d15f368 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 15 Jan 2019 10:29:55 -0500 +Subject: [PATCH 6/9] backends/native: update glyph cache on resume + +As mentioned in a previous commit, the proprietary NVIDIA +driver garbles memory on suspend. That behavior, means that +clutter's glyph cache (which is stored in GPU memory) gets +corrupted on suspend. + +This commit ensures the glyph cache is blown away when +the logind session becomes active (on VT switch and resume). +--- + src/backends/native/meta-backend-native.c | 5 ++++- + 1 file changed, 4 insertions(+), 1 deletion(-) + +diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c +index f593197e7..db9b63ac4 100644 +--- a/src/backends/native/meta-backend-native.c ++++ b/src/backends/native/meta-backend-native.c +@@ -660,7 +660,10 @@ void meta_backend_native_resume (MetaBackendNative *native) + MetaIdleMonitor *idle_monitor; + + if (cogl_has_feature (cogl_context, COGL_FEATURE_ID_UNSTABLE_TEXTURES)) +- g_signal_emit_by_name (display, "gl-video-memory-purged"); ++ { ++ clutter_clear_glyph_cache (); ++ g_signal_emit_by_name (display, "gl-video-memory-purged"); ++ } + + meta_monitor_manager_kms_resume (monitor_manager_kms); + +-- +2.21.0 + diff --git a/SOURCES/0006-cogl-Rename-feature-OFFSCREEN_BLIT-to-BLIT_FRAMEBUFF.patch b/SOURCES/0006-cogl-Rename-feature-OFFSCREEN_BLIT-to-BLIT_FRAMEBUFF.patch new file mode 100644 index 0000000..6bc5e2c --- /dev/null +++ b/SOURCES/0006-cogl-Rename-feature-OFFSCREEN_BLIT-to-BLIT_FRAMEBUFF.patch @@ -0,0 +1,115 @@ +From 579c85d17b17fc7ad3d6c88af39932ce8faeaabe Mon Sep 17 00:00:00 2001 +From: Pekka Paalanen +Date: Mon, 6 May 2019 15:58:33 +0300 +Subject: [PATCH 06/12] cogl: Rename feature OFFSCREEN_BLIT to BLIT_FRAMEBUFFER + +The feature is not limited to offscreen framebuffer blits anymore since +"cogl: Allow glBlitFramebuffer between onscreen/offscreen". + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/615 + +(cherry picked from commit 55c084e6e1059d8f94c699b01c408523ed504196) +--- + cogl/cogl/cogl-blit.c | 2 +- + cogl/cogl/cogl-framebuffer-private.h | 2 +- + cogl/cogl/cogl-framebuffer.c | 2 +- + cogl/cogl/cogl-private.h | 2 +- + cogl/cogl/driver/gl/cogl-framebuffer-gl.c | 2 +- + cogl/cogl/driver/gl/gl/cogl-driver-gl.c | 2 +- + cogl/cogl/driver/gl/gles/cogl-driver-gles.c | 2 +- + 7 files changed, 7 insertions(+), 7 deletions(-) + +diff --git a/cogl/cogl/cogl-blit.c b/cogl/cogl/cogl-blit.c +index a61eb66d2..c561b2e45 100644 +--- a/cogl/cogl/cogl-blit.c ++++ b/cogl/cogl/cogl-blit.c +@@ -158,7 +158,7 @@ _cogl_blit_framebuffer_begin (CoglBlitData *data) + supported. */ + if ((_cogl_texture_get_format (data->src_tex) & COGL_PREMULT_BIT) != + (_cogl_texture_get_format (data->dst_tex) & COGL_PREMULT_BIT) || +- !_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT)) ++ !_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER)) + return FALSE; + + dst_offscreen = _cogl_offscreen_new_with_texture_full +diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h +index f68153d8b..cb1f87354 100644 +--- a/cogl/cogl/cogl-framebuffer-private.h ++++ b/cogl/cogl/cogl-framebuffer-private.h +@@ -380,7 +380,7 @@ _cogl_push_framebuffers (CoglFramebuffer *draw_buffer, + * + * This blits a region of the color buffer of the source buffer + * to the destination buffer. This function should only be +- * called if the COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT feature is ++ * called if the COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER feature is + * advertised. + * + * The source and destination rectangles are defined in offscreen +diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c +index 90976a611..5cc4eada4 100644 +--- a/cogl/cogl/cogl-framebuffer.c ++++ b/cogl/cogl/cogl-framebuffer.c +@@ -1464,7 +1464,7 @@ _cogl_blit_framebuffer (CoglFramebuffer *src, + int dst_x1, dst_y1, dst_x2, dst_y2; + + _COGL_RETURN_IF_FAIL (_cogl_has_private_feature +- (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT)); ++ (ctx, COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER)); + + /* The buffers must use the same premult convention */ + _COGL_RETURN_IF_FAIL ((src->internal_format & COGL_PREMULT_BIT) == +diff --git a/cogl/cogl/cogl-private.h b/cogl/cogl/cogl-private.h +index 9f918b851..d9fbe68c7 100644 +--- a/cogl/cogl/cogl-private.h ++++ b/cogl/cogl/cogl-private.h +@@ -42,7 +42,7 @@ typedef enum + { + COGL_PRIVATE_FEATURE_TEXTURE_2D_FROM_EGL_IMAGE, + COGL_PRIVATE_FEATURE_MESA_PACK_INVERT, +- COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT, ++ COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER, + COGL_PRIVATE_FEATURE_FOUR_CLIP_PLANES, + COGL_PRIVATE_FEATURE_PBOS, + COGL_PRIVATE_FEATURE_VBOS, +diff --git a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c +index 83e1d263a..90d08954d 100644 +--- a/cogl/cogl/driver/gl/cogl-framebuffer-gl.c ++++ b/cogl/cogl/driver/gl/cogl-framebuffer-gl.c +@@ -402,7 +402,7 @@ _cogl_framebuffer_gl_flush_state (CoglFramebuffer *draw_buffer, + /* NB: Currently we only take advantage of binding separate + * read/write buffers for framebuffer blit purposes. */ + _COGL_RETURN_IF_FAIL (_cogl_has_private_feature +- (ctx, COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT)); ++ (ctx, COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER)); + + _cogl_framebuffer_gl_bind (draw_buffer, GL_DRAW_FRAMEBUFFER); + _cogl_framebuffer_gl_bind (read_buffer, GL_READ_FRAMEBUFFER); +diff --git a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c +index 4d46844d5..e06e27961 100644 +--- a/cogl/cogl/driver/gl/gl/cogl-driver-gl.c ++++ b/cogl/cogl/driver/gl/gl/cogl-driver-gl.c +@@ -467,7 +467,7 @@ _cogl_driver_update_features (CoglContext *ctx, + + if (ctx->glBlitFramebuffer) + COGL_FLAGS_SET (private_features, +- COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT, TRUE); ++ COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER, TRUE); + + if (ctx->glRenderbufferStorageMultisampleIMG) + { +diff --git a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c +index 23158d5c7..bcb0bdf07 100644 +--- a/cogl/cogl/driver/gl/gles/cogl-driver-gles.c ++++ b/cogl/cogl/driver/gl/gles/cogl-driver-gles.c +@@ -326,7 +326,7 @@ _cogl_driver_update_features (CoglContext *context, + + if (context->glBlitFramebuffer) + COGL_FLAGS_SET (private_features, +- COGL_PRIVATE_FEATURE_OFFSCREEN_BLIT, TRUE); ++ COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER, TRUE); + + if (_cogl_check_extension ("GL_OES_element_index_uint", gl_extensions)) + { +-- +2.21.0 + diff --git a/SOURCES/0007-backends-native-update-cursor-on-resume.patch b/SOURCES/0007-backends-native-update-cursor-on-resume.patch new file mode 100644 index 0000000..721996f --- /dev/null +++ b/SOURCES/0007-backends-native-update-cursor-on-resume.patch @@ -0,0 +1,38 @@ +From 59ba24c09e5d2a3210ca3d259789f7ba5ae6266a Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 15 Jan 2019 10:29:55 -0500 +Subject: [PATCH 7/9] backends/native: update cursor on resume + +As mentioned in a previous commit, the proprietary NVIDIA +driver garbles memory on suspend. That behavior, means that +the cursor gets corrupted on suspend. + +This commit forces the cursor to redraw itself when the +logind session becomes active (on VT switch and resume). +--- + src/backends/native/meta-backend-native.c | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c +index db9b63ac4..479e9326b 100644 +--- a/src/backends/native/meta-backend-native.c ++++ b/src/backends/native/meta-backend-native.c +@@ -54,6 +54,7 @@ + #include "backends/native/meta-renderer-native.h" + #include "backends/native/meta-stage-native.h" + #include "clutter/evdev/clutter-evdev.h" ++#include "core/display-private.h" + #include "core/meta-border.h" + #include "meta/main.h" + +@@ -662,6 +663,7 @@ void meta_backend_native_resume (MetaBackendNative *native) + if (cogl_has_feature (cogl_context, COGL_FEATURE_ID_UNSTABLE_TEXTURES)) + { + clutter_clear_glyph_cache (); ++ meta_display_update_cursor (display); + g_signal_emit_by_name (display, "gl-video-memory-purged"); + } + +-- +2.21.0 + diff --git a/SOURCES/0007-cogl-Expose-cogl_blit_framebuffer.patch b/SOURCES/0007-cogl-Expose-cogl_blit_framebuffer.patch new file mode 100644 index 0000000..a5c9686 --- /dev/null +++ b/SOURCES/0007-cogl-Expose-cogl_blit_framebuffer.patch @@ -0,0 +1,261 @@ +From be13d3c844a6623563ae4e74dbb3409baf16fc9c Mon Sep 17 00:00:00 2001 +From: Pekka Paalanen +Date: Mon, 3 Dec 2018 14:34:41 +0200 +Subject: [PATCH 07/12] cogl: Expose cogl_blit_framebuffer + +The function will be used in copying from a primary GPU framebuffer to a +secondary GPU framebuffer using the primary GPU specifically when the +secondary GPU is not render-capable. + +To allow falling back in case glBlitFramebuffer cannot be used, add boolean +return value, and GError argument for debugging purposes. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/615 +(cherry picked from commit 6061abbf90cd1d62e262ebf3636470d2219e04a7) +--- + cogl/cogl/cogl-blit.c | 11 ++--- + cogl/cogl/cogl-framebuffer-private.h | 55 ----------------------- + cogl/cogl/cogl-framebuffer.c | 40 +++++++++++------ + cogl/cogl/cogl-framebuffer.h | 66 +++++++++++++++++++++++++++- + 4 files changed, 98 insertions(+), 74 deletions(-) + +diff --git a/cogl/cogl/cogl-blit.c b/cogl/cogl/cogl-blit.c +index c561b2e45..ae5a8a345 100644 +--- a/cogl/cogl/cogl-blit.c ++++ b/cogl/cogl/cogl-blit.c +@@ -207,11 +207,12 @@ _cogl_blit_framebuffer_blit (CoglBlitData *data, + int width, + int height) + { +- _cogl_blit_framebuffer (data->src_fb, +- data->dest_fb, +- src_x, src_y, +- dst_x, dst_y, +- width, height); ++ cogl_blit_framebuffer (data->src_fb, ++ data->dest_fb, ++ src_x, src_y, ++ dst_x, dst_y, ++ width, height, ++ NULL); + } + + static void +diff --git a/cogl/cogl/cogl-framebuffer-private.h b/cogl/cogl/cogl-framebuffer-private.h +index cb1f87354..7d71fb1dc 100644 +--- a/cogl/cogl/cogl-framebuffer-private.h ++++ b/cogl/cogl/cogl-framebuffer-private.h +@@ -367,61 +367,6 @@ void + _cogl_push_framebuffers (CoglFramebuffer *draw_buffer, + CoglFramebuffer *read_buffer); + +-/* +- * _cogl_blit_framebuffer: +- * @src: The source #CoglFramebuffer +- * @dest: The destination #CoglFramebuffer +- * @src_x: Source x position +- * @src_y: Source y position +- * @dst_x: Destination x position +- * @dst_y: Destination y position +- * @width: Width of region to copy +- * @height: Height of region to copy +- * +- * This blits a region of the color buffer of the source buffer +- * to the destination buffer. This function should only be +- * called if the COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER feature is +- * advertised. +- * +- * The source and destination rectangles are defined in offscreen +- * framebuffer orientation. When copying between an offscreen and +- * onscreen framebuffers, the image is y-flipped accordingly. +- * +- * The two buffers must have the same value types (e.g. floating-point, +- * unsigned int, signed int, or fixed-point), but color formats do not +- * need to match. This limitation comes from OpenGL ES 3.0 definition +- * of glBlitFramebuffer. +- * +- * Note that this function differs a lot from the glBlitFramebuffer +- * function provided by the GL_EXT_framebuffer_blit extension. Notably +- * it doesn't support having different sizes for the source and +- * destination rectangle. This doesn't seem +- * like a particularly useful feature. If the application wanted to +- * scale the results it may make more sense to draw a primitive +- * instead. +- * +- * The GL function is documented to be affected by the scissor. This +- * function therefore ensure that an empty clip stack is flushed +- * before performing the blit which means the scissor is effectively +- * ignored. +- * +- * The function also doesn't support specifying the buffers to copy +- * and instead only the color buffer is copied. When copying the depth +- * or stencil buffers the extension on GLES2.0 only supports copying +- * the full buffer which would be awkward to document with this +- * API. If we wanted to support that feature it may be better to have +- * a separate function to copy the entire buffer for a given mask. +- */ +-void +-_cogl_blit_framebuffer (CoglFramebuffer *src, +- CoglFramebuffer *dest, +- int src_x, +- int src_y, +- int dst_x, +- int dst_y, +- int width, +- int height); +- + void + _cogl_framebuffer_push_projection (CoglFramebuffer *framebuffer); + +diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c +index 5cc4eada4..6d35c6b13 100644 +--- a/cogl/cogl/cogl-framebuffer.c ++++ b/cogl/cogl/cogl-framebuffer.c +@@ -1449,26 +1449,38 @@ cogl_framebuffer_read_pixels (CoglFramebuffer *framebuffer, + return ret; + } + +-void +-_cogl_blit_framebuffer (CoglFramebuffer *src, +- CoglFramebuffer *dest, +- int src_x, +- int src_y, +- int dst_x, +- int dst_y, +- int width, +- int height) ++gboolean ++cogl_blit_framebuffer (CoglFramebuffer *src, ++ CoglFramebuffer *dest, ++ int src_x, ++ int src_y, ++ int dst_x, ++ int dst_y, ++ int width, ++ int height, ++ GError **error) + { + CoglContext *ctx = src->context; + int src_x1, src_y1, src_x2, src_y2; + int dst_x1, dst_y1, dst_x2, dst_y2; + +- _COGL_RETURN_IF_FAIL (_cogl_has_private_feature +- (ctx, COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER)); ++ if (!_cogl_has_private_feature (ctx, COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER)) ++ { ++ g_set_error_literal (error, COGL_SYSTEM_ERROR, ++ COGL_SYSTEM_ERROR_UNSUPPORTED, ++ "Cogl BLIT_FRAMEBUFFER is not supported by the system."); ++ return FALSE; ++ } + + /* The buffers must use the same premult convention */ +- _COGL_RETURN_IF_FAIL ((src->internal_format & COGL_PREMULT_BIT) == +- (dest->internal_format & COGL_PREMULT_BIT)); ++ if ((src->internal_format & COGL_PREMULT_BIT) != ++ (dest->internal_format & COGL_PREMULT_BIT)) ++ { ++ g_set_error_literal (error, COGL_SYSTEM_ERROR, ++ COGL_SYSTEM_ERROR_UNSUPPORTED, ++ "cogl_blit_framebuffer premult mismatch."); ++ return FALSE; ++ } + + /* Make sure the current framebuffers are bound. We explicitly avoid + flushing the clip state so we can bind our own empty state */ +@@ -1526,6 +1538,8 @@ _cogl_blit_framebuffer (CoglFramebuffer *src, + dst_x1, dst_y1, dst_x2, dst_y2, + GL_COLOR_BUFFER_BIT, + GL_NEAREST); ++ ++ return TRUE; + } + + void +diff --git a/cogl/cogl/cogl-framebuffer.h b/cogl/cogl/cogl-framebuffer.h +index 48a77e1ed..230a78627 100644 +--- a/cogl/cogl/cogl-framebuffer.h ++++ b/cogl/cogl/cogl-framebuffer.h +@@ -3,7 +3,8 @@ + * + * A Low Level GPU Graphics and Utilities API + * +- * Copyright (C) 2011 Intel Corporation. ++ * Copyright (C) 2007,2008,2009,2011 Intel Corporation. ++ * Copyright (C) 2019 DisplayLink (UK) Ltd. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation +@@ -1846,6 +1847,69 @@ typedef enum /*< prefix=COGL_FRAMEBUFFER_ERROR >*/ + gboolean + cogl_is_framebuffer (void *object); + ++/** ++ * cogl_blit_framebuffer: ++ * @src: The source #CoglFramebuffer ++ * @dest: The destination #CoglFramebuffer ++ * @src_x: Source x position ++ * @src_y: Source y position ++ * @dst_x: Destination x position ++ * @dst_y: Destination y position ++ * @width: Width of region to copy ++ * @height: Height of region to copy ++ * @error: optional error object ++ * ++ * @return FALSE for an immediately detected error, TRUE otherwise. ++ * ++ * This blits a region of the color buffer of the source buffer ++ * to the destination buffer. This function should only be ++ * called if the COGL_PRIVATE_FEATURE_BLIT_FRAMEBUFFER feature is ++ * advertised. ++ * ++ * The source and destination rectangles are defined in offscreen ++ * framebuffer orientation. When copying between an offscreen and ++ * onscreen framebuffers, the image is y-flipped accordingly. ++ * ++ * The two buffers must have the same value types (e.g. floating-point, ++ * unsigned int, signed int, or fixed-point), but color formats do not ++ * need to match. This limitation comes from OpenGL ES 3.0 definition ++ * of glBlitFramebuffer. ++ * ++ * Note that this function differs a lot from the glBlitFramebuffer ++ * function provided by the GL_EXT_framebuffer_blit extension. Notably ++ * it doesn't support having different sizes for the source and ++ * destination rectangle. This doesn't seem ++ * like a particularly useful feature. If the application wanted to ++ * scale the results it may make more sense to draw a primitive ++ * instead. ++ * ++ * The GL function is documented to be affected by the scissor. This ++ * function therefore ensure that an empty clip stack is flushed ++ * before performing the blit which means the scissor is effectively ++ * ignored. ++ * ++ * The function also doesn't support specifying the buffers to copy ++ * and instead only the color buffer is copied. When copying the depth ++ * or stencil buffers the extension on GLES2.0 only supports copying ++ * the full buffer which would be awkward to document with this ++ * API. If we wanted to support that feature it may be better to have ++ * a separate function to copy the entire buffer for a given mask. ++ * ++ * The @c error argument is optional, it can be NULL. If it is not NULL ++ * and this function returns FALSE, an error object with a code from ++ * COGL_SYSTEM_ERROR will be created. ++ */ ++gboolean ++cogl_blit_framebuffer (CoglFramebuffer *src, ++ CoglFramebuffer *dest, ++ int src_x, ++ int src_y, ++ int dst_x, ++ int dst_y, ++ int width, ++ int height, ++ GError **error); ++ + G_END_DECLS + + #endif /* __COGL_FRAMEBUFFER_H */ +-- +2.21.0 + diff --git a/SOURCES/0008-background-purge-all-background-textures-on-suspend.patch b/SOURCES/0008-background-purge-all-background-textures-on-suspend.patch new file mode 100644 index 0000000..1034111 --- /dev/null +++ b/SOURCES/0008-background-purge-all-background-textures-on-suspend.patch @@ -0,0 +1,110 @@ +From c78a614b0d45a4bc8101a93c7138c9fb6102d13c Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Wed, 9 Jan 2019 16:57:05 -0500 +Subject: [PATCH 8/9] background: purge all background textures on suspend + +This commit makes sure all background textures get purged +on suspend, which is important for nvidia. +--- + src/compositor/meta-background-image.c | 28 ++++++++++++++++++++++++++ + src/compositor/meta-background.c | 17 +++++++++++++++- + src/meta/meta-background-image.h | 2 ++ + 3 files changed, 46 insertions(+), 1 deletion(-) + +diff --git a/src/compositor/meta-background-image.c b/src/compositor/meta-background-image.c +index 14d3baf57..98909cb53 100644 +--- a/src/compositor/meta-background-image.c ++++ b/src/compositor/meta-background-image.c +@@ -283,6 +283,34 @@ meta_background_image_cache_purge (MetaBackgroundImageCache *cache, + image->in_cache = FALSE; + } + ++/** ++ * meta_background_image_cache_unload_all: ++ * @cache: a #MetaBackgroundImageCache ++ * ++ * Remove all entries from the cache and unloads them; this would be used ++ * if textures in video memory have been invalidated. ++ */ ++void ++meta_background_image_cache_unload_all (MetaBackgroundImageCache *cache) ++{ ++ GHashTableIter iter; ++ gpointer key, value; ++ ++ g_return_if_fail (META_IS_BACKGROUND_IMAGE_CACHE (cache)); ++ ++ g_hash_table_iter_init (&iter, cache->images); ++ while (g_hash_table_iter_next (&iter, &key, &value)) ++ { ++ MetaBackgroundImage *image = value; ++ ++ g_clear_pointer (&image->texture, cogl_object_unref); ++ image->in_cache = FALSE; ++ image->loaded = FALSE; ++ } ++ ++ g_hash_table_remove_all (cache->images); ++} ++ + G_DEFINE_TYPE (MetaBackgroundImage, meta_background_image, G_TYPE_OBJECT); + + static void +diff --git a/src/compositor/meta-background.c b/src/compositor/meta-background.c +index c033395fe..abdfcc7df 100644 +--- a/src/compositor/meta-background.c ++++ b/src/compositor/meta-background.c +@@ -303,6 +303,18 @@ meta_background_finalize (GObject *object) + G_OBJECT_CLASS (meta_background_parent_class)->finalize (object); + } + ++static void ++free_textures (MetaBackground *self) ++{ ++ free_color_texture (self); ++ free_wallpaper_texture (self); ++ ++ set_file (self, &self->file1, &self->background_image1, NULL); ++ set_file (self, &self->file2, &self->background_image2, NULL); ++ ++ mark_changed (self); ++} ++ + static void + meta_background_constructed (GObject *object) + { +@@ -312,7 +324,7 @@ meta_background_constructed (GObject *object) + G_OBJECT_CLASS (meta_background_parent_class)->constructed (object); + + g_signal_connect_object (self->display, "gl-video-memory-purged", +- G_CALLBACK (mark_changed), object, G_CONNECT_SWAPPED); ++ G_CALLBACK (free_textures), object, G_CONNECT_SWAPPED); + + g_signal_connect_object (monitor_manager, "monitors-changed", + G_CALLBACK (on_monitors_changed), self, +@@ -950,8 +962,11 @@ meta_background_set_blend (MetaBackground *self, + void + meta_background_refresh_all (void) + { ++ MetaBackgroundImageCache *cache = meta_background_image_cache_get_default (); + GSList *l; + ++ meta_background_image_cache_unload_all (cache); ++ + for (l = all_backgrounds; l; l = l->next) + mark_changed (l->data); + } +diff --git a/src/meta/meta-background-image.h b/src/meta/meta-background-image.h +index 137a6ff8e..87e40d251 100644 +--- a/src/meta/meta-background-image.h ++++ b/src/meta/meta-background-image.h +@@ -66,4 +66,6 @@ META_EXPORT + void meta_background_image_cache_purge (MetaBackgroundImageCache *cache, + GFile *file); + ++void meta_background_image_cache_unload_all (MetaBackgroundImageCache *cache); ++ + #endif /* __META_BACKGROUND_IMAGE_H__ */ +-- +2.21.0 + diff --git a/SOURCES/0008-clutter-stage-view-Use-cogl_blit_framebuffer-for-sha.patch b/SOURCES/0008-clutter-stage-view-Use-cogl_blit_framebuffer-for-sha.patch new file mode 100644 index 0000000..09e8db9 --- /dev/null +++ b/SOURCES/0008-clutter-stage-view-Use-cogl_blit_framebuffer-for-sha.patch @@ -0,0 +1,42 @@ +From bbeb161e8ab31bbef3c7d378e9a8d4ecc786c25d Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Thu, 26 Sep 2019 10:20:36 +0200 +Subject: [PATCH 08/12] clutter/stage-view: Use cogl_blit_framebuffer() for + shadow FB + +If there is no transformation, use `cogl_blit_framebuffer()` as a +shortcut in `clutter_stage_view_blit_offscreen()`, that dramatically +improves performance when using a shadow framebuffer. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/809 +(cherry picked from commit 3400c555a032832a689c208486891352a6cb92de) +--- + clutter/clutter/clutter-stage-view.c | 12 ++++++++++++ + 1 file changed, 12 insertions(+) + +diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c +index cd6cd35cb..00cbfd1ce 100644 +--- a/clutter/clutter/clutter-stage-view.c ++++ b/clutter/clutter/clutter-stage-view.c +@@ -126,6 +126,18 @@ clutter_stage_view_blit_offscreen (ClutterStageView *view, + clutter_stage_view_get_instance_private (view); + CoglMatrix matrix; + ++ clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix); ++ if (cogl_matrix_is_identity (&matrix)) ++ { ++ if (cogl_blit_framebuffer (priv->offscreen, ++ priv->framebuffer, ++ rect->x, rect->y, ++ rect->x, rect->y, ++ rect->width, rect->height, ++ NULL)) ++ return; ++ } ++ + clutter_stage_view_ensure_offscreen_blit_pipeline (view); + cogl_framebuffer_push_matrix (priv->framebuffer); + +-- +2.21.0 + diff --git a/SOURCES/0009-MetaShapedTexture-save-and-restore-textures-on-suspe.patch b/SOURCES/0009-MetaShapedTexture-save-and-restore-textures-on-suspe.patch new file mode 100644 index 0000000..4b38154 --- /dev/null +++ b/SOURCES/0009-MetaShapedTexture-save-and-restore-textures-on-suspe.patch @@ -0,0 +1,712 @@ +From d8cc418899276b45cb1a787493e0998e3b008fe5 Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Thu, 10 Jan 2019 10:48:02 -0500 +Subject: [PATCH 9/9] MetaShapedTexture: save and restore textures on suspend + +The proprietary nvidia driver garbles GPU memory on suspend. + +In order to workaround that limitation, this commit copies all +textures to host memory on suspend and restores them on resume. + +One complication comes from external textures (such as those +given to us by Xwayland for X clients). We can't just restore +those textures, since they aren't writable. + +This commit addresses that complication by keeping a local texture +around for those external textures, and using it instead for parts +of the window that haven't been redrawn since resume. +--- + src/compositor/meta-shaped-texture.c | 487 +++++++++++++++++++++++++-- + src/meta/meta-shaped-texture.h | 2 + + 2 files changed, 468 insertions(+), 21 deletions(-) + +diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c +index d64e214e5..ea8daa03d 100644 +--- a/src/compositor/meta-shaped-texture.c ++++ b/src/compositor/meta-shaped-texture.c +@@ -40,7 +40,9 @@ + #include "compositor/meta-texture-tower.h" + #include "compositor/region-utils.h" + #include "core/boxes-private.h" ++#include + #include "meta/meta-shaped-texture.h" ++#include "meta-texture-rectangle.h" + + /* MAX_MIPMAPPING_FPS needs to be as small as possible for the best GPU + * performance, but higher than the refresh rate of commonly slow updating +@@ -72,8 +74,12 @@ static void meta_shaped_texture_get_preferred_height (ClutterActor *self, + + static gboolean meta_shaped_texture_get_paint_volume (ClutterActor *self, ClutterPaintVolume *volume); + ++static void disable_backing_store (MetaShapedTexture *stex); ++ + static void cullable_iface_init (MetaCullableInterface *iface); + ++static gboolean meta_debug_show_backing_store = FALSE; ++ + enum + { + SIZE_CHANGED, +@@ -83,6 +89,14 @@ enum + + static guint signals[LAST_SIGNAL]; + ++typedef struct ++{ ++ CoglTexture *texture; ++ CoglTexture *mask_texture; ++ cairo_surface_t *mask_surface; ++ cairo_region_t *region; ++} MetaTextureBackingStore; ++ + struct _MetaShapedTexture + { + ClutterActor parent; +@@ -114,6 +128,16 @@ struct _MetaShapedTexture + int viewport_dst_width; + int viewport_dst_height; + ++ /* textures get corrupted on suspend, so save them */ ++ cairo_surface_t *saved_base_surface; ++ cairo_surface_t *saved_mask_surface; ++ ++ /* We can't just restore external textures, so we need to track ++ * which parts of the external texture are freshly drawn from ++ * the client after corruption, and fill in the rest from our ++ * saved snapshot */ ++ MetaTextureBackingStore *backing_store; ++ + int tex_width, tex_height; + int fallback_width, fallback_height; + int dst_width, dst_height; +@@ -148,6 +172,9 @@ meta_shaped_texture_class_init (MetaShapedTextureClass *klass) + 0, + NULL, NULL, NULL, + G_TYPE_NONE, 0); ++ ++ if (g_getenv ("MUTTER_DEBUG_BACKING_STORE")) ++ meta_debug_show_backing_store = TRUE; + } + + static void +@@ -159,6 +186,11 @@ invalidate_size (MetaShapedTexture *stex) + static void + meta_shaped_texture_init (MetaShapedTexture *stex) + { ++ MetaBackend *backend = meta_get_backend (); ++ ClutterBackend *clutter_backend = clutter_get_default_backend (); ++ CoglContext *cogl_context = ++ clutter_backend_get_cogl_context (clutter_backend); ++ + stex->paint_tower = meta_texture_tower_new (); + + stex->texture = NULL; +@@ -171,6 +203,12 @@ meta_shaped_texture_init (MetaShapedTexture *stex) + "notify::scale-x", + G_CALLBACK (invalidate_size), + stex); ++ ++ if (cogl_has_feature (cogl_context, COGL_FEATURE_ID_UNSTABLE_TEXTURES)) ++ { ++ g_signal_connect_object (backend, "suspending", G_CALLBACK (meta_shaped_texture_save), stex, G_CONNECT_SWAPPED); ++ g_signal_connect_object (backend, "resuming", G_CALLBACK (meta_shaped_texture_restore), stex, G_CONNECT_SWAPPED); ++ } + } + + static void +@@ -311,24 +349,72 @@ meta_shaped_texture_dispose (GObject *object) + G_OBJECT_CLASS (meta_shaped_texture_parent_class)->dispose (object); + } + ++static int ++get_layer_indices (MetaShapedTexture *stex, ++ int *main_layer_index, ++ int *backing_mask_layer_index, ++ int *backing_layer_index, ++ int *mask_layer_index) ++{ ++ int next_layer_index = 0; ++ ++ if (main_layer_index) ++ *main_layer_index = next_layer_index; ++ ++ next_layer_index++; ++ ++ if (stex->backing_store) ++ { ++ if (backing_mask_layer_index) ++ *backing_mask_layer_index = next_layer_index; ++ next_layer_index++; ++ if (backing_layer_index) ++ *backing_layer_index = next_layer_index; ++ next_layer_index++; ++ } ++ else ++ { ++ if (backing_mask_layer_index) ++ *backing_mask_layer_index = -1; ++ if (backing_layer_index) ++ *backing_layer_index = -1; ++ } ++ ++ if (mask_layer_index) ++ *mask_layer_index = next_layer_index; ++ ++ return next_layer_index; ++} ++ + static CoglPipeline * + get_base_pipeline (MetaShapedTexture *stex, + CoglContext *ctx) + { + CoglPipeline *pipeline; ++ int main_layer_index; ++ int backing_layer_index; ++ int backing_mask_layer_index; ++ int i, number_of_layers; + + if (stex->base_pipeline) + return stex->base_pipeline; + + pipeline = cogl_pipeline_new (ctx); +- cogl_pipeline_set_layer_wrap_mode_s (pipeline, 0, +- COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); +- cogl_pipeline_set_layer_wrap_mode_t (pipeline, 0, +- COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); +- cogl_pipeline_set_layer_wrap_mode_s (pipeline, 1, +- COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); +- cogl_pipeline_set_layer_wrap_mode_t (pipeline, 1, +- COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); ++ ++ number_of_layers = get_layer_indices (stex, ++ &main_layer_index, ++ &backing_mask_layer_index, ++ &backing_layer_index, ++ NULL); ++ ++ for (i = 0; i < number_of_layers; i++) ++ { ++ cogl_pipeline_set_layer_wrap_mode_s (pipeline, i, ++ COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); ++ cogl_pipeline_set_layer_wrap_mode_t (pipeline, i, ++ COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); ++ } ++ + if (!stex->is_y_inverted) + { + CoglMatrix matrix; +@@ -336,7 +422,22 @@ get_base_pipeline (MetaShapedTexture *stex, + cogl_matrix_init_identity (&matrix); + cogl_matrix_scale (&matrix, 1, -1, 1); + cogl_matrix_translate (&matrix, 0, -1, 0); +- cogl_pipeline_set_layer_matrix (pipeline, 0, &matrix); ++ cogl_pipeline_set_layer_matrix (pipeline, main_layer_index, &matrix); ++ } ++ ++ if (stex->backing_store) ++ { ++ g_autofree char *backing_description = NULL; ++ cogl_pipeline_set_layer_combine (pipeline, backing_mask_layer_index, ++ "RGBA = REPLACE(PREVIOUS)", ++ NULL); ++ backing_description = g_strdup_printf ("RGBA = INTERPOLATE(PREVIOUS, TEXTURE_%d, TEXTURE_%d[A])", ++ backing_layer_index, ++ backing_mask_layer_index); ++ cogl_pipeline_set_layer_combine (pipeline, ++ backing_layer_index, ++ backing_description, ++ NULL); + } + + if (stex->transform != META_MONITOR_TRANSFORM_NORMAL) +@@ -379,7 +480,7 @@ get_base_pipeline (MetaShapedTexture *stex, + } + + if (stex->snippet) +- cogl_pipeline_add_layer_snippet (pipeline, 0, stex->snippet); ++ cogl_pipeline_add_layer_snippet (pipeline, main_layer_index, stex->snippet); + + stex->base_pipeline = pipeline; + +@@ -398,12 +499,15 @@ get_masked_pipeline (MetaShapedTexture *stex, + CoglContext *ctx) + { + CoglPipeline *pipeline; ++ int mask_layer_index; + + if (stex->masked_pipeline) + return stex->masked_pipeline; + ++ get_layer_indices (stex, NULL, NULL, NULL, &mask_layer_index); ++ + pipeline = cogl_pipeline_copy (get_base_pipeline (stex, ctx)); +- cogl_pipeline_set_layer_combine (pipeline, 1, ++ cogl_pipeline_set_layer_combine (pipeline, mask_layer_index, + "RGBA = MODULATE (PREVIOUS, TEXTURE[A])", + NULL); + +@@ -517,6 +621,8 @@ set_cogl_texture (MetaShapedTexture *stex, + if (stex->texture) + cogl_object_unref (stex->texture); + ++ g_clear_pointer (&stex->saved_base_surface, cairo_surface_destroy); ++ + stex->texture = cogl_tex; + + if (cogl_tex != NULL) +@@ -579,6 +685,10 @@ do_paint (MetaShapedTexture *stex, + CoglContext *ctx; + ClutterActorBox alloc; + CoglPipelineFilter filter; ++ int main_layer_index; ++ int backing_mask_layer_index; ++ int backing_layer_index; ++ int mask_layer_index; + + clutter_actor_get_scale (CLUTTER_ACTOR (stex), &tex_scale, NULL); + ensure_size_valid (stex); +@@ -665,6 +775,12 @@ do_paint (MetaShapedTexture *stex, + } + } + ++ get_layer_indices (stex, ++ &main_layer_index, ++ &backing_mask_layer_index, ++ &backing_layer_index, ++ &mask_layer_index); ++ + /* First, paint the unblended parts, which are part of the opaque region. */ + if (use_opaque_region) + { +@@ -686,8 +802,24 @@ do_paint (MetaShapedTexture *stex, + if (!cairo_region_is_empty (region)) + { + opaque_pipeline = get_unblended_pipeline (stex, ctx); +- cogl_pipeline_set_layer_texture (opaque_pipeline, 0, paint_tex); +- cogl_pipeline_set_layer_filters (opaque_pipeline, 0, filter, filter); ++ cogl_pipeline_set_layer_texture (opaque_pipeline, main_layer_index, paint_tex); ++ cogl_pipeline_set_layer_filters (opaque_pipeline, main_layer_index, filter, filter); ++ ++ if (stex->backing_store) ++ { ++ cogl_pipeline_set_layer_texture (opaque_pipeline, ++ backing_mask_layer_index, ++ stex->backing_store->mask_texture); ++ cogl_pipeline_set_layer_filters (opaque_pipeline, ++ backing_mask_layer_index, ++ filter, filter); ++ cogl_pipeline_set_layer_texture (opaque_pipeline, ++ backing_layer_index, ++ stex->backing_store->texture); ++ cogl_pipeline_set_layer_filters (opaque_pipeline, ++ backing_layer_index, ++ filter, filter); ++ } + + n_rects = cairo_region_num_rectangles (region); + for (i = 0; i < n_rects; i++) +@@ -726,12 +858,28 @@ do_paint (MetaShapedTexture *stex, + else + { + blended_pipeline = get_masked_pipeline (stex, ctx); +- cogl_pipeline_set_layer_texture (blended_pipeline, 1, stex->mask_texture); +- cogl_pipeline_set_layer_filters (blended_pipeline, 1, filter, filter); ++ cogl_pipeline_set_layer_texture (blended_pipeline, mask_layer_index, stex->mask_texture); ++ cogl_pipeline_set_layer_filters (blended_pipeline, mask_layer_index, filter, filter); + } + +- cogl_pipeline_set_layer_texture (blended_pipeline, 0, paint_tex); +- cogl_pipeline_set_layer_filters (blended_pipeline, 0, filter, filter); ++ cogl_pipeline_set_layer_texture (blended_pipeline, main_layer_index, paint_tex); ++ cogl_pipeline_set_layer_filters (blended_pipeline, main_layer_index, filter, filter); ++ ++ if (stex->backing_store) ++ { ++ cogl_pipeline_set_layer_texture (blended_pipeline, ++ backing_mask_layer_index, ++ stex->backing_store->mask_texture); ++ cogl_pipeline_set_layer_filters (blended_pipeline, ++ backing_mask_layer_index, ++ filter, filter); ++ cogl_pipeline_set_layer_texture (blended_pipeline, ++ backing_layer_index, ++ stex->backing_store->texture); ++ cogl_pipeline_set_layer_filters (blended_pipeline, ++ backing_layer_index, ++ filter, filter); ++ } + + CoglColor color; + cogl_color_init_from_4ub (&color, opacity, opacity, opacity, opacity); +@@ -925,6 +1073,7 @@ meta_shaped_texture_set_mask_texture (MetaShapedTexture *stex, + g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); + + g_clear_pointer (&stex->mask_texture, cogl_object_unref); ++ g_clear_pointer (&stex->saved_mask_surface, cairo_surface_destroy); + + if (mask_texture != NULL) + { +@@ -946,6 +1095,65 @@ meta_shaped_texture_is_obscured (MetaShapedTexture *stex) + return FALSE; + } + ++static void ++meta_texture_backing_store_redraw_mask (MetaTextureBackingStore *backing_store) ++{ ++ CoglError *error = NULL; ++ ++ if (!cogl_texture_set_data (backing_store->mask_texture, COGL_PIXEL_FORMAT_A_8, ++ cairo_image_surface_get_stride (backing_store->mask_surface), ++ cairo_image_surface_get_data (backing_store->mask_surface), 0, ++ &error)) ++ { ++ ++ g_warning ("Failed to update backing mask texture"); ++ g_clear_pointer (&error, cogl_error_free); ++ } ++} ++ ++static gboolean ++meta_texture_backing_store_shrink (MetaTextureBackingStore *backing_store, ++ const cairo_rectangle_int_t *area) ++{ ++ cairo_t *cr; ++ ++ cairo_region_subtract_rectangle (backing_store->region, area); ++ ++ /* If the client has finally redrawn the entire surface, we can ++ * ditch our snapshot ++ */ ++ if (cairo_region_is_empty (backing_store->region)) ++ return FALSE; ++ ++ cr = cairo_create (backing_store->mask_surface); ++ cairo_set_operator (cr, CAIRO_OPERATOR_SOURCE); ++ cairo_paint (cr); ++ gdk_cairo_region (cr, backing_store->region); ++ cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR); ++ cairo_fill (cr); ++ cairo_destroy (cr); ++ ++ meta_texture_backing_store_redraw_mask (backing_store); ++ ++ return TRUE; ++} ++ ++static void ++shrink_backing_region (MetaShapedTexture *stex, ++ const cairo_rectangle_int_t *area) ++{ ++ gboolean still_backing_texture; ++ ++ if (!stex->backing_store) ++ return; ++ ++ still_backing_texture = ++ meta_texture_backing_store_shrink (stex->backing_store, area); ++ ++ if (!still_backing_texture) ++ disable_backing_store (stex); ++} ++ + /** + * meta_shaped_texture_update_area: + * @stex: #MetaShapedTexture +@@ -1041,6 +1249,8 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, + &clip); + } + ++ shrink_backing_region (stex, &clip); ++ + meta_texture_tower_update_area (stex->paint_tower, + clip.x, + clip.y, +@@ -1268,8 +1478,9 @@ should_get_via_offscreen (MetaShapedTexture *stex) + } + + static cairo_surface_t * +-get_image_via_offscreen (MetaShapedTexture *stex, +- cairo_rectangle_int_t *clip) ++get_image_via_offscreen (MetaShapedTexture *stex, ++ cairo_rectangle_int_t *clip, ++ CoglTexture **texture) + { + ClutterBackend *clutter_backend = clutter_get_default_backend (); + CoglContext *cogl_context = +@@ -1340,9 +1551,29 @@ get_image_via_offscreen (MetaShapedTexture *stex, + clip->width, clip->height, + CLUTTER_CAIRO_FORMAT_ARGB32, + cairo_image_surface_get_data (surface)); ++ cairo_surface_mark_dirty (surface); ++ ++ if (texture) ++ { ++ *texture = cogl_object_ref (image_texture); ++ ++ if (G_UNLIKELY (meta_debug_show_backing_store)) ++ { ++ cairo_t *cr; ++ ++ cr = cairo_create (surface); ++ cairo_set_source_rgba (cr, 1.0, 0.0, 0.0, 0.75); ++ cairo_paint (cr); ++ cairo_destroy (cr); ++ } ++ ++ cogl_texture_set_data (*texture, CLUTTER_CAIRO_FORMAT_ARGB32, ++ cairo_image_surface_get_stride (surface), ++ cairo_image_surface_get_data (surface), 0, NULL); ++ } ++ + cogl_object_unref (fb); + +- cairo_surface_mark_dirty (surface); + + return surface; + } +@@ -1404,7 +1635,7 @@ meta_shaped_texture_get_image (MetaShapedTexture *stex, + } + + if (should_get_via_offscreen (stex)) +- return get_image_via_offscreen (stex, transformed_clip); ++ return get_image_via_offscreen (stex, transformed_clip, NULL); + + if (transformed_clip) + texture = cogl_texture_new_from_sub_texture (texture, +@@ -1465,6 +1696,220 @@ meta_shaped_texture_get_image (MetaShapedTexture *stex, + return surface; + } + ++static void ++meta_texture_backing_store_free (MetaTextureBackingStore *backing_store) ++{ ++ g_clear_pointer (&backing_store->texture, cogl_object_unref); ++ g_clear_pointer (&backing_store->mask_texture, cogl_object_unref); ++ g_clear_pointer (&backing_store->mask_surface, cairo_surface_destroy); ++ g_clear_pointer (&backing_store->region, cairo_region_destroy); ++ ++ g_slice_free (MetaTextureBackingStore, backing_store); ++} ++ ++static MetaTextureBackingStore * ++meta_texture_backing_store_new (CoglTexture *texture) ++{ ++ MetaTextureBackingStore *backing_store = NULL; ++ ClutterBackend *backend = clutter_get_default_backend (); ++ CoglContext *context = clutter_backend_get_cogl_context (backend); ++ CoglTexture *mask_texture = NULL; ++ guchar *mask_data; ++ int width, height, stride; ++ cairo_surface_t *surface; ++ cairo_region_t *region; ++ cairo_rectangle_int_t backing_rectangle; ++ ++ width = cogl_texture_get_width (texture); ++ height = cogl_texture_get_height (texture); ++ stride = cairo_format_stride_for_width (CAIRO_FORMAT_A8, width); ++ ++ /* we start off by only letting the backing texture through, and none of the real texture */ ++ backing_rectangle.x = 0; ++ backing_rectangle.y = 0; ++ backing_rectangle.width = width; ++ backing_rectangle.height = height; ++ ++ region = cairo_region_create_rectangle (&backing_rectangle); ++ ++ /* initialize mask to transparent, so the entire backing store shows through ++ * up front ++ */ ++ mask_data = g_malloc0 (stride * height); ++ surface = cairo_image_surface_create_for_data (mask_data, ++ CAIRO_FORMAT_A8, ++ width, ++ height, ++ stride); ++ ++ if (meta_texture_rectangle_check (texture)) ++ { ++ mask_texture = COGL_TEXTURE (cogl_texture_rectangle_new_with_size (context, ++ width, ++ height)); ++ cogl_texture_set_components (mask_texture, COGL_TEXTURE_COMPONENTS_A); ++ cogl_texture_set_region (mask_texture, ++ 0, 0, ++ 0, 0, ++ width, height, ++ width, height, ++ COGL_PIXEL_FORMAT_A_8, ++ stride, mask_data); ++ } ++ else ++ { ++ CoglError *error = NULL; ++ ++ mask_texture = COGL_TEXTURE (cogl_texture_2d_new_from_data (context, width, height, ++ COGL_PIXEL_FORMAT_A_8, ++ stride, mask_data, &error)); ++ ++ if (error) ++ { ++ g_warning ("Failed to allocate mask texture: %s", error->message); ++ cogl_error_free (error); ++ } ++ } ++ ++ if (mask_texture) ++ { ++ backing_store = g_slice_new0 (MetaTextureBackingStore); ++ backing_store->texture = cogl_object_ref (texture); ++ backing_store->mask_texture = mask_texture; ++ backing_store->mask_surface = surface; ++ backing_store->region = region; ++ } ++ ++ return backing_store; ++} ++ ++static void ++enable_backing_store (MetaShapedTexture *stex, ++ CoglTexture *texture) ++{ ++ g_clear_pointer (&stex->backing_store, meta_texture_backing_store_free); ++ ++ stex->backing_store = meta_texture_backing_store_new (texture); ++ ++ meta_shaped_texture_reset_pipelines (stex); ++} ++ ++static void ++disable_backing_store (MetaShapedTexture *stex) ++{ ++ g_clear_pointer (&stex->backing_store, meta_texture_backing_store_free); ++ ++ meta_shaped_texture_reset_pipelines (stex); ++} ++ ++void ++meta_shaped_texture_save (MetaShapedTexture *stex) ++{ ++ ++ CoglTexture *texture, *mask_texture; ++ cairo_surface_t *surface; ++ ++ g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); ++ ++ texture = COGL_TEXTURE (stex->texture); ++ ++ if (texture == NULL) ++ return; ++ ++ g_clear_pointer (&stex->saved_base_surface, cairo_surface_destroy); ++ g_clear_pointer (&stex->saved_mask_surface, cairo_surface_destroy); ++ g_clear_pointer (&stex->backing_store, meta_texture_backing_store_free); ++ ++ if (should_get_via_offscreen (stex)) ++ { ++ CoglTexture *backing_texture; ++ ++ meta_shaped_texture_reset_pipelines (stex); ++ ++ surface = get_image_via_offscreen (stex, NULL, &backing_texture); ++ ++ enable_backing_store (stex, backing_texture); ++ cogl_object_unref (backing_texture); ++ } ++ else ++ { ++ surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, ++ cogl_texture_get_width (texture), ++ cogl_texture_get_height (texture)); ++ ++ cogl_texture_get_data (texture, CLUTTER_CAIRO_FORMAT_ARGB32, ++ cairo_image_surface_get_stride (surface), ++ cairo_image_surface_get_data (surface)); ++ } ++ ++ stex->saved_base_surface = surface; ++ ++ mask_texture = stex->mask_texture; ++ if (mask_texture != NULL) ++ { ++ cairo_surface_t *mask_surface; ++ ++ mask_surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, ++ cogl_texture_get_width (mask_texture), ++ cogl_texture_get_height (mask_texture)); ++ ++ cogl_texture_get_data (mask_texture, CLUTTER_CAIRO_FORMAT_ARGB32, ++ cairo_image_surface_get_stride (mask_surface), ++ cairo_image_surface_get_data (mask_surface)); ++ ++ cairo_surface_mark_dirty (mask_surface); ++ ++ stex->saved_mask_surface = mask_surface; ++ } ++} ++ ++void ++meta_shaped_texture_restore (MetaShapedTexture *stex) ++{ ++ CoglTexture *texture; ++ CoglError *error = NULL; ++ ++ texture = meta_shaped_texture_get_texture (stex); ++ ++ if (texture == NULL) ++ return; ++ ++ if (stex->mask_texture) ++ { ++ if (!cogl_texture_set_data (stex->mask_texture, CLUTTER_CAIRO_FORMAT_ARGB32, ++ cairo_image_surface_get_stride (stex->saved_mask_surface), ++ cairo_image_surface_get_data (stex->saved_mask_surface), 0, ++ &error)) ++ { ++ g_warning ("Failed to restore mask texture"); ++ g_clear_pointer (&error, cogl_error_free); ++ } ++ g_clear_pointer (&stex->saved_mask_surface, cairo_surface_destroy); ++ } ++ ++ /* if the main texture doesn't support direct writes, then ++ * write to the local backing texture instead, and blend old ++ * versus new at paint time. ++ */ ++ if (stex->backing_store) ++ { ++ meta_texture_backing_store_redraw_mask (stex->backing_store); ++ texture = stex->backing_store->texture; ++ } ++ ++ if (!cogl_texture_set_data (texture, CLUTTER_CAIRO_FORMAT_ARGB32, ++ cairo_image_surface_get_stride (stex->saved_base_surface), ++ cairo_image_surface_get_data (stex->saved_base_surface), 0, ++ &error)) ++ { ++ g_warning ("Failed to restore texture"); ++ g_clear_pointer (&error, cogl_error_free); ++ } ++ g_clear_pointer (&stex->saved_base_surface, cairo_surface_destroy); ++ ++ clutter_actor_queue_redraw (CLUTTER_ACTOR (stex)); ++} ++ + void + meta_shaped_texture_set_fallback_size (MetaShapedTexture *stex, + int fallback_width, +diff --git a/src/meta/meta-shaped-texture.h b/src/meta/meta-shaped-texture.h +index c36b8547f..22b4fbd53 100644 +--- a/src/meta/meta-shaped-texture.h ++++ b/src/meta/meta-shaped-texture.h +@@ -66,6 +66,8 @@ META_EXPORT + cairo_surface_t * meta_shaped_texture_get_image (MetaShapedTexture *stex, + cairo_rectangle_int_t *clip); + ++void meta_shaped_texture_save (MetaShapedTexture *self); ++void meta_shaped_texture_restore (MetaShapedTexture *self); + G_END_DECLS + + #endif /* __META_SHAPED_TEXTURE_H__ */ +-- +2.21.0 + diff --git a/SOURCES/0009-clutter-stage-view-Ignore-clipping-rectangle-for-off.patch b/SOURCES/0009-clutter-stage-view-Ignore-clipping-rectangle-for-off.patch new file mode 100644 index 0000000..ea67449 --- /dev/null +++ b/SOURCES/0009-clutter-stage-view-Ignore-clipping-rectangle-for-off.patch @@ -0,0 +1,49 @@ +From 46bb54bcd9c90f90dd170355209f8c379680d5c1 Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Tue, 1 Oct 2019 14:16:25 +0200 +Subject: [PATCH 09/12] clutter/stage-view: Ignore clipping rectangle for + offscreen blit +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +In `clutter_stage_view_blit_offscreen()`, the given clipping rectangle +is in “view” coordinates whereas we intend to copy the whole actual +framebuffer, meaning that we cannot use the clipping rectangle. + +Use the actual framebuffer size, starting at (0, 0) instead. + +That fixes the issue with partial repainting with shadow framebuffer +when fractional scaling is enabled. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/820 +(cherry picked from commit 0a3f25c3039b586f5b5721e91136c5d2fccecca1) +--- + clutter/clutter/clutter-stage-view.c | 9 ++++++--- + 1 file changed, 6 insertions(+), 3 deletions(-) + +diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c +index 00cbfd1ce..503c31e78 100644 +--- a/clutter/clutter/clutter-stage-view.c ++++ b/clutter/clutter/clutter-stage-view.c +@@ -129,11 +129,14 @@ clutter_stage_view_blit_offscreen (ClutterStageView *view, + clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix); + if (cogl_matrix_is_identity (&matrix)) + { ++ int fb_width = cogl_framebuffer_get_width (priv->framebuffer); ++ int fb_height = cogl_framebuffer_get_height (priv->framebuffer); ++ + if (cogl_blit_framebuffer (priv->offscreen, + priv->framebuffer, +- rect->x, rect->y, +- rect->x, rect->y, +- rect->width, rect->height, ++ 0, 0, ++ 0, 0, ++ fb_width, fb_height, + NULL)) + return; + } +-- +2.21.0 + diff --git a/SOURCES/0010-cogl-Flush-journal-before-blitting.patch b/SOURCES/0010-cogl-Flush-journal-before-blitting.patch new file mode 100644 index 0000000..f3935eb --- /dev/null +++ b/SOURCES/0010-cogl-Flush-journal-before-blitting.patch @@ -0,0 +1,34 @@ +From 4c7fe200e05f9a028d440ed2032961d1b798c83b Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Tue, 1 Oct 2019 15:54:47 +0200 +Subject: [PATCH 10/12] cogl: Flush journal before blitting + +Make sure to submit all pending primitives before blitting, otherwise +rendering from the shell may be incomplete leaving partial drawing of +the shell widgets. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/820 +(cherry picked from commit 0cdf13ac12c570d38737fddb68946157c0b7a4d2) +--- + cogl/cogl/cogl-framebuffer.c | 5 +++++ + 1 file changed, 5 insertions(+) + +diff --git a/cogl/cogl/cogl-framebuffer.c b/cogl/cogl/cogl-framebuffer.c +index 6d35c6b13..948cd112d 100644 +--- a/cogl/cogl/cogl-framebuffer.c ++++ b/cogl/cogl/cogl-framebuffer.c +@@ -1482,6 +1482,11 @@ cogl_blit_framebuffer (CoglFramebuffer *src, + return FALSE; + } + ++ /* Make sure any batched primitives get submitted to the driver ++ * before blitting ++ */ ++ _cogl_framebuffer_flush_journal (src); ++ + /* Make sure the current framebuffers are bound. We explicitly avoid + flushing the clip state so we can bind our own empty state */ + _cogl_framebuffer_flush_state (dest, +-- +2.21.0 + diff --git a/SOURCES/0011-clutter-stage-view-Separate-offscreen-and-shadowfb.patch b/SOURCES/0011-clutter-stage-view-Separate-offscreen-and-shadowfb.patch new file mode 100644 index 0000000..9dd46a0 --- /dev/null +++ b/SOURCES/0011-clutter-stage-view-Separate-offscreen-and-shadowfb.patch @@ -0,0 +1,304 @@ +From cf8f1fb8478e4b76c91e825d1537396b014689a0 Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Tue, 22 Oct 2019 17:03:03 +0200 +Subject: [PATCH 11/12] clutter/stage-view: Separate offscreen and shadowfb + +Previously, we would use a single offscreen framebuffer for both +transformations and when a shadow framebuffer should be used, but that +can be dreadfully slow when using software rendering with a discrete GPU +due to bandwidth limitations. + +Keep the offscreen framebuffer for transformations only and add another +intermediate shadow framebuffer used as a copy of the onscreen +framebuffer. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/917 + +(cherry picked from commit 2b8b450fe16c21f0f37a1779560c0e5da61a9b89) +--- + clutter/clutter/clutter-stage-view.c | 162 +++++++++++++++++----- + clutter/clutter/cogl/clutter-stage-cogl.c | 6 +- + 2 files changed, 128 insertions(+), 40 deletions(-) + +diff --git a/clutter/clutter/clutter-stage-view.c b/clutter/clutter/clutter-stage-view.c +index 503c31e78..c536ac720 100644 +--- a/clutter/clutter/clutter-stage-view.c ++++ b/clutter/clutter/clutter-stage-view.c +@@ -29,6 +29,7 @@ enum + PROP_LAYOUT, + PROP_FRAMEBUFFER, + PROP_OFFSCREEN, ++ PROP_SHADOWFB, + PROP_SCALE, + + PROP_LAST +@@ -43,7 +44,10 @@ typedef struct _ClutterStageViewPrivate + CoglFramebuffer *framebuffer; + + CoglOffscreen *offscreen; +- CoglPipeline *pipeline; ++ CoglPipeline *offscreen_pipeline; ++ ++ CoglOffscreen *shadowfb; ++ CoglPipeline *shadowfb_pipeline; + + guint dirty_viewport : 1; + guint dirty_projection : 1; +@@ -69,6 +73,8 @@ clutter_stage_view_get_framebuffer (ClutterStageView *view) + + if (priv->offscreen) + return priv->offscreen; ++ else if (priv->shadowfb) ++ return priv->shadowfb; + else + return priv->framebuffer; + } +@@ -82,6 +88,24 @@ clutter_stage_view_get_onscreen (ClutterStageView *view) + return priv->framebuffer; + } + ++static CoglPipeline * ++clutter_stage_view_create_framebuffer_pipeline (CoglFramebuffer *framebuffer) ++{ ++ CoglPipeline *pipeline; ++ ++ pipeline = cogl_pipeline_new (cogl_framebuffer_get_context (framebuffer)); ++ ++ cogl_pipeline_set_layer_filters (pipeline, 0, ++ COGL_PIPELINE_FILTER_NEAREST, ++ COGL_PIPELINE_FILTER_NEAREST); ++ cogl_pipeline_set_layer_texture (pipeline, 0, ++ cogl_offscreen_get_texture (framebuffer)); ++ cogl_pipeline_set_layer_wrap_mode (pipeline, 0, ++ COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); ++ ++ return pipeline; ++} ++ + static void + clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view) + { +@@ -92,71 +116,122 @@ clutter_stage_view_ensure_offscreen_blit_pipeline (ClutterStageView *view) + + g_assert (priv->offscreen != NULL); + +- if (priv->pipeline) ++ if (priv->offscreen_pipeline) + return; + +- priv->pipeline = +- cogl_pipeline_new (cogl_framebuffer_get_context (priv->offscreen)); +- cogl_pipeline_set_layer_filters (priv->pipeline, 0, +- COGL_PIPELINE_FILTER_NEAREST, +- COGL_PIPELINE_FILTER_NEAREST); +- cogl_pipeline_set_layer_texture (priv->pipeline, 0, +- cogl_offscreen_get_texture (priv->offscreen)); +- cogl_pipeline_set_layer_wrap_mode (priv->pipeline, 0, +- COGL_PIPELINE_WRAP_MODE_CLAMP_TO_EDGE); ++ priv->offscreen_pipeline = ++ clutter_stage_view_create_framebuffer_pipeline (priv->offscreen); + + if (view_class->setup_offscreen_blit_pipeline) +- view_class->setup_offscreen_blit_pipeline (view, priv->pipeline); ++ view_class->setup_offscreen_blit_pipeline (view, priv->offscreen_pipeline); + } + +-void +-clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view) ++static void ++clutter_stage_view_ensure_shadowfb_blit_pipeline (ClutterStageView *view) + { + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); + +- g_clear_pointer (&priv->pipeline, cogl_object_unref); ++ if (priv->shadowfb_pipeline) ++ return; ++ ++ priv->shadowfb_pipeline = ++ clutter_stage_view_create_framebuffer_pipeline (priv->shadowfb); + } + + void +-clutter_stage_view_blit_offscreen (ClutterStageView *view, +- const cairo_rectangle_int_t *rect) ++clutter_stage_view_invalidate_offscreen_blit_pipeline (ClutterStageView *view) + { + ClutterStageViewPrivate *priv = + clutter_stage_view_get_instance_private (view); ++ ++ g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref); ++} ++ ++static void ++clutter_stage_view_copy_to_framebuffer (ClutterStageView *view, ++ const cairo_rectangle_int_t *rect, ++ CoglPipeline *pipeline, ++ CoglFramebuffer *src_framebuffer, ++ CoglFramebuffer *dst_framebuffer, ++ gboolean can_blit) ++{ + CoglMatrix matrix; + +- clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix); +- if (cogl_matrix_is_identity (&matrix)) ++ /* First, try with blit */ ++ if (can_blit) + { +- int fb_width = cogl_framebuffer_get_width (priv->framebuffer); +- int fb_height = cogl_framebuffer_get_height (priv->framebuffer); +- +- if (cogl_blit_framebuffer (priv->offscreen, +- priv->framebuffer, ++ if (cogl_blit_framebuffer (src_framebuffer, ++ dst_framebuffer, + 0, 0, + 0, 0, +- fb_width, fb_height, ++ cogl_framebuffer_get_width (dst_framebuffer), ++ cogl_framebuffer_get_height (dst_framebuffer), + NULL)) + return; + } + +- clutter_stage_view_ensure_offscreen_blit_pipeline (view); +- cogl_framebuffer_push_matrix (priv->framebuffer); ++ /* If blit fails, fallback to the slower painting method */ ++ cogl_framebuffer_push_matrix (dst_framebuffer); + +- /* Set transform so 0,0 is on the top left corner and 1,1 on +- * the bottom right corner. +- */ + cogl_matrix_init_identity (&matrix); + cogl_matrix_translate (&matrix, -1, 1, 0); + cogl_matrix_scale (&matrix, 2, -2, 0); +- cogl_framebuffer_set_projection_matrix (priv->framebuffer, &matrix); ++ cogl_framebuffer_set_projection_matrix (dst_framebuffer, &matrix); + +- cogl_framebuffer_draw_rectangle (priv->framebuffer, +- priv->pipeline, ++ cogl_framebuffer_draw_rectangle (dst_framebuffer, ++ pipeline, + 0, 0, 1, 1); + +- cogl_framebuffer_pop_matrix (priv->framebuffer); ++ cogl_framebuffer_pop_matrix (dst_framebuffer); ++} ++ ++void ++clutter_stage_view_blit_offscreen (ClutterStageView *view, ++ const cairo_rectangle_int_t *rect) ++{ ++ ClutterStageViewPrivate *priv = ++ clutter_stage_view_get_instance_private (view); ++ ++ if (priv->offscreen) ++ { ++ gboolean can_blit; ++ CoglMatrix matrix; ++ ++ clutter_stage_view_ensure_offscreen_blit_pipeline (view); ++ clutter_stage_view_get_offscreen_transformation_matrix (view, &matrix); ++ can_blit = cogl_matrix_is_identity (&matrix); ++ ++ if (priv->shadowfb) ++ { ++ clutter_stage_view_copy_to_framebuffer (view, ++ rect, ++ priv->offscreen_pipeline, ++ priv->offscreen, ++ priv->shadowfb, ++ can_blit); ++ } ++ else ++ { ++ clutter_stage_view_copy_to_framebuffer (view, ++ rect, ++ priv->offscreen_pipeline, ++ priv->offscreen, ++ priv->framebuffer, ++ can_blit); ++ } ++ } ++ ++ if (priv->shadowfb) ++ { ++ clutter_stage_view_ensure_shadowfb_blit_pipeline (view); ++ clutter_stage_view_copy_to_framebuffer (view, ++ rect, ++ priv->shadowfb_pipeline, ++ priv->shadowfb, ++ priv->framebuffer, ++ TRUE); ++ } + } + + float +@@ -256,6 +331,9 @@ clutter_stage_view_get_property (GObject *object, + case PROP_OFFSCREEN: + g_value_set_boxed (value, priv->offscreen); + break; ++ case PROP_SHADOWFB: ++ g_value_set_boxed (value, priv->shadowfb); ++ break; + case PROP_SCALE: + g_value_set_float (value, priv->scale); + break; +@@ -301,6 +379,9 @@ clutter_stage_view_set_property (GObject *object, + case PROP_OFFSCREEN: + priv->offscreen = g_value_dup_boxed (value); + break; ++ case PROP_SHADOWFB: ++ priv->shadowfb = g_value_dup_boxed (value); ++ break; + case PROP_SCALE: + priv->scale = g_value_get_float (value); + break; +@@ -317,8 +398,10 @@ clutter_stage_view_dispose (GObject *object) + clutter_stage_view_get_instance_private (view); + + g_clear_pointer (&priv->framebuffer, cogl_object_unref); ++ g_clear_pointer (&priv->shadowfb, cogl_object_unref); + g_clear_pointer (&priv->offscreen, cogl_object_unref); +- g_clear_pointer (&priv->pipeline, cogl_object_unref); ++ g_clear_pointer (&priv->offscreen_pipeline, cogl_object_unref); ++ g_clear_pointer (&priv->shadowfb_pipeline, cogl_object_unref); + + G_OBJECT_CLASS (clutter_stage_view_parent_class)->dispose (object); + } +@@ -373,6 +456,15 @@ clutter_stage_view_class_init (ClutterStageViewClass *klass) + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_STATIC_STRINGS); + ++ obj_props[PROP_SHADOWFB] = ++ g_param_spec_boxed ("shadowfb", ++ "Shadow framebuffer", ++ "Framebuffer used as intermediate shadow buffer", ++ COGL_TYPE_HANDLE, ++ G_PARAM_READWRITE | ++ G_PARAM_CONSTRUCT_ONLY | ++ G_PARAM_STATIC_STRINGS); ++ + obj_props[PROP_SCALE] = + g_param_spec_float ("scale", + "View scale", +diff --git a/clutter/clutter/cogl/clutter-stage-cogl.c b/clutter/clutter/cogl/clutter-stage-cogl.c +index e0c39185b..eab76e52f 100644 +--- a/clutter/clutter/cogl/clutter-stage-cogl.c ++++ b/clutter/clutter/cogl/clutter-stage-cogl.c +@@ -477,11 +477,7 @@ paint_stage (ClutterStageCogl *stage_cogl, + _clutter_stage_maybe_setup_viewport (stage, view); + _clutter_stage_paint_view (stage, view, clip); + +- if (clutter_stage_view_get_onscreen (view) != +- clutter_stage_view_get_framebuffer (view)) +- { +- clutter_stage_view_blit_offscreen (view, clip); +- } ++ clutter_stage_view_blit_offscreen (view, clip); + } + + static void +-- +2.21.0 + diff --git a/SOURCES/0012-renderer-native-Separate-offscreen-and-shadowfb.patch b/SOURCES/0012-renderer-native-Separate-offscreen-and-shadowfb.patch new file mode 100644 index 0000000..cd748a9 --- /dev/null +++ b/SOURCES/0012-renderer-native-Separate-offscreen-and-shadowfb.patch @@ -0,0 +1,98 @@ +From ca3e9e3b3b84fe95affbe5485212c6ecfa1a4b51 Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Tue, 22 Oct 2019 17:05:46 +0200 +Subject: [PATCH 12/12] renderer-native: Separate offscreen and shadowfb + +Create the intermediate shadow framebuffer for use exclusively when a +shadowfb is required. + +Keep the previous offscreen framebuffer is as an intermediate +framebuffer for transformations only. + +This way, we can apply transformations between in-memory framebuffers +prior to blit the result to screen, and achieve acceptable performance +even with software rendering on discrete GPU. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/917 + +(cherry picked from commit 551641c74822ca2e3c685e49603836ebf5397df2) +--- + src/backends/native/meta-renderer-native.c | 29 ++++++++++++++++++---- + 1 file changed, 24 insertions(+), 5 deletions(-) + +diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c +index 3cd01bcb7..ffb64a6bd 100644 +--- a/src/backends/native/meta-renderer-native.c ++++ b/src/backends/native/meta-renderer-native.c +@@ -3287,7 +3287,6 @@ meta_renderer_native_create_onscreen (MetaRendererNative *renderer_native, + static CoglOffscreen * + meta_renderer_native_create_offscreen (MetaRendererNative *renderer, + CoglContext *context, +- MetaMonitorTransform transform, + gint view_width, + gint view_height, + GError **error) +@@ -3489,6 +3488,7 @@ meta_renderer_native_create_view (MetaRenderer *renderer, + MetaMonitorTransform view_transform; + CoglOnscreen *onscreen = NULL; + CoglOffscreen *offscreen = NULL; ++ CoglOffscreen *shadowfb = NULL; + float scale; + int width, height; + MetaRendererView *view; +@@ -3515,18 +3515,35 @@ meta_renderer_native_create_view (MetaRenderer *renderer, + if (!onscreen) + g_error ("Failed to allocate onscreen framebuffer: %s", error->message); + +- if (view_transform != META_MONITOR_TRANSFORM_NORMAL || +- should_force_shadow_fb (renderer_native, +- renderer_native->primary_gpu_kms)) ++ if (view_transform != META_MONITOR_TRANSFORM_NORMAL) + { + offscreen = meta_renderer_native_create_offscreen (renderer_native, + cogl_context, +- view_transform, + width, + height, + &error); + if (!offscreen) + g_error ("Failed to allocate back buffer texture: %s", error->message); ++ ++ } ++ ++ if (should_force_shadow_fb (renderer_native, ++ renderer_native->primary_gpu_kms)) ++ { ++ int shadow_width; ++ int shadow_height; ++ ++ /* The shadowfb must be the same size as the on-screen framebuffer */ ++ shadow_width = cogl_framebuffer_get_width (COGL_FRAMEBUFFER (onscreen)); ++ shadow_height = cogl_framebuffer_get_height (COGL_FRAMEBUFFER (onscreen)); ++ ++ shadowfb = meta_renderer_native_create_offscreen (renderer_native, ++ cogl_context, ++ shadow_width, ++ shadow_height, ++ &error); ++ if (!shadowfb) ++ g_error ("Failed to allocate shadow buffer texture: %s", error->message); + } + + view = g_object_new (META_TYPE_RENDERER_VIEW, +@@ -3534,10 +3551,12 @@ meta_renderer_native_create_view (MetaRenderer *renderer, + "scale", scale, + "framebuffer", onscreen, + "offscreen", offscreen, ++ "shadowfb", shadowfb, + "logical-monitor", logical_monitor, + "transform", view_transform, + NULL); + g_clear_pointer (&offscreen, cogl_object_unref); ++ g_clear_pointer (&shadowfb, cogl_object_unref); + + meta_onscreen_native_set_view (onscreen, view); + +-- +2.21.0 + diff --git a/SOURCES/add-support-for-plain-old-x-device-configuration.patch b/SOURCES/add-support-for-plain-old-x-device-configuration.patch new file mode 100644 index 0000000..beefaf2 --- /dev/null +++ b/SOURCES/add-support-for-plain-old-x-device-configuration.patch @@ -0,0 +1,378 @@ +From 3f7ba6739773f43a3ad2a5d26cb8c3365f77cc00 Mon Sep 17 00:00:00 2001 +From: Rui Matos +Date: Mon, 9 Oct 2017 18:39:52 +0200 +Subject: [PATCH 1/3] backends/x11: Add a synaptics check for two finger scroll + availability + +Commit "backends/x11: Support synaptics configuration" added support +for synaptics two finger scrolling but didn't add the code to check +that it is available resulting in the upper layer always assuming it +isn't. +--- + src/backends/x11/meta-input-settings-x11.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c +index 051a1c605..887bc8b42 100644 +--- a/src/backends/x11/meta-input-settings-x11.c ++++ b/src/backends/x11/meta-input-settings-x11.c +@@ -630,6 +630,17 @@ meta_input_settings_x11_has_two_finger_scroll (MetaInputSettings *settings, + guchar *available = NULL; + gboolean has_two_finger = TRUE; + ++ if (is_device_synaptics (device)) ++ { ++ available = get_property (device, "Synaptics Capabilities", ++ XA_INTEGER, 8, 4); ++ if (!available || !available[3]) ++ has_two_finger = FALSE; ++ ++ meta_XFree (available); ++ return has_two_finger; ++ } ++ + available = get_property (device, "libinput Scroll Methods Available", + XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS); + if (!available || !available[SCROLL_METHOD_FIELD_2FG]) +-- +2.21.0 + + +From 717561b28f35e05d40fb941baba781436a0abf68 Mon Sep 17 00:00:00 2001 +From: Rui Matos +Date: Mon, 9 Oct 2017 18:55:56 +0200 +Subject: [PATCH 2/3] backends/x11: Add disable while typing support for + synaptics + +This is basically a copy of the old g-s-d mouse plugin code to manage +syndaemon when the synaptics driver is being used. +--- + src/backends/x11/meta-input-settings-x11.c | 112 +++++++++++++++++++++ + 1 file changed, 112 insertions(+) + +diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c +index 887bc8b42..12a592c75 100644 +--- a/src/backends/x11/meta-input-settings-x11.c ++++ b/src/backends/x11/meta-input-settings-x11.c +@@ -35,6 +35,9 @@ + #ifdef HAVE_LIBGUDEV + #include + #endif ++#ifdef __linux ++#include ++#endif + + #include "backends/meta-logical-monitor.h" + #include "backends/x11/meta-backend-x11.h" +@@ -46,6 +49,8 @@ typedef struct _MetaInputSettingsX11Private + #ifdef HAVE_LIBGUDEV + GUdevClient *udev_client; + #endif ++ gboolean syndaemon_spawned; ++ GPid syndaemon_pid; + } MetaInputSettingsX11Private; + + G_DEFINE_TYPE_WITH_PRIVATE (MetaInputSettingsX11, meta_input_settings_x11, +@@ -337,6 +342,107 @@ change_synaptics_speed (ClutterInputDevice *device, + XCloseDevice (xdisplay, xdevice); + } + ++/* Ensure that syndaemon dies together with us, to avoid running several of ++ * them */ ++static void ++setup_syndaemon (gpointer user_data) ++{ ++#ifdef __linux ++ prctl (PR_SET_PDEATHSIG, SIGHUP); ++#endif ++} ++ ++static gboolean ++have_program_in_path (const char *name) ++{ ++ gchar *path; ++ gboolean result; ++ ++ path = g_find_program_in_path (name); ++ result = (path != NULL); ++ g_free (path); ++ return result; ++} ++ ++static void ++syndaemon_died (GPid pid, ++ gint status, ++ gpointer user_data) ++{ ++ MetaInputSettingsX11 *settings_x11 = META_INPUT_SETTINGS_X11 (user_data); ++ MetaInputSettingsX11Private *priv = ++ meta_input_settings_x11_get_instance_private (settings_x11); ++ GError *error = NULL; ++ ++ if (!g_spawn_check_exit_status (status, &error)) ++ { ++ if ((WIFSIGNALED (status) && WTERMSIG (status) != SIGHUP) || ++ error->domain == G_SPAWN_EXIT_ERROR) ++ g_warning ("Syndaemon exited unexpectedly: %s", error->message); ++ g_error_free (error); ++ } ++ ++ g_spawn_close_pid (pid); ++ priv->syndaemon_spawned = FALSE; ++} ++ ++static void ++set_synaptics_disable_w_typing (MetaInputSettings *settings, ++ gboolean state) ++{ ++ MetaInputSettingsX11 *settings_x11 = META_INPUT_SETTINGS_X11 (settings); ++ MetaInputSettingsX11Private *priv = ++ meta_input_settings_x11_get_instance_private (settings_x11); ++ ++ if (state) ++ { ++ GError *error = NULL; ++ GPtrArray *args; ++ ++ if (priv->syndaemon_spawned) ++ return; ++ ++ if (!have_program_in_path ("syndaemon")) ++ return; ++ ++ args = g_ptr_array_new (); ++ ++ g_ptr_array_add (args, (gpointer)"syndaemon"); ++ g_ptr_array_add (args, (gpointer)"-i"); ++ g_ptr_array_add (args, (gpointer)"1.0"); ++ g_ptr_array_add (args, (gpointer)"-t"); ++ g_ptr_array_add (args, (gpointer)"-K"); ++ g_ptr_array_add (args, (gpointer)"-R"); ++ g_ptr_array_add (args, NULL); ++ ++ /* we must use G_SPAWN_DO_NOT_REAP_CHILD to avoid ++ * double-forking, otherwise syndaemon will immediately get ++ * killed again through (PR_SET_PDEATHSIG when the intermediate ++ * process dies */ ++ g_spawn_async (g_get_home_dir (), (char **) args->pdata, NULL, ++ G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD, setup_syndaemon, NULL, ++ &priv->syndaemon_pid, &error); ++ ++ priv->syndaemon_spawned = (error == NULL); ++ g_ptr_array_free (args, TRUE); ++ ++ if (error) ++ { ++ g_warning ("Failed to launch syndaemon: %s", error->message); ++ g_error_free (error); ++ } ++ else ++ { ++ g_child_watch_add (priv->syndaemon_pid, syndaemon_died, settings); ++ } ++ } ++ else if (priv->syndaemon_spawned) ++ { ++ kill (priv->syndaemon_pid, SIGHUP); ++ priv->syndaemon_spawned = FALSE; ++ } ++} ++ + static void + meta_input_settings_x11_set_send_events (MetaInputSettings *settings, + ClutterInputDevice *device, +@@ -461,6 +567,12 @@ meta_input_settings_x11_set_disable_while_typing (MetaInputSettings *settings, + { + guchar value = (enabled) ? 1 : 0; + ++ if (is_device_synaptics (device)) ++ { ++ set_synaptics_disable_w_typing (settings, enabled); ++ return; ++ } ++ + change_property (device, "libinput Disable While Typing Enabled", + XA_INTEGER, 8, &value, 1); + } +-- +2.21.0 + + +From 0afa6d0940ca4f5ffafd24effd2c414963a44277 Mon Sep 17 00:00:00 2001 +From: Rui Matos +Date: Tue, 10 Oct 2017 19:07:27 +0200 +Subject: [PATCH 3/3] backends/x11: Support plain old X device configuration + +We re-use part of the code added to support synaptics and add a few +bits specific for xorg-x11-drv-evdev devices. +--- + src/backends/x11/meta-input-settings-x11.c | 97 +++++++++++++++++----- + 1 file changed, 74 insertions(+), 23 deletions(-) + +diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c +index 12a592c75..80e5ed10e 100644 +--- a/src/backends/x11/meta-input-settings-x11.c ++++ b/src/backends/x11/meta-input-settings-x11.c +@@ -182,36 +182,36 @@ is_device_synaptics (ClutterInputDevice *device) + return TRUE; + } + ++static gboolean ++is_device_libinput (ClutterInputDevice *device) ++{ ++ guchar *has_setting; ++ ++ /* We just need looking for a synaptics-specific property */ ++ has_setting = get_property (device, "libinput Send Events Modes Available", XA_INTEGER, 8, 2); ++ if (!has_setting) ++ return FALSE; ++ ++ meta_XFree (has_setting); ++ return TRUE; ++} ++ + static void +-change_synaptics_tap_left_handed (ClutterInputDevice *device, +- gboolean tap_enabled, +- gboolean left_handed) ++change_x_device_left_handed (ClutterInputDevice *device, ++ gboolean left_handed) + { + MetaDisplay *display = meta_get_display (); + MetaX11Display *x11_display = display ? display->x11_display : NULL; + MetaBackend *backend = meta_get_backend (); + Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); + XDevice *xdevice; +- guchar *tap_action, *buttons; ++ guchar *buttons; + guint buttons_capacity = 16, n_buttons; + + xdevice = XOpenDevice(xdisplay, clutter_input_device_get_device_id (device)); + if (!xdevice) + return; + +- tap_action = get_property (device, "Synaptics Tap Action", +- XA_INTEGER, 8, 7); +- if (!tap_action) +- goto out; +- +- tap_action[4] = tap_enabled ? (left_handed ? 3 : 1) : 0; +- tap_action[5] = tap_enabled ? (left_handed ? 1 : 3) : 0; +- tap_action[6] = tap_enabled ? 2 : 0; +- +- change_property (device, "Synaptics Tap Action", +- XA_INTEGER, 8, tap_action, 7); +- meta_XFree (tap_action); +- + if (x11_display) + meta_x11_error_trap_push (x11_display); + buttons = g_new (guchar, buttons_capacity); +@@ -235,17 +235,39 @@ change_synaptics_tap_left_handed (ClutterInputDevice *device, + + if (x11_display && meta_x11_error_trap_pop_with_return (x11_display)) + { +- g_warning ("Could not set synaptics touchpad left-handed for %s", ++ g_warning ("Could not set left-handed for %s", + clutter_input_device_get_device_name (device)); + } + +- out: + XCloseDevice (xdisplay, xdevice); + } + + static void +-change_synaptics_speed (ClutterInputDevice *device, +- gdouble speed) ++change_synaptics_tap_left_handed (ClutterInputDevice *device, ++ gboolean tap_enabled, ++ gboolean left_handed) ++{ ++ guchar *tap_action; ++ ++ tap_action = get_property (device, "Synaptics Tap Action", ++ XA_INTEGER, 8, 7); ++ if (!tap_action) ++ return; ++ ++ tap_action[4] = tap_enabled ? (left_handed ? 3 : 1) : 0; ++ tap_action[5] = tap_enabled ? (left_handed ? 1 : 3) : 0; ++ tap_action[6] = tap_enabled ? 2 : 0; ++ ++ change_property (device, "Synaptics Tap Action", ++ XA_INTEGER, 8, tap_action, 7); ++ meta_XFree (tap_action); ++ ++ change_x_device_left_handed (device, left_handed); ++} ++ ++static void ++change_x_device_speed (ClutterInputDevice *device, ++ gdouble speed) + { + MetaDisplay *display = meta_get_display (); + MetaX11Display *x11_display = display ? display->x11_display : NULL; +@@ -342,6 +364,23 @@ change_synaptics_speed (ClutterInputDevice *device, + XCloseDevice (xdisplay, xdevice); + } + ++static void ++change_x_device_scroll_button (ClutterInputDevice *device, ++ guint button) ++{ ++ guchar value; ++ ++ value = button > 0 ? 1 : 0; ++ change_property (device, "Evdev Wheel Emulation", ++ XA_INTEGER, 8, &value, 1); ++ if (button > 0) ++ { ++ value = button; ++ change_property (device, "Evdev Wheel Emulation Button", ++ XA_INTEGER, 8, &value, 1); ++ } ++} ++ + /* Ensure that syndaemon dies together with us, to avoid running several of + * them */ + static void +@@ -510,9 +549,10 @@ meta_input_settings_x11_set_speed (MetaInputSettings *settings, + Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); + gfloat value = speed; + +- if (is_device_synaptics (device)) ++ if (is_device_synaptics (device) || ++ !is_device_libinput (device)) + { +- change_synaptics_speed (device, speed); ++ change_x_device_speed (device, speed); + return; + } + +@@ -554,6 +594,11 @@ meta_input_settings_x11_set_left_handed (MetaInputSettings *settings, + g_object_unref (settings); + return; + } ++ else if (!is_device_libinput (device) && device_type != CLUTTER_PAD_DEVICE) ++ { ++ change_x_device_left_handed (device, enabled); ++ return; ++ } + + change_property (device, "libinput Left Handed Enabled", + XA_INTEGER, 8, &value, 1); +@@ -767,6 +812,12 @@ meta_input_settings_x11_set_scroll_button (MetaInputSettings *settings, + ClutterInputDevice *device, + guint button) + { ++ if (!is_device_libinput (device)) ++ { ++ change_x_device_scroll_button (device, button); ++ return; ++ } ++ + change_property (device, "libinput Button Scrolling Button", + XA_INTEGER, 32, &button, 1); + } +-- +2.21.0 + diff --git a/SOURCES/covscan-fixes.patch b/SOURCES/covscan-fixes.patch new file mode 100644 index 0000000..25bfe3c --- /dev/null +++ b/SOURCES/covscan-fixes.patch @@ -0,0 +1,246 @@ +From 55417eea4294210495eceebd6dd4b832f371f054 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20Dre=C3=9Fler?= +Date: Sun, 14 Apr 2019 17:15:06 +0200 +Subject: [PATCH 1/5] display: Fix a possible bug in + meta_display_sync_wayland_focus + +The check for the focus xwindow is called, but not used. Fix that by +renaming the variable to reflect better what it does and actually using +the return value of the check. + +This was the original intention of the author in commit +05899596d10918df5359d89baa82e6fedd0ae208 and got broken in commit +8e7e1eeef59c4f74046e6783b6334c1432255c5a. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/535 +--- + src/core/display.c | 8 ++++---- + 1 file changed, 4 insertions(+), 4 deletions(-) + +diff --git a/src/core/display.c b/src/core/display.c +index 0de99edb2..4c8907f40 100644 +--- a/src/core/display.c ++++ b/src/core/display.c +@@ -1208,15 +1208,15 @@ meta_display_sync_wayland_input_focus (MetaDisplay *display) + MetaWindow *focus_window = NULL; + MetaBackend *backend = meta_get_backend (); + MetaStage *stage = META_STAGE (meta_backend_get_stage (backend)); +- gboolean is_focus_xwindow = FALSE; ++ gboolean is_no_focus_xwindow = FALSE; + + if (display->x11_display) +- meta_x11_display_xwindow_is_a_no_focus_window (display->x11_display, +- display->x11_display->focus_xwindow); ++ is_no_focus_xwindow = meta_x11_display_xwindow_is_a_no_focus_window (display->x11_display, ++ display->x11_display->focus_xwindow); + + if (!meta_display_windows_are_interactable (display)) + focus_window = NULL; +- else if (is_focus_xwindow) ++ else if (is_no_focus_xwindow) + focus_window = NULL; + else if (display->focus_window && display->focus_window->surface) + focus_window = display->focus_window; +-- +2.21.0 + + +From 17cc0a2a21c504b8631bf2ce0f508f611f9b1d3e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Mon, 27 May 2019 20:03:25 +0000 +Subject: [PATCH 2/5] renderer-x11-nested: Fix copy-and-paste error + +The rounding added in commit c5471e5b8b1 mixed up some variables, +whoops. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/598 +--- + src/backends/x11/nested/meta-renderer-x11-nested.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/backends/x11/nested/meta-renderer-x11-nested.c b/src/backends/x11/nested/meta-renderer-x11-nested.c +index 71a85a8c2..5000bf357 100644 +--- a/src/backends/x11/nested/meta-renderer-x11-nested.c ++++ b/src/backends/x11/nested/meta-renderer-x11-nested.c +@@ -203,7 +203,7 @@ meta_renderer_x11_nested_create_view (MetaRenderer *renderer, + height = logical_monitor->rect.height; + } + width = roundf (width * view_scale); +- height = roundf (width * view_scale); ++ height = roundf (height * view_scale); + + fake_onscreen = create_offscreen (cogl_context, width, height); + +-- +2.21.0 + + +From a58fabbb0e3173359d3374b931815c21ce65032d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Mon, 27 May 2019 19:59:53 +0000 +Subject: [PATCH 3/5] input-mapper: Remove unnecessary return value + +Since commit ae6d9e35bd, there is a fallback to META_MATCH_IS_BUILTIN, +so the condition for returning FALSE is never met. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/598 +--- + src/backends/meta-input-mapper.c | 15 +++------------ + 1 file changed, 3 insertions(+), 12 deletions(-) + +diff --git a/src/backends/meta-input-mapper.c b/src/backends/meta-input-mapper.c +index acc9b1618..fc4f3bd59 100644 +--- a/src/backends/meta-input-mapper.c ++++ b/src/backends/meta-input-mapper.c +@@ -353,7 +353,7 @@ find_builtin_output (MetaInputMapper *mapper, + return panel != NULL; + } + +-static gboolean ++static void + guess_candidates (MetaInputMapper *mapper, + MetaMapperInputInfo *input, + DeviceCandidates *info) +@@ -387,15 +387,7 @@ guess_candidates (MetaInputMapper *mapper, + find_builtin_output (mapper, &info->candidates[META_MATCH_IS_BUILTIN]); + } + +- if (best < N_OUTPUT_MATCHES) +- { +- info->best = best; +- return TRUE; +- } +- else +- { +- return FALSE; +- } ++ info->best = best; + } + + static void +@@ -408,8 +400,7 @@ mapping_helper_add (MappingHelper *helper, + + info.input = input; + +- if (!guess_candidates (mapper, input, &info)) +- return; ++ guess_candidates (mapper, input, &info); + + for (i = 0; i < helper->device_maps->len; i++) + { +-- +2.21.0 + + +From 4eb025cf36a9118cc496ae9143ee2eb510b6228c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Mon, 27 May 2019 20:22:50 +0000 +Subject: [PATCH 4/5] workspace-manager: Remove unnecessary assignment + +The initialization to -1 is never used, instead the variables are +re-initialized to 0 before the loop that uses them. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/598 +--- + src/core/meta-workspace-manager.c | 2 -- + 1 file changed, 2 deletions(-) + +diff --git a/src/core/meta-workspace-manager.c b/src/core/meta-workspace-manager.c +index af7344709..8e1f03fe8 100644 +--- a/src/core/meta-workspace-manager.c ++++ b/src/core/meta-workspace-manager.c +@@ -600,8 +600,6 @@ meta_workspace_manager_calc_workspace_layout (MetaWorkspaceManager *workspace_ma + + grid = g_new (int, grid_area); + +- current_row = -1; +- current_col = -1; + i = 0; + + switch (workspace_manager->starting_corner) +-- +2.21.0 + + +From a854a337ac8807f310ac2c474f9be290089f79f3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Mon, 27 May 2019 20:43:21 +0000 +Subject: [PATCH 5/5] x11-display: Simplify bell handling + +Since commit 956ab4bd made libcanberra mandatory, we never use +the system bell for handling the `audible-bell` setting. So +instead of reacting to settings changes with the exact same call +to XkbChangeEnabledControls(), just call it once when initializing. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/598 +--- + src/x11/meta-x11-display.c | 39 +++++++------------------------------- + 1 file changed, 7 insertions(+), 32 deletions(-) + +diff --git a/src/x11/meta-x11-display.c b/src/x11/meta-x11-display.c +index 8ce12b994..065ffcdda 100644 +--- a/src/x11/meta-x11-display.c ++++ b/src/x11/meta-x11-display.c +@@ -463,6 +463,13 @@ init_x11_bell (MetaX11Display *x11_display) + &mask); + } + } ++ ++ /* We are playing sounds using libcanberra support, we handle the ++ * bell whether its an audible bell or a visible bell */ ++ XkbChangeEnabledControls (x11_display->xdisplay, ++ XkbUseCoreKbd, ++ XkbAudibleBellMask, ++ 0); + } + + /* +@@ -480,32 +487,6 @@ shutdown_x11_bell (MetaX11Display *x11_display) + XkbAudibleBellMask); + } + +-/* +- * Turns the bell to audible or visual. This tells X what to do, but +- * not Mutter; you will need to set the "visual bell" pref for that. +- */ +-static void +-set_x11_bell_is_audible (MetaX11Display *x11_display, +- gboolean is_audible) +-{ +- /* When we are playing sounds using libcanberra support, we handle the +- * bell whether its an audible bell or a visible bell */ +- gboolean enable_system_bell = FALSE; +- +- XkbChangeEnabledControls (x11_display->xdisplay, +- XkbUseCoreKbd, +- XkbAudibleBellMask, +- enable_system_bell ? XkbAudibleBellMask : 0); +-} +- +-static void +-on_is_audible_changed (MetaBell *bell, +- gboolean is_audible, +- MetaX11Display *x11_display) +-{ +- set_x11_bell_is_audible (x11_display, is_audible); +-} +- + static void + set_desktop_geometry_hint (MetaX11Display *x11_display) + { +@@ -1320,12 +1301,6 @@ meta_x11_display_new (MetaDisplay *display, GError **error) + + init_x11_bell (x11_display); + +- g_signal_connect_object (display->bell, "is-audible-changed", +- G_CALLBACK (on_is_audible_changed), +- x11_display, 0); +- +- set_x11_bell_is_audible (x11_display, meta_prefs_bell_is_audible ()); +- + meta_x11_startup_notification_init (x11_display); + + return x11_display; +-- +2.21.0 + diff --git a/SOURCES/deal-more-gracefully-with-oversized-windows.patch b/SOURCES/deal-more-gracefully-with-oversized-windows.patch new file mode 100644 index 0000000..9a7a36d --- /dev/null +++ b/SOURCES/deal-more-gracefully-with-oversized-windows.patch @@ -0,0 +1,85 @@ +From 575490895047e0709bc84826fe6d6a73028d7bbc Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 12 Mar 2014 02:04:13 +0100 +Subject: [PATCH] constraints: Enforce X11 size limits + +X11 limits windows to a maximum of 32767x32767, enforce that restriction +to keep insanely huge windows from crashing the WM. +--- + src/core/constraints.c | 42 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 42 insertions(+) + +diff --git a/src/core/constraints.c b/src/core/constraints.c +index 117131b15..379372245 100644 +--- a/src/core/constraints.c ++++ b/src/core/constraints.c +@@ -109,6 +109,7 @@ typedef enum + PRIORITY_TITLEBAR_VISIBLE = 4, + PRIORITY_PARTIALLY_VISIBLE_ON_WORKAREA = 4, + PRIORITY_CUSTOM_RULE = 4, ++ PRIORITY_XLIMITS = 4, + PRIORITY_MAXIMUM = 4 /* Dummy value used for loop end = max(all priorities) */ + } ConstraintPriority; + +@@ -201,6 +202,10 @@ static gboolean constrain_partially_onscreen (MetaWindow *window, + ConstraintInfo *info, + ConstraintPriority priority, + gboolean check_only); ++static gboolean constrain_xlimits (MetaWindow *window, ++ ConstraintInfo *info, ++ ConstraintPriority priority, ++ gboolean check_only); + + static void setup_constraint_info (ConstraintInfo *info, + MetaWindow *window, +@@ -236,6 +241,7 @@ static const Constraint all_constraints[] = { + {constrain_fully_onscreen, "constrain_fully_onscreen"}, + {constrain_titlebar_visible, "constrain_titlebar_visible"}, + {constrain_partially_onscreen, "constrain_partially_onscreen"}, ++ {constrain_xlimits, "constrain_xlimits"}, + {NULL, NULL} + }; + +@@ -1780,3 +1786,39 @@ constrain_partially_onscreen (MetaWindow *window, + + return retval; + } ++ ++ ++#define MAX_WINDOW_SIZE 32767 ++ ++static gboolean ++constrain_xlimits (MetaWindow *window, ++ ConstraintInfo *info, ++ ConstraintPriority priority, ++ gboolean check_only) ++{ ++ int max_w, max_h; ++ gboolean constraint_already_satisfied; ++ ++ if (priority > PRIORITY_XLIMITS) ++ return TRUE; ++ ++ max_w = max_h = MAX_WINDOW_SIZE; ++ ++ if (window->frame) ++ { ++ MetaFrameBorders borders; ++ meta_frame_calc_borders (window->frame, &borders); ++ ++ max_w -= (borders.total.left + borders.total.right); ++ max_h -= (borders.total.top + borders.total.bottom); ++ } ++ ++ constraint_already_satisfied = info->current.width < max_w && info->current.height < max_h; ++ if (check_only || constraint_already_satisfied) ++ return constraint_already_satisfied; ++ ++ info->current.width = MIN (info->current.width, max_w); ++ info->current.height = MIN (info->current.height, max_h); ++ ++ return TRUE; ++} +-- +2.21.0 + diff --git a/SOURCES/fix-text-selection-drawing.patch b/SOURCES/fix-text-selection-drawing.patch new file mode 100644 index 0000000..11554aa --- /dev/null +++ b/SOURCES/fix-text-selection-drawing.patch @@ -0,0 +1,138 @@ +From 30d6e3abe2a0251b11513d66d15a59cd0705a828 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Mon, 27 May 2019 17:48:41 +0000 +Subject: [PATCH 1/2] clutter-text: Fix selection color drawing + +Commit cabcad185 removed the call to cogl_set_source_color4ub() before +cogl_fill_path(), so instead of the previously assigned selection color, +the background is drawn with the last set source. + +In order to honour the newly added framebuffer parameter and still apply +the correct color, switch from cogl_fill_path() to the (deprecated!) +cogl_framebuffer_fill_path() method. + +https://gitlab.gnome.org/GNOME/mutter/issues/494 +--- + clutter/clutter/clutter-text.c | 11 ++++++++++- + 1 file changed, 10 insertions(+), 1 deletion(-) + +diff --git a/clutter/clutter/clutter-text.c b/clutter/clutter/clutter-text.c +index fb9d926df..000bbbbd4 100644 +--- a/clutter/clutter/clutter-text.c ++++ b/clutter/clutter/clutter-text.c +@@ -1975,6 +1975,7 @@ selection_paint (ClutterText *self, + else + { + /* Paint selection background first */ ++ CoglPipeline *color_pipeline = cogl_pipeline_copy (default_color_pipeline); + PangoLayout *layout = clutter_text_get_layout (self); + CoglPath *selection_path = cogl_path_new (); + CoglColor cogl_color = { 0, }; +@@ -1987,11 +1988,19 @@ selection_paint (ClutterText *self, + else + color = &priv->text_color; + ++ cogl_color_init_from_4ub (&cogl_color, ++ color->red, ++ color->green, ++ color->blue, ++ paint_opacity * color->alpha / 255); ++ cogl_color_premultiply (&cogl_color); ++ cogl_pipeline_set_color (color_pipeline, &cogl_color); ++ + clutter_text_foreach_selection_rectangle_prescaled (self, + add_selection_rectangle_to_path, + selection_path); + +- cogl_path_fill (selection_path); ++ cogl_framebuffer_fill_path (fb, color_pipeline, selection_path); + + /* Paint selected text */ + cogl_framebuffer_push_path_clip (fb, selection_path); +-- +2.21.0 + + +From 13a1624c1050c91cd4d8a298f7a10fafe56fe9e5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Mon, 27 May 2019 22:40:47 +0000 +Subject: [PATCH 2/2] cogl-path: Undeprecate framebuffer functions + +It looks like deprecating the functions with explicit framebuffer/pipeline +arguments made it to (cogl) master by mistake: + +https://mail.gnome.org/archives/clutter-list/2016-April/msg00008.html + +We now use one of them, so this is a good time to undeprecate the lot. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/597 +--- + cogl/cogl-path/cogl-path-functions.h | 6 ------ + cogl/cogl-path/cogl-path.c | 3 --- + 2 files changed, 9 deletions(-) + +diff --git a/cogl/cogl-path/cogl-path-functions.h b/cogl/cogl-path/cogl-path-functions.h +index d4ef328d2..318fed028 100644 +--- a/cogl/cogl-path/cogl-path-functions.h ++++ b/cogl/cogl-path/cogl-path-functions.h +@@ -460,9 +460,7 @@ cogl_path_fill (CoglPath *path); + * use while filling a path. + * + * Stability: unstable +- * Deprecated: 1.16: Use cogl_path_fill() instead + */ +-COGL_DEPRECATED_FOR (cogl_path_fill) + void + cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, +@@ -492,9 +490,7 @@ cogl_path_stroke (CoglPath *path); + * regardless of the current transformation matrix. + * + * Stability: unstable +- * Deprecated: 1.16: Use cogl_path_stroke() instead + */ +-COGL_DEPRECATED_FOR (cogl_path_stroke) + void + cogl_framebuffer_stroke_path (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, +@@ -529,9 +525,7 @@ cogl_framebuffer_push_path_clip (CoglFramebuffer *framebuffer, + * + * Since: 1.8 + * Stability: Unstable +- * Deprecated: 1.16: Use cogl_framebuffer_push_path_clip() instead + */ +-COGL_DEPRECATED_FOR (cogl_framebuffer_push_path_clip) + void + cogl_clip_push_from_path (CoglPath *path); + +diff --git a/cogl/cogl-path/cogl-path.c b/cogl/cogl-path/cogl-path.c +index 4d86c6fb5..8774406f8 100644 +--- a/cogl/cogl-path/cogl-path.c ++++ b/cogl/cogl-path/cogl-path.c +@@ -1504,7 +1504,6 @@ cogl_framebuffer_push_path_clip (CoglFramebuffer *framebuffer, + COGL_FRAMEBUFFER_STATE_CLIP; + } + +-/* XXX: deprecated */ + void + cogl_clip_push_from_path (CoglPath *path) + { +@@ -1575,7 +1574,6 @@ _cogl_path_build_stroke_attribute_buffer (CoglPath *path) + data->stroke_n_attributes = n_attributes; + } + +-/* XXX: deprecated */ + void + cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, +@@ -1588,7 +1586,6 @@ cogl_framebuffer_fill_path (CoglFramebuffer *framebuffer, + _cogl_path_fill_nodes (path, framebuffer, pipeline, 0 /* flags */); + } + +-/* XXX: deprecated */ + void + cogl_framebuffer_stroke_path (CoglFramebuffer *framebuffer, + CoglPipeline *pipeline, +-- +2.21.0 + diff --git a/SOURCES/handle-hotplug-better.patch b/SOURCES/handle-hotplug-better.patch new file mode 100644 index 0000000..57668d9 --- /dev/null +++ b/SOURCES/handle-hotplug-better.patch @@ -0,0 +1,614 @@ +From d442ef48412e3dc1b24a9f97b02ee3383404d501 Mon Sep 17 00:00:00 2001 +From: Emil Velikov +Date: Wed, 12 Jun 2019 16:58:54 +0000 +Subject: [PATCH 1/8] renderer/native: add missing eglTerminate in EGLDevice + error path +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Currently the EGLDevice code gets the display and calls eglInitialize. +As a follow-up it checks the required EGL extensions - technically it +could check the EGL device extensions earlier. + +In either case, eglTerminate is missing. Thus the connection to the +display was still bound. + +This was highlighted with Mesa commit d6edccee8da ("egl: add +EGL_platform_device support") + amdgpu. + +In that case, since the eglTerminate is missing, we end up reusing the +underlying amdgpu_device due to some caching in libdrm_amdgpu. The +latter in itself being a good solution since it allows buffer sharing +across primary and render node of the same device. + +Note: we should really get this in branches all the way back to 3.30. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/619 + +Fixes: 934184e23 ("MetaRendererNative: Add EGLDevice based rendering support") +Cc: Jonas Ådahl +Signed-off-by: Emil Velikov + + +(cherry picked from commit 9213574870faee7fe40609791fc48f4b44f861c0) +--- + src/backends/native/meta-renderer-native.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c +index dbfc97aae..207b654fa 100644 +--- a/src/backends/native/meta-renderer-native.c ++++ b/src/backends/native/meta-renderer-native.c +@@ -4038,6 +4038,7 @@ create_renderer_gpu_data_egl_device (MetaRendererNative *renderer_native, + G_IO_ERROR_FAILED, + "Missing EGL extensions required for EGLDevice renderer: %s", + missing_extensions_str); ++ meta_egl_terminate (egl, egl_display, NULL); + g_free (missing_extensions_str); + g_free (missing_extensions); + return NULL; +-- +2.24.1 + + +From e18dfc888343585d21b3f64568571009c4967a95 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Mon, 17 Jun 2019 18:18:12 +0200 +Subject: [PATCH 2/8] renderer/native: Use g_set_error() instead of + _cogl_set_error() + +It's even a GError, so lets use the proper API. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/622 +(cherry picked from commit 1efb32d3000ca06ee3cfcc146dc812866d243619) +--- + src/backends/native/meta-renderer-native.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c +index 207b654fa..e7aa6f389 100644 +--- a/src/backends/native/meta-renderer-native.c ++++ b/src/backends/native/meta-renderer-native.c +@@ -1277,7 +1277,7 @@ meta_renderer_native_egl_context_created (CoglDisplay *cogl_display, + cogl_display_egl->dummy_surface, + cogl_display_egl->egl_context)) + { +- _cogl_set_error (error, COGL_WINSYS_ERROR, ++ g_set_error (error, COGL_WINSYS_ERROR, + COGL_WINSYS_ERROR_CREATE_CONTEXT, + "Failed to make context current"); + return FALSE; +-- +2.24.1 + + +From 1947a81db93624d57471ce1edf5548c7774c3569 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Mon, 17 Jun 2019 18:18:42 +0200 +Subject: [PATCH 3/8] renderer/native: Make sure we're not destroying an active + EGLSurface + +When making a new surface/context pair current, mesa may want to flush +the old context. Make sure we don't try to flush any freed memory by +unmaking a surface/context pair current before freeing it. + +Not doing this results in the following valgrind warnings: + +==15986== Invalid read of size 8 +==15986== at 0x69A6D80: dri_flush_front_buffer (gbm_dri.c:92) +==15986== by 0x1750D458: intel_flush_front (brw_context.c:251) +==15986== by 0x1750D4BB: intel_glFlush (brw_context.c:296) +==15986== by 0x1739D8DD: dri2_make_current (egl_dri2.c:1461) +==15986== by 0x17393A3A: eglMakeCurrent (eglapi.c:869) +==15986== by 0x54381FB: InternalMakeCurrentVendor (in /home/jonas/Dev/gnome/install/lib/libEGL.so.1.1.0) +==15986== by 0x5438515: eglMakeCurrent (in /home/jonas/Dev/gnome/install/lib/libEGL.so.1.1.0) +==15986== by 0x522A782: _cogl_winsys_egl_make_current (cogl-winsys-egl.c:303) +==15986== by 0x49B64C8: meta_renderer_native_create_view (meta-renderer-native.c:3076) +==15986== by 0x48D26E7: meta_renderer_create_view (meta-renderer.c:78) +==15986== by 0x48D277A: meta_renderer_rebuild_views (meta-renderer.c:111) +==15986== by 0x49BF46E: meta_stage_native_rebuild_views (meta-stage-native.c:142) +==15986== Address 0x1b076600 is 0 bytes inside a block of size 48 free'd +==15986== at 0x4839A0C: free (vg_replace_malloc.c:540) +==15986== by 0x49B59F3: meta_renderer_native_release_onscreen (meta-renderer-native.c:2651) +==15986== by 0x5211441: _cogl_onscreen_free (cogl-onscreen.c:167) +==15986== by 0x5210D81: _cogl_object_onscreen_indirect_free (cogl-onscreen.c:51) +==15986== by 0x51D0066: _cogl_object_default_unref (cogl-object.c:103) +==15986== by 0x520F989: _cogl_framebuffer_unref (cogl-framebuffer.c:1814) +==15986== by 0x51D00B1: cogl_object_unref (cogl-object.c:115) +==15986== by 0x536F3C7: clutter_stage_view_dispose (clutter-stage-view.c:304) +==15986== by 0x4B7DAF2: g_object_unref (gobject.c:3309) +==15986== by 0x4A9596C: g_list_foreach (glist.c:1013) +==15986== by 0x4A9599A: g_list_free_full (glist.c:223) +==15986== by 0x48D2737: meta_renderer_rebuild_views (meta-renderer.c:100) +==15986== Block was alloc'd at +==15986== at 0x483AB1A: calloc (vg_replace_malloc.c:762) +==15986== by 0x69A76B2: gbm_dri_surface_create (gbm_dri.c:1252) +==15986== by 0x69A6BFE: gbm_surface_create (gbm.c:600) +==15986== by 0x49B4E29: meta_renderer_native_create_surface_gbm (meta-renderer-native.c:2221) +==15986== by 0x49B57DB: meta_onscreen_native_allocate (meta-renderer-native.c:2569) +==15986== by 0x49B6423: meta_renderer_native_create_view (meta-renderer-native.c:3062) +==15986== by 0x48D26E7: meta_renderer_create_view (meta-renderer.c:78) +==15986== by 0x48D277A: meta_renderer_rebuild_views (meta-renderer.c:111) +==15986== by 0x49BF46E: meta_stage_native_rebuild_views (meta-stage-native.c:142) +==15986== by 0x49A75B5: meta_backend_native_update_screen_size (meta-backend-native.c:520) +==15986== by 0x48B01BB: meta_backend_sync_screen_size (meta-backend.c:224) +==15986== by 0x48B09B7: meta_backend_real_post_init (meta-backend.c:501) + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/622 +(cherry picked from commit 56ddaaa3809240a357b5e19b5789d1aa49aaecc3) +--- + src/backends/native/meta-renderer-native.c | 13 +++++++++++++ + 1 file changed, 13 insertions(+) + +diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c +index e7aa6f389..b7bc3121a 100644 +--- a/src/backends/native/meta-renderer-native.c ++++ b/src/backends/native/meta-renderer-native.c +@@ -3040,6 +3040,8 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen) + { + CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); + CoglContext *cogl_context = framebuffer->context; ++ CoglDisplay *cogl_display = cogl_context_get_display (cogl_context); ++ CoglDisplayEGL *cogl_display_egl = cogl_display->winsys; + CoglRenderer *cogl_renderer = cogl_context->display->renderer; + CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; + CoglOnscreenEGL *onscreen_egl = onscreen->winsys; +@@ -3052,6 +3054,17 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen) + + onscreen_native = onscreen_egl->platform; + ++ if (onscreen_egl->egl_surface != EGL_NO_SURFACE && ++ (cogl_display_egl->current_draw_surface == onscreen_egl->egl_surface || ++ cogl_display_egl->current_read_surface == onscreen_egl->egl_surface)) ++ { ++ if (!_cogl_winsys_egl_make_current (cogl_display, ++ cogl_display_egl->dummy_surface, ++ cogl_display_egl->dummy_surface, ++ cogl_display_egl->egl_context)) ++ g_warning ("Failed to clear current context"); ++ } ++ + g_list_free_full (onscreen_native->pending_page_flip_retries, + (GDestroyNotify) retry_page_flip_data_free); + if (onscreen_native->retry_page_flips_source) +-- +2.24.1 + + +From 60551e5e6f984a7ed3ba3339f027ed7b37f802c4 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Mon, 17 Jun 2019 19:16:12 +0200 +Subject: [PATCH 4/8] renderer/native: Fix EGLSurface destruction order + +Make sure to destroy the EGL surface after releasing held buffers, +otherwise we'll get the following valgrind warnings: + +==24016== Invalid read of size 8 +==24016== at 0x1739943F: release_buffer (platform_drm.c:73) +==24016== by 0x49AC355: meta_drm_buffer_gbm_finalize (meta-drm-buffer-gbm.c:213) +==24016== by 0x4B75B61: g_object_unref (gobject.c:3346) +==24016== by 0x49B4B41: free_current_bo (meta-renderer-native.c:991) +==24016== by 0x49B816F: meta_renderer_native_release_onscreen (meta-renderer-native.c:2971) +==24016== by 0x5209441: _cogl_onscreen_free (cogl-onscreen.c:167) +==24016== by 0x5208D81: _cogl_object_onscreen_indirect_free (cogl-onscreen.c:51) +==24016== by 0x51C8066: _cogl_object_default_unref (cogl-object.c:103) +==24016== by 0x5207989: _cogl_framebuffer_unref (cogl-framebuffer.c:1814) +==24016== by 0x51C80B1: cogl_object_unref (cogl-object.c:115) +==24016== by 0x53673C7: clutter_stage_view_dispose (clutter-stage-view.c:304) +==24016== by 0x4B75AF2: g_object_unref (gobject.c:3309) +==24016== Address 0x18e742a8 is 536 bytes inside a block of size 784 free'd +==24016== at 0x4839A0C: free (vg_replace_malloc.c:540) +==24016== by 0x17399764: dri2_drm_destroy_surface (platform_drm.c:231) +==24016== by 0x1738550A: eglDestroySurface (eglapi.c:1145) +==24016== by 0x5440286: eglDestroySurface (in /home/jonas/Dev/gnome/install/lib/libEGL.so.1.1.0) +==24016== by 0x49613A5: meta_egl_destroy_surface (meta-egl.c:432) +==24016== by 0x49B80F9: meta_renderer_native_release_onscreen (meta-renderer-native.c:2954) +==24016== by 0x5209441: _cogl_onscreen_free (cogl-onscreen.c:167) +==24016== by 0x5208D81: _cogl_object_onscreen_indirect_free (cogl-onscreen.c:51) +==24016== by 0x51C8066: _cogl_object_default_unref (cogl-object.c:103) +==24016== by 0x5207989: _cogl_framebuffer_unref (cogl-framebuffer.c:1814) +==24016== by 0x51C80B1: cogl_object_unref (cogl-object.c:115) +==24016== by 0x53673C7: clutter_stage_view_dispose (clutter-stage-view.c:304) +==24016== Block was alloc'd at +==24016== at 0x483AB1A: calloc (vg_replace_malloc.c:762) +==24016== by 0x173997AE: dri2_drm_create_window_surface (platform_drm.c:145) +==24016== by 0x17388906: _eglCreateWindowSurfaceCommon (eglapi.c:929) +==24016== by 0x5440197: eglCreateWindowSurface (in /home/jonas/Dev/gnome/install/lib/libEGL.so.1.1.0) +==24016== by 0x49612FF: meta_egl_create_window_surface (meta-egl.c:396) +==24016== by 0x49B752E: meta_renderer_native_create_surface_gbm (meta-renderer-native.c:2538) +==24016== by 0x49B7E6C: meta_onscreen_native_allocate (meta-renderer-native.c:2870) +==24016== by 0x49B8BCF: meta_renderer_native_create_view (meta-renderer-native.c:3387) +==24016== by 0x48D274B: meta_renderer_create_view (meta-renderer.c:78) +==24016== by 0x48D27DE: meta_renderer_rebuild_views (meta-renderer.c:111) +==24016== by 0x49BB4FB: meta_stage_native_rebuild_views (meta-stage-native.c:142) +==24016== by 0x49A733C: meta_backend_native_update_screen_size (meta-backend-native.c:517) + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/622 +(cherry picked from commit d9fb11b04319c00fd89715dd9207fe54e1d18c2d) +--- + src/backends/native/meta-renderer-native.c | 38 +++++++++++++++------- + 1 file changed, 27 insertions(+), 11 deletions(-) + +diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c +index b7bc3121a..62c27c191 100644 +--- a/src/backends/native/meta-renderer-native.c ++++ b/src/backends/native/meta-renderer-native.c +@@ -3035,6 +3035,28 @@ meta_onscreen_native_allocate (CoglOnscreen *onscreen, + return TRUE; + } + ++static void ++destroy_egl_surface (CoglOnscreen *onscreen) ++{ ++ CoglOnscreenEGL *onscreen_egl = onscreen->winsys; ++ ++ if (onscreen_egl->egl_surface != EGL_NO_SURFACE) ++ { ++ MetaOnscreenNative *onscreen_native = onscreen_egl->platform; ++ MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native); ++ CoglFramebuffer *framebuffer = COGL_FRAMEBUFFER (onscreen); ++ CoglContext *cogl_context = framebuffer->context; ++ CoglRenderer *cogl_renderer = cogl_context->display->renderer; ++ CoglRendererEGL *cogl_renderer_egl = cogl_renderer->winsys; ++ ++ meta_egl_destroy_surface (egl, ++ cogl_renderer_egl->edpy, ++ onscreen_egl->egl_surface, ++ NULL); ++ onscreen_egl->egl_surface = EGL_NO_SURFACE; ++ } ++} ++ + static void + meta_renderer_native_release_onscreen (CoglOnscreen *onscreen) + { +@@ -3077,17 +3099,6 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen) + g_source_destroy); + } + +- if (onscreen_egl->egl_surface != EGL_NO_SURFACE) +- { +- MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native); +- +- meta_egl_destroy_surface (egl, +- cogl_renderer_egl->edpy, +- onscreen_egl->egl_surface, +- NULL); +- onscreen_egl->egl_surface = EGL_NO_SURFACE; +- } +- + renderer_gpu_data = + meta_renderer_native_get_gpu_data (onscreen_native->renderer_native, + onscreen_native->render_gpu); +@@ -3100,6 +3111,8 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen) + + free_current_bo (onscreen); + ++ destroy_egl_surface (onscreen); ++ + if (onscreen_native->gbm.surface) + { + gbm_surface_destroy (onscreen_native->gbm.surface); +@@ -3110,6 +3123,9 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen) + case META_RENDERER_NATIVE_MODE_EGL_DEVICE: + release_dumb_fb (&onscreen_native->egl.dumb_fb, + onscreen_native->render_gpu); ++ ++ destroy_egl_surface (onscreen); ++ + if (onscreen_native->egl.stream != EGL_NO_STREAM_KHR) + { + MetaEgl *egl = meta_onscreen_native_get_egl (onscreen_native); +-- +2.24.1 + + +From c447010a23edc03c7a1103b477972ad666c2600f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Wed, 19 Jun 2019 20:55:48 +0200 +Subject: [PATCH 5/8] renderer/native: Remove left-over function declarations + +There are no callers and no definitions of these. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/655 +--- + src/backends/native/meta-renderer-native.h | 12 ------------ + 1 file changed, 12 deletions(-) + +diff --git a/src/backends/native/meta-renderer-native.h b/src/backends/native/meta-renderer-native.h +index a006dcbe7..8468208e1 100644 +--- a/src/backends/native/meta-renderer-native.h ++++ b/src/backends/native/meta-renderer-native.h +@@ -55,18 +55,6 @@ gboolean meta_renderer_native_supports_mirroring (MetaRendererNative *renderer_n + + void meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native); + +-gboolean meta_renderer_native_set_legacy_view_size (MetaRendererNative *renderer_native, +- MetaRendererView *view, +- int width, +- int height, +- GError **error); +- +-void meta_renderer_native_set_ignore_crtc (MetaRendererNative *renderer_native, +- uint32_t id, +- gboolean ignore); +- +-MetaRendererView * meta_renderer_native_create_legacy_view (MetaRendererNative *renderer_native); +- + void meta_renderer_native_finish_frame (MetaRendererNative *renderer_native); + + int64_t meta_renderer_native_get_frame_counter (MetaRendererNative *renderer_native); +-- +2.24.1 + + +From 7f97403d12df19cf936a341cc218743ec339aa0a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Wed, 19 Jun 2019 20:57:14 +0200 +Subject: [PATCH 6/8] renderer/native: Queue mode reset from new rebuild_views + vfunc + +Simplify the call site a bit and make the native renderer know it should +queue mode reset itself when views have been rebuilt. This is done +partly due to more things needing to be dealt with after views have been +rebuilt. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/655 +--- + src/backends/meta-renderer.c | 8 ++++++++ + src/backends/meta-renderer.h | 1 + + src/backends/native/meta-renderer-native.c | 17 ++++++++++++++++- + src/backends/native/meta-renderer-native.h | 2 -- + src/backends/native/meta-stage-native.c | 1 - + 5 files changed, 25 insertions(+), 4 deletions(-) + +diff --git a/src/backends/meta-renderer.c b/src/backends/meta-renderer.c +index 28637437b..87ba9f9f0 100644 +--- a/src/backends/meta-renderer.c ++++ b/src/backends/meta-renderer.c +@@ -90,6 +90,12 @@ meta_renderer_create_view (MetaRenderer *renderer, + */ + void + meta_renderer_rebuild_views (MetaRenderer *renderer) ++{ ++ return META_RENDERER_GET_CLASS (renderer)->rebuild_views (renderer); ++} ++ ++static void ++meta_renderer_real_rebuild_views (MetaRenderer *renderer) + { + MetaRendererPrivate *priv = meta_renderer_get_instance_private (renderer); + MetaBackend *backend = meta_get_backend (); +@@ -181,4 +187,6 @@ meta_renderer_class_init (MetaRendererClass *klass) + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meta_renderer_finalize; ++ ++ klass->rebuild_views = meta_renderer_real_rebuild_views; + } +diff --git a/src/backends/meta-renderer.h b/src/backends/meta-renderer.h +index dae52cb9a..478baee91 100644 +--- a/src/backends/meta-renderer.h ++++ b/src/backends/meta-renderer.h +@@ -43,6 +43,7 @@ struct _MetaRendererClass + CoglRenderer * (* create_cogl_renderer) (MetaRenderer *renderer); + MetaRendererView * (* create_view) (MetaRenderer *renderer, + MetaLogicalMonitor *logical_monitor); ++ void (* rebuild_views) (MetaRenderer *renderer); + }; + + CoglRenderer * meta_renderer_create_cogl_renderer (MetaRenderer *renderer); +diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c +index 62c27c191..70e1c4f9d 100644 +--- a/src/backends/native/meta-renderer-native.c ++++ b/src/backends/native/meta-renderer-native.c +@@ -258,6 +258,9 @@ cogl_pixel_format_from_drm_format (uint32_t drm_format, + CoglPixelFormat *out_format, + CoglTextureComponents *out_components); + ++static void ++meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native); ++ + static MetaBackend * + backend_from_renderer_native (MetaRendererNative *renderer_native) + { +@@ -3186,7 +3189,7 @@ meta_renderer_native_supports_mirroring (MetaRendererNative *renderer_native) + return TRUE; + } + +-void ++static void + meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native) + { + MetaRenderer *renderer = META_RENDERER (renderer_native); +@@ -3552,6 +3555,17 @@ meta_renderer_native_create_view (MetaRenderer *renderer, + return view; + } + ++static void ++meta_renderer_native_rebuild_views (MetaRenderer *renderer) ++{ ++ MetaRendererClass *parent_renderer_class = ++ META_RENDERER_CLASS (meta_renderer_native_parent_class); ++ ++ parent_renderer_class->rebuild_views (renderer); ++ ++ meta_renderer_native_queue_modes_reset (META_RENDERER_NATIVE (renderer)); ++} ++ + void + meta_renderer_native_finish_frame (MetaRendererNative *renderer_native) + { +@@ -4350,6 +4364,7 @@ meta_renderer_native_class_init (MetaRendererNativeClass *klass) + + renderer_class->create_cogl_renderer = meta_renderer_native_create_cogl_renderer; + renderer_class->create_view = meta_renderer_native_create_view; ++ renderer_class->rebuild_views = meta_renderer_native_rebuild_views; + + obj_props[PROP_MONITOR_MANAGER] = + g_param_spec_object ("monitor-manager", +diff --git a/src/backends/native/meta-renderer-native.h b/src/backends/native/meta-renderer-native.h +index 8468208e1..9eecdead1 100644 +--- a/src/backends/native/meta-renderer-native.h ++++ b/src/backends/native/meta-renderer-native.h +@@ -53,8 +53,6 @@ struct gbm_device * meta_gbm_device_from_gpu (MetaGpuKms *gpu_kms); + + gboolean meta_renderer_native_supports_mirroring (MetaRendererNative *renderer_native); + +-void meta_renderer_native_queue_modes_reset (MetaRendererNative *renderer_native); +- + void meta_renderer_native_finish_frame (MetaRendererNative *renderer_native); + + int64_t meta_renderer_native_get_frame_counter (MetaRendererNative *renderer_native); +diff --git a/src/backends/native/meta-stage-native.c b/src/backends/native/meta-stage-native.c +index add3e81fd..9b9c45ef3 100644 +--- a/src/backends/native/meta-stage-native.c ++++ b/src/backends/native/meta-stage-native.c +@@ -140,7 +140,6 @@ meta_stage_native_rebuild_views (MetaStageNative *stage_native) + ClutterActor *stage = meta_backend_get_stage (backend); + + meta_renderer_rebuild_views (renderer); +- meta_renderer_native_queue_modes_reset (META_RENDERER_NATIVE (renderer)); + clutter_stage_update_resource_scales (CLUTTER_STAGE (stage)); + ensure_frame_callbacks (stage_native); + } +-- +2.24.1 + + +From 025054c93e43e8359c9ecafb6edea1eb4b7ad681 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Wed, 19 Jun 2019 21:14:05 +0200 +Subject: [PATCH 7/8] renderer/native: Discard page flip retries when + rebuilding views + +Rebuilding views means we don't care to retry page flip attempts for +previous views, especially since connectors may have been disconnected, +making a page flip retry hit an assert a flipped CRTC has connectors +associated with it. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/655 +--- + src/backends/native/meta-renderer-native.c | 50 +++++++++++++++++----- + 1 file changed, 39 insertions(+), 11 deletions(-) + +diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c +index 70e1c4f9d..3cd01bcb7 100644 +--- a/src/backends/native/meta-renderer-native.c ++++ b/src/backends/native/meta-renderer-native.c +@@ -3060,6 +3060,24 @@ destroy_egl_surface (CoglOnscreen *onscreen) + } + } + ++static void ++discard_onscreen_page_flip_retries (MetaOnscreenNative *onscreen_native) ++{ ++ g_list_free_full (onscreen_native->pending_page_flip_retries, ++ (GDestroyNotify) retry_page_flip_data_free); ++ onscreen_native->pending_page_flip_retries = NULL; ++ ++ if (onscreen_native->retry_page_flips_source) ++ { ++ MetaBackend *backend = ++ backend_from_renderer_native (onscreen_native->renderer_native); ++ ++ meta_backend_thaw_updates (backend); ++ g_clear_pointer (&onscreen_native->retry_page_flips_source, ++ g_source_destroy); ++ } ++} ++ + static void + meta_renderer_native_release_onscreen (CoglOnscreen *onscreen) + { +@@ -3090,17 +3108,7 @@ meta_renderer_native_release_onscreen (CoglOnscreen *onscreen) + g_warning ("Failed to clear current context"); + } + +- g_list_free_full (onscreen_native->pending_page_flip_retries, +- (GDestroyNotify) retry_page_flip_data_free); +- if (onscreen_native->retry_page_flips_source) +- { +- MetaBackend *backend = +- backend_from_renderer_native (onscreen_native->renderer_native); +- +- meta_backend_thaw_updates (backend); +- g_clear_pointer (&onscreen_native->retry_page_flips_source, +- g_source_destroy); +- } ++ discard_onscreen_page_flip_retries (onscreen_native); + + renderer_gpu_data = + meta_renderer_native_get_gpu_data (onscreen_native->renderer_native, +@@ -3555,12 +3563,32 @@ meta_renderer_native_create_view (MetaRenderer *renderer, + return view; + } + ++static void ++discard_page_flip_retries (MetaRenderer *renderer) ++{ ++ GList *l; ++ ++ for (l = meta_renderer_get_views (renderer); l; l = l->next) ++ { ++ ClutterStageView *stage_view = l->data; ++ CoglFramebuffer *framebuffer = ++ clutter_stage_view_get_onscreen (stage_view); ++ CoglOnscreen *onscreen = COGL_ONSCREEN (framebuffer); ++ CoglOnscreenEGL *onscreen_egl = onscreen->winsys; ++ MetaOnscreenNative *onscreen_native = onscreen_egl->platform; ++ ++ discard_onscreen_page_flip_retries (onscreen_native); ++ } ++} ++ + static void + meta_renderer_native_rebuild_views (MetaRenderer *renderer) + { + MetaRendererClass *parent_renderer_class = + META_RENDERER_CLASS (meta_renderer_native_parent_class); + ++ discard_page_flip_retries (renderer); ++ + parent_renderer_class->rebuild_views (renderer); + + meta_renderer_native_queue_modes_reset (META_RENDERER_NATIVE (renderer)); +-- +2.24.1 + + +From f4fdec6003e2cf9fa4b1882e92faf1da64e6052e Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Wed, 27 Nov 2019 17:34:35 +0100 +Subject: [PATCH 8/8] =?UTF-8?q?crtc-kms:=20Ignore=2090=C2=B0=20rotations?= +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +They tend to require special modifiers or won't work at all; ignore +them. +--- + src/backends/native/meta-crtc-kms.c | 4 ---- + 1 file changed, 4 deletions(-) + +diff --git a/src/backends/native/meta-crtc-kms.c b/src/backends/native/meta-crtc-kms.c +index 8c2fbfe3c..8374376d5 100644 +--- a/src/backends/native/meta-crtc-kms.c ++++ b/src/backends/native/meta-crtc-kms.c +@@ -368,12 +368,8 @@ parse_transforms (MetaCrtc *crtc, + + if (strcmp (prop->enums[i].name, "rotate-0") == 0) + transform = META_MONITOR_TRANSFORM_NORMAL; +- else if (strcmp (prop->enums[i].name, "rotate-90") == 0) +- transform = META_MONITOR_TRANSFORM_90; + else if (strcmp (prop->enums[i].name, "rotate-180") == 0) + transform = META_MONITOR_TRANSFORM_180; +- else if (strcmp (prop->enums[i].name, "rotate-270") == 0) +- transform = META_MONITOR_TRANSFORM_270; + + if (transform != -1) + { +-- +2.24.1 + diff --git a/SOURCES/idle-monitor-reset-fix.patch b/SOURCES/idle-monitor-reset-fix.patch new file mode 100644 index 0000000..b67e015 --- /dev/null +++ b/SOURCES/idle-monitor-reset-fix.patch @@ -0,0 +1,128 @@ +From 35333114a991440d671e3642170aa080df45a171 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Mon, 16 Sep 2019 16:17:48 +0200 +Subject: [PATCH 1/3] idle-monitor: Make helper function static + +It wasn't used outside the file, so no reason to not have it static. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/799 +--- + src/backends/meta-idle-monitor-private.h | 1 - + src/backends/meta-idle-monitor.c | 8 ++++---- + 2 files changed, 4 insertions(+), 5 deletions(-) + +diff --git a/src/backends/meta-idle-monitor-private.h b/src/backends/meta-idle-monitor-private.h +index 93948b14b..cc08f8c8e 100644 +--- a/src/backends/meta-idle-monitor-private.h ++++ b/src/backends/meta-idle-monitor-private.h +@@ -54,7 +54,6 @@ struct _MetaIdleMonitorClass + GObjectClass parent_class; + }; + +-void _meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch); + void meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor); + + #endif /* META_IDLE_MONITOR_PRIVATE_H */ +diff --git a/src/backends/meta-idle-monitor.c b/src/backends/meta-idle-monitor.c +index e83d6c778..de1c7e0ba 100644 +--- a/src/backends/meta-idle-monitor.c ++++ b/src/backends/meta-idle-monitor.c +@@ -54,8 +54,8 @@ static GParamSpec *obj_props[PROP_LAST]; + + G_DEFINE_TYPE (MetaIdleMonitor, meta_idle_monitor, G_TYPE_OBJECT) + +-void +-_meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch) ++static void ++meta_idle_monitor_watch_fire (MetaIdleMonitorWatch *watch) + { + MetaIdleMonitor *monitor; + guint id; +@@ -324,7 +324,7 @@ idle_monitor_dispatch_timeout (GSource *source, + if (ready_time > now) + return G_SOURCE_CONTINUE; + +- _meta_idle_monitor_watch_fire (watch); ++ meta_idle_monitor_watch_fire (watch); + g_source_set_ready_time (watch->timeout_source, -1); + + return G_SOURCE_CONTINUE; +@@ -511,7 +511,7 @@ meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor) + + if (watch->timeout_msec == 0) + { +- _meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch); ++ meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch); + } + else + { +-- +2.23.0 + + +From 07276cf94d84489d450c17b7dec5a8075c60440a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Mon, 16 Sep 2019 16:36:05 +0200 +Subject: [PATCH 2/3] idle-monitor: Remove redundant type cast + +No need to type cast a `MetaIdleMonitorWatch *` to a +`MetaIdleMonitorWatch *`. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/799 +--- + src/backends/meta-idle-monitor.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/backends/meta-idle-monitor.c b/src/backends/meta-idle-monitor.c +index de1c7e0ba..e5124abc1 100644 +--- a/src/backends/meta-idle-monitor.c ++++ b/src/backends/meta-idle-monitor.c +@@ -511,7 +511,7 @@ meta_idle_monitor_reset_idletime (MetaIdleMonitor *monitor) + + if (watch->timeout_msec == 0) + { +- meta_idle_monitor_watch_fire ((MetaIdleMonitorWatch *) watch); ++ meta_idle_monitor_watch_fire (watch); + } + else + { +-- +2.23.0 + + +From 73c1f387765ef528c7323e6e7ca3c05899cfcc4a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Mon, 16 Sep 2019 16:36:51 +0200 +Subject: [PATCH 3/3] idle-monitor: Reset timeout before firing watch + +The watch might be removed during firing, meaning the source is +destroyed after returning. Avoid use-after-free by unsetting the timeout +before firing. Returning G_SOURCE_CONTINUE in that case is harmless, as +source is destroyed. + +Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/796 + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/799 +--- + src/backends/meta-idle-monitor.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/src/backends/meta-idle-monitor.c b/src/backends/meta-idle-monitor.c +index e5124abc1..9fa481742 100644 +--- a/src/backends/meta-idle-monitor.c ++++ b/src/backends/meta-idle-monitor.c +@@ -324,9 +324,10 @@ idle_monitor_dispatch_timeout (GSource *source, + if (ready_time > now) + return G_SOURCE_CONTINUE; + +- meta_idle_monitor_watch_fire (watch); + g_source_set_ready_time (watch->timeout_source, -1); + ++ meta_idle_monitor_watch_fire (watch); ++ + return G_SOURCE_CONTINUE; + } + +-- +2.23.0 + diff --git a/SOURCES/inherit-xrandr-metamodes.patch b/SOURCES/inherit-xrandr-metamodes.patch new file mode 100644 index 0000000..9f3f6c9 --- /dev/null +++ b/SOURCES/inherit-xrandr-metamodes.patch @@ -0,0 +1,365 @@ +From 2fd3910c29d2af2a7c64b82f075cd3647d7e4bee Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Mon, 18 Mar 2019 17:08:11 +0100 +Subject: [PATCH 1/2] monitor-config-manager: Use current mode when deriving + current config + +Instead of overriding the existing mode with the preferred mode of the monitor, +use the one already configured. Also use the MetaMonitor API for deriving the +position of the monitor in the screen coordinate space. +--- + src/backends/meta-monitor-config-manager.c | 77 +++++++++++++--------- + 1 file changed, 47 insertions(+), 30 deletions(-) + +diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c +index c09edbe00..a3387aa0f 100644 +--- a/src/backends/meta-monitor-config-manager.c ++++ b/src/backends/meta-monitor-config-manager.c +@@ -592,20 +592,19 @@ create_monitor_config (MetaMonitor *monitor, + } + + static MetaLogicalMonitorConfig * +-create_preferred_logical_monitor_config (MetaMonitorManager *monitor_manager, +- MetaMonitor *monitor, +- int x, +- int y, +- MetaLogicalMonitorConfig *primary_logical_monitor_config, +- MetaLogicalMonitorLayoutMode layout_mode) ++create_logical_monitor_config (MetaMonitorManager *monitor_manager, ++ MetaMonitor *monitor, ++ MetaMonitorMode *mode, ++ int x, ++ int y, ++ MetaLogicalMonitorConfig *primary_logical_monitor_config, ++ MetaLogicalMonitorLayoutMode layout_mode) + { +- MetaMonitorMode *mode; + int width, height; + float scale; + MetaMonitorConfig *monitor_config; + MetaLogicalMonitorConfig *logical_monitor_config; + +- mode = meta_monitor_get_preferred_mode (monitor); + meta_monitor_mode_get_resolution (mode, &width, &height); + + if ((meta_monitor_manager_get_capabilities (monitor_manager) & +@@ -645,22 +644,40 @@ create_preferred_logical_monitor_config (MetaMonitorManager *monitor_ma + } + + static MetaLogicalMonitorConfig * +-create_logical_monitor_config_from_output (MetaMonitorManager *monitor_manager, +- MetaMonitor *monitor, +- MetaLogicalMonitorConfig *primary_logical_monitor_config, +- MetaLogicalMonitorLayoutMode layout_mode) ++create_preferred_logical_monitor_config (MetaMonitorManager *monitor_manager, ++ MetaMonitor *monitor, ++ int x, ++ int y, ++ MetaLogicalMonitorConfig *primary_logical_monitor_config, ++ MetaLogicalMonitorLayoutMode layout_mode) + { +- MetaOutput *output; +- MetaCrtc *crtc; ++ return create_logical_monitor_config (monitor_manager, ++ monitor, ++ meta_monitor_get_preferred_mode (monitor), ++ x, y, ++ primary_logical_monitor_config, ++ layout_mode); ++} + +- output = meta_monitor_get_main_output (monitor); +- crtc = meta_output_get_assigned_crtc (output); +- return create_preferred_logical_monitor_config (monitor_manager, +- monitor, +- crtc->rect.x, +- crtc->rect.y, +- primary_logical_monitor_config, +- layout_mode); ++static MetaLogicalMonitorConfig * ++create_logical_monitor_config_from_monitor (MetaMonitorManager *monitor_manager, ++ MetaMonitor *monitor, ++ MetaLogicalMonitorConfig *primary_logical_monitor_config, ++ MetaLogicalMonitorLayoutMode layout_mode) ++{ ++ MetaRectangle monitor_layout; ++ MetaMonitorMode *mode; ++ ++ meta_monitor_derive_layout (monitor, &monitor_layout); ++ mode = meta_monitor_get_current_mode (monitor); ++ ++ return create_logical_monitor_config (monitor_manager, ++ monitor, ++ mode, ++ monitor_layout.x, ++ monitor_layout.y, ++ primary_logical_monitor_config, ++ layout_mode); + } + + MetaMonitorsConfig * +@@ -688,10 +705,10 @@ meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_man + layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager); + + primary_logical_monitor_config = +- create_logical_monitor_config_from_output (monitor_manager, +- primary_monitor, +- NULL, +- layout_mode); ++ create_logical_monitor_config_from_monitor (monitor_manager, ++ primary_monitor, ++ NULL, ++ layout_mode); + + primary_logical_monitor_config->is_primary = TRUE; + logical_monitor_configs = g_list_append (NULL, +@@ -710,10 +727,10 @@ meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_man + continue; + + logical_monitor_config = +- create_logical_monitor_config_from_output (monitor_manager, +- monitor, +- primary_logical_monitor_config, +- layout_mode); ++ create_logical_monitor_config_from_monitor (monitor_manager, ++ monitor, ++ primary_logical_monitor_config, ++ layout_mode); + + logical_monitor_configs = g_list_append (logical_monitor_configs, + logical_monitor_config); +-- +2.21.0 + + +From d8c34e4cd7e500567e72e0f219295d7c2162dcf3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Mon, 18 Mar 2019 17:10:37 +0100 +Subject: [PATCH 2/2] monitor-manager: Don't try to derive current config on + non-X11 + +This commit also reworks the initial config state reading some. Appart from +avoiding trying to inherit from backends where it doesn't make sense, it does +the following changes: + + * Replace the name "initial" with "inherited", as the initial config in the + context of monitor management is the one used initialization. E.g. if there is + a applicable configuration in monitors.xml, the initial config is taken from + there. + + * Don't make "_create_()" functions have side effects. Previously + meta_monitor_config_manager_create_initial() also set state on the config + manager object. Instead, add a meta_monitor_config_manager_ensure_inherited() + and meta_monitor_manager_get_inherited_config() function to make things more + explicit. + + * Don't recreate "is-applicable" logic, just use the existing helper. +--- + src/backends/meta-monitor-config-manager.c | 39 +++++++++++-------- + src/backends/meta-monitor-config-manager.h | 5 +++ + src/backends/meta-monitor-manager-private.h | 4 +- + src/backends/meta-monitor-manager.c | 32 ++++++++------- + .../x11/meta-monitor-manager-xrandr.c | 3 +- + 5 files changed, 49 insertions(+), 34 deletions(-) + +diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c +index a3387aa0f..bc1a39db8 100644 +--- a/src/backends/meta-monitor-config-manager.c ++++ b/src/backends/meta-monitor-config-manager.c +@@ -42,7 +42,7 @@ struct _MetaMonitorConfigManager + MetaMonitorConfigStore *config_store; + + MetaMonitorsConfig *current_config; +- MetaMonitorsConfig *initial_config; ++ MetaMonitorsConfig *inherited_config; + GQueue config_history; + }; + +@@ -680,11 +680,10 @@ create_logical_monitor_config_from_monitor (MetaMonitorManager *monito + layout_mode); + } + +-MetaMonitorsConfig * +-meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_manager) ++static MetaMonitorsConfig * ++meta_monitor_config_manager_derive_current (MetaMonitorConfigManager *config_manager) + { + MetaMonitorManager *monitor_manager = config_manager->monitor_manager; +- MetaMonitorsConfig *initial_config; + GList *logical_monitor_configs; + MetaMonitor *primary_monitor; + MetaLogicalMonitorLayoutMode layout_mode; +@@ -692,12 +691,6 @@ meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_man + GList *monitors; + GList *l; + +- if (config_manager->initial_config != NULL) +- return g_object_ref (config_manager->initial_config); +- +- if (meta_monitor_config_store_get_config_count (config_manager->config_store) > 0) +- return NULL; +- + primary_monitor = find_primary_monitor (monitor_manager); + if (!primary_monitor || !meta_monitor_is_active (primary_monitor)) + return NULL; +@@ -736,14 +729,26 @@ meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_man + logical_monitor_config); + } + +- initial_config = meta_monitors_config_new (monitor_manager, +- logical_monitor_configs, +- layout_mode, +- META_MONITORS_CONFIG_FLAG_NONE); ++ return meta_monitors_config_new (monitor_manager, ++ logical_monitor_configs, ++ layout_mode, ++ META_MONITORS_CONFIG_FLAG_NONE); ++} ++ ++void ++meta_monitor_config_manager_ensure_inherited_config (MetaMonitorConfigManager *config_manager) ++{ ++ if (config_manager->inherited_config) ++ return; + +- config_manager->initial_config = g_object_ref (initial_config); ++ config_manager->inherited_config = ++ meta_monitor_config_manager_derive_current (config_manager); ++} + +- return initial_config; ++MetaMonitorsConfig * ++meta_monitor_config_manager_get_inherited_config (MetaMonitorConfigManager *config_manager) ++{ ++ return config_manager->inherited_config; + } + + MetaMonitorsConfig * +@@ -1282,7 +1287,7 @@ meta_monitor_config_manager_dispose (GObject *object) + META_MONITOR_CONFIG_MANAGER (object); + + g_clear_object (&config_manager->current_config); +- g_clear_object (&config_manager->initial_config); ++ g_clear_object (&config_manager->inherited_config); + meta_monitor_config_manager_clear_history (config_manager); + + G_OBJECT_CLASS (meta_monitor_config_manager_parent_class)->dispose (object); +diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h +index 409611bb0..bb847b96e 100644 +--- a/src/backends/meta-monitor-config-manager.h ++++ b/src/backends/meta-monitor-config-manager.h +@@ -96,6 +96,11 @@ MetaMonitorsConfig * meta_monitor_config_manager_get_stored (MetaMonitorConfigMa + + META_EXPORT_TEST + MetaMonitorsConfig * meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_manager); ++ ++void meta_monitor_config_manager_ensure_inherited_config (MetaMonitorConfigManager *config_manager); ++ ++MetaMonitorsConfig * meta_monitor_config_manager_get_inherited_config (MetaMonitorConfigManager *config_manager); ++ + META_EXPORT_TEST + MetaMonitorsConfig * meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_manager); + +diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h +index cdb8f4209..223b5dfbd 100644 +--- a/src/backends/meta-monitor-manager-private.h ++++ b/src/backends/meta-monitor-manager-private.h +@@ -44,7 +44,8 @@ typedef enum _MetaMonitorManagerCapability + META_MONITOR_MANAGER_CAPABILITY_NONE = 0, + META_MONITOR_MANAGER_CAPABILITY_MIRRORING = (1 << 0), + META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE = (1 << 1), +- META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED = (1 << 2) ++ META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED = (1 << 2), ++ META_MONITOR_MANAGER_CAPABILITY_CAN_DERIVE_CURRENT = (1 << 3), + } MetaMonitorManagerCapability; + + /* Equivalent to the 'method' enum in org.gnome.Mutter.DisplayConfig */ +@@ -133,6 +134,7 @@ struct _MetaMonitorManager + int persistent_timeout_id; + + MetaMonitorConfigManager *config_manager; ++ MetaMonitorsConfig *initial_config; + + GnomePnpIds *pnp_ids; + +diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c +index bb4b44188..076dca8cb 100644 +--- a/src/backends/meta-monitor-manager.c ++++ b/src/backends/meta-monitor-manager.c +@@ -531,14 +531,21 @@ should_use_stored_config (MetaMonitorManager *manager) + !meta_monitor_manager_has_hotplug_mode_update (manager)); + } + ++static gboolean ++can_derive_current_config (MetaMonitorManager *manager) ++{ ++ MetaMonitorManagerCapability capabilities; ++ ++ capabilities = meta_monitor_manager_get_capabilities (manager); ++ return !!(capabilities & META_MONITOR_MANAGER_CAPABILITY_CAN_DERIVE_CURRENT); ++} ++ + MetaMonitorsConfig * + meta_monitor_manager_ensure_configured (MetaMonitorManager *manager) + { +- g_autoptr (MetaMonitorsConfig) initial_config = NULL; + MetaMonitorsConfig *config = NULL; + GError *error = NULL; + gboolean use_stored_config; +- MetaMonitorsConfigKey *current_state_key; + MetaMonitorsConfigMethod method; + MetaMonitorsConfigMethod fallback_method = + META_MONITORS_CONFIG_METHOD_TEMPORARY; +@@ -549,17 +556,8 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager) + else + method = META_MONITORS_CONFIG_METHOD_TEMPORARY; + +- initial_config = meta_monitor_config_manager_create_initial (manager->config_manager); +- +- if (initial_config) +- { +- current_state_key = meta_create_monitors_config_key_for_current_state (manager); +- +- /* don't ever reuse initial configuration, if the monitor topology changed +- */ +- if (current_state_key && !meta_monitors_config_key_equal (current_state_key, initial_config->key)) +- g_clear_object (&initial_config); +- } ++ if (can_derive_current_config (manager)) ++ meta_monitor_config_manager_ensure_inherited_config (manager->config_manager); + + if (use_stored_config) + { +@@ -628,9 +626,13 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager) + g_clear_object (&config); + } + +- config = g_steal_pointer (&initial_config); +- if (config) ++ config = ++ meta_monitor_config_manager_get_inherited_config (manager->config_manager); ++ if (config && ++ meta_monitor_manager_is_config_complete (manager, config)) + { ++ config = g_object_ref (config); ++ + if (!meta_monitor_manager_apply_monitors_config (manager, + config, + method, +diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c +index d60f00325..b8d6342b6 100644 +--- a/src/backends/x11/meta-monitor-manager-xrandr.c ++++ b/src/backends/x11/meta-monitor-manager-xrandr.c +@@ -999,7 +999,8 @@ static MetaMonitorManagerCapability + meta_monitor_manager_xrandr_get_capabilities (MetaMonitorManager *manager) + { + return (META_MONITOR_MANAGER_CAPABILITY_MIRRORING | +- META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED); ++ META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED | ++ META_MONITOR_MANAGER_CAPABILITY_CAN_DERIVE_CURRENT); + } + + static gboolean +-- +2.21.0 + diff --git a/SOURCES/input-after-long-idle-fix.patch b/SOURCES/input-after-long-idle-fix.patch new file mode 100644 index 0000000..9c4c2a6 --- /dev/null +++ b/SOURCES/input-after-long-idle-fix.patch @@ -0,0 +1,374 @@ +From 05bca153bb92c5daa5b961214ff7f80af88cb7cf Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Thu, 24 Oct 2019 21:19:36 +0200 +Subject: [PATCH 1/2] display: Move finishing of touch sequence to the backend + +We need to manipulate an X11 grab when a touch sequence ends; move that +logic to where it belongs - in the X11 backend. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/886 +--- + src/backends/meta-backend-private.h | 16 ++++++++++++ + src/backends/meta-backend.c | 14 +++++++++++ + src/backends/x11/meta-backend-x11.c | 23 +++++++++++++++++ + src/core/display.c | 33 +++++++++++-------------- + src/core/meta-gesture-tracker-private.h | 9 +------ + 5 files changed, 69 insertions(+), 26 deletions(-) + +diff --git a/src/backends/meta-backend-private.h b/src/backends/meta-backend-private.h +index 7eba1806b..81ec81e5f 100644 +--- a/src/backends/meta-backend-private.h ++++ b/src/backends/meta-backend-private.h +@@ -49,6 +49,14 @@ + #define DEFAULT_XKB_RULES_FILE "evdev" + #define DEFAULT_XKB_MODEL "pc105+inet" + ++typedef enum ++{ ++ META_SEQUENCE_NONE, ++ META_SEQUENCE_ACCEPTED, ++ META_SEQUENCE_REJECTED, ++ META_SEQUENCE_PENDING_END ++} MetaSequenceState; ++ + struct _MetaBackendClass + { + GObjectClass parent_class; +@@ -71,6 +79,10 @@ struct _MetaBackendClass + int device_id, + uint32_t timestamp); + ++ void (* finish_touch_sequence) (MetaBackend *backend, ++ ClutterEventSequence *sequence, ++ MetaSequenceState state); ++ + void (* warp_pointer) (MetaBackend *backend, + int x, + int y); +@@ -135,6 +147,10 @@ gboolean meta_backend_ungrab_device (MetaBackend *backend, + int device_id, + uint32_t timestamp); + ++void meta_backend_finish_touch_sequence (MetaBackend *backend, ++ ClutterEventSequence *sequence, ++ MetaSequenceState state); ++ + void meta_backend_warp_pointer (MetaBackend *backend, + int x, + int y); +diff --git a/src/backends/meta-backend.c b/src/backends/meta-backend.c +index c980cf150..bb7d66f2a 100644 +--- a/src/backends/meta-backend.c ++++ b/src/backends/meta-backend.c +@@ -1086,6 +1086,20 @@ meta_backend_ungrab_device (MetaBackend *backend, + return META_BACKEND_GET_CLASS (backend)->ungrab_device (backend, device_id, timestamp); + } + ++/** ++ * meta_backend_finish_touch_sequence: (skip) ++ */ ++void ++meta_backend_finish_touch_sequence (MetaBackend *backend, ++ ClutterEventSequence *sequence, ++ MetaSequenceState state) ++{ ++ if (META_BACKEND_GET_CLASS (backend)->finish_touch_sequence) ++ META_BACKEND_GET_CLASS (backend)->finish_touch_sequence (backend, ++ sequence, ++ state); ++} ++ + /** + * meta_backend_warp_pointer: (skip) + */ +diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c +index c10365f9d..cdefa50a9 100644 +--- a/src/backends/x11/meta-backend-x11.c ++++ b/src/backends/x11/meta-backend-x11.c +@@ -591,6 +591,28 @@ meta_backend_x11_ungrab_device (MetaBackend *backend, + return (ret == Success); + } + ++static void ++meta_backend_x11_finish_touch_sequence (MetaBackend *backend, ++ ClutterEventSequence *sequence, ++ MetaSequenceState state) ++{ ++ MetaBackendX11 *x11 = META_BACKEND_X11 (backend); ++ MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); ++ int event_mode; ++ ++ if (state == META_SEQUENCE_ACCEPTED) ++ event_mode = XIAcceptTouch; ++ else if (state == META_SEQUENCE_REJECTED) ++ event_mode = XIRejectTouch; ++ else ++ g_return_if_reached (); ++ ++ XIAllowTouchEvents (priv->xdisplay, ++ META_VIRTUAL_CORE_POINTER_ID, ++ clutter_x11_event_sequence_get_touch_detail (sequence), ++ DefaultRootWindow (priv->xdisplay), event_mode); ++} ++ + static void + meta_backend_x11_warp_pointer (MetaBackend *backend, + int x, +@@ -776,6 +798,7 @@ meta_backend_x11_class_init (MetaBackendX11Class *klass) + backend_class->post_init = meta_backend_x11_post_init; + backend_class->grab_device = meta_backend_x11_grab_device; + backend_class->ungrab_device = meta_backend_x11_ungrab_device; ++ backend_class->finish_touch_sequence = meta_backend_x11_finish_touch_sequence; + backend_class->warp_pointer = meta_backend_x11_warp_pointer; + backend_class->get_current_logical_monitor = meta_backend_x11_get_current_logical_monitor; + backend_class->get_keymap = meta_backend_x11_get_keymap; +diff --git a/src/core/display.c b/src/core/display.c +index 4c8907f40..eb7dc43b6 100644 +--- a/src/core/display.c ++++ b/src/core/display.c +@@ -42,6 +42,7 @@ + #include + #include + ++#include "backends/meta-backend-private.h" + #include "backends/meta-cursor-sprite-xcursor.h" + #include "backends/meta-cursor-tracker-private.h" + #include "backends/meta-idle-monitor-dbus.h" +@@ -598,27 +599,23 @@ gesture_tracker_state_changed (MetaGestureTracker *tracker, + MetaSequenceState state, + MetaDisplay *display) + { +- if (meta_is_wayland_compositor ()) ++ switch (state) + { +- if (state == META_SEQUENCE_ACCEPTED) +- meta_display_cancel_touch (display); +- } +- else +- { +- MetaBackendX11 *backend = META_BACKEND_X11 (meta_get_backend ()); +- int event_mode; ++ case META_SEQUENCE_NONE: ++ case META_SEQUENCE_PENDING_END: ++ return; ++ case META_SEQUENCE_ACCEPTED: ++ meta_display_cancel_touch (display); + +- if (state == META_SEQUENCE_ACCEPTED) +- event_mode = XIAcceptTouch; +- else if (state == META_SEQUENCE_REJECTED) +- event_mode = XIRejectTouch; +- else +- return; ++ /* Intentional fall-through */ ++ case META_SEQUENCE_REJECTED: ++ { ++ MetaBackend *backend; + +- XIAllowTouchEvents (meta_backend_x11_get_xdisplay (backend), +- META_VIRTUAL_CORE_POINTER_ID, +- clutter_x11_event_sequence_get_touch_detail (sequence), +- DefaultRootWindow (display->x11_display->xdisplay), event_mode); ++ backend = meta_get_backend (); ++ meta_backend_finish_touch_sequence (backend, sequence, state); ++ break; ++ } + } + } + +diff --git a/src/core/meta-gesture-tracker-private.h b/src/core/meta-gesture-tracker-private.h +index a9db35ebc..e7bfc5472 100644 +--- a/src/core/meta-gesture-tracker-private.h ++++ b/src/core/meta-gesture-tracker-private.h +@@ -26,6 +26,7 @@ + + #include + ++#include "backends/meta-backend-private.h" + #include "clutter/clutter.h" + #include "meta/window.h" + +@@ -39,14 +40,6 @@ + typedef struct _MetaGestureTracker MetaGestureTracker; + typedef struct _MetaGestureTrackerClass MetaGestureTrackerClass; + +-typedef enum +-{ +- META_SEQUENCE_NONE, +- META_SEQUENCE_ACCEPTED, +- META_SEQUENCE_REJECTED, +- META_SEQUENCE_PENDING_END +-} MetaSequenceState; +- + struct _MetaGestureTracker + { + GObject parent_instance; +-- +2.23.0 + + +From 8cf4f500defb421d5c96f2c1f9fcf7bb5545d70d Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Fri, 25 Oct 2019 10:06:55 +0200 +Subject: [PATCH 2/2] x11: Limit touch replay pointer events to when replaying + +When a touch sequence was rejected, the emulated pointer events would be +replayed with old timestamps. This caused issues with grabs as they +would be ignored due to being too old. This was mitigated by making sure +device event timestamps never travelled back in time by tampering with +any event that had a timestamp seemingly in the past. + +This failed when the most recent timestamp that had been received were +much older than the timestamp of the new event. This could for example +happen when a session was left not interacted with for 40+ days or so; +when interacted with again, as any new timestamp would according to +XSERVER_TIME_IS_BEFORE() still be in the past compared to the "most +recent" one. The effect is that we'd always use the `latest_evtime` for +all new device events without ever updating it. + +The end result of this was that passive grabs would become active when +interacted with, but would then newer be released, as the timestamps to +XIAllowEvents() would out of date, resulting in the desktop effectively +freezing, as the Shell would have an active pointer grab. + +To avoid the situation where we get stuck with an old `latest_evtime` +timestamp, limit the tampering with device event timestamp to 1) only +pointer events, and 2) only during the replay sequence. The second part +is implemented by sending an asynchronous message via the X server after +rejecting a touch sequence, only potentially tampering with the device +event timestamps until the reply. This should avoid the stuck timestamp +as in those situations, we'll always have a relatively up to date +`latest_evtime` meaning XSERVER_TIME_IS_BEFORE() will not get confused. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/886 +--- + src/backends/x11/meta-backend-x11.c | 71 +++++++++++++++++++++++------ + 1 file changed, 58 insertions(+), 13 deletions(-) + +diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c +index cdefa50a9..821b30f5b 100644 +--- a/src/backends/x11/meta-backend-x11.c ++++ b/src/backends/x11/meta-backend-x11.c +@@ -66,6 +66,10 @@ struct _MetaBackendX11Private + XSyncAlarm user_active_alarm; + XSyncCounter counter; + ++ int current_touch_replay_sync_serial; ++ int pending_touch_replay_sync_serial; ++ Atom touch_replay_sync_atom; ++ + int xinput_opcode; + int xinput_event_base; + int xinput_error_base; +@@ -174,6 +178,26 @@ meta_backend_x11_translate_device_event (MetaBackendX11 *x11, + backend_x11_class->translate_device_event (x11, device_event); + } + ++static void ++maybe_translate_touch_replay_pointer_event (MetaBackendX11 *x11, ++ XIDeviceEvent *device_event) ++{ ++ MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); ++ ++ if (!device_event->send_event && ++ device_event->time != META_CURRENT_TIME && ++ priv->current_touch_replay_sync_serial != ++ priv->pending_touch_replay_sync_serial && ++ XSERVER_TIME_IS_BEFORE (device_event->time, priv->latest_evtime)) ++ { ++ /* Emulated pointer events received after XIRejectTouch is received ++ * on a passive touch grab will contain older timestamps, update those ++ * so we dont get InvalidTime at grabs. ++ */ ++ device_event->time = priv->latest_evtime; ++ } ++} ++ + static void + translate_device_event (MetaBackendX11 *x11, + XIDeviceEvent *device_event) +@@ -183,19 +207,7 @@ translate_device_event (MetaBackendX11 *x11, + meta_backend_x11_translate_device_event (x11, device_event); + + if (!device_event->send_event && device_event->time != META_CURRENT_TIME) +- { +- if (XSERVER_TIME_IS_BEFORE (device_event->time, priv->latest_evtime)) +- { +- /* Emulated pointer events received after XIRejectTouch is received +- * on a passive touch grab will contain older timestamps, update those +- * so we dont get InvalidTime at grabs. +- */ +- device_event->time = priv->latest_evtime; +- } +- +- /* Update the internal latest evtime, for any possible later use */ +- priv->latest_evtime = device_event->time; +- } ++ priv->latest_evtime = device_event->time; + } + + static void +@@ -260,6 +272,9 @@ maybe_spoof_event_as_stage_event (MetaBackendX11 *x11, + case XI_Motion: + case XI_ButtonPress: + case XI_ButtonRelease: ++ maybe_translate_touch_replay_pointer_event (x11, ++ (XIDeviceEvent *) input_event); ++ /* Intentional fall-through */ + case XI_KeyPress: + case XI_KeyRelease: + case XI_TouchBegin: +@@ -327,6 +342,17 @@ handle_host_xevent (MetaBackend *backend, + MetaBackendX11Private *priv = meta_backend_x11_get_instance_private (x11); + gboolean bypass_clutter = FALSE; + ++ switch (event->type) ++ { ++ case ClientMessage: ++ if (event->xclient.window == meta_backend_x11_get_xwindow (x11) && ++ event->xclient.message_type == priv->touch_replay_sync_atom) ++ priv->current_touch_replay_sync_serial = event->xclient.data.l[0]; ++ break; ++ default: ++ break; ++ } ++ + XGetEventData (priv->xdisplay, &event->xcookie); + + { +@@ -534,6 +560,10 @@ meta_backend_x11_post_init (MetaBackend *backend) + monitor_manager = meta_backend_get_monitor_manager (backend); + g_signal_connect (monitor_manager, "monitors-changed-internal", + G_CALLBACK (on_monitors_changed), backend); ++ ++ priv->touch_replay_sync_atom = XInternAtom (priv->xdisplay, ++ "_MUTTER_TOUCH_SEQUENCE_SYNC", ++ False); + } + + static ClutterBackend * +@@ -611,6 +641,21 @@ meta_backend_x11_finish_touch_sequence (MetaBackend *backend, + META_VIRTUAL_CORE_POINTER_ID, + clutter_x11_event_sequence_get_touch_detail (sequence), + DefaultRootWindow (priv->xdisplay), event_mode); ++ ++ if (state == META_SEQUENCE_REJECTED) ++ { ++ XClientMessageEvent ev; ++ ++ ev = (XClientMessageEvent) { ++ .type = ClientMessage, ++ .window = meta_backend_x11_get_xwindow (x11), ++ .message_type = priv->touch_replay_sync_atom, ++ .format = 32, ++ .data.l[0] = ++priv->pending_touch_replay_sync_serial, ++ }; ++ XSendEvent (priv->xdisplay, meta_backend_x11_get_xwindow (x11), ++ False, 0, (XEvent *) &ev); ++ } + } + + static void +-- +2.23.0 + diff --git a/SPECS/mutter.spec b/SPECS/mutter.spec new file mode 100644 index 0000000..9e14457 --- /dev/null +++ b/SPECS/mutter.spec @@ -0,0 +1,1301 @@ +%global gtk3_version 3.19.8 +%global glib_version 2.53.2 +%global gsettings_desktop_schemas_version 3.21.4 +%global json_glib_version 0.12.0 +%global libinput_version 1.4 +%global pipewire_version 0.2.2 +%global mutter_api_version 4 + +Name: mutter +Version: 3.32.2 +Release: 34%{?dist} +Summary: Window and compositing manager based on Clutter + +License: GPLv2+ +#VCS: git:git://git.gnome.org/mutter +URL: http://www.gnome.org +Source0: http://download.gnome.org/sources/%{name}/3.32/%{name}-%{version}.tar.xz + +# Work-around for OpenJDK's compliance test +Patch0: 0001-window-actor-Special-case-shaped-Java-windows.patch + +# Allow Xwayland grabs by default, on a selected set of X11 apps +# https://bugzilla.redhat.com/1500399 +Patch1: 0001-wayland-Allow-Xwayland-grabs-on-selected-apps.patch + +Patch2: fix-text-selection-drawing.patch +Patch3: covscan-fixes.patch +Patch4: 0001-enum-types-Use-basename-in-header-comment.patch +Patch5: 0001-workspace-manager-Expose-layout-properties.patch + +# Fix corruption on suspend and resume with nvidia (rhbz#1663440) +Patch10001: 0001-cogl-add-new-UNSTABLE_TEXTURES-feature.patch +Patch10002: 0002-backend-switch-to-using-generated-logind-proxy.patch +Patch10003: 0003-backend-add-signals-for-reporting-suspend-and-resume.patch +Patch10004: 0004-wayland-force-X-clients-to-redraw-on-resume.patch +Patch10005: 0005-backends-native-emit-gl-video-memory-purged-when-bec.patch +Patch10006: 0006-backends-native-update-glyph-cache-on-resume.patch +Patch10007: 0007-backends-native-update-cursor-on-resume.patch +Patch10008: 0008-background-purge-all-background-textures-on-suspend.patch +Patch10009: 0009-MetaShapedTexture-save-and-restore-textures-on-suspe.patch + +# RHEL 7 downstream patches +Patch100: deal-more-gracefully-with-oversized-windows.patch +# Work-around for Xvnc resizing (rhbz#1265511) +Patch101: 0001-monitor-manager-xrandr-Work-around-spurious-hotplugs.patch +Patch102: 0001-monitor-manager-xrandr-Force-an-update-when-resuming.patch +Patch103: 0001-monitor-manager-Consider-external-layout-before-defa.patch +Patch104: 0001-events-Don-t-move-sloppy-focus-while-buttons-are-pre.patch +Patch105: 0001-backends-x11-Support-synaptics-configuration.patch +Patch107: 0001-clutter-Extend-touchpad-device-property-check-for-Sy.patch +# http://bugzilla.gnome.org/show_bug.cgi?id=733277 +Patch109: 0001-Add-support-for-quad-buffer-stereo.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1618632 +# https://bugzilla.redhat.com/show_bug.cgi?id=1497303 +Patch110: 0001-monitor-manager-only-reuse-initial-config-if-monitor.patch +Patch112: add-support-for-plain-old-x-device-configuration.patch +Patch113: 0001-main-be-more-aggressive-in-assuming-X11-backend.patch +Patch114: 0001-clutter-Only-reset-scroll-axes-on-slave-devices.patch + +# Inherit xorg.conf (rhbz#1690506) +Patch115: inherit-xrandr-metamodes.patch + +# Fix test blocker when running on cirrus (rhbz#1735382) +Patch116: 0001-iconcache-Avoid-xrender-picture-formats-when-creatin.patch + +# Don't focus or activate unmanaging windows (rhbz#1741547) +Patch117: 0001-workspace-Focus-only-ancestors-that-are-focusable.patch +Patch118: 0002-window-Emit-an-error-and-return-when-trying-to-activ.patch + +# Don't freeze on rapid input (rhbz#1759525) +Patch119: 0001-events-Sync-pending-pointer-events-without-a-window.patch + +# Don't freeze if input happens after many days of inactivity (rhbz#1766649) +Patch120: input-after-long-idle-fix.patch + +# Fix invalid read in idle monitor (rhbz#1766695) +Patch121: idle-monitor-reset-fix.patch + +# Improve shadow-fb performance on llvmpipe +# https://bugzilla.redhat.com/1737553 +Patch201: 0001-cogl-Remove-unused-OFFSCREEN_BLIT-feature-flag.patch +Patch202: 0002-cogl-Fix-doc-for-_cogl_blit_framebuffer.patch +Patch203: 0003-cogl-Replace-ANGLE-with-GLES3-and-NV-framebuffer_bli.patch +Patch204: 0004-cogl-Relax-formats-on-glBlitFramebuffer.patch +Patch205: 0005-cogl-Allow-glBlitFramebuffer-between-onscreen-offscr.patch +Patch206: 0006-cogl-Rename-feature-OFFSCREEN_BLIT-to-BLIT_FRAMEBUFF.patch +Patch207: 0007-cogl-Expose-cogl_blit_framebuffer.patch +Patch208: 0008-clutter-stage-view-Use-cogl_blit_framebuffer-for-sha.patch +Patch209: 0009-clutter-stage-view-Ignore-clipping-rectangle-for-off.patch +Patch210: 0010-cogl-Flush-journal-before-blitting.patch +Patch211: 0011-clutter-stage-view-Separate-offscreen-and-shadowfb.patch +Patch212: 0012-renderer-native-Separate-offscreen-and-shadowfb.patch + +# Handle lack of RANDR (#1776530) +Patch250: 0001-monitor-manager-xrandr-Move-dpms-state-and-screen-si.patch +Patch251: 0002-monitor-manager-xrandr-Create-dummy-screen-sized-mon.patch + +# Fix build due to egl.pc provider change +Patch260: 0001-EGL-Include-EGL-eglmesaext.h.patch + +# Fix popups with styli +Patch261: 0001-wayland-Check-stylus-serials-on-meta_wayland_seat_ca.patch + +# Fix led-less pad mode switch buttons +Patch262: 0001-x11-Check-wacom-button-flags-to-determine-whether-bu.patch + +# Wacom fixes +Patch263: 0001-backends-Consider-pen-eraser-devices-when-looking-fo.patch +Patch264: 0001-backends-Always-enable-tap-to-click-drag-on-opaque-W.patch +Patch265: 0001-backends-x11-Observe-multiple-pad-mode-switch-button.patch +Patch266: 0001-backends-Check-both-input-settings-and-mapper-for-ta.patch +Patch267: 0001-core-Let-pad-mode-switch-events-always-go-through-Me.patch +Patch268: 0001-Create-explicit-WacomDevices-for-tablet-touchpad-dev.patch +Patch269: 0001-Skip-wacom-touchpads-when-updating-setting.patch + +# Revert stored-config behavior for VMs (#1365717) +Patch280: 0001-Revert-MetaMonitorManager-ignore-hotplug_mode_update.patch + +# Respect xrandr --panning (#1690170) +Patch281: 0001-crtc-xrandr-Respect-configured-RANDR-panning.patch + +# gnome-shell core dump after connection to docking station (#1809079) +Patch282: handle-hotplug-better.patch + +BuildRequires: chrpath +BuildRequires: pango-devel +BuildRequires: startup-notification-devel +BuildRequires: gnome-desktop3-devel +BuildRequires: glib2-devel >= %{glib_version} +BuildRequires: gtk3-devel >= %{gtk3_version} +BuildRequires: pkgconfig +BuildRequires: gobject-introspection-devel >= 1.41.0 +BuildRequires: libSM-devel +BuildRequires: libwacom-devel +BuildRequires: libX11-devel +BuildRequires: libXdamage-devel +BuildRequires: libXext-devel +BuildRequires: libXfixes-devel +BuildRequires: libXi-devel +BuildRequires: libXrandr-devel +BuildRequires: libXrender-devel +BuildRequires: libXcursor-devel +BuildRequires: libXcomposite-devel +BuildRequires: libxcb-devel +BuildRequires: libxkbcommon-devel +BuildRequires: libxkbcommon-x11-devel +BuildRequires: libxkbfile-devel +BuildRequires: libXtst-devel +BuildRequires: mesa-libEGL-devel +BuildRequires: mesa-libGLES-devel +BuildRequires: mesa-libGL-devel +BuildRequires: mesa-libgbm-devel +BuildRequires: pam-devel +BuildRequires: pipewire-devel >= %{pipewire_version} +BuildRequires: systemd-devel +BuildRequires: upower-devel +BuildRequires: xorg-x11-server-Xorg +BuildRequires: xkeyboard-config-devel +BuildRequires: zenity +BuildRequires: desktop-file-utils +# Bootstrap requirements +BuildRequires: gtk-doc gnome-common gettext-devel git +BuildRequires: libcanberra-devel +BuildRequires: gsettings-desktop-schemas-devel >= %{gsettings_desktop_schemas_version} +BuildRequires: gnome-settings-daemon-devel +BuildRequires: meson +BuildRequires: pkgconfig(gudev-1.0) +BuildRequires: pkgconfig(libdrm) +BuildRequires: pkgconfig(gbm) +BuildRequires: pkgconfig(wayland-server) +BuildRequires: pkgconfig(wayland-eglstream) + +BuildRequires: json-glib-devel >= %{json_glib_version} +BuildRequires: libgudev1-devel +BuildRequires: libinput-devel >= %{libinput_version} +BuildRequires: xorg-x11-server-Xwayland + +Obsoletes: mutter-wayland < 3.13.0 +Obsoletes: mutter-wayland-devel < 3.13.0 + +# Make sure yum updates gnome-shell as well; otherwise we might end up with +# broken gnome-shell installations due to mutter ABI changes. +Conflicts: gnome-shell < 3.21.1 + +Requires: control-center-filesystem +Requires: gsettings-desktop-schemas%{?_isa} >= %{gsettings_desktop_schemas_version} +Requires: gtk3%{?_isa} >= %{gtk3_version} +Requires: pipewire%{_isa} >= %{pipewire_version} +Requires: startup-notification +Requires: dbus +Requires: zenity + +Requires: json-glib%{?_isa} >= %{json_glib_version} +Requires: libinput%{?_isa} >= %{libinput_version} + +%description +Mutter is a window and compositing manager that displays and manages +your desktop via OpenGL. Mutter combines a sophisticated display engine +using the Clutter toolkit with solid window-management logic inherited +from the Metacity window manager. + +While Mutter can be used stand-alone, it is primarily intended to be +used as the display core of a larger system such as GNOME Shell. For +this reason, Mutter is very extensible via plugins, which are used both +to add fancy visual effects and to rework the window management +behaviors to meet the needs of the environment. + +%package devel +Summary: Development package for %{name} +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description devel +Header files and libraries for developing Mutter plugins. Also includes +utilities for testing Metacity/Mutter themes. + +%package tests +Summary: Tests for the %{name} package +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description tests +The %{name}-tests package contains tests that can be used to verify +the functionality of the installed %{name} package. + +%prep +%autosetup -S git + +%build +%meson -Degl_device=true -Dwayland_eglstream=true +%meson_build + +%install +%meson_install + +%find_lang %{name} + +# Mutter contains a .desktop file so we just need to validate it +desktop-file-validate %{buildroot}/%{_datadir}/applications/%{name}.desktop + +%ldconfig_scriptlets + +%files -f %{name}.lang +%license COPYING +%doc NEWS +%{_bindir}/mutter +%{_datadir}/applications/*.desktop +%{_libdir}/lib*.so.* +%{_libdir}/mutter-%{mutter_api_version}/ +%{_libexecdir}/mutter-restart-helper +%{_datadir}/GConf/gsettings/mutter-schemas.convert +%{_datadir}/glib-2.0/schemas/org.gnome.mutter.gschema.xml +%{_datadir}/glib-2.0/schemas/org.gnome.mutter.wayland.gschema.xml +%{_datadir}/gnome-control-center/keybindings/50-mutter-*.xml +%{_mandir}/man1/mutter.1* + +%files devel +%{_includedir}/* +%{_libdir}/lib*.so +%{_libdir}/pkgconfig/* + +%files tests +%{_libexecdir}/installed-tests/mutter-%{mutter_api_version} +%{_datadir}/installed-tests/mutter-%{mutter_api_version} +%{_datadir}/mutter-%{mutter_api_version}/tests + +%changelog +* Thu Mar 05 2020 Jonas Ådahl - 3.32.2-34 +- gnome-shell core dump after connection to docking station + Resolves: #1809079 + +* Mon Feb 24 2020 Jonas Ådahl - 3.32.2-33 +- Respect xrandr --panning + Resolves: #1690170 + +* Mon Feb 24 2020 Jonas Ådahl - 3.32.2-32 +- Revert stored-config behavior for VMs + Resolves: #1365717 + +* Mon Feb 24 2020 Carlos Garnacho - 3.32.2-31 +- Fixup detection of multiple mode switch buttons + Resolves: #1687979 + +* Fri Feb 21 2020 Carlos Garnacho - 3.32.2-30 +- Avoid toggling wacom touchpads on tap-to-click/drag setting updates + Resolves: #1716754 + +* Thu Feb 13 2020 Carlos Garnacho - 3.32.2-29 +- Fixup Wacom pad OSD so it appears on the right monitor + Resolves: #1777556 + +* Thu Feb 13 2020 Carlos Garnacho - 3.32.2-28 +- Fixup automatic enabling of wacom touchpad tapping + Resolves: #1716754 + +* Thu Feb 13 2020 Carlos Garnacho - 3.32.2-27 +- Fixup handling of multiple mode switch buttons in pads + Resolves: #1687979 + +* Mon Dec 16 2019 Carlos Garnacho - 3.32.2-26 +- Let pad OSD update on mode switching + Resolves: #1716774 + +* Fri Dec 13 2019 Carlos Garnacho - 3.32.2-25 +- Fix Wacom OSDs so they appear on the right monitor + Resolves: #1777556 + +* Fri Dec 13 2019 Carlos Garnacho - 3.32.2-24 +- Handle multiple mode switch buttons in Cintiq 27QHD + Resolves: #1687979 + +* Fri Dec 13 2019 Carlos Garnacho - 3.32.2-23 +- Enable tapping features by default on standalone Wacom tablets + Resolves: #1716754 + +* Fri Dec 13 2019 Carlos Garnacho - 3.32.2-22 +- Fix detection of Wacom tablet features on X11 + Resolves: #1759619 + +* Wed Dec 04 2019 Carlos Garnacho - 3.32.2-21 +- Fix mode switch pad buttons without LEDs + Resolves: #1666070 + +* Mon Dec 01 2019 Tomas Pelka - 3.32.2-20 +- Need rebuild in correct build target + Resolves: #1730891 + +* Fri Nov 29 2019 Carlos Garnacho - 3.32.2-19 +- Fix pop ups with stylus input + Resolves: #1730891 + +* Wed Nov 27 2019 Jonas Ådahl - 3.32.2-18 +- Revert memory leak fix + Resolves: #1777911 + +* Wed Nov 27 2019 Florian Müllner - 3.32.2-17 +- Fix some memory leaks + Resolves: #1719819 + +* Wed Nov 27 2019 Jonas Ådahl - 3.32.2-16 +- Fix build due to egl.pc provider change + Related: #1776530 + +* Wed Nov 27 2019 Jonas Ådahl - 3.32.2-15 +- Handle lack of RANDR + Resolves: #1776530 + +* Mon Nov 4 2019 Olivier Fourdan - 3.32.2-14 +- Backports shadow FB improvements on llvmpipe + Resolves: #1737553 + +* Wed Oct 30 2019 Jonas Ådahl - 3.32.2-13 +- Fix invalid read in idle monitor + Resolves: #1766695 + +* Wed Oct 30 2019 Jonas Ådahl - 3.32.2-12 +- Don't freeze if input happens after many days of inactivity + Resolves: #1766649 + +* Fri Oct 25 2019 Jonas Ådahl - 3.32.2-11 +- Don't freeze on rapid input + Resolves: #1759525 + +* Fri Aug 16 2019 Jonas Ådahl - 3.32.2-10 +- Don't focus or activate unmanaging windows + Resolves: #1741547 + +* Mon Aug 05 2019 Ray Strode - 3.32.2-9 +- Another 16bpp graphics card crash + Related: #1735382 + Resolves: #1737326 + +* Fri Aug 02 2019 Ray Strode - 3.32.2-8 +- Fix crash in window icon handling on 16bpp graphics cards + Resolves: #1735382 + +* Tue Jul 23 2019 Ray Strode - 3.32.2-7 +- Fix bug leading to 100% cpu usage on suspend/resume + Resolves: #1724551 + +* Mon Jul 15 2019 Jonas Ådahl - 3.32.2-6 +- Don't ignore current mode when deriving current config + Resolves: #1690506 + +* Thu Jun 20 2019 Carlos Garnacho - 3.32.2-5 +- Ensure pad XDevices do not get buttons remapped + Resolves: #1687949 + +* Wed Jun 12 2019 Florian Müllner - 3.32.2-4 +- Expose workspace layout as properties + Related: #1704360 + +* Thu May 30 2019 Florian Müllner - 3.32.2-3 +- Avoid arch-specific bits in header comments + Related: #1698884 +* Tue May 28 2019 Florian Müllner - 3.32.2-2 +- Fix a couple of issues pointed out by covscan + Resolves: #1698884 + +* Thu May 23 2019 Florian Müllner - 3.32.2-1 +- Update to 3.32.2 + Resolves: #1698884 + +* Tue Apr 02 2019 Carlos Garnacho - 3.28.3-19 +- Fix synaptics/evdev driver support forward port to not break tablet pads + Resolves: #1687949 + +* Thu Feb 21 2019 Jonas Ådahl - 3.28.3-18 +- Remove patch enabling monitor framebuffer scaling + Related: #1668883 + +* Mon Feb 11 2019 Ray Strode - 3.28.3-17 +- Fix bug in suspend/resume corruption patch leading to inhibit fd + not getting fetched + Related: #1663440 + +* Mon Feb 11 2019 Florian Müllner - 3.28.3-16 +- Backport forward_key() method + Related: #1668979 + +* Mon Feb 11 2019 Florian Müllner - 3.28.3-15 +- Re-add dropped downstream patches (rhbz#1668883) + +* Tue Feb 05 2019 Olivier Fourdan - 3.28.3-14 +- Restore update monitor fix (rhbz#1635123) + +* Fri Feb 01 2019 Jonas Ådahl - 3.28.3-13 +- Fix screen recording on HiDPI monitor (rhbz#1670287) + +* Thu Jan 31 2019 Ray Strode - 3.28.3-12 +- Drop "Always update monitor for non user op" patch. It's already + in tree and getting misapplied + Related: #1663440 +- Fix suspend and resume corruption on NVidia + Resolves: #1663440 + +* Tue Jan 22 2019 Olivier Fourdan - 3.28.3-11 +- Fix a new crash in recordwindow related to behavior changes in + recent backport additions (rhbz#1657661) + +* Fri Jan 11 2019 Jonas Ådahl - 3.28.3-10 +- Backport screen cast cursor side channel patches (rhbz#1658971) + +* Fri Jan 11 2019 Jonas Ådahl - 3.28.3-9 +- Avoid EGLStream backend deadlock (rhbz#1656905) + +* Fri Jan 11 2019 Jonas Ådahl - 3.28.3-8 +- Get texture pixels via offscreen for EGLStreams (rhbz#1656926) + +* Mon Jan 07 2019 Olivier Fourdan - 3.28.3-7 +- Backport the RecordWindow screencast mode (rhbz#1657661) + +* Fri Jan 04 2019 Ray Strode - 3.28.3-6 +- Add shadow framebuffer for server cards to fix blending + performance + Resolves: #1591250 + +* Fri Oct 26 2018 Olivier Fourdan - 3.28.3-5 +- Allow Xwayland grabs on a selected set of X11 applications. + (rhbz#1500399) + +* Tue Oct 23 2018 Olivier Fourdan - 3.28.3-4 +- More backport fixes from upstream "gnome-3-28" branch +- enable eglstream support (rhbz#1639782) + +* Mon Oct 15 2018 Jonas Ådahl - 3.28.3-3 +- Fix garbled window titles (rhbz#1639194) + +* Thu Oct 04 2018 Olivier Fourdan - 3.28.3-2 +- Backport fixes from upstream "gnome-3-28" branch: +- [wayland] laptop with lid closed and external monitor can't log in to + wayland session (rhbz#1635106) +- [Wayland] Crash with Xwayland grabs enabled in mutter (rhbz#1635110) +- [Wayland] Crash on monitor hotplug (rhbz#1635123) +- [wayland] mutter crashes if drmModeSetCrtc() failed (rhbz#1635155) +- mutter crashes if a modal window closes whilst being dragged (rhbz#1635159) +- gnome-shell crashed with SIGSEGV in meta_monitor_mode_get_resolution() + (rhbz#1635164) +- [wayland] crash when drmModeGetResources() fails (rhbz#1635167) +- [wayland] Can't create new back buffer on Intel i915 (rhbz#1635170) +- [wayland] keyboard: Create a separate keymap shm file per resource + (rhbz#1635235) +- Crash in gnome-shell/mutter after a window is destroyed (rhbz#1635237) +- [x11] Using a cursor theme missing cursors can crash mutter (rhbz#1635241) +- [wayland] Warning messages when starting mutter (rhbz#1635248) +- [wayland] mutter/gnome-shell crash after failed DnD in nautilus + (rhbz#1635718) + +* Thu Aug 09 2018 Kalev Lember - 3.28.3-1 +- Update to 3.28.3 +- Apply HW cursor on-demand patches +- Apply monitor transform regression patch + +* Wed Aug 08 2018 Jonas Ådahl - 3.28.1-4 +- Backport remote-access controller API patch + +* Tue Aug 07 2018 Jonas Ådahl - 3.28.1-3 +- Backport remote desktop related patches + +* Wed Aug 01 2018 Jan Grulich - 3.28.1-2 +- Support PipeWire 0.2.2+ + +* Fri Apr 13 2018 Florian Müllner - 3.28.1-1 +- Update to 3.28.1 + +* Mon Mar 12 2018 Florian Müllner - 3.28.0-1 +- Update to 3.28.0 + +* Mon Mar 05 2018 Florian Müllner - 3.27.92-1 +- Update to 3.27.92 + +* Wed Feb 28 2018 Adam Williamson - 3.27.91-2 +- Backport MR#36 to fix RHBZ #1547691 (GGO #2), mouse issues + +* Wed Feb 21 2018 Florian Müllner - 3.27.91-1 +- Update to 3.27.91 + +* Tue Feb 13 2018 Björn Esser - 3.27.1-4 +- Rebuild against newer gnome-desktop3 package +- Add patch for adjustments to pipewire 0.1.8 API + +* Thu Feb 08 2018 Fedora Release Engineering - 3.27.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_28_Mass_Rebuild + +* Sat Jan 06 2018 Igor Gnatenko - 3.27.1-2 +- Remove obsolete scriptlets + +* Mon Oct 30 2017 Florian Müllner - 3.27.1-1 +- Include 32-bit build fixes + +* Tue Oct 17 2017 Florian Müllner - 3.27.1-1 +- Update to 3.27.1 + +* Fri Oct 06 2017 Florian Müllner - 3.26.1-2 +- Fix screencasts + +* Wed Oct 04 2017 Florian Müllner - 3.26.1-1 +- Update to 3.26.1 + +* Thu Sep 21 2017 Florian Müllner - 3.26.0-5 +- Adjust to pipewire API break + +* Wed Sep 20 2017 Florian Müllner - 3.26.0-5 +- Enable tablet support + +* Tue Sep 12 2017 Adam Williamson - 3.26.0-4 +- Also backport BGO #787570 fix from upstream + +* Tue Sep 12 2017 Adam Williamson - 3.26.0-3 +- Backport upstream fixes for crasher bug BGO #787568 + +* Tue Sep 12 2017 Florian Müllner - 3.26.0-2 +- Enable remote desktop support + +* Tue Sep 12 2017 Florian Müllner - 3.26.0-1 +- Update to 3.26.0 + +* Thu Sep 07 2017 Florian Müllner - 3.25.92-1 +- Update to 3.25.92 + +* Thu Aug 24 2017 Bastien Nocera - 3.25.91-2 ++ mutter-3.25.91-2 +- Fix inverted red and blue channels with newer Mesa + +* Tue Aug 22 2017 Florian Müllner - 3.25.91-1 +- Update to 3.25.91 + +* Thu Aug 10 2017 Florian Müllner - 3.25.90-1 +- Update to 3.25.90 + +* Thu Aug 03 2017 Fedora Release Engineering - 3.25.4-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Binutils_Mass_Rebuild + +* Wed Jul 26 2017 Fedora Release Engineering - 3.25.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_27_Mass_Rebuild + +* Wed Jul 19 2017 Florian Müllner - 3.25.4-1 +- Update to 3.25.4 + +* Wed Jun 21 2017 Florian Müllner - 3.25.3-1 +- Update to 3.25.3 + +* Wed May 24 2017 Florian Müllner - 3.25.2-1 +- Update to 3.25.2 + +* Thu May 18 2017 Florian Müllner - 3.25.1-2 +- Fix copy+paste of UTF8 strings between X11 and wayland + +* Thu Apr 27 2017 Florian Müllner - 3.25.1-1 +- Update to 3.25.1 + +* Tue Apr 11 2017 Florian Müllner - 3.24.1-1 +- Update to 3.24.1 + +* Mon Mar 20 2017 Florian Müllner - 3.24.0-1 +- Update to 3.24.0 + +* Tue Mar 14 2017 Florian Müllner - 3.23.92-1 +- Update to 3.23.92 + +* Fri Mar 10 2017 Florian Müllner - 3.23.91-4 +- Apply startup-notification hack again + +* Tue Mar 07 2017 Adam Williamson - 3.23.91-3 +- Backport more color fixes, should really fix BGO #779234, RHBZ #1428559 + +* Thu Mar 02 2017 Adam Williamson - 3.23.91-2 +- Backport fix for a color issue in 3.23.91 (BGO #779234, RHBZ #1428559) + +* Wed Mar 01 2017 Florian Müllner - 3.23.91-1 +- Update to 3.23.91 + +* Thu Feb 16 2017 Florian Müllner - 3.23.90-1 +- Update to 3.23.90 + +* Fri Feb 10 2017 Fedora Release Engineering - 3.23.3-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_26_Mass_Rebuild + +* Thu Dec 15 2016 Florian Müllner - 3.23.3-1 +- Update to 3.23.3 + +* Fri Dec 02 2016 Florian Müllner - 3.23.2-2 +- Fix build error on 32-bit platforms + +* Thu Nov 24 2016 Kevin Fenzi - 3.23.2-2 +- Some fixes to get building. Still needs patch1 rebased. + +* Wed Nov 23 2016 Florian Müllner - 3.23.2-1 +- Update to 3.23.2 + +* Tue Nov 8 2016 Matthias Clasen - 3.23.1-2 +- Fix 1376471 + +* Sun Oct 30 2016 Florian Müllner - 3.23.1-1 +- Update to 3.23.1 + +* Tue Oct 18 2016 Kalev Lember - 3.22.1-3 +- Backport a fix to make gnome-screenshot --area work + +* Tue Oct 11 2016 Adam Jackson - 3.22.1-2 +- Prefer eglGetPlatformDisplay() to eglGetDisplay() + +* Tue Oct 11 2016 Florian Müllner - 3.22.1-1 +- Update to 3.22.1 + +* Wed Sep 28 2016 Florian Müllner - 3.22.0-2 +- Include fix for crash on VT switch + +* Mon Sep 19 2016 Florian Müllner - 3.22.0-1 +- Update to 3.22.0 + +* Tue Sep 13 2016 Florian Müllner - 3.21.92-1 +- Update to 3.21.92 + +* Thu Sep 08 2016 Kalev Lember - 3.21.91-2 +- wayland/cursor-role: Increase buffer use count on construction (#1373372) + +* Tue Aug 30 2016 Florian Müllner - 3.21.91-1 +- Update to 3.21.91 + +* Mon Aug 29 2016 Kalev Lember - 3.21.90-3 +- clutter/evdev: Fix absolute pointer motion events (#1369492) + +* Sat Aug 20 2016 Kalev Lember - 3.21.90-2 +- Update minimum dep versions + +* Fri Aug 19 2016 Florian Müllner - 3.21.90-1 +- Update to 3.21.90 + +* Wed Jul 20 2016 Florian Müllner - 3.21.4-1 +- Update to 3.21.4 +- Drop downstream patch +- Fix build error on 32-bit + +* Tue Jun 21 2016 Florian Müllner - 3.21.3-1 +- Update to 3.21.3 + +* Fri May 27 2016 Florian Müllner - 3.21.2-1 +- Update to 3.21.2 + +* Fri Apr 29 2016 Florian Müllner - 3.21.1-1 +- Update to 3.21.1 + +* Wed Apr 13 2016 Florian Müllner - 3.20.1-1 +- Update to 3.20.1 + +* Tue Mar 22 2016 Florian Müllner - 3.20.0-1 +- Update to 3.20.0 + +* Wed Mar 16 2016 Florian Müllner - 3.19.92-1 +- Update to 3.19.92 + +* Thu Mar 03 2016 Florian Müllner - 3.19.91-2 +- Include fix for invalid cursor wl_buffer access + +* Thu Mar 03 2016 Florian Müllner - 3.19.91-1 +- Update to 3.19.91 + +* Fri Feb 19 2016 Florian Müllner - 3.19.90-1 +- Update to 3.19.90 + +* Thu Feb 04 2016 Fedora Release Engineering - 3.19.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_24_Mass_Rebuild + +* Thu Jan 21 2016 Florian Müllner - 3.19.4-1 +- Update to 3.19.4 + +* Thu Dec 17 2015 Florian Müllner - 3.19.3-1 +- Update to 3.19.3 + +* Wed Nov 25 2015 Florian Müllner - 3.19.2-1 +- Update to 3.19.2 + +* Tue Nov 10 2015 Ray Strode 3.19.1-5.20151110git049f1556d +- Update to git snapshot + +* Thu Oct 29 2015 Florian Müllner - 3.19.1-1 +- Update to 3.19.1 + +* Wed Oct 21 2015 Ray Strode 3.18.1-4 +- Force the cursor visible on vt switches after setting + the crtc to workaround that qxl bug from before in a + different situation + Related: #1273247 + +* Wed Oct 21 2015 Kalev Lember - 3.18.1-3 +- Backport a fix for a common Wayland crash (#1266486) + +* Thu Oct 15 2015 Kalev Lember - 3.18.1-2 +- Bump gnome-shell conflicts version + +* Thu Oct 15 2015 Florian Müllner - 3.18.1-1 +- Update to 3.18.1 + +* Mon Sep 21 2015 Florian Müllner - 3.18.0-1 +- Update to 3.18.0 + +* Wed Sep 16 2015 Florian Müllner - 3.17.92-1 +- Update to 3.17.92 + +* Thu Sep 03 2015 Florian Müllner - 3.17.91-1 +- Update to 3.17.91 + +* Thu Sep 03 2015 Ray Strode 3.17.90-2 +- Add workaround for qxl cursor visibility wonkiness that we + did for f22 + Related: #1200901 + +* Thu Aug 20 2015 Florian Müllner - 3.17.90-1 +- Update to 3.17.90 + +* Thu Jul 23 2015 Florian Müllner - 3.17.4-1 +- Update to 3.17.4 + +* Wed Jul 22 2015 David King - 3.17.3-2 +- Bump for new gnome-desktop3 + +* Thu Jul 02 2015 Florian Müllner - 3.17.3-1 +- Update to 3.17.3 + +* Wed Jun 17 2015 Fedora Release Engineering - 3.17.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_23_Mass_Rebuild + +* Wed May 27 2015 Florian Müllner - 3.17.2-1 +- Update to 3.17.2 + +* Thu Apr 30 2015 Florian Müllner - 3.17.1-1 +- Update to 3.17.1 + +* Thu Apr 16 2015 Kalev Lember - 3.16.1.1-2 +- Bump gnome-shell conflicts version + +* Wed Apr 15 2015 Rui Matos - 3.16.1.1-1 +- Update to 3.16.1.1 + +* Tue Apr 14 2015 Florian Müllner - 3.16.1-1 +- Update to 3.16.1 + +* Mon Mar 23 2015 Florian Müllner - 3.16.0-1 +- Update to 3.16.0 + +* Tue Mar 17 2015 Kalev Lember - 3.15.92-2 +- Update minimum dep versions +- Use license macro for the COPYING file + +* Tue Mar 17 2015 Florian Müllner - 3.15.92-1 +- Update to 3.15.92 + +* Tue Mar 10 2015 Peter Hutterer - 3.15.91-2 +- Rebuild for libinput soname bump + +* Wed Mar 04 2015 Florian Müllner - 3.15.91-1 +- Update to 3.15.91 + +* Fri Feb 20 2015 Florian Müllner - 3.15.90-1 +- Update to 3.15.90 + +* Mon Feb 02 2015 Adam Williamson - 3.15.4-2 +- backport ad90b7dd to fix BGO #743412 / RHBZ #1185811 + +* Wed Jan 21 2015 Florian Müllner - 3.15.4-1 +- Update to 3.15.4 + +* Mon Jan 19 2015 Peter Hutterer 3.15.3-3 +- Rebuild for libinput soname bump + +* Mon Jan 12 2015 Ray Strode 3.15.3-2 +- Add specific BuildRequires for wayland bits, so we don't + get wayland support by happenstance. +- Add BuildRequires for autogoo since ./autogen.sh is run as part of + the build process + +* Fri Dec 19 2014 Florian Müllner - 3.15.3-1 +- Revert unsatisfiable wayland requirement + +* Fri Dec 19 2014 Florian Müllner - 3.15.3-1 +- Update to 3.15.3 + +* Thu Nov 27 2014 Florian Müllner - 3.15.2-1 +- Update to 3.15.2 + +* Wed Nov 12 2014 Vadim Rutkovsky - 3.15.1-2 +- Build installed tests + +* Thu Oct 30 2014 Florian Müllner - 3.15.1-1 +- Update to 3.15.1 + +* Tue Oct 21 2014 Florian Müllner - 3.14.1-2 +- Fix regression in handling raise-on-click option (rhbz#1151918) + +* Tue Oct 14 2014 Florian Müllner - 3.14.1-1 +- Update to 3.14.1 + +* Fri Oct 03 2014 Adam Williamson - 3.14.0-3 +- backport fix for BGO #737233 / RHBZ #1145952 (desktop right click broken) + +* Mon Sep 22 2014 Kalev Lember - 3.14.0-2 +- Bump gnome-shell conflicts version + +* Mon Sep 22 2014 Florian Müllner - 3.14.0-1 +- Update to 3.14.0 + +* Wed Sep 17 2014 Florian Müllner - 3.13.92-1 +- Update to 3.13.92 + +* Fri Sep 12 2014 Peter Hutterer - 3.13.91-2 +- Rebuild for libinput soname bump + +* Wed Sep 03 2014 Florian Müllner - 3.31.91-1 +- Update to 3.13.91, drop downstream patches + +* Tue Aug 26 2014 Adel Gadllah - 3.13.90-4 +- Apply fix for RH #1133166 + +* Mon Aug 25 2014 Hans de Goede - 3.13.90-3 +- Add a patch from upstream fixing gnome-shell crashing non stop on + multi monitor setups (rhbz#1103221) + +* Fri Aug 22 2014 Kevin Fenzi 3.13.90-2 +- Rebuild for new wayland + +* Wed Aug 20 2014 Florian Müllner - 3.13.90-1 +- Update to 3.13.90 + +* Mon Aug 18 2014 Kalev Lember - 3.13.4-3 +- Rebuilt for upower 0.99.1 soname bump + +* Sun Aug 17 2014 Fedora Release Engineering - 3.13.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_22_Mass_Rebuild + +* Wed Jul 23 2014 Florian Müllner - 3.13.4-1 +- Update to 3.13.4 + +* Tue Jul 22 2014 Kalev Lember - 3.13.3-2 +- Rebuilt for gobject-introspection 1.41.4 + +* Fri Jun 27 2014 Florian Müllner - 3.13.3-1 +- New gobject-introspection has been built, drop the last patch again + +* Wed Jun 25 2014 Florian Müllner - 3.13.3-1 +- Revert annotation updates until we get a new gobject-introspection build + +* Wed Jun 25 2014 Florian Müllner - 3.13.3-1 +- Update to 3.13.1 + +* Wed Jun 11 2014 Florian Müllner - 3.13.2-2 +- Backport fix for legacy fullscreen check + +* Sat Jun 07 2014 Fedora Release Engineering - 3.13.2-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_21_Mass_Rebuild + +* Tue May 27 2014 Florian Müllner - 3.13.2-1 +- Update to 3.13.2, drop upstreamed patches + +* Thu May 8 2014 Matthias Clasen - 3.13.1-5 +- Fix shrinking terminals + +* Wed May 07 2014 Kalev Lember - 3.13.1-4 +- Backport an upstream fix for a Wayland session crash + +* Wed May 07 2014 Kalev Lember - 3.13.1-3 +- Install mutter-launch as setuid root + +* Thu May 01 2014 Kalev Lember - 3.13.1-2 +- Obsolete mutter-wayland + +* Wed Apr 30 2014 Florian Müllner - 3.13.1-1 +- Update to 3.13.1 + +* Tue Apr 15 2014 Florian Müllner - 3.12.1-1 +- Update to 3.12.1 + +* Sat Apr 05 2014 Kalev Lember - 3.12.0-2 +- Update dep versions + +* Tue Mar 25 2014 Florian Müllner - 3.12.0-1 +- Update to 3.12.0 + +* Wed Mar 19 2014 Florian Müllner - 3.11.92-1 +- Update to 3.11.92 + +* Thu Mar 06 2014 Florian Müllner - 3.11.91-1 +- Update to 3.11.91 + +* Thu Feb 20 2014 Kalev Lember - 3.11.90-2 +- Rebuilt for cogl soname bump + +* Wed Feb 19 2014 Florian Müllner - 3.11.90-1 +- Update to 3.11.90 + +* Wed Feb 19 2014 Richard Hughes - 3.11.5-4 +- Rebuilt for gnome-desktop soname bump + +* Mon Feb 10 2014 Peter Hutterer - 3.11.5-3 +- Rebuild for libevdev soname bump + +* Wed Feb 05 2014 Richard Hughes - 3.11.5-2 +- Rebuilt for cogl soname bump + +* Wed Feb 05 2014 Florian Müllner - 3.11.5-1 +- Update to 3.11.5 + +* Wed Jan 15 2014 Florian Müllner - 3.11.4-1 +- Update to 3.11.4 + +* Fri Dec 20 2013 Florian Müllner - 3.11.3-1 +- Update to 3.11.3 + +* Wed Nov 13 2013 Florian Müllner - 3.11.2-1 +- Update to 3.11.2 + +* Wed Oct 30 2013 Florian Müllner - 3.11.1-1 +- Update to 3.11.1 + +* Tue Oct 15 2013 Florian Müllner - 3.10.1.1-1 +- Update to 3.10.1.1 + +* Mon Oct 14 2013 Florian Müllner - 3.10.1-1 +- Update to 3.10.1 + +* Wed Sep 25 2013 Florian Müllner - 3.10.0.1-1 +- Update to 3.10.0.1 + +* Mon Sep 23 2013 Florian Müllner - 3.10.0-1 +- Update to 3.10.0 + +* Tue Sep 17 2013 Kalev Lember - 3.9.92-2 +- Update the description and URL +- Tighten -devel subpackage deps with _isa +- Use the make_install macro + +* Mon Sep 16 2013 Florian Müllner - 3.9.92-1 +- Update to 3.9.92 + +* Tue Sep 03 2013 Kalev Lember - 3.9.91-2 +- Rebuilt for libgnome-desktop soname bump + +* Tue Sep 03 2013 Florian Müllner - 3.9.91-1 +- Update to 3.9.91 + +* Thu Aug 22 2013 Florian Müllner - 3.9.90-1 +- Update to 3.9.90 + +* Fri Aug 09 2013 Kalev Lember - 3.9.5-2 +- Rebuilt for cogl 1.15.4 soname bump + +* Tue Jul 30 2013 Florian Müllner - 3.9.5-1 +- Update to 3.9.5 + +* Wed Jul 10 2013 Florian Müllner - 3.9.4-1 +- Update to 3.9.4 + +* Tue Jun 18 2013 Florian Müllner - 3.9.3-1 +- Update to 3.9.3 + +* Tue May 28 2013 Florian Müllner - 3.9.2-1 +- Update to 3.9.2 + +* Wed May 01 2013 Florian Müllner - 3.9.1-1 +- Update to 3.9.1 + +* Tue Apr 23 2013 Florian Müllner - 3.8.1-1 +- Update to 3.8.1 + +* Tue Mar 26 2013 Florian Müllner - 3.8.0-1 +- Update to 3.8.0 + +* Tue Mar 19 2013 Florian Müllner - 3.7.92-1 +- Update to 3.7.92 + +* Mon Mar 04 2013 Florian Müllner - 3.7.91-1 +- Update to 3.7.91 + +* Wed Feb 20 2013 Florian Müllner - 3.7.90-1 +- Update to 3.7.90 + +* Tue Feb 05 2013 Florian Müllner - 3.7.5-1 +- Update to 3.7.5 + +* Fri Jan 25 2013 Peter Robinson 3.7.4-2 +- Rebuild for new cogl + +* Tue Jan 15 2013 Florian Müllner - 3.7.4-1 +- Update to 3.7.4 + +* Tue Dec 18 2012 Florian Müllner - 3.7.3-1 +- Update to 3.7.3 + +* Mon Nov 19 2012 Florian Müllner - 3.7.2-1 +- Update to 3.7.2 + +* Fri Nov 09 2012 Kalev Lember - 3.7.1-1 +- Update to 3.7.1 + +* Mon Oct 15 2012 Florian Müllner - 3.6.1-1 +- Update to 3.6.1 + +* Tue Sep 25 2012 Florian Müllner - 3.6.0-1 +- Update to 3.6.0 + +* Wed Sep 19 2012 Florian Müllner - 3.5.92-1 +- Update to 3.5.92 + +* Tue Sep 04 2012 Debarshi Ray - 3.5.91-2 +- Rebuild against new cogl + +* Tue Sep 04 2012 Debarshi Ray - 3.5.91-1 +- Update to 3.5.91 + +* Tue Aug 28 2012 Matthias Clasen - 3.5.90-2 +- Rebuild against new cogl/clutter + +* Tue Aug 21 2012 Richard Hughes - 3.5.90-1 +- Update to 3.5.90 + +* Tue Aug 07 2012 Richard Hughes - 3.5.5-1 +- Update to 3.5.5 + +* Fri Jul 27 2012 Fedora Release Engineering - 3.5.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Tue Jul 17 2012 Richard Hughes - 3.5.4-1 +- Update to 3.5.4 + +* Tue Jun 26 2012 Matthias Clasen - 3.5.3-1 +- Update to 3.5.3 + +* Fri Jun 8 2012 Matthias Clasen - 3.5.2-3 +- Make resize grip area larger + +* Thu Jun 07 2012 Matthias Clasen - 3.5.2-2 +- Don't check for Xinerama anymore - it is now mandatory + +* Thu Jun 07 2012 Richard Hughes - 3.5.2-1 +- Update to 3.5.2 +- Remove upstreamed patches + +* Wed May 09 2012 Adam Jackson 3.4.1-3 +- mutter-never-slice-shape-mask.patch, mutter-use-cogl-texrect-api.patch: + Fix window texturing on hardware without ARB_texture_non_power_of_two + (#813648) + +* Wed Apr 18 2012 Kalev Lember - 3.4.1-2 +- Silence glib-compile-schemas scriplets + +* Wed Apr 18 2012 Kalev Lember - 3.4.1-1 +- Update to 3.4.1 +- Conflict with gnome-shell versions older than 3.4.1 + +* Tue Mar 27 2012 Richard Hughes - 3.4.0-1 +- Update to 3.4.0 + +* Wed Mar 21 2012 Kalev Lember - 3.3.92-1 +- Update to 3.3.92 + +* Sat Mar 10 2012 Matthias Clasen - 3.3.90-2 +- Rebuild against new cogl + +* Sat Feb 25 2012 Matthias Clasen - 3.3.90-1 +- Update to 3.3.90 + +* Tue Feb 7 2012 Matthias Clasen - 3.3.5-1 +- Update to 3.3.5 + +* Fri Jan 20 2012 Matthias Clasen - 3.3.4-1 +- Update to 3.3.4 + +* Thu Jan 19 2012 Matthias Clasen - 3.3.3-2 +- Rebuild against new cogl + +* Thu Jan 5 2012 Matthias Clasen - 3.3.3-1 +- Update to 3.3.3 + +* Wed Nov 23 2011 Matthias Clasen - 3.3.2-2 +- Rebuild against new clutter + +* Tue Nov 22 2011 Matthias Clasen - 3.3.2-1 +- Update to 3.3.2 + +* Wed Oct 26 2011 Fedora Release Engineering - 3.2.1-2 +- Rebuilt for glibc bug#747377 + +* Wed Oct 19 2011 Matthias Clasen - 3.2.1-1 +- Update to 3.2.1 + +* Mon Sep 26 2011 Owen Taylor - 3.2.0-1 +- Update to 3.2.0 + +* Tue Sep 20 2011 Matthias Clasen - 3.1.92-1 +- Update to 3.1.92 + +* Wed Sep 14 2011 Owen Taylor - 3.1.91.1-1 +- Update to 3.1.91.1 + +* Wed Aug 31 2011 Matthias Clasen - 3.1.90.1-1 +- Update to 3.1.90.1 + +* Wed Jul 27 2011 Matthias Clasen - 3.1.4-1 +- Update to 3.1.4 + +* Wed Jul 27 2011 Matthias Clasen - 3.1.3.1-3 +- Rebuild + +* Mon Jul 4 2011 Peter Robinson - 3.1.3.1-2 +- rebuild against new clutter/cogl + +* Mon Jul 04 2011 Adam Williamson - 3.1.3.1-1 +- Update to 3.1.3.1 + +* Thu Jun 30 2011 Owen Taylor - 3.1.3-1 +- Update to 3.1.3 + +* Wed May 25 2011 Owen Taylor - 3.0.2.1-1 +- Update to 3.0.2.1 + +* Fri Apr 29 2011 Matthias Clasen - 3.0.1-3 +- Actually apply the patch for #700276 + +* Thu Apr 28 2011 Matthias Clasen - 3.0.1-2 +- Make session saving of gnome-shell work + +* Mon Apr 25 2011 Owen Taylor - 3.0.1-1 +- Update to 3.0.1 + +* Mon Apr 4 2011 Owen Taylor - 3.0.0-1 +- Update to 3.0.0 + +* Mon Mar 28 2011 Matthias Clasen - 2.91.93-1 +- Update to 2.91.93 + +* Wed Mar 23 2011 Matthias Clasen - 2.91.92-1 +- Update to 2.91.92 + +* Mon Mar 7 2011 Owen Taylor - 2.91.91-1 +- Update to 2.91.91 + +* Tue Mar 1 2011 Matthias Clasen - 2.91.90-2 +- Build against libcanberra, to enable AccessX feedback features + +* Tue Feb 22 2011 Matthias Clasen - 2.91.90-1 +- Update to 2.91.90 + +* Thu Feb 10 2011 Matthias Clasen - 2.91.6-4 +- Rebuild against newer gtk + +* Tue Feb 08 2011 Fedora Release Engineering - 2.91.6-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Wed Feb 2 2011 Matthias Clasen - 2.91.6-2 +- Rebuild against newer gtk + +* Tue Feb 1 2011 Owen Taylor - 2.91.6-1 +- Update to 2.91.6 + +* Tue Jan 11 2011 Matthias Clasen - 2.91.5-1 +- Update to 2.91.5 + +* Fri Jan 7 2011 Matthias Clasen - 2.91.4-1 +- Update to 2.91.4 + +* Fri Dec 3 2010 Matthias Clasen - 2.91.3-2 +- Rebuild against new gtk +- Drop no longer needed %%clean etc + +* Mon Nov 29 2010 Owen Taylor - 2.91.3-1 +- Update to 2.91.3 + +* Tue Nov 9 2010 Owen Taylor - 2.91.2-1 +- Update to 2.91.2 + +* Tue Nov 2 2010 Matthias Clasen - 2.91.1-2 +- Rebuild against newer gtk3 + +* Fri Oct 29 2010 Owen Taylor - 2.91.1-1 +- Update to 2.91.1 + +* Mon Oct 4 2010 Owen Taylor - 2.91.0-1 +- Update to 2.91.0 + +* Wed Sep 22 2010 Matthias Clasen - 2.31.5-4 +- Rebuild against newer gobject-introspection + +* Wed Jul 14 2010 Colin Walters - 2.31.5-3 +- Rebuild for new gobject-introspection + +* Tue Jul 13 2010 Adel Gadllah - 2.31.5-2 +- Build against gtk3 + +* Mon Jul 12 2010 Colin Walters - 2.31.5-1 +- New upstream version + +* Mon Jul 12 2010 Colin Walters - 2.31.2-5 +- Rebuild against new gobject-introspection + +* Tue Jul 6 2010 Colin Walters - 2.31.2-4 +- Changes to support snapshot builds + +* Fri Jun 25 2010 Colin Walters - 2.31.2-3 +- drop gir-repository-devel dep + +* Wed May 26 2010 Adam Miller - 2.31.2-2 +- removed "--with-clutter" as configure is claiming it to be an unknown option + +* Wed May 26 2010 Adam Miller - 2.31.2-1 +- New upstream 2.31.2 release + +* Thu Mar 25 2010 Peter Robinson 2.29.1-1 +- New upstream 2.29.1 release + +* Wed Mar 17 2010 Peter Robinson 2.29.0-1 +- New upstream 2.29.0 release + +* Tue Feb 16 2010 Adam Jackson 2.28.1-0.2 +- mutter-2.28.1-add-needed.patch: Fix FTBFS from --no-add-needed + +* Thu Feb 4 2010 Peter Robinson 2.28.1-0.1 +- Move to git snapshot + +* Wed Oct 7 2009 Owen Taylor - 2.28.0-1 +- Update to 2.28.0 + +* Tue Sep 15 2009 Owen Taylor - 2.27.5-1 +- Update to 2.27.5 + +* Fri Sep 4 2009 Owen Taylor - 2.27.4-1 +- Remove workaround for #520209 +- Update to 2.27.4 + +* Sat Aug 29 2009 Owen Taylor - 2.27.3-3 +- Fix %%preun GConf script to properly be for package removal + +* Fri Aug 28 2009 Owen Taylor - 2.27.3-2 +- Add a workaround for Red Hat bug #520209 + +* Fri Aug 28 2009 Owen Taylor - 2.27.3-1 +- Update to 2.27.3, remove mutter-metawindow.patch + +* Fri Aug 21 2009 Peter Robinson 2.27.2-2 +- Add upstream patch needed by latest mutter-moblin + +* Tue Aug 11 2009 Peter Robinson 2.27.2-1 +- New upstream 2.27.2 release. Drop upstreamed patches. + +* Wed Jul 29 2009 Peter Robinson 2.27.1-5 +- Add upstream patches for clutter 1.0 + +* Wed Jul 29 2009 Peter Robinson 2.27.1-4 +- Add patch to fix mutter --replace + +* Sat Jul 25 2009 Fedora Release Engineering - 2.27.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Sat Jul 18 2009 Peter Robinson 2.27.1-2 +- Updates from review request + +* Fri Jul 17 2009 Peter Robinson 2.27.1-1 +- Update to official 2.27.1 and review updates + +* Thu Jun 18 2009 Peter Robinson 2.27.0-0.2 +- Updates from initial reviews + +* Thu Jun 18 2009 Peter Robinson 2.27.0-0.1 +- Initial packaging