diff --git a/.gitignore b/.gitignore index 8f5c56c..f2ae9b2 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -SOURCES/mutter-3.26.2.tar.xz +SOURCES/mutter-3.28.3.tar.xz diff --git a/.mutter.metadata b/.mutter.metadata index 8d83fd2..6b4e4ce 100644 --- a/.mutter.metadata +++ b/.mutter.metadata @@ -1 +1 @@ -8d9dffa9c1ceaf07761b80662828fb7d60e76dd1 SOURCES/mutter-3.26.2.tar.xz +a7a01f50c75dc6c1e0fe708656cfce1546624568 SOURCES/mutter-3.28.3.tar.xz diff --git a/SOURCES/0001-Revert-build-Require-libgudev-232.patch b/SOURCES/0001-Revert-build-Require-libgudev-232.patch index ec6bf21..e55d8bb 100644 --- a/SOURCES/0001-Revert-build-Require-libgudev-232.patch +++ b/SOURCES/0001-Revert-build-Require-libgudev-232.patch @@ -1,19 +1,20 @@ -From 23f4b91105c4fa9fa2231d2e1049728a6383cd65 Mon Sep 17 00:00:00 2001 +From 6a807a31b5d762797850948761d66c1ab4fbfd7b Mon Sep 17 00:00:00 2001 From: Olivier Fourdan Date: Fri, 15 Sep 2017 09:39:18 +0200 Subject: [PATCH] Revert "build: Require libgudev >= 232" This reverts commit 361bf847af82c7dca097302fe64c575079280c9c. --- - configure.ac | 4 ++-- - src/backends/native/meta-launcher.c | 4 ++++ - 2 files changed, 6 insertions(+), 2 deletions(-) + configure.ac | 4 ++-- + src/backends/native/meta-launcher.c | 2 ++ + src/backends/native/meta-monitor-manager-kms.c | 3 +++ + 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/configure.ac b/configure.ac -index 805707933..813ca008a 100644 +index e6b2bf8..2fde187 100644 --- a/configure.ac +++ b/configure.ac -@@ -225,10 +225,10 @@ AC_MSG_CHECKING([gudev]) +@@ -227,10 +227,10 @@ AC_MSG_CHECKING([gudev]) if test x$with_gudev = xno ; then AC_MSG_RESULT([disabled]) else @@ -27,20 +28,32 @@ index 805707933..813ca008a 100644 else AC_MSG_RESULT(no) diff --git a/src/backends/native/meta-launcher.c b/src/backends/native/meta-launcher.c -index eb35f88be..90b4b98ba 100644 +index 8b066c9..22ea2ad 100644 --- a/src/backends/native/meta-launcher.c +++ b/src/backends/native/meta-launcher.c -@@ -49,6 +49,10 @@ +@@ -46,6 +46,8 @@ + #include "meta-cursor-renderer-native.h" + #include "meta-renderer-native.h" + ++G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUdevClient, g_object_unref) ++ + struct _MetaLauncher + { + Login1Session *session_proxy; +diff --git a/src/backends/native/meta-monitor-manager-kms.c b/src/backends/native/meta-monitor-manager-kms.c +index 1a2eaec..2a13cdb 100644 +--- a/src/backends/native/meta-monitor-manager-kms.c ++++ b/src/backends/native/meta-monitor-manager-kms.c +@@ -52,6 +52,9 @@ #define DRM_CARD_UDEV_DEVICE_TYPE "drm_minor" +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUdevDevice, g_object_unref) -+G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUdevClient, g_object_unref) +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GUdevEnumerator, g_object_unref) + - struct _MetaLauncher + typedef struct { - Login1Session *session_proxy; + GSource source; -- -2.13.5 +1.8.3.1 diff --git a/SOURCES/0001-backends-Monitor-changes-in-active-tools-settings.patch b/SOURCES/0001-backends-Monitor-changes-in-active-tools-settings.patch deleted file mode 100644 index 444e6ff..0000000 --- a/SOURCES/0001-backends-Monitor-changes-in-active-tools-settings.patch +++ /dev/null @@ -1,142 +0,0 @@ -From 62f0fb12b1fa946779f0efa406159a355811fdc5 Mon Sep 17 00:00:00 2001 -From: Carlos Garnacho -Date: Mon, 19 Feb 2018 16:50:52 +0100 -Subject: [PATCH] backends: Monitor changes in active tools' settings - -So the changes can be instantly applied while the tool is in proximity. -Before we would just do it on proximity-in, which doesn't provide a -good look&feel while modifying the tool settings in g-c-c. - -https://gitlab.gnome.org/GNOME/mutter/issues/38 - -Closes: #38 ---- - src/backends/meta-input-settings.c | 71 ++++++++++++++++++++++++++++++++++++-- - 1 file changed, 68 insertions(+), 3 deletions(-) - -diff --git a/src/backends/meta-input-settings.c b/src/backends/meta-input-settings.c -index 0658755..ec0fc9f 100644 ---- a/src/backends/meta-input-settings.c -+++ b/src/backends/meta-input-settings.c -@@ -41,6 +41,16 @@ static GQuark quark_tool_settings = 0; - - typedef struct _MetaInputSettingsPrivate MetaInputSettingsPrivate; - typedef struct _DeviceMappingInfo DeviceMappingInfo; -+typedef struct _CurrentToolInfo CurrentToolInfo; -+ -+struct _CurrentToolInfo -+{ -+ MetaInputSettings *input_settings; -+ ClutterInputDevice *device; -+ ClutterInputDeviceTool *tool; -+ GSettings *settings; -+ guint changed_id; -+}; - - struct _DeviceMappingInfo - { -@@ -68,6 +78,8 @@ struct _MetaInputSettingsPrivate - - GHashTable *mappable_devices; - -+ GHashTable *current_tools; -+ - ClutterVirtualInputDevice *virtual_pad_keyboard; - - #ifdef HAVE_LIBWACOM -@@ -144,6 +156,7 @@ meta_input_settings_dispose (GObject *object) - g_clear_object (&priv->keyboard_settings); - g_clear_object (&priv->gsd_settings); - g_clear_pointer (&priv->mappable_devices, g_hash_table_unref); -+ g_clear_pointer (&priv->current_tools, g_hash_table_unref); - - if (priv->monitors_changed_id && priv->monitor_manager) - { -@@ -1510,22 +1523,71 @@ meta_input_settings_device_removed (ClutterDeviceManager *device_manager, - - priv = meta_input_settings_get_instance_private (input_settings); - g_hash_table_remove (priv->mappable_devices, device); -+ g_hash_table_remove (priv->current_tools, device); - - if (g_hash_table_remove (priv->two_finger_devices, device) && - g_hash_table_size (priv->two_finger_devices) == 0) - apply_device_settings (input_settings, NULL); - } - -+static void -+current_tool_changed_cb (GSettings *settings, -+ const char *key, -+ gpointer user_data) -+{ -+ CurrentToolInfo *info = user_data; -+ -+ apply_stylus_settings (info->input_settings, info->device, info->tool); -+} -+ -+static CurrentToolInfo * -+current_tool_info_new (MetaInputSettings *input_settings, -+ ClutterInputDevice *device, -+ ClutterInputDeviceTool *tool) -+{ -+ CurrentToolInfo *info; -+ -+ info = g_new0 (CurrentToolInfo, 1); -+ info->input_settings = input_settings; -+ info->device = device; -+ info->tool = tool; -+ info->settings = lookup_tool_settings (tool, device); -+ info->changed_id = -+ g_signal_connect (info->settings, "changed", -+ G_CALLBACK (current_tool_changed_cb), -+ info); -+ return info; -+} -+ -+static void -+current_tool_info_free (CurrentToolInfo *info) -+{ -+ g_signal_handler_disconnect (info->settings, info->changed_id); -+ g_free (info); -+} -+ - static void - meta_input_settings_tool_changed (ClutterDeviceManager *device_manager, - ClutterInputDevice *device, - ClutterInputDeviceTool *tool, - MetaInputSettings *input_settings) - { -- if (!tool) -- return; -+ MetaInputSettingsPrivate *priv; - -- apply_stylus_settings (input_settings, device, tool); -+ priv = meta_input_settings_get_instance_private (input_settings); -+ -+ if (tool) -+ { -+ CurrentToolInfo *current_tool; -+ -+ current_tool = current_tool_info_new (input_settings, device, tool); -+ g_hash_table_insert (priv->current_tools, device, current_tool); -+ apply_stylus_settings (input_settings, device, tool); -+ } -+ else -+ { -+ g_hash_table_remove (priv->current_tools, device); -+ } - } - - static void -@@ -1616,6 +1678,9 @@ meta_input_settings_init (MetaInputSettings *settings) - priv->mappable_devices = - g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) device_mapping_info_free); - -+ priv->current_tools = -+ g_hash_table_new_full (NULL, NULL, NULL, (GDestroyNotify) current_tool_info_free); -+ - priv->monitor_manager = g_object_ref (meta_monitor_manager_get ()); - g_signal_connect (priv->monitor_manager, "monitors-changed-internal", - G_CALLBACK (monitors_changed_cb), settings); --- -2.16.1 - diff --git a/SOURCES/0001-backends-x11-Fix-time-comparison-bug-causing-hang.patch b/SOURCES/0001-backends-x11-Fix-time-comparison-bug-causing-hang.patch deleted file mode 100644 index 6a87a0f..0000000 --- a/SOURCES/0001-backends-x11-Fix-time-comparison-bug-causing-hang.patch +++ /dev/null @@ -1,33 +0,0 @@ -From 05bf09ea4aa5a7dc22869075ea2096c4a293d70d Mon Sep 17 00:00:00 2001 -From: Jeff Smith -Date: Wed, 31 Jan 2018 23:27:19 -0600 -Subject: [PATCH] backends/x11: Fix time-comparison bug causing hang - -A comparison in translate_device_event() does not account for the fact -that X's clock wraps about every 49.7 days. When triggered, this causes -an unresponsive GUI. - -Replace simple less-than comparison with XSERVER_TIME_IS_BEFORE macro, -which accounts for the wrapping of X's clock. - -Closes: https://gitlab.gnome.org/GNOME/mutter/issues/12 ---- - src/backends/x11/meta-backend-x11.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - -diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c -index 233532435..f447f785f 100644 ---- a/src/backends/x11/meta-backend-x11.c -+++ b/src/backends/x11/meta-backend-x11.c -@@ -112,7 +112,7 @@ translate_device_event (MetaBackendX11 *x11, - - if (!device_event->send_event && device_event->time != CurrentTime) - { -- if (device_event->time < priv->latest_evtime) -+ 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 --- -2.17.1 - diff --git a/SOURCES/0001-backends-x11-Preserve-XI1-XDevice-throughout-Clutter.patch b/SOURCES/0001-backends-x11-Preserve-XI1-XDevice-throughout-Clutter.patch deleted file mode 100644 index 0a1fc86..0000000 --- a/SOURCES/0001-backends-x11-Preserve-XI1-XDevice-throughout-Clutter.patch +++ /dev/null @@ -1,127 +0,0 @@ -From bc17d94ef058564c1a1adf28a8696164455fea1b Mon Sep 17 00:00:00 2001 -From: Carlos Garnacho -Date: Tue, 30 Jan 2018 13:07:32 +0100 -Subject: [PATCH] backends/x11: Preserve XI1 XDevice throughout - ClutterInputDevice lifetime - -Opening and closing the device may result into XI2 grabs being cut short, -resulting into pad buttons being rendered ineffective, and other possible -misbehaviors. This is an XInput flaw that fell in the gap between XI1 and -XI2, and has no easy fix. It pays us for mixing both versions, I guess... - -Work this around by keeping the XI1 XDevice attached to the -ClutterInputDevice, this way it will live long enough that this is not -a concern. - -Investigation of this bug was mostly carried by Peter Hutterer, I'm just -the executing hand. - -https://gitlab.gnome.org/GNOME/mutter/issues/7 - -Closes: #7 ---- - src/backends/x11/meta-input-settings-x11.c | 48 ++++++++++++++++++++++++++---- - 1 file changed, 42 insertions(+), 6 deletions(-) - -diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c -index d1ee37a..7a876ef 100644 ---- a/src/backends/x11/meta-input-settings-x11.c -+++ b/src/backends/x11/meta-input-settings-x11.c -@@ -55,6 +55,46 @@ enum { - SCROLL_METHOD_NUM_FIELDS - }; - -+static void -+device_free_xdevice (gpointer user_data) -+{ -+ MetaDisplay *display = meta_get_display (); -+ MetaBackend *backend = meta_get_backend (); -+ Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); -+ XDevice *xdev = user_data; -+ -+ meta_error_trap_push (display); -+ XCloseDevice (xdisplay, xdev); -+ meta_error_trap_pop (display); -+} -+ -+static XDevice * -+device_ensure_xdevice (ClutterInputDevice *device) -+{ -+ MetaDisplay *display = meta_get_display (); -+ MetaBackend *backend = meta_get_backend (); -+ Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); -+ int device_id = clutter_input_device_get_device_id (device); -+ XDevice *xdev = NULL; -+ -+ xdev = g_object_get_data (G_OBJECT (device), "meta-input-settings-xdevice"); -+ if (xdev) -+ return xdev; -+ -+ meta_error_trap_push (display); -+ xdev = XOpenDevice (xdisplay, device_id); -+ meta_error_trap_pop (display); -+ -+ if (xdev) -+ { -+ g_object_set_data_full (G_OBJECT (device), -+ "meta-input-settings-xdevice", -+ xdev, (GDestroyNotify) device_free_xdevice); -+ } -+ -+ return xdev; -+} -+ - static void * - get_property (ClutterInputDevice *device, - const gchar *property, -@@ -540,7 +580,6 @@ meta_input_settings_x11_set_tablet_mapping (MetaInputSettings *settings, - MetaDisplay *display = meta_get_display (); - MetaBackend *backend = meta_get_backend (); - Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); -- int device_id = clutter_input_device_get_device_id (device); - XDevice *xdev; - - if (!display) -@@ -548,13 +587,12 @@ meta_input_settings_x11_set_tablet_mapping (MetaInputSettings *settings, - - /* Grab the puke bucket! */ - meta_error_trap_push (display); -- xdev = XOpenDevice (xdisplay, device_id); -+ xdev = device_ensure_xdevice (device); - if (xdev) - { - XSetDeviceMode (xdisplay, xdev, - mapping == G_DESKTOP_TABLET_MAPPING_ABSOLUTE ? - Absolute : Relative); -- XCloseDevice (xdisplay, xdev); - } - - if (meta_error_trap_pop_with_return (display)) -@@ -737,7 +775,6 @@ meta_input_settings_x11_set_stylus_button_map (MetaInputSettings *setti - MetaDisplay *display = meta_get_display (); - MetaBackend *backend = meta_get_backend (); - Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); -- int device_id = clutter_input_device_get_device_id (device); - XDevice *xdev; - - if (!display) -@@ -745,7 +782,7 @@ meta_input_settings_x11_set_stylus_button_map (MetaInputSettings *setti - - /* Grab the puke bucket! */ - meta_error_trap_push (display); -- xdev = XOpenDevice (xdisplay, device_id); -+ xdev = device_ensure_xdevice (device); - if (xdev) - { - guchar map[3] = { -@@ -755,7 +792,6 @@ meta_input_settings_x11_set_stylus_button_map (MetaInputSettings *setti - }; - - XSetDeviceButtonMapping (xdisplay, xdev, map, G_N_ELEMENTS (map)); -- XCloseDevice (xdisplay, xdev); - } - - if (meta_error_trap_pop_with_return (display)) --- -1.8.3.1 - diff --git a/SOURCES/0001-backends-x11-wacom-pressure-curve-is-a-32-bit-proper.patch b/SOURCES/0001-backends-x11-wacom-pressure-curve-is-a-32-bit-proper.patch deleted file mode 100644 index f13f593..0000000 --- a/SOURCES/0001-backends-x11-wacom-pressure-curve-is-a-32-bit-proper.patch +++ /dev/null @@ -1,35 +0,0 @@ -From ac502c921d2e813e6e916a589a07bc58ca4c12e7 Mon Sep 17 00:00:00 2001 -From: Peter Hutterer -Date: Fri, 9 Feb 2018 11:53:17 +1000 -Subject: [PATCH] backends/x11: wacom pressure curve is a 32-bit property - -The property has been 32 bits since around 2011 and has not changed, mutter -expects it to be 8 bits. The mismatch causes change_property to never -actually change the property. - -https://gitlab.gnome.org/GNOME/mutter/issues/26 - -Closes: #26 ---- - src/backends/x11/meta-input-settings-x11.c | 4 ++-- - 1 file changed, 2 insertions(+), 2 deletions(-) - -diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c -index 7d1d360a3..9687fb36f 100644 ---- a/src/backends/x11/meta-input-settings-x11.c -+++ b/src/backends/x11/meta-input-settings-x11.c -@@ -813,9 +813,9 @@ meta_input_settings_x11_set_stylus_pressure (MetaInputSettings *settings, - ClutterInputDeviceTool *tool, - const gint32 pressure[4]) - { -- guchar values[4] = { pressure[0], pressure[1], pressure[2], pressure[3] }; -+ guint32 values[4] = { pressure[0], pressure[1], pressure[2], pressure[3] }; - -- change_property (device, "Wacom Pressurecurve", XA_INTEGER, 8, -+ change_property (device, "Wacom Pressurecurve", XA_INTEGER, 32, - &values, G_N_ELEMENTS (values)); - } - --- -2.16.1 - 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..529c05e --- /dev/null +++ b/SOURCES/0001-clutter-Only-reset-scroll-axes-on-slave-devices.patch @@ -0,0 +1,27 @@ +From ee5b766580c702858bb10bab764a39f95a5b6432 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 62f558380..ec7268ca8 100644 +--- a/clutter/clutter/x11/clutter-device-manager-xi2.c ++++ b/clutter/clutter/x11/clutter-device-manager-xi2.c +@@ -1803,7 +1803,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.14.3 + diff --git a/SOURCES/0001-clutter-stage-don-t-use-deprecated-api.patch b/SOURCES/0001-clutter-stage-don-t-use-deprecated-api.patch deleted file mode 100644 index d3b0103..0000000 --- a/SOURCES/0001-clutter-stage-don-t-use-deprecated-api.patch +++ /dev/null @@ -1,217 +0,0 @@ -From e69a6ac0e44e8d5fd72d7bc60f118044b0407e8f Mon Sep 17 00:00:00 2001 -From: rpm-build -Date: Thu, 9 Nov 2017 16:18:02 -0500 -Subject: [PATCH] 0001-clutter-stage-don-t-use-deprecated-api.patch - ---- - clutter/clutter/clutter-stage.c | 21 ++++++++++++--------- - 1 file changed, 12 insertions(+), 9 deletions(-) - -diff --git a/clutter/clutter/clutter-stage.c b/clutter/clutter/clutter-stage.c -index 02ab07b..e4f9342 100644 ---- a/clutter/clutter/clutter-stage.c -+++ b/clutter/clutter/clutter-stage.c -@@ -1459,64 +1459,65 @@ _clutter_stage_do_pick_on_view (ClutterStage *stage, - fb_height = view_layout.height * fb_scale; - cogl_push_framebuffer (fb); - - /* needed for when a context switch happens */ - _clutter_stage_maybe_setup_viewport (stage, view); - - /* FIXME: For some reason leaving the cogl clip stack empty causes the - * picking to not work at all, so setting it the whole framebuffer content - * for now. */ - cogl_framebuffer_push_scissor_clip (fb, 0, 0, - view_layout.width * fb_scale, - view_layout.height * fb_scale); - - _clutter_stage_window_get_dirty_pixel (priv->impl, view, &dirty_x, &dirty_y); - - if (G_LIKELY (!(clutter_pick_debug_flags & CLUTTER_DEBUG_DUMP_PICK_BUFFERS))) - { - CLUTTER_NOTE (PICK, "Pushing pick scissor clip x: %d, y: %d, 1x1", - (int) dirty_x * fb_scale, - (int) dirty_y * fb_scale); - cogl_framebuffer_push_scissor_clip (fb, dirty_x * fb_scale, dirty_y * fb_scale, 1, 1); - } - - viewport_offset_x = x * fb_scale - dirty_x * fb_scale; - viewport_offset_y = y * fb_scale - dirty_y * fb_scale; - CLUTTER_NOTE (PICK, "Setting viewport to %f, %f, %f, %f", - priv->viewport[0] * fb_scale - viewport_offset_x, - priv->viewport[1] * fb_scale - viewport_offset_y, - priv->viewport[2] * fb_scale, - priv->viewport[3] * fb_scale); -- cogl_set_viewport (priv->viewport[0] * fb_scale - viewport_offset_x, -- priv->viewport[1] * fb_scale - viewport_offset_y, -- priv->viewport[2] * fb_scale, -- priv->viewport[3] * fb_scale); -+ cogl_framebuffer_set_viewport (fb, -+ priv->viewport[0] * fb_scale - viewport_offset_x, -+ priv->viewport[1] * fb_scale - viewport_offset_y, -+ priv->viewport[2] * fb_scale, -+ priv->viewport[3] * fb_scale); - - read_x = dirty_x * fb_scale; - read_y = dirty_y * fb_scale; - - CLUTTER_NOTE (PICK, "Performing pick at %i,%i on view %dx%d+%d+%d s: %d", - x, y, - view_layout.width, view_layout.height, - view_layout.x, view_layout.y, fb_scale); - - cogl_color_init_from_4ub (&stage_pick_id, 255, 255, 255, 255); - cogl_clear (&stage_pick_id, COGL_BUFFER_BIT_COLOR | COGL_BUFFER_BIT_DEPTH); - - /* Disable dithering (if any) when doing the painting in pick mode */ - dither_enabled_save = cogl_framebuffer_get_dither_enabled (fb); - cogl_framebuffer_set_dither_enabled (fb, FALSE); - - /* Render the entire scence in pick mode - just single colored silhouette's - * are drawn offscreen (as we never swap buffers) - */ - context->pick_mode = mode; - _clutter_stage_paint_view (stage, view, NULL); - context->pick_mode = CLUTTER_PICK_NONE; - - /* Read the color of the screen co-ords pixel. RGBA_8888_PRE is used - even though we don't care about the alpha component because under - GLES this is the only format that is guaranteed to work so Cogl - will end up having to do a conversion if any other format is - used. The format is requested as pre-multiplied because Cogl - assumes that all pixels in the framebuffer are premultiplied so - it avoids a conversion. */ -@@ -3590,123 +3591,125 @@ calculate_z_translation (float z_near) - * z_2d = --------------------------- + z_near - * sin (0.5°) - */ - - /* We expect the compiler should boil this down to z_near * CONSTANT - * already, but just in case we use precomputed constants - */ - #if 0 - # define A tanf (_DEG_TO_RAD (30.f)) - # define B sinf (_DEG_TO_RAD (120.f)) - # define C cosf (_DEG_TO_RAD (30.5f)) - # define D sinf (_DEG_TO_RAD (.5f)) - #else - # define A 0.57735025882720947265625f - # define B 0.866025388240814208984375f - # define C 0.86162912845611572265625f - # define D 0.00872653536498546600341796875f - #endif - - return z_near - * A * B * C - / D - + z_near; - } - - void - _clutter_stage_maybe_setup_viewport (ClutterStage *stage, - ClutterStageView *view) - { - ClutterStagePrivate *priv = stage->priv; -+ CoglFramebuffer *fb = clutter_stage_view_get_framebuffer (view); - - if (clutter_stage_view_is_dirty_viewport (view)) - { - cairo_rectangle_int_t view_layout; - ClutterPerspective perspective; - float fb_scale; - float viewport_offset_x; - float viewport_offset_y; - float z_2d; - - CLUTTER_NOTE (PAINT, - "Setting up the viewport { w:%f, h:%f }", - priv->viewport[2], - priv->viewport[3]); - - fb_scale = clutter_stage_view_get_scale (view); - clutter_stage_view_get_layout (view, &view_layout); - - viewport_offset_x = view_layout.x * fb_scale; - viewport_offset_y = view_layout.y * fb_scale; -- cogl_set_viewport (priv->viewport[0] * fb_scale - viewport_offset_x, -- priv->viewport[1] * fb_scale - viewport_offset_y, -- priv->viewport[2] * fb_scale, -- priv->viewport[3] * fb_scale); -+ cogl_framebuffer_set_viewport (fb, -+ priv->viewport[0] * fb_scale - viewport_offset_x, -+ priv->viewport[1] * fb_scale - viewport_offset_y, -+ priv->viewport[2] * fb_scale, -+ priv->viewport[3] * fb_scale); - - perspective = priv->perspective; - - /* Ideally we want to regenerate the perspective matrix whenever - * the size changes but if the user has provided a custom matrix - * then we don't want to override it */ - if (!priv->has_custom_perspective) - { - perspective.aspect = priv->viewport[2] / priv->viewport[3]; - z_2d = calculate_z_translation (perspective.z_near); - - /* NB: z_2d is only enough room for 85% of the stage_height between - * the stage and the z_near plane. For behind the stage plane we - * want a more consistent gap of 10 times the stage_height before - * hitting the far plane so we calculate that relative to the final - * height of the stage plane at the z_2d_distance we got... */ - perspective.z_far = z_2d + - tanf (_DEG_TO_RAD (perspective.fovy / 2.0f)) * z_2d * 20.0f; - - clutter_stage_set_perspective_internal (stage, &perspective); - } - else - z_2d = calculate_z_translation (perspective.z_near); - - cogl_matrix_init_identity (&priv->view); - cogl_matrix_view_2d_in_perspective (&priv->view, - perspective.fovy, - perspective.aspect, - perspective.z_near, - z_2d, - priv->viewport[2], - priv->viewport[3]); - - clutter_stage_view_set_dirty_viewport (view, FALSE); - } - - if (clutter_stage_view_is_dirty_projection (view)) - { -- cogl_set_projection_matrix (&priv->projection); -+ cogl_framebuffer_set_projection_matrix (fb, &priv->projection); - - clutter_stage_view_set_dirty_projection (view, FALSE); - } - } - - #undef _DEG_TO_RAD - - /** - * clutter_stage_ensure_redraw: - * @stage: a #ClutterStage - * - * Ensures that @stage is redrawn - * - * This function should not be called by applications: it is - * used when embedding a #ClutterStage into a toolkit with - * another windowing system, like GTK+. - * - * Since: 1.0 - */ - void - clutter_stage_ensure_redraw (ClutterStage *stage) - { - ClutterMasterClock *master_clock; - ClutterStagePrivate *priv; - - g_return_if_fail (CLUTTER_IS_STAGE (stage)); - - priv = stage->priv; - - if (!priv->relayout_pending && !priv->redraw_pending) --- -2.14.3 - diff --git a/SOURCES/0001-clutter-x11-Implement-keycode-lookup-from-keysyms-on.patch b/SOURCES/0001-clutter-x11-Implement-keycode-lookup-from-keysyms-on.patch new file mode 100644 index 0000000..b577bc8 --- /dev/null +++ b/SOURCES/0001-clutter-x11-Implement-keycode-lookup-from-keysyms-on.patch @@ -0,0 +1,317 @@ +From 8dfcfa0607754caab5032532ccc9d97b4393708e Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Fri, 29 Jun 2018 14:31:23 +0200 +Subject: [PATCH] clutter/x11: Implement keycode lookup from keysyms on virtual + key devices + +Unfortunately XKeysymToKeycode() falls short in that it coalesces keysyms +into keycodes pertaining to the first level (i.e. lowercase). Add a +ClutterKeymapX11 method (much alike its GdkKeymap counterpart) to look up +all matches for the given keysym. + +Two other helper methods have been added so the virtual device can fetch +the current keyboard group, and latch modifiers for key emission. Combining +all this, the virtual device is now able to handle keycodes in further +levels. + +Closes: https://gitlab.gnome.org/GNOME/gnome-shell/issues/135 + +(cherry picked from commit 85284acb000ddc70afcf716b6c198b4b5bf5741e) +--- + clutter/clutter/x11/clutter-keymap-x11.c | 178 +++++++++++++++++- + clutter/clutter/x11/clutter-keymap-x11.h | 8 + + .../x11/clutter-virtual-input-device-x11.c | 22 ++- + 3 files changed, 204 insertions(+), 4 deletions(-) + +diff --git a/clutter/clutter/x11/clutter-keymap-x11.c b/clutter/clutter/x11/clutter-keymap-x11.c +index 914e31434..c34e676a4 100644 +--- a/clutter/clutter/x11/clutter-keymap-x11.c ++++ b/clutter/clutter/x11/clutter-keymap-x11.c +@@ -38,6 +38,14 @@ + + typedef struct _ClutterKeymapX11Class ClutterKeymapX11Class; + typedef struct _DirectionCacheEntry DirectionCacheEntry; ++typedef struct _ClutterKeymapKey ClutterKeymapKey; ++ ++struct _ClutterKeymapKey ++{ ++ guint keycode; ++ guint group; ++ guint level; ++}; + + struct _DirectionCacheEntry + { +@@ -59,6 +67,7 @@ struct _ClutterKeymapX11 + + ClutterModifierType num_lock_mask; + ClutterModifierType scroll_lock_mask; ++ ClutterModifierType level3_shift_mask; + + PangoDirection current_direction; + +@@ -69,6 +78,7 @@ struct _ClutterKeymapX11 + Atom current_group_atom; + guint current_cache_serial; + DirectionCacheEntry group_direction_cache[4]; ++ int current_group; + #endif + + guint caps_lock_state : 1; +@@ -198,6 +208,9 @@ get_xkb (ClutterKeymapX11 *keymap_x11) + if (keymap_x11->scroll_lock_mask == 0) + keymap_x11->scroll_lock_mask = XkbKeysymToModifiers (backend_x11->xdpy, + XK_Scroll_Lock); ++ if (keymap_x11->level3_shift_mask == 0) ++ keymap_x11->level3_shift_mask = XkbKeysymToModifiers (backend_x11->xdpy, ++ XK_ISO_Level3_Shift); + + return keymap_x11->xkb_desc; + } +@@ -469,6 +482,7 @@ static void + clutter_keymap_x11_init (ClutterKeymapX11 *keymap) + { + keymap->current_direction = PANGO_DIRECTION_NEUTRAL; ++ keymap->current_group = -1; + } + + static ClutterTranslateReturn +@@ -498,7 +512,8 @@ clutter_keymap_x11_translate_event (ClutterEventTranslator *translator, + { + case XkbStateNotify: + CLUTTER_NOTE (EVENT, "Updating keyboard state"); +- update_direction (keymap_x11, XkbStateGroup (&xkb_event->state)); ++ keymap_x11->current_group = XkbStateGroup (&xkb_event->state); ++ update_direction (keymap_x11, keymap_x11->current_group); + update_locked_mods (keymap_x11, xkb_event->state.locked_mods); + retval = CLUTTER_TRANSLATE_REMOVE; + break; +@@ -665,3 +680,164 @@ _clutter_keymap_x11_get_direction (ClutterKeymapX11 *keymap) + #endif + return PANGO_DIRECTION_NEUTRAL; + } ++ ++static gboolean ++clutter_keymap_x11_get_entries_for_keyval (ClutterKeymapX11 *keymap_x11, ++ guint keyval, ++ ClutterKeymapKey **keys, ++ gint *n_keys) ++{ ++#ifdef HAVE_XKB ++ if (CLUTTER_BACKEND_X11 (keymap_x11->backend)->use_xkb) ++ { ++ XkbDescRec *xkb = get_xkb (keymap_x11); ++ GArray *retval; ++ gint keycode; ++ ++ keycode = keymap_x11->min_keycode; ++ retval = g_array_new (FALSE, FALSE, sizeof (ClutterKeymapKey)); ++ ++ while (keycode <= keymap_x11->max_keycode) ++ { ++ gint max_shift_levels = XkbKeyGroupsWidth (xkb, keycode); ++ gint group = 0; ++ gint level = 0; ++ gint total_syms = XkbKeyNumSyms (xkb, keycode); ++ gint i = 0; ++ KeySym *entry; ++ ++ /* entry is an array with all syms for group 0, all ++ * syms for group 1, etc. and for each group the ++ * shift level syms are in order ++ */ ++ entry = XkbKeySymsPtr (xkb, keycode); ++ ++ while (i < total_syms) ++ { ++ g_assert (i == (group * max_shift_levels + level)); ++ ++ if (entry[i] == keyval) ++ { ++ ClutterKeymapKey key; ++ ++ key.keycode = keycode; ++ key.group = group; ++ key.level = level; ++ ++ g_array_append_val (retval, key); ++ ++ g_assert (XkbKeySymEntry (xkb, keycode, level, group) == ++ keyval); ++ } ++ ++ ++level; ++ ++ if (level == max_shift_levels) ++ { ++ level = 0; ++ ++group; ++ } ++ ++ ++i; ++ } ++ ++ ++keycode; ++ } ++ ++ if (retval->len > 0) ++ { ++ *keys = (ClutterKeymapKey*) retval->data; ++ *n_keys = retval->len; ++ } ++ else ++ { ++ *keys = NULL; ++ *n_keys = 0; ++ } ++ ++ g_array_free (retval, retval->len > 0 ? FALSE : TRUE); ++ ++ return *n_keys > 0; ++ } ++ else ++#endif ++ { ++ return FALSE; ++ } ++} ++ ++void ++clutter_keymap_x11_latch_modifiers (ClutterKeymapX11 *keymap_x11, ++ uint32_t level, ++ gboolean enable) ++{ ++#ifdef HAVE_XKB ++ ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (keymap_x11->backend); ++ uint32_t modifiers[] = { ++ 0, ++ ShiftMask, ++ keymap_x11->level3_shift_mask, ++ keymap_x11->level3_shift_mask | ShiftMask, ++ }; ++ uint32_t value = 0; ++ ++ if (!backend_x11->use_xkb) ++ return; ++ ++ level = CLAMP (level, 0, G_N_ELEMENTS (modifiers) - 1); ++ ++ if (enable) ++ value = modifiers[level]; ++ else ++ value = 0; ++ ++ XkbLatchModifiers (clutter_x11_get_default_display (), ++ XkbUseCoreKbd, modifiers[level], ++ value); ++#endif ++} ++ ++static uint32_t ++clutter_keymap_x11_get_current_group (ClutterKeymapX11 *keymap_x11) ++{ ++ ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (keymap_x11->backend); ++ XkbStateRec state_rec; ++ ++ if (keymap_x11->current_group >= 0) ++ return keymap_x11->current_group; ++ ++ XkbGetState (backend_x11->xdpy, XkbUseCoreKbd, &state_rec); ++ return XkbStateGroup (&state_rec); ++} ++ ++gboolean ++clutter_keymap_x11_keycode_for_keyval (ClutterKeymapX11 *keymap_x11, ++ guint keyval, ++ guint *keycode_out, ++ guint *level_out) ++{ ++ ClutterKeymapKey *keys; ++ gint i, n_keys, group; ++ gboolean found = FALSE; ++ ++ g_return_val_if_fail (keycode_out != NULL, FALSE); ++ g_return_val_if_fail (level_out != NULL, FALSE); ++ ++ group = clutter_keymap_x11_get_current_group (keymap_x11); ++ ++ if (!clutter_keymap_x11_get_entries_for_keyval (keymap_x11, keyval, &keys, &n_keys)) ++ return FALSE; ++ ++ for (i = 0; i < n_keys && !found; i++) ++ { ++ if (keys[i].group == group) ++ { ++ *keycode_out = keys[i].keycode; ++ *level_out = keys[i].level; ++ found = TRUE; ++ } ++ } ++ ++ g_free (keys); ++ return found; ++} +diff --git a/clutter/clutter/x11/clutter-keymap-x11.h b/clutter/clutter/x11/clutter-keymap-x11.h +index ad673a2a7..4b5b403c8 100644 +--- a/clutter/clutter/x11/clutter-keymap-x11.h ++++ b/clutter/clutter/x11/clutter-keymap-x11.h +@@ -51,6 +51,14 @@ gboolean _clutter_keymap_x11_get_is_modifier (ClutterKeymapX11 *keymap, + + PangoDirection _clutter_keymap_x11_get_direction (ClutterKeymapX11 *keymap); + ++gboolean clutter_keymap_x11_keycode_for_keyval (ClutterKeymapX11 *keymap_x11, ++ guint keyval, ++ guint *keycode_out, ++ guint *level_out); ++void clutter_keymap_x11_latch_modifiers (ClutterKeymapX11 *keymap_x11, ++ uint32_t level, ++ gboolean enable); ++ + G_END_DECLS + + #endif /* __CLUTTER_KEYMAP_X11_H__ */ +diff --git a/clutter/clutter/x11/clutter-virtual-input-device-x11.c b/clutter/clutter/x11/clutter-virtual-input-device-x11.c +index 416c944b3..b86ded0d0 100644 +--- a/clutter/clutter/x11/clutter-virtual-input-device-x11.c ++++ b/clutter/clutter/x11/clutter-virtual-input-device-x11.c +@@ -32,6 +32,8 @@ + + #include "clutter-virtual-input-device.h" + #include "x11/clutter-virtual-input-device-x11.h" ++#include "x11/clutter-backend-x11.h" ++#include "x11/clutter-keymap-x11.h" + + struct _ClutterVirtualInputDeviceX11 + { +@@ -135,11 +137,25 @@ clutter_virtual_input_device_x11_notify_keyval (ClutterVirtualInputDevice *virtu + uint32_t keyval, + ClutterKeyState key_state) + { +- KeyCode keycode; ++ ClutterBackendX11 *backend_x11 = CLUTTER_BACKEND_X11 (clutter_get_default_backend ()); ++ ClutterKeymapX11 *keymap = backend_x11->keymap; ++ uint32_t keycode, level; ++ ++ if (!clutter_keymap_x11_keycode_for_keyval (keymap, keyval, &keycode, &level)) ++ { ++ g_warning ("No keycode found for keyval %x in current group", keyval); ++ return; ++ } ++ ++ if (key_state == CLUTTER_KEY_STATE_PRESSED) ++ clutter_keymap_x11_latch_modifiers (keymap, level, TRUE); + +- keycode = XKeysymToKeycode (clutter_x11_get_default_display (), keyval); + XTestFakeKeyEvent (clutter_x11_get_default_display (), +- keycode, key_state == CLUTTER_KEY_STATE_PRESSED, 0); ++ (KeyCode) keycode, ++ key_state == CLUTTER_KEY_STATE_PRESSED, 0); ++ ++ if (key_state == CLUTTER_KEY_STATE_RELEASED) ++ clutter_keymap_x11_latch_modifiers (keymap, level, FALSE); + } + + static void +-- +2.19.0.rc0 + diff --git a/SOURCES/0001-clutter-x11-Implement-missing-ClutterInputDevice-pad.patch b/SOURCES/0001-clutter-x11-Implement-missing-ClutterInputDevice-pad.patch deleted file mode 100644 index 69ca7a4..0000000 --- a/SOURCES/0001-clutter-x11-Implement-missing-ClutterInputDevice-pad.patch +++ /dev/null @@ -1,481 +0,0 @@ -From 1d745a858470b29b44e5b0e308488a477c4526cb Mon Sep 17 00:00:00 2001 -From: Carlos Garnacho -Date: Thu, 22 Feb 2018 17:48:17 +0100 -Subject: [PATCH 1/2] clutter/x11: Implement missing ClutterInputDevice pad - vmethods - -Use libwacom to be able to find out modes, groups and button roles on -pad devices. - -https://gitlab.gnome.org/GNOME/mutter/issues/48 - -Closes: #48 ---- - clutter/clutter/x11/clutter-device-manager-xi2.c | 11 +++ - clutter/clutter/x11/clutter-device-manager-xi2.h | 8 ++ - clutter/clutter/x11/clutter-input-device-xi2.c | 97 ++++++++++++++++++++++++ - clutter/clutter/x11/clutter-input-device-xi2.h | 10 +++ - clutter/configure.ac | 32 +++++++- - 5 files changed, 156 insertions(+), 2 deletions(-) - -diff --git a/clutter/clutter/x11/clutter-device-manager-xi2.c b/clutter/clutter/x11/clutter-device-manager-xi2.c -index d2610cc..dee2604 100644 ---- a/clutter/clutter/x11/clutter-device-manager-xi2.c -+++ b/clutter/clutter/x11/clutter-device-manager-xi2.c -@@ -495,11 +495,18 @@ create_device (ClutterDeviceManagerXI2 *manager_xi2, - "device-node", node_path, - "n-rings", num_rings, - "n-strips", num_strips, -+ "n-mode-groups", MAX (num_rings, num_strips), - NULL); - - translate_device_classes (backend_x11->xdpy, retval, - info->classes, - info->num_classes); -+ -+#ifdef HAVE_LIBWACOM -+ if (source == CLUTTER_PAD_DEVICE) -+ clutter_input_device_xi2_ensure_wacom_info (retval, manager_xi2->wacom_db); -+#endif -+ - g_free (vendor_id); - g_free (product_id); - -@@ -2063,4 +2070,8 @@ clutter_device_manager_xi2_init (ClutterDeviceManagerXI2 *self) - (GDestroyNotify) g_object_unref); - self->tools_by_serial = g_hash_table_new_full (NULL, NULL, NULL, - (GDestroyNotify) g_object_unref); -+ -+#ifdef HAVE_LIBWACOM -+ self->wacom_db = libwacom_database_new (); -+#endif - } -diff --git a/clutter/clutter/x11/clutter-device-manager-xi2.h b/clutter/clutter/x11/clutter-device-manager-xi2.h -index c8e66f9..be25759 100644 ---- a/clutter/clutter/x11/clutter-device-manager-xi2.h -+++ b/clutter/clutter/x11/clutter-device-manager-xi2.h -@@ -26,6 +26,10 @@ - - #include - -+#ifdef HAVE_LIBWACOM -+#include -+#endif -+ - G_BEGIN_DECLS - - #define CLUTTER_TYPE_DEVICE_MANAGER_XI2 (_clutter_device_manager_xi2_get_type ()) -@@ -51,6 +55,10 @@ struct _ClutterDeviceManagerXI2 - GList *slave_devices; - - int opcode; -+ -+#ifdef HAVE_LIBWACOM -+ WacomDeviceDatabase *wacom_db; -+#endif - }; - - struct _ClutterDeviceManagerXI2Class -diff --git a/clutter/clutter/x11/clutter-input-device-xi2.c b/clutter/clutter/x11/clutter-input-device-xi2.c -index 7fb0e05..2d9b6d2 100644 ---- a/clutter/clutter/x11/clutter-input-device-xi2.c -+++ b/clutter/clutter/x11/clutter-input-device-xi2.c -@@ -45,6 +45,10 @@ struct _ClutterInputDeviceXI2 - - gint device_id; - ClutterInputDeviceTool *current_tool; -+ -+#ifdef HAVE_LIBWACOM -+ WacomDevice *wacom_device; -+#endif - }; - - #define N_BUTTONS 5 -@@ -88,15 +92,94 @@ clutter_input_device_xi2_is_grouped (ClutterInputDevice *device, - } - - static void -+clutter_input_device_xi2_finalize (GObject *object) -+{ -+#ifdef HAVE_LIBWACOM -+ ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (object); -+ -+ if (device_xi2->wacom_device) -+ libwacom_destroy (device_xi2->wacom_device); -+#endif -+ -+ G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->finalize (object); -+} -+ -+static gint -+clutter_input_device_xi2_get_group_n_modes (ClutterInputDevice *device, -+ gint group) -+{ -+#ifdef HAVE_LIBWACOM -+ ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (device); -+ -+ if (device_xi2->wacom_device) -+ { -+ if (group == 0) -+ { -+ if (libwacom_has_ring (device_xi2->wacom_device)) -+ return libwacom_get_ring_num_modes (device_xi2->wacom_device); -+ else if (libwacom_get_num_strips (device_xi2->wacom_device) >= 1) -+ return libwacom_get_strips_num_modes (device_xi2->wacom_device); -+ } -+ else if (group == 1) -+ { -+ if (libwacom_has_ring2 (device_xi2->wacom_device)) -+ return libwacom_get_ring2_num_modes (device_xi2->wacom_device); -+ else if (libwacom_get_num_strips (device_xi2->wacom_device) >= 2) -+ return libwacom_get_strips_num_modes (device_xi2->wacom_device); -+ } -+ } -+#endif -+ -+ return -1; -+} -+ -+#ifdef HAVE_LIBWACOM -+static int -+clutter_input_device_xi2_get_button_group (ClutterInputDevice *device, -+ guint button) -+{ -+ ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (device); -+ -+ if (device_xi2->wacom_device) -+ { -+ if (button >= libwacom_get_num_buttons (device_xi2->wacom_device)) -+ return -1; -+ -+ return libwacom_get_button_led_group (device_xi2->wacom_device, -+ 'A' + button); -+ } -+ else -+ return -1; -+} -+#endif -+ -+static gboolean -+clutter_input_device_xi2_is_mode_switch_button (ClutterInputDevice *device, -+ guint group, -+ guint button) -+{ -+ int button_group = -1; -+ -+#ifdef HAVE_LIBWACOM -+ button_group = clutter_input_device_xi2_get_button_group (device, button); -+#endif -+ -+ return button_group == (int) group; -+} -+ -+static void - clutter_input_device_xi2_class_init (ClutterInputDeviceXI2Class *klass) - { - GObjectClass *gobject_class = G_OBJECT_CLASS (klass); - ClutterInputDeviceClass *device_class = CLUTTER_INPUT_DEVICE_CLASS (klass); - - gobject_class->constructed = clutter_input_device_xi2_constructed; -+ gobject_class->finalize = clutter_input_device_xi2_finalize; - - device_class->keycode_to_evdev = clutter_input_device_xi2_keycode_to_evdev; - device_class->is_grouped = clutter_input_device_xi2_is_grouped; -+ device_class->get_group_n_modes = clutter_input_device_xi2_get_group_n_modes; -+ device_class->is_mode_switch_button = clutter_input_device_xi2_is_mode_switch_button; - } - - static void -@@ -196,3 +279,17 @@ clutter_input_device_xi2_get_current_tool (ClutterInputDevice *device) - ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (device); - return device_xi2->current_tool; - } -+ -+#ifdef HAVE_LIBWACOM -+void -+clutter_input_device_xi2_ensure_wacom_info (ClutterInputDevice *device, -+ WacomDeviceDatabase *wacom_db) -+{ -+ ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (device); -+ const gchar *node_path; -+ -+ node_path = clutter_input_device_get_device_node (device); -+ device_xi2->wacom_device = libwacom_new_from_path (wacom_db, node_path, -+ WFALLBACK_NONE, NULL); -+} -+#endif -diff --git a/clutter/clutter/x11/clutter-input-device-xi2.h b/clutter/clutter/x11/clutter-input-device-xi2.h -index b93684f..e30fb4d 100644 ---- a/clutter/clutter/x11/clutter-input-device-xi2.h -+++ b/clutter/clutter/x11/clutter-input-device-xi2.h -@@ -27,6 +27,10 @@ - #include - #include - -+#ifdef HAVE_LIBWACOM -+#include -+#endif -+ - G_BEGIN_DECLS - - #define CLUTTER_TYPE_INPUT_DEVICE_XI2 (_clutter_input_device_xi2_get_type ()) -@@ -45,6 +49,12 @@ void clutter_input_device_xi2_update_tool (ClutterInputDevice *device, - ClutterInputDeviceTool *tool); - ClutterInputDeviceTool * clutter_input_device_xi2_get_current_tool (ClutterInputDevice *device); - -+#ifdef HAVE_LIBWACOM -+void clutter_input_device_xi2_ensure_wacom_info (ClutterInputDevice *device, -+ WacomDeviceDatabase *wacom_db); -+ -+#endif -+ - G_END_DECLS - - #endif /* __CLUTTER_INPUT_DEVICE_XI2_H__ */ -diff --git a/clutter/configure.ac b/clutter/configure.ac -index 3c3d0c5..5474fa0 100644 ---- a/clutter/configure.ac -+++ b/clutter/configure.ac -@@ -121,6 +121,7 @@ m4_define([xcomposite_req_version], [0.4]) - m4_define([gdk_req_version], [3.3.18]) - m4_define([libinput_req_version], [1.4.0]) - m4_define([libudev_req_version], [136]) -+m4_define([libwacom_req_version], [0.13]) - - AC_SUBST([GLIB_REQ_VERSION], [glib_req_version]) - AC_SUBST([COGL_REQ_VERSION], [cogl_req_version]) -@@ -133,6 +134,7 @@ AC_SUBST([XCOMPOSITE_REQ_VERSION], [xcomposite_req_version]) - AC_SUBST([GDK_REQ_VERSION], [gdk_req_version]) - AC_SUBST([LIBINPUT_REQ_VERSION], [libinput_req_version]) - AC_SUBST([LIBUDEV_REQ_VERSION], [libudev_req_version]) -+AC_SUBST([LIBWACOM_REQ_VERSION], [libwacom_req_version]) - - # Checks for typedefs, structures, and compiler characteristics. - AM_PATH_GLIB_2_0([glib_req_version], -@@ -508,6 +510,32 @@ X11_EXTS=${X11_EXTS#* } - - AC_CACHE_SAVE - -+dnl === Libwacom support for X11 =============================================== -+AC_ARG_WITH(libwacom, -+ AC_HELP_STRING([--without-libwacom], -+ [disable the use of libwacom for advanced tablet management]),, -+ with_libwacom=auto) -+ -+have_libwacom=no -+AC_MSG_CHECKING([libwacom]) -+if test x$with_libwacom = xno ; then -+ AC_MSG_RESULT([disabled]) -+else -+ if $PKG_CONFIG --exists libwacom '>=' $LIBWACOM_REQ_VERSION; then -+ have_libwacom=yes -+ AC_MSG_RESULT(yes) -+ PKG_CHECK_MODULES([LIBWACOM], [libwacom]) -+ AC_SUBST(LIBWACOM_CFLAGS) -+ AC_SUBST(LIBWACOM_LIBS) -+ AC_DEFINE([HAVE_LIBWACOM], 1, [Building with libwacom for advanced tablet management]) -+ else -+ AC_MSG_RESULT(no) -+ if test x$with_libwacom = xyes ; then -+ AC_MSG_ERROR([libwacom forced but not found]) -+ fi -+ fi -+fi -+ - dnl === Enable GDK-Pixbuf in tests ============================================ - - m4_define([pixbuf_default], [yes]) -@@ -679,8 +707,8 @@ AS_IF([test "x$CLUTTER_BASE_PC_FILES_PRIVATE" = "x" && test "x$BACKEND_PC_FILES_ - AC_SUBST(CLUTTER_REQUIRES) - AC_SUBST(CLUTTER_REQUIRES_PRIVATE) - --CLUTTER_CFLAGS="$FLAVOUR_CFLAGS $CLUTTER_DEPS_CFLAGS $CLUTTER_DEPS_PRIVATE_CFLAGS $GLIB_CFLAGS" --CLUTTER_LIBS="$FLAVOUR_LIBS $CLUTTER_DEPS_LIBS $CLUTTER_DEPS_PRIVATE_LIBS $GLIB_LIBS" -+CLUTTER_CFLAGS="$FLAVOUR_CFLAGS $CLUTTER_DEPS_CFLAGS $CLUTTER_DEPS_PRIVATE_CFLAGS $GLIB_CFLAGS $LIBWACOM_CFLAGS" -+CLUTTER_LIBS="$FLAVOUR_LIBS $CLUTTER_DEPS_LIBS $CLUTTER_DEPS_PRIVATE_LIBS $GLIB_LIBS $LIBWACOM_LIBS" - AC_SUBST(CLUTTER_CFLAGS) - AC_SUBST(CLUTTER_LIBS) - --- -1.8.3.1 - - -From f8fa4b8fa13fba9ed484be74fb7fc82499d46261 Mon Sep 17 00:00:00 2001 -From: Carlos Garnacho -Date: Thu, 22 Feb 2018 17:50:42 +0100 -Subject: [PATCH 2/2] clutter/x11: Communicate proper group/mode on pad events. - -So we can trigger actions for the right mode. - -https://gitlab.gnome.org/GNOME/mutter/issues/48 - -Closes: #48 ---- - clutter/clutter/x11/clutter-device-manager-xi2.c | 15 +++++- - clutter/clutter/x11/clutter-input-device-xi2.c | 61 ++++++++++++++++++++++++ - clutter/clutter/x11/clutter-input-device-xi2.h | 9 ++++ - 3 files changed, 84 insertions(+), 1 deletion(-) - -diff --git a/clutter/clutter/x11/clutter-device-manager-xi2.c b/clutter/clutter/x11/clutter-device-manager-xi2.c -index dee2604..d269a38 100644 ---- a/clutter/clutter/x11/clutter-device-manager-xi2.c -+++ b/clutter/clutter/x11/clutter-device-manager-xi2.c -@@ -1133,7 +1133,7 @@ translate_pad_event (ClutterEvent *event, - ClutterInputDevice *device) - { - gdouble value; -- guint number; -+ guint number, mode = 0; - - if (!translate_pad_axis (device, &xev->valuators, - &event->any.type, -@@ -1147,15 +1147,21 @@ translate_pad_event (ClutterEvent *event, - if (xev->evtype == XI_Motion) - value = -1; - -+#ifdef HAVE_LIBWACOM -+ mode = clutter_input_device_xi2_get_pad_group_mode (device, number); -+#endif -+ - if (event->any.type == CLUTTER_PAD_RING) - { - event->pad_ring.ring_number = number; - event->pad_ring.angle = value; -+ event->pad_ring.mode = mode; - } - else - { - event->pad_strip.strip_number = number; - event->pad_strip.value = value; -+ event->pad_strip.mode = mode; - } - - event->any.time = xev->time; -@@ -1382,6 +1388,13 @@ clutter_device_manager_xi2_translate_event (ClutterEventTranslator *translator, - - /* Pad buttons are 0-indexed */ - event->pad_button.button = xev->detail - 1; -+#ifdef HAVE_LIBWACOM -+ clutter_input_device_xi2_update_pad_state (device, -+ event->pad_button.button, -+ (xi_event->evtype == XI_ButtonPress), -+ &event->pad_button.group, -+ &event->pad_button.mode); -+#endif - clutter_event_set_device (event, device); - clutter_event_set_source_device (event, source_device); - -diff --git a/clutter/clutter/x11/clutter-input-device-xi2.c b/clutter/clutter/x11/clutter-input-device-xi2.c -index 2d9b6d2..f62ba85 100644 ---- a/clutter/clutter/x11/clutter-input-device-xi2.c -+++ b/clutter/clutter/x11/clutter-input-device-xi2.c -@@ -48,6 +48,7 @@ struct _ClutterInputDeviceXI2 - - #ifdef HAVE_LIBWACOM - WacomDevice *wacom_device; -+ GArray *group_modes; - #endif - }; - -@@ -68,6 +69,15 @@ clutter_input_device_xi2_constructed (GObject *gobject) - - if (G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->constructed) - G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->constructed (gobject); -+ -+#ifdef HAVE_LIBWACOM -+ if (clutter_input_device_get_device_type (CLUTTER_INPUT_DEVICE (gobject)) == CLUTTER_PAD_DEVICE) -+ { -+ device_xi2->group_modes = g_array_new (FALSE, TRUE, sizeof (guint)); -+ g_array_set_size (device_xi2->group_modes, -+ clutter_input_device_get_n_mode_groups (CLUTTER_INPUT_DEVICE (gobject))); -+ } -+#endif - } - - static gboolean -@@ -99,6 +109,8 @@ clutter_input_device_xi2_finalize (GObject *object) - - if (device_xi2->wacom_device) - libwacom_destroy (device_xi2->wacom_device); -+ -+ g_array_unref (device_xi2->group_modes); - #endif - - G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->finalize (object); -@@ -292,4 +304,53 @@ clutter_input_device_xi2_ensure_wacom_info (ClutterInputDevice *device, - device_xi2->wacom_device = libwacom_new_from_path (wacom_db, node_path, - WFALLBACK_NONE, NULL); - } -+ -+guint -+clutter_input_device_xi2_get_pad_group_mode (ClutterInputDevice *device, -+ guint group) -+{ -+ ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (device); -+ -+ if (group >= device_xi2->group_modes->len) -+ return 0; -+ -+ return g_array_index (device_xi2->group_modes, guint, group); -+} -+ -+void -+clutter_input_device_xi2_update_pad_state (ClutterInputDevice *device, -+ guint button, -+ guint state, -+ guint *group, -+ guint *mode) -+{ -+ ClutterInputDeviceXI2 *device_xi2 = CLUTTER_INPUT_DEVICE_XI2 (device); -+ guint button_group, *group_mode; -+ 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; -+ -+ group_mode = &g_array_index (device_xi2->group_modes, guint, button_group); -+ -+ if (is_mode_switch && state) -+ { -+ guint next, n_modes; -+ -+ n_modes = clutter_input_device_get_group_n_modes (device, button_group); -+ next = (*group_mode + 1) % n_modes; -+ *group_mode = next; -+ } -+ -+ if (group) -+ *group = button_group; -+ if (mode) -+ *mode = *group_mode; -+} - #endif -diff --git a/clutter/clutter/x11/clutter-input-device-xi2.h b/clutter/clutter/x11/clutter-input-device-xi2.h -index e30fb4d..2194e1b 100644 ---- a/clutter/clutter/x11/clutter-input-device-xi2.h -+++ b/clutter/clutter/x11/clutter-input-device-xi2.h -@@ -53,6 +53,15 @@ ClutterInputDeviceTool * clutter_input_device_xi2_get_current_tool (ClutterInput - void clutter_input_device_xi2_ensure_wacom_info (ClutterInputDevice *device, - WacomDeviceDatabase *wacom_db); - -+guint clutter_input_device_xi2_get_pad_group_mode (ClutterInputDevice *device, -+ guint group); -+ -+void clutter_input_device_xi2_update_pad_state (ClutterInputDevice *device, -+ guint button, -+ guint state, -+ guint *group, -+ guint *mode); -+ - #endif - - G_END_DECLS --- -1.8.3.1 - diff --git a/SOURCES/0001-monitor-manager-Consider-external-layout-before-defa.patch b/SOURCES/0001-monitor-manager-Consider-external-layout-before-defa.patch index 0fffa56..5ef6094 100644 --- a/SOURCES/0001-monitor-manager-Consider-external-layout-before-defa.patch +++ b/SOURCES/0001-monitor-manager-Consider-external-layout-before-defa.patch @@ -13,14 +13,14 @@ back to the default linear config. --- src/backends/meta-monitor-config-manager.c | 75 ++++++++++++++++++++++ src/backends/meta-monitor-config-manager.h | 1 + - src/backends/meta-monitor-manager.c | 19 ++++++ - 3 files changed, 95 insertions(+) + src/backends/meta-monitor-manager.c | 19 ++++++++ + 3 files changed, 97 insertions(+) diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c index 197892bf2..ae988f64a 100644 --- a/src/backends/meta-monitor-config-manager.c +++ b/src/backends/meta-monitor-config-manager.c -@@ -559,6 +559,81 @@ create_preferred_logical_monitor_config (MetaMonitorManager *monitor_ma +@@ -559,6 +559,83 @@ create_preferred_logical_monitor_config (MetaMonitorManager *monitor_ma return logical_monitor_config; } @@ -31,12 +31,14 @@ index 197892bf2..ae988f64a 100644 + 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, -+ output->crtc->rect.x, -+ output->crtc->rect.y, ++ crtc->rect.x, ++ crtc->rect.y, + primary_logical_monitor_config, + layout_mode); +} 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..ede04d7 --- /dev/null +++ b/SOURCES/0001-monitor-manager-only-reuse-initial-config-if-monitor.patch @@ -0,0 +1,505 @@ +From 0cc90f343f4caadb5c4279623a0811c378715a09 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 585ee7034..1ad342a44 100644 +--- a/src/backends/meta-monitor-config-manager.c ++++ b/src/backends/meta-monitor-config-manager.c +@@ -13,60 +13,61 @@ + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + + #include "config.h" + + #include "backends/meta-monitor-config-manager.h" + + #include "backends/meta-monitor-config-migration.h" + #include "backends/meta-monitor-config-store.h" + #include "backends/meta-monitor-manager-private.h" + #include "backends/meta-output.h" + #include "core/boxes-private.h" + + #define CONFIG_HISTORY_MAX_SIZE 3 + + struct _MetaMonitorConfigManager + { + GObject parent; + + MetaMonitorManager *monitor_manager; + + MetaMonitorConfigStore *config_store; + + MetaMonitorsConfig *current_config; ++ MetaMonitorsConfig *initial_config; + GQueue config_history; + }; + + G_DEFINE_TYPE (MetaMonitorConfigManager, meta_monitor_config_manager, + G_TYPE_OBJECT) + + G_DEFINE_TYPE (MetaMonitorsConfig, meta_monitors_config, + G_TYPE_OBJECT) + + static void + meta_crtc_info_free (MetaCrtcInfo *info); + + static void + meta_output_info_free (MetaOutputInfo *info); + + MetaMonitorConfigManager * + meta_monitor_config_manager_new (MetaMonitorManager *monitor_manager) + { + MetaMonitorConfigManager *config_manager; + + config_manager = g_object_new (META_TYPE_MONITOR_CONFIG_MANAGER, NULL); + config_manager->monitor_manager = monitor_manager; + config_manager->config_store = + meta_monitor_config_store_new (monitor_manager); + + return config_manager; + } + + MetaMonitorConfigStore * + meta_monitor_config_manager_get_store (MetaMonitorConfigManager *config_manager) +@@ -552,115 +553,123 @@ create_preferred_logical_monitor_config (MetaMonitorManager *monitor_ma + .width = width, + .height = height + }, + .scale = scale, + .monitor_configs = g_list_append (NULL, monitor_config) + }; + + 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) ++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; + MetaLogicalMonitorConfig *primary_logical_monitor_config; + 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; + + 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); ++ 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 * + meta_monitor_config_manager_create_linear (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; + int x; + GList *monitors; + GList *l; + + primary_monitor = find_primary_monitor (monitor_manager); + if (!primary_monitor) + return NULL; + + layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager); + + primary_logical_monitor_config = + create_preferred_logical_monitor_config (monitor_manager, + primary_monitor, + 0, 0, + NULL, + layout_mode); + primary_logical_monitor_config->is_primary = TRUE; + logical_monitor_configs = g_list_append (NULL, + primary_logical_monitor_config); + +@@ -1135,60 +1144,61 @@ meta_monitor_config_manager_get_current (MetaMonitorConfigManager *config_manage + { + return config_manager->current_config; + } + + MetaMonitorsConfig * + meta_monitor_config_manager_pop_previous (MetaMonitorConfigManager *config_manager) + { + return g_queue_pop_head (&config_manager->config_history); + } + + MetaMonitorsConfig * + meta_monitor_config_manager_get_previous (MetaMonitorConfigManager *config_manager) + { + return g_queue_peek_head (&config_manager->config_history); + } + + void + meta_monitor_config_manager_clear_history (MetaMonitorConfigManager *config_manager) + { + g_queue_foreach (&config_manager->config_history, (GFunc) g_object_unref, NULL); + g_queue_clear (&config_manager->config_history); + } + + static void + meta_monitor_config_manager_dispose (GObject *object) + { + MetaMonitorConfigManager *config_manager = + 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); + } + + static void + meta_monitor_config_manager_init (MetaMonitorConfigManager *config_manager) + { + g_queue_init (&config_manager->config_history); + } + + static void + meta_monitor_config_manager_class_init (MetaMonitorConfigManagerClass *klass) + { + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->dispose = meta_monitor_config_manager_dispose; + } + + void + meta_monitor_config_free (MetaMonitorConfig *monitor_config) + { + meta_monitor_spec_free (monitor_config->monitor_spec); + g_free (monitor_config->mode_spec); + g_free (monitor_config); + } + + void + meta_logical_monitor_config_free (MetaLogicalMonitorConfig *logical_monitor_config) + { +diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h +index c36df38e6..29ef8f8ce 100644 +--- a/src/backends/meta-monitor-config-manager.h ++++ b/src/backends/meta-monitor-config-manager.h +@@ -60,61 +60,61 @@ typedef enum _MetaMonitorsConfigFlag + struct _MetaMonitorsConfig + { + GObject parent; + + MetaMonitorsConfigKey *key; + GList *logical_monitor_configs; + + GList *disabled_monitor_specs; + + MetaMonitorsConfigFlag flags; + + MetaLogicalMonitorLayoutMode layout_mode; + }; + + #define META_TYPE_MONITORS_CONFIG (meta_monitors_config_get_type ()) + G_DECLARE_FINAL_TYPE (MetaMonitorsConfig, meta_monitors_config, + META, MONITORS_CONFIG, GObject) + + MetaMonitorConfigManager * meta_monitor_config_manager_new (MetaMonitorManager *monitor_manager); + + MetaMonitorConfigStore * meta_monitor_config_manager_get_store (MetaMonitorConfigManager *config_manager); + + gboolean meta_monitor_config_manager_assign (MetaMonitorManager *manager, + MetaMonitorsConfig *config, + GPtrArray **crtc_infos, + GPtrArray **output_infos, + GError **error); + + MetaMonitorsConfig * meta_monitor_config_manager_get_stored (MetaMonitorConfigManager *config_manager); + +-MetaMonitorsConfig * meta_monitor_config_manager_create_current (MetaMonitorConfigManager *config_manager); ++MetaMonitorsConfig * meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_manager); + MetaMonitorsConfig * meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_manager); + + MetaMonitorsConfig * meta_monitor_config_manager_create_fallback (MetaMonitorConfigManager *config_manager); + + MetaMonitorsConfig * meta_monitor_config_manager_create_suggested (MetaMonitorConfigManager *config_manager); + + MetaMonitorsConfig * meta_monitor_config_manager_create_for_orientation (MetaMonitorConfigManager *config_manager, + MetaMonitorTransform transform); + + MetaMonitorsConfig * meta_monitor_config_manager_create_for_rotate_monitor (MetaMonitorConfigManager *config_manager); + + MetaMonitorsConfig * meta_monitor_config_manager_create_for_switch_config (MetaMonitorConfigManager *config_manager, + MetaMonitorSwitchConfigType config_type); + + void meta_monitor_config_manager_set_current (MetaMonitorConfigManager *config_manager, + MetaMonitorsConfig *config); + + MetaMonitorsConfig * meta_monitor_config_manager_get_current (MetaMonitorConfigManager *config_manager); + + MetaMonitorsConfig * meta_monitor_config_manager_pop_previous (MetaMonitorConfigManager *config_manager); + + MetaMonitorsConfig * meta_monitor_config_manager_get_previous (MetaMonitorConfigManager *config_manager); + + void meta_monitor_config_manager_clear_history (MetaMonitorConfigManager *config_manager); + + void meta_monitor_config_manager_save_current (MetaMonitorConfigManager *config_manager); + + MetaMonitorsConfig * meta_monitors_config_new_full (GList *logical_monitor_configs, + GList *disabled_monitors, + MetaLogicalMonitorLayoutMode layout_mode, +diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c +index 4503eb841..f7ada0136 100644 +--- a/src/backends/meta-monitor-manager.c ++++ b/src/backends/meta-monitor-manager.c +@@ -469,73 +469,87 @@ meta_monitor_manager_apply_monitors_config (MetaMonitorManager *manager, + + return TRUE; + } + + gboolean + meta_monitor_manager_has_hotplug_mode_update (MetaMonitorManager *manager) + { + GList *l; + + for (l = manager->gpus; l; l = l->next) + { + MetaGpu *gpu = l->data; + + if (meta_gpu_has_hotplug_mode_update (gpu)) + return TRUE; + } + + return FALSE; + } + + static gboolean + should_use_stored_config (MetaMonitorManager *manager) + { + return (manager->in_init || + !meta_monitor_manager_has_hotplug_mode_update (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; + + use_stored_config = should_use_stored_config (manager); + if (use_stored_config) + method = META_MONITORS_CONFIG_METHOD_PERSISTENT; + 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); + if (config) + { + if (!meta_monitor_manager_apply_monitors_config (manager, + config, + method, + &error)) + { + config = NULL; + g_warning ("Failed to use stored monitor configuration: %s", + error->message); + g_clear_error (&error); + } + else + { + g_object_ref (config); + goto done; + } + } + } + + config = meta_monitor_config_manager_create_suggested (manager->config_manager); + if (config) + { + if (!meta_monitor_manager_apply_monitors_config (manager, + config, + method, + &error)) +@@ -549,61 +563,61 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager) + { + goto done; + } + } + + config = meta_monitor_config_manager_get_previous (manager->config_manager); + if (config) + { + config = g_object_ref (config); + + if (meta_monitor_manager_is_config_complete (manager, config)) + { + if (!meta_monitor_manager_apply_monitors_config (manager, + config, + method, + &error)) + { + g_warning ("Failed to use suggested monitor configuration: %s", + error->message); + g_clear_error (&error); + } + else + { + goto done; + } + } + + 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, + 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) + { + if (!meta_monitor_manager_apply_monitors_config (manager, + config, + method, + &error)) + { + g_clear_object (&config); + g_warning ("Failed to use linear monitor configuration: %s", + error->message); + g_clear_error (&error); +-- +2.17.1 + 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 index 127f61d..857ab93 100644 --- a/SOURCES/0001-monitor-manager-xrandr-Force-an-update-when-resuming.patch +++ b/SOURCES/0001-monitor-manager-xrandr-Force-an-update-when-resuming.patch @@ -1,107 +1,526 @@ -From ed7cad0561b79e68ddd91f0e12042087199676ea Mon Sep 17 00:00:00 2001 +From 100795c2729305f919ff9611c877ea3e74d528b7 Mon Sep 17 00:00:00 2001 From: Rui Matos -Date: Sun, 25 Oct 2015 16:14:58 +0100 -Subject: [PATCH 3/8] monitor-manager-xrandr: Force an update when resuming - from suspend +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/x11/meta-monitor-manager-xrandr.c | 188 ++++++++++++++++++------- - 1 file changed, 137 insertions(+), 51 deletions(-) + src/backends/meta-gpu.c | 7 ++ + src/backends/meta-gpu.h | 2 + + src/backends/x11/meta-gpu-xrandr.c | 26 ++++- + .../x11/meta-monitor-manager-xrandr.c | 96 +++++++++++++++++-- + 4 files changed, 121 insertions(+), 10 deletions(-) -diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c -index 8d1bdfb69..d451fcccc 100644 ---- a/src/backends/x11/meta-monitor-manager-xrandr.c -+++ b/src/backends/x11/meta-monitor-manager-xrandr.c -@@ -61,6 +61,11 @@ struct _MetaMonitorManagerXrandr - XRRScreenResources *resources; - int rr_event_base; - int rr_error_base; -+ -+ guint logind_watch_id; -+ guint logind_signal_sub_id; -+ -+ gboolean need_hardware_poll; - gboolean has_randr15; +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 +@@ -37,60 +37,67 @@ enum + static GParamSpec *obj_props[PROP_LAST]; - xcb_timestamp_t last_xrandr_set_timestamp; -@@ -787,8 +792,15 @@ meta_monitor_manager_xrandr_read_current (MetaMonitorManager *manager) - manager->screen_width = WidthOfScreen (screen); - manager->screen_height = HeightOfScreen (screen); + typedef struct _MetaGpuPrivate + { + MetaMonitorManager *monitor_manager; -- resources = XRRGetScreenResourcesCurrent (manager_xrandr->xdisplay, -- DefaultRootWindow (manager_xrandr->xdisplay)); -+ if (manager_xrandr->need_hardware_poll) -+ { -+ resources = XRRGetScreenResources (manager_xrandr->xdisplay, -+ DefaultRootWindow (manager_xrandr->xdisplay)); -+ manager_xrandr->need_hardware_poll = FALSE; -+ } -+ else -+ resources = XRRGetScreenResourcesCurrent (manager_xrandr->xdisplay, -+ DefaultRootWindow (manager_xrandr->xdisplay)); - if (!resources) - return; + GList *outputs; + GList *crtcs; + GList *modes; + } MetaGpuPrivate; -@@ -1910,6 +1922,115 @@ meta_monitor_manager_xrandr_get_default_layout_mode (MetaMonitorManager *manager - return META_LOGICAL_MONITOR_LAYOUT_MODE_PHYSICAL; + G_DEFINE_TYPE_WITH_PRIVATE (MetaGpu, meta_gpu, G_TYPE_OBJECT) + + gboolean + meta_gpu_has_hotplug_mode_update (MetaGpu *gpu) + { + MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); + GList *l; + + for (l = priv->outputs; l; l = l->next) + { + MetaOutput *output = l->data; + + if (output->hotplug_mode_update) + return TRUE; + } + + return FALSE; } -+static gboolean -+is_xvnc (MetaMonitorManager *manager) ++void ++meta_gpu_poll_hardware (MetaGpu *gpu) +{ -+ unsigned int i; -+ -+ for (i = 0; i < manager->n_outputs; ++i) -+ if (g_str_has_prefix (manager->outputs[i].name, "VNC-")) -+ return TRUE; -+ -+ return FALSE; ++ 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) + { + MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); + gboolean ret; + GList *old_outputs; + GList *old_crtcs; + GList *old_modes; + + /* TODO: Get rid of this when objects incref:s what they need instead */ + old_outputs = priv->outputs; + old_crtcs = priv->crtcs; + old_modes = priv->modes; + + ret = META_GPU_GET_CLASS (gpu)->read_current (gpu, error); + + g_list_free_full (old_outputs, g_object_unref); + g_list_free_full (old_modes, g_object_unref); + g_list_free_full (old_crtcs, g_object_unref); + + return ret; + } + + MetaMonitorManager * + meta_gpu_get_monitor_manager (MetaGpu *gpu) + { + MetaGpuPrivate *priv = meta_gpu_get_instance_private (gpu); + + return priv->monitor_manager; +diff --git a/src/backends/meta-gpu.h b/src/backends/meta-gpu.h +index 4badcbd26..3cec8e5b0 100644 +--- a/src/backends/meta-gpu.h ++++ b/src/backends/meta-gpu.h +@@ -8,59 +8,61 @@ + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA + * 02111-1307, USA. + */ + + #ifndef META_GPU_H + #define META_GPU_H + + #include + + #include "backends/meta-monitor-manager-private.h" + + #define META_TYPE_GPU (meta_gpu_get_type ()) + G_DECLARE_DERIVABLE_TYPE (MetaGpu, meta_gpu, META, GPU, GObject) + + struct _MetaGpuClass + { + GObjectClass parent_class; + + gboolean (* read_current) (MetaGpu *gpu, + GError **error); ++ void (* poll_hardware) (MetaGpu *gpu); + }; + + int meta_gpu_get_kms_fd (MetaGpu *gpu); + + const char * meta_gpu_get_kms_file_path (MetaGpu *gpu); + ++void meta_gpu_poll_hardware (MetaGpu *gpu); + gboolean meta_gpu_read_current (MetaGpu *gpu, + GError **error); + + gboolean meta_gpu_has_hotplug_mode_update (MetaGpu *gpu); + + MetaMonitorManager * meta_gpu_get_monitor_manager (MetaGpu *gpu); + + GList * meta_gpu_get_outputs (MetaGpu *gpu); + + GList * meta_gpu_get_crtcs (MetaGpu *gpu); + + GList * meta_gpu_get_modes (MetaGpu *gpu); + + void meta_gpu_take_outputs (MetaGpu *gpu, + GList *outputs); + + void meta_gpu_take_crtcs (MetaGpu *gpu, + GList *crtcs); + + void meta_gpu_take_modes (MetaGpu *gpu, + GList *modes); + + #endif /* META_GPU_H */ +diff --git a/src/backends/x11/meta-gpu-xrandr.c b/src/backends/x11/meta-gpu-xrandr.c +index 14b46d530..add80c0d2 100644 +--- a/src/backends/x11/meta-gpu-xrandr.c ++++ b/src/backends/x11/meta-gpu-xrandr.c +@@ -17,97 +17,107 @@ + * 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 . + */ + + #include "config.h" + + #include "backends/x11/meta-gpu-xrandr.h" + + #include + #include + #include + + #include "backends/meta-output.h" + #include "backends/x11/meta-crtc-xrandr.h" + #include "backends/x11/meta-monitor-manager-xrandr.h" + #include "backends/x11/meta-output-xrandr.h" + + struct _MetaGpuXrandr + { + MetaGpu parent; + + XRRScreenResources *resources; + + int max_screen_width; + int max_screen_height; ++ ++ gboolean need_hardware_poll; + }; + + G_DEFINE_TYPE (MetaGpuXrandr, meta_gpu_xrandr, META_TYPE_GPU) + + XRRScreenResources * + meta_gpu_xrandr_get_resources (MetaGpuXrandr *gpu_xrandr) + { + return gpu_xrandr->resources; + } + + void + meta_gpu_xrandr_get_max_screen_size (MetaGpuXrandr *gpu_xrandr, + int *max_width, + int *max_height) + { + *max_width = gpu_xrandr->max_screen_width; + *max_height = gpu_xrandr->max_screen_height; + } + + static int + compare_outputs (const void *one, + const void *two) + { + const MetaOutput *o_one = one, *o_two = two; + + return strcmp (o_one->name, o_two->name); + } + + static char * + get_xmode_name (XRRModeInfo *xmode) + { + int width = xmode->width; + int height = xmode->height; + + return g_strdup_printf ("%dx%d", width, height); + } + +static void -+meta_monitor_manager_xrandr_update (MetaMonitorManagerXrandr *manager_xrandr) ++meta_gpu_xrandr_poll_hardware (MetaGpu *gpu) +{ -+ MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr); -+ gboolean is_hotplug; -+ gboolean is_our_configuration; -+ unsigned int timestamp; -+ -+ meta_monitor_manager_read_current_state (manager); ++ MetaGpuXrandr *gpu_xrandr = META_GPU_XRANDR (gpu); + -+ timestamp = manager_xrandr->resources->timestamp; -+ if (is_xvnc (manager)) -+ timestamp += 100; ++ gpu_xrandr->need_hardware_poll = TRUE; ++} + -+ is_hotplug = (timestamp < manager_xrandr->resources->configTimestamp); -+ is_our_configuration = (manager_xrandr->resources->timestamp == -+ manager_xrandr->last_xrandr_set_timestamp); -+ if (is_hotplug) + static gboolean + meta_gpu_xrandr_read_current (MetaGpu *gpu, + GError **error) + { + MetaGpuXrandr *gpu_xrandr = META_GPU_XRANDR (gpu); + 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); + XRRScreenResources *resources; + RROutput primary_output; + unsigned int i, j; + GList *l; + int min_width, min_height; + Screen *screen; + BOOL dpms_capable, dpms_enabled; + CARD16 dpms_state; + GList *outputs = NULL; + GList *modes = NULL; + GList *crtcs = NULL; + + if (gpu_xrandr->resources) + XRRFreeScreenResources (gpu_xrandr->resources); + gpu_xrandr->resources = NULL; + + dpms_capable = DPMSCapable (xdisplay); + + if (dpms_capable && + DPMSInfo (xdisplay, &dpms_state, &dpms_enabled) && +@@ -121,62 +131,72 @@ meta_gpu_xrandr_read_current (MetaGpu *gpu, + case DPMSModeStandby: + monitor_manager->power_save_mode = META_POWER_SAVE_STANDBY; + break; + case DPMSModeSuspend: + monitor_manager->power_save_mode = META_POWER_SAVE_SUSPEND; + break; + case DPMSModeOff: + monitor_manager->power_save_mode = META_POWER_SAVE_OFF; + break; + default: + monitor_manager->power_save_mode = META_POWER_SAVE_UNSUPPORTED; + break; + } + } + else + { + monitor_manager->power_save_mode = META_POWER_SAVE_UNSUPPORTED; + } + + 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); + +- resources = XRRGetScreenResourcesCurrent (xdisplay, +- DefaultRootWindow (xdisplay)); ++ if (gpu_xrandr->need_hardware_poll) + { -+ meta_monitor_manager_on_hotplug (manager); ++ resources = XRRGetScreenResources (xdisplay, ++ DefaultRootWindow (xdisplay)); ++ gpu_xrandr->need_hardware_poll = FALSE; + } + else + { -+ MetaMonitorsConfig *config; ++ resources = XRRGetScreenResourcesCurrent (xdisplay, ++ DefaultRootWindow (xdisplay)); ++ } + -+ if (is_our_configuration) -+ { -+ MetaMonitorConfigManager *config_manager = -+ meta_monitor_manager_get_config_manager (manager); + if (!resources) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "Failed to retrieve Xrandr screen resources"); + return FALSE; + } + + gpu_xrandr->resources = resources; + + outputs = NULL; + modes = NULL; + crtcs = NULL; + + for (i = 0; i < (unsigned)resources->nmode; i++) + { + XRRModeInfo *xmode = &resources->modes[i]; + MetaCrtcMode *mode; + + mode = g_object_new (META_TYPE_CRTC_MODE, NULL); + + mode->mode_id = xmode->id; + mode->width = xmode->width; + mode->height = xmode->height; + mode->refresh_rate = (xmode->dotClock / + ((float)xmode->hTotal * xmode->vTotal)); + mode->flags = xmode->modeFlags; + mode->name = get_xmode_name (xmode); + + modes = g_list_append (modes, mode); + } +@@ -255,42 +275,44 @@ meta_gpu_xrandr_read_current (MetaGpu *gpu, + } + } + } + } + + return TRUE; + } + + MetaGpuXrandr * + meta_gpu_xrandr_new (MetaMonitorManagerXrandr *monitor_manager_xrandr) + { + return g_object_new (META_TYPE_GPU_XRANDR, + "monitor-manager", monitor_manager_xrandr, + NULL); + } + + static void + meta_gpu_xrandr_finalize (GObject *object) + { + MetaGpuXrandr *gpu_xrandr = META_GPU_XRANDR (object); + + g_clear_pointer (&gpu_xrandr->resources, + XRRFreeScreenResources); + + G_OBJECT_CLASS (meta_gpu_xrandr_parent_class)->finalize (object); + } + + static void + meta_gpu_xrandr_init (MetaGpuXrandr *gpu_xrandr) + { ++ gpu_xrandr->need_hardware_poll = TRUE; + } + + static void + meta_gpu_xrandr_class_init (MetaGpuXrandrClass *klass) + { + GObjectClass *object_class = G_OBJECT_CLASS (klass); + MetaGpuClass *gpu_class = META_GPU_CLASS (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 90a3952db..2d9a32339 100644 +--- a/src/backends/x11/meta-monitor-manager-xrandr.c ++++ b/src/backends/x11/meta-monitor-manager-xrandr.c +@@ -33,95 +33,101 @@ + #include + + #include + #include + #include + #include + + #include "meta-backend-x11.h" + #include + #include + #include "backends/meta-crtc.h" + #include "backends/meta-monitor-config-manager.h" + #include "backends/meta-logical-monitor.h" + #include "backends/meta-output.h" + #include "backends/x11/meta-crtc-xrandr.h" + #include "backends/x11/meta-gpu-xrandr.h" + #include "backends/x11/meta-output-xrandr.h" + + /* Look for DPI_FALLBACK in: + * http://git.gnome.org/browse/gnome-settings-daemon/tree/plugins/xsettings/gsd-xsettings-manager.c + * for the reasoning */ + #define DPI_FALLBACK 96.0 + + struct _MetaMonitorManagerXrandr + { + MetaMonitorManager parent_instance; + + Display *xdisplay; + int rr_event_base; + int rr_error_base; + -+ config = meta_monitor_config_manager_get_current (config_manager); -+ } -+ else -+ { -+ config = NULL; -+ } ++ guint logind_watch_id; ++ guint logind_signal_sub_id; + -+ meta_monitor_manager_rebuild_derived (manager, config); -+ } -+} + gboolean has_randr15; + + /* + * The X server deals with multiple GPUs for us, soe just see what the X + * server gives us as one single GPU, even though it may actually be backed + * by multiple. + */ + MetaGpu *gpu; + + xcb_timestamp_t last_xrandr_set_timestamp; + + #ifdef HAVE_XRANDR15 + GHashTable *tiled_monitor_atoms; + #endif /* HAVE_XRANDR15 */ + + float *supported_scales; + int n_supported_scales; + }; + + struct _MetaMonitorManagerXrandrClass + { + MetaMonitorManagerClass parent_class; + }; + + G_DEFINE_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, META_TYPE_MONITOR_MANAGER); + + #ifdef HAVE_XRANDR15 + typedef struct _MetaMonitorXrandrData + { + Atom xrandr_name; + } MetaMonitorXrandrData; + + GQuark quark_meta_monitor_xrandr_data; + #endif /* HAVE_RANDR15 */ + ++static void meta_monitor_manager_xrandr_update (MetaMonitorManagerXrandr *manager_xrandr); + + Display * + meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *manager_xrandr) + { + return manager_xrandr->xdisplay; + } + + gboolean + meta_monitor_manager_xrandr_has_randr15 (MetaMonitorManagerXrandr *manager_xrandr) + { + return manager_xrandr->has_randr15; + } + + static GBytes * + meta_monitor_manager_xrandr_read_edid (MetaMonitorManager *manager, + MetaOutput *output) + { + return meta_output_xrandr_read_edid (output); + } + + static void + meta_monitor_manager_xrandr_set_power_save_mode (MetaMonitorManager *manager, + MetaPowerSave mode) + { + MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (manager); + CARD16 state; + + switch (mode) { + case META_POWER_SAVE_ON: + state = DPMSModeOn; + break; +@@ -934,198 +940,272 @@ meta_monitor_manager_xrandr_calculate_supported_scales (MetaMonitorManager + manager_xrandr->n_supported_scales * sizeof (float)); + } + + static MetaMonitorManagerCapability + meta_monitor_manager_xrandr_get_capabilities (MetaMonitorManager *manager) + { + return (META_MONITOR_MANAGER_CAPABILITY_MIRRORING | + META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED); + } + + static gboolean + meta_monitor_manager_xrandr_get_max_screen_size (MetaMonitorManager *manager, + int *max_width, + int *max_height) + { + MetaMonitorManagerXrandr *manager_xrandr = + META_MONITOR_MANAGER_XRANDR (manager); + + meta_gpu_xrandr_get_max_screen_size (META_GPU_XRANDR (manager_xrandr->gpu), + max_width, max_height); + + return TRUE; + } + + static MetaLogicalMonitorLayoutMode + 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, @@ -120,7 +539,7 @@ index 8d1bdfb69..d451fcccc 100644 + g_variant_get (parameters, "(b)", &suspending); + if (!suspending) + { -+ manager_xrandr->need_hardware_poll = TRUE; ++ meta_gpu_poll_hardware (manager_xrandr->gpu); + meta_monitor_manager_xrandr_update (manager_xrandr); + } +} @@ -159,25 +578,60 @@ index 8d1bdfb69..d451fcccc 100644 +} + static void - meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr) + meta_monitor_manager_xrandr_constructed (GObject *object) { -@@ -1948,6 +2069,15 @@ meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr) + MetaMonitorManagerXrandr *manager_xrandr = + META_MONITOR_MANAGER_XRANDR (object); + MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr); + MetaBackendX11 *backend = + META_BACKEND_X11 (meta_monitor_manager_get_backend (manager)); + + manager_xrandr->xdisplay = meta_backend_x11_get_xdisplay (backend); + + manager_xrandr->gpu = META_GPU (meta_gpu_xrandr_new (manager_xrandr)); + meta_monitor_manager_add_gpu (manager, manager_xrandr->gpu); + + if (!XRRQueryExtension (manager_xrandr->xdisplay, + &manager_xrandr->rr_event_base, + &manager_xrandr->rr_error_base)) + { + return; + } + else + { + int major_version, minor_version; + /* We only use ScreenChangeNotify, but GDK uses the others, + and we don't want to step on its toes */ + XRRSelectInput (manager_xrandr->xdisplay, + DefaultRootWindow (manager_xrandr->xdisplay), + RRScreenChangeNotifyMask + | RRCrtcChangeNotifyMask + | RROutputPropertyNotifyMask); + + manager_xrandr->has_randr15 = FALSE; + XRRQueryVersion (manager_xrandr->xdisplay, &major_version, + &minor_version); + #ifdef HAVE_XRANDR15 + if (major_version > 1 || + (major_version == 1 && + minor_version >= 5)) + { + manager_xrandr->has_randr15 = TRUE; + manager_xrandr->tiled_monitor_atoms = g_hash_table_new (NULL, NULL); + } meta_monitor_manager_xrandr_init_monitors (manager_xrandr); #endif } -+ -+ 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); -+ manager_xrandr->need_hardware_poll = TRUE; + + G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->constructed (object); } static void -@@ -1962,6 +2092,10 @@ meta_monitor_manager_xrandr_finalize (GObject *object) + meta_monitor_manager_xrandr_finalize (GObject *object) + { + MetaMonitorManagerXrandr *manager_xrandr = META_MONITOR_MANAGER_XRANDR (object); + + g_clear_object (&manager_xrandr->gpu); g_hash_table_destroy (manager_xrandr->tiled_monitor_atoms); g_free (manager_xrandr->supported_scales); @@ -188,72 +642,135 @@ index 8d1bdfb69..d451fcccc 100644 G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object); } -@@ -1996,64 +2130,16 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass) + 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 + meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass) + { + MetaMonitorManagerClass *manager_class = META_MONITOR_MANAGER_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->finalize = meta_monitor_manager_xrandr_finalize; + object_class->constructed = meta_monitor_manager_xrandr_constructed; + + manager_class->read_edid = meta_monitor_manager_xrandr_read_edid; + manager_class->ensure_initial_config = meta_monitor_manager_xrandr_ensure_initial_config; + manager_class->apply_monitors_config = meta_monitor_manager_xrandr_apply_monitors_config; + manager_class->set_power_save_mode = meta_monitor_manager_xrandr_set_power_save_mode; + manager_class->change_backlight = meta_monitor_manager_xrandr_change_backlight; + manager_class->get_crtc_gamma = meta_monitor_manager_xrandr_get_crtc_gamma; + manager_class->set_crtc_gamma = meta_monitor_manager_xrandr_set_crtc_gamma; + #ifdef HAVE_XRANDR15 + manager_class->tiled_monitor_added = meta_monitor_manager_xrandr_tiled_monitor_added; + manager_class->tiled_monitor_removed = meta_monitor_manager_xrandr_tiled_monitor_removed; + #endif + manager_class->is_transform_handled = meta_monitor_manager_xrandr_is_transform_handled; + manager_class->calculate_monitor_mode_scale = meta_monitor_manager_xrandr_calculate_monitor_mode_scale; + manager_class->calculate_supported_scales = meta_monitor_manager_xrandr_calculate_supported_scales; + manager_class->get_capabilities = meta_monitor_manager_xrandr_get_capabilities; + manager_class->get_max_screen_size = meta_monitor_manager_xrandr_get_max_screen_size; + manager_class->get_default_layout_mode = meta_monitor_manager_xrandr_get_default_layout_mode; + + quark_meta_monitor_xrandr_data = g_quark_from_static_string ("-meta-monitor-xrandr-data"); } --static gboolean --is_xvnc (MetaMonitorManager *manager) --{ -- unsigned int i; -- -- for (i = 0; i < manager->n_outputs; ++i) -- if (g_str_has_prefix (manager->outputs[i].name, "VNC-")) -- return TRUE; -- -- return FALSE; --} -- - gboolean - meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr, - XEvent *event) + static gboolean + is_xvnc (MetaMonitorManager *manager) { -- MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr); -- gboolean is_hotplug; -- gboolean is_our_configuration; -- unsigned int timestamp; -- - if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify) - return FALSE; + MetaMonitorManagerXrandr *manager_xrandr = + META_MONITOR_MANAGER_XRANDR (manager); + GList *l; - XRRUpdateConfiguration (event); + for (l = meta_gpu_get_outputs (manager_xrandr->gpu); l; l = l->next) + { + MetaOutput *output = l->data; -- meta_monitor_manager_read_current_state (manager); -- -- -- timestamp = manager_xrandr->resources->timestamp; -- if (is_xvnc (manager)) -- timestamp += 100; -- -- is_hotplug = (timestamp < manager_xrandr->resources->configTimestamp); -- is_our_configuration = (manager_xrandr->resources->timestamp == -- manager_xrandr->last_xrandr_set_timestamp); -- if (is_hotplug) -- { -- meta_monitor_manager_on_hotplug (manager); -- } -- else -- { -- MetaMonitorsConfig *config; -- -- if (is_our_configuration) -- { -- MetaMonitorConfigManager *config_manager = -- meta_monitor_manager_get_config_manager (manager); + if (g_str_has_prefix (output->name, "VNC-")) + return TRUE; + } + + 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; + XRRScreenResources *resources; + gboolean is_hotplug; + gboolean is_our_configuration; + unsigned int timestamp; + +- if ((event->type - manager_xrandr->rr_event_base) != RRScreenChangeNotify) +- return FALSE; - -- config = meta_monitor_config_manager_get_current (config_manager); -- } -- else -- { -- config = NULL; -- } +- XRRUpdateConfiguration (event); - -- meta_monitor_manager_xrandr_rebuild_derived (manager, config); -- } + meta_monitor_manager_read_current_state (manager); + + gpu_xrandr = META_GPU_XRANDR (manager_xrandr->gpu); + resources = meta_gpu_xrandr_get_resources (gpu_xrandr); + + 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) + { + meta_monitor_manager_on_hotplug (manager); + } + else + { + MetaMonitorsConfig *config; + + if (is_our_configuration) + { + MetaMonitorConfigManager *config_manager = + meta_monitor_manager_get_config_manager (manager); + + config = meta_monitor_config_manager_get_current (config_manager); + } + else + { + config = NULL; + } + + 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.14.2 +2.17.1 diff --git a/SOURCES/0001-monitor-manager-xrandr-Work-around-spurious-hotplugs.patch b/SOURCES/0001-monitor-manager-xrandr-Work-around-spurious-hotplugs.patch index 73e1cd5..ff9cd9f 100644 --- a/SOURCES/0001-monitor-manager-xrandr-Work-around-spurious-hotplugs.patch +++ b/SOURCES/0001-monitor-manager-xrandr-Work-around-spurious-hotplugs.patch @@ -1,8 +1,7 @@ -From 73cae2c78af65cdfd6fa0c8257b4d3ae593f9f74 Mon Sep 17 00:00:00 2001 +From ad61347e9d92380fbbb4effd8a19349777d76715 Mon Sep 17 00:00:00 2001 From: Rui Matos Date: Tue, 6 Oct 2015 21:16:18 +0200 -Subject: [PATCH 2/8] monitor-manager-xrandr: Work around spurious hotplugs on - Xvnc +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 @@ -10,25 +9,31 @@ 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. --- - src/backends/x11/meta-monitor-manager-xrandr.c | 20 ++++++++++++++++++-- - 1 file changed, 18 insertions(+), 2 deletions(-) + .../x11/meta-monitor-manager-xrandr.c | 25 ++++++++++++++++++- + 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c -index c369d4960..8d1bdfb69 100644 +index dbe3e4e3b..90a3952db 100644 --- a/src/backends/x11/meta-monitor-manager-xrandr.c +++ b/src/backends/x11/meta-monitor-manager-xrandr.c -@@ -1909,6 +1909,18 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass) +@@ -1058,6 +1058,24 @@ meta_monitor_manager_xrandr_class_init (MetaMonitorManagerXrandrClass *klass) g_quark_from_static_string ("-meta-monitor-xrandr-data"); } +static gboolean +is_xvnc (MetaMonitorManager *manager) +{ -+ unsigned int i; ++ MetaMonitorManagerXrandr *manager_xrandr = ++ META_MONITOR_MANAGER_XRANDR (manager); ++ GList *l; + -+ for (i = 0; i < manager->n_outputs; ++i) -+ if (g_str_has_prefix (manager->outputs[i].name, "VNC-")) -+ return TRUE; ++ for (l = meta_gpu_get_outputs (manager_xrandr->gpu); l; l = l->next) ++ { ++ MetaOutput *output = l->data; ++ ++ if (g_str_has_prefix (output->name, "VNC-")) ++ return TRUE; ++ } + + return FALSE; +} @@ -36,28 +41,27 @@ index c369d4960..8d1bdfb69 100644 gboolean meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr, XEvent *event) -@@ -1916,6 +1928,7 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra - MetaMonitorManager *manager = META_MONITOR_MANAGER (manager_xrandr); +@@ -1067,6 +1085,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; -@@ -1925,8 +1938,11 @@ meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xra - meta_monitor_manager_read_current_state (manager); - +@@ -1078,7 +1097,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 = (manager_xrandr->resources->timestamp < -- manager_xrandr->resources->configTimestamp); -+ timestamp = manager_xrandr->resources->timestamp; +- is_hotplug = resources->timestamp < resources->configTimestamp; ++ timestamp = resources->timestamp; + if (is_xvnc (manager)) + timestamp += 100; + -+ is_hotplug = (timestamp < manager_xrandr->resources->configTimestamp); - is_our_configuration = (manager_xrandr->resources->timestamp == ++ is_hotplug = timestamp < resources->configTimestamp; + is_our_configuration = (resources->timestamp == manager_xrandr->last_xrandr_set_timestamp); if (is_hotplug) -- -2.14.2 +2.17.0 diff --git a/SOURCES/0001-renderer-native-Check-calculated-transform-when-crea.patch b/SOURCES/0001-renderer-native-Check-calculated-transform-when-crea.patch new file mode 100644 index 0000000..1079d4c --- /dev/null +++ b/SOURCES/0001-renderer-native-Check-calculated-transform-when-crea.patch @@ -0,0 +1,88 @@ +From 91c5c94434b22895f97b3ae47a889ccb902b86aa Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Mon, 23 Jul 2018 21:36:57 +0200 +Subject: [PATCH] renderer/native: Check calculated transform when creating + view + +The "backends: Move MetaOutput::crtc field into private struct" +accidentally changed the view transform calculation code to assume that +"MetaCrtc::transform" corresponds to the transform of the CRTC; so is +not the case yet; one must calculate the transform from the logical +monitor, and check whether it is supported by the CRTC using +meta_monitor_manager_is_transform_handled(). This commit restores the +old behaviour that doesn't use MetaCrtc::transform when calculating the +view transform. + +Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/216 +--- + src/backends/native/meta-renderer-native.c | 9 +++++++-- + src/backends/x11/nested/meta-renderer-x11-nested.c | 8 ++++++-- + 2 files changed, 13 insertions(+), 4 deletions(-) + +diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c +index fc6b223026..8dc0da7104 100644 +--- a/src/backends/native/meta-renderer-native.c ++++ b/src/backends/native/meta-renderer-native.c +@@ -2720,9 +2720,14 @@ calculate_view_transform (MetaMonitorManager *monitor_manager, + MetaMonitor *main_monitor; + MetaOutput *main_output; + MetaCrtc *crtc; ++ MetaMonitorTransform crtc_transform; ++ + main_monitor = meta_logical_monitor_get_monitors (logical_monitor)->data; + main_output = meta_monitor_get_main_output (main_monitor); + crtc = meta_output_get_assigned_crtc (main_output); ++ crtc_transform = ++ meta_monitor_logical_to_crtc_transform (main_monitor, ++ logical_monitor->transform); + + /* + * Pick any monitor and output and check; all CRTCs of a logical monitor will +@@ -2731,10 +2736,10 @@ calculate_view_transform (MetaMonitorManager *monitor_manager, + + if (meta_monitor_manager_is_transform_handled (monitor_manager, + crtc, +- crtc->transform)) ++ crtc_transform)) + return META_MONITOR_TRANSFORM_NORMAL; + else +- return crtc->transform; ++ return crtc_transform; + } + + static MetaRendererView * +diff --git a/src/backends/x11/nested/meta-renderer-x11-nested.c b/src/backends/x11/nested/meta-renderer-x11-nested.c +index 8fdf46b0b5..b29b9c69e2 100644 +--- a/src/backends/x11/nested/meta-renderer-x11-nested.c ++++ b/src/backends/x11/nested/meta-renderer-x11-nested.c +@@ -51,10 +51,14 @@ calculate_view_transform (MetaMonitorManager *monitor_manager, + MetaMonitor *main_monitor; + MetaOutput *main_output; + MetaCrtc *crtc; ++ MetaMonitorTransform crtc_transform; + + main_monitor = meta_logical_monitor_get_monitors (logical_monitor)->data; + main_output = meta_monitor_get_main_output (main_monitor); + crtc = meta_output_get_assigned_crtc (main_output); ++ crtc_transform = ++ meta_monitor_logical_to_crtc_transform (main_monitor, ++ logical_monitor->transform); + /* + * Pick any monitor and output and check; all CRTCs of a logical monitor will + * always have the same transform assigned to them. +@@ -62,10 +66,10 @@ calculate_view_transform (MetaMonitorManager *monitor_manager, + + if (meta_monitor_manager_is_transform_handled (monitor_manager, + crtc, +- crtc->transform)) ++ crtc_transform)) + return META_MONITOR_TRANSFORM_NORMAL; + else +- return crtc->transform; ++ return crtc_transform; + } + + static MetaRendererView * +-- +2.17.1 + diff --git a/SOURCES/0001-renderer-x11-Enable-GPU-memory-purge-error-extension.patch b/SOURCES/0001-renderer-x11-Enable-GPU-memory-purge-error-extension.patch deleted file mode 100644 index 094910d..0000000 --- a/SOURCES/0001-renderer-x11-Enable-GPU-memory-purge-error-extension.patch +++ /dev/null @@ -1,44 +0,0 @@ -From 4b2d21ff03ed389138fcb9bca778aec02bafcadb Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Fri, 2 Feb 2018 14:34:50 +0800 -Subject: [PATCH] renderer/x11: Enable GPU memory purge error extension if - available - -This was done by the clutter X11 backend before prior to introducing -MetaRenderer, but during that work, enabling of said extension was lost. -Let's turn it on again. - -https://bugzilla.gnome.org/show_bug.cgi?id=739178 ---- - src/backends/x11/meta-backend-x11.c | 2 -- - src/backends/x11/meta-renderer-x11.c | 1 + - 2 files changed, 1 insertion(+), 2 deletions(-) - -diff --git a/src/backends/x11/meta-backend-x11.c b/src/backends/x11/meta-backend-x11.c -index 233532435..c7602cc70 100644 ---- a/src/backends/x11/meta-backend-x11.c -+++ b/src/backends/x11/meta-backend-x11.c -@@ -705,8 +705,6 @@ meta_backend_x11_init (MetaBackendX11 *x11) - */ - XInitThreads(); - -- clutter_x11_request_reset_on_video_memory_purge (); -- - /* We do X11 event retrieval ourselves */ - clutter_x11_disable_event_retrieval (); - } -diff --git a/src/backends/x11/meta-renderer-x11.c b/src/backends/x11/meta-renderer-x11.c -index 90924e038..003211d85 100644 ---- a/src/backends/x11/meta-renderer-x11.c -+++ b/src/backends/x11/meta-renderer-x11.c -@@ -73,6 +73,7 @@ meta_renderer_x11_create_cogl_renderer (MetaRenderer *renderer) - cogl_renderer = cogl_renderer_new (); - cogl_renderer_set_custom_winsys (cogl_renderer, get_x11_cogl_winsys_vtable); - cogl_xlib_renderer_set_foreign_display (cogl_renderer, xdisplay); -+ cogl_xlib_renderer_request_reset_on_video_memory_purge (cogl_renderer, TRUE); - - /* Set up things so that if the INTEL_swap_event extension is not present, - * but the driver is known to have good thread support, we use an extra --- -2.14.3 - diff --git a/SOURCES/0001-wayland-Do-not-fail-on-stalled-.X11-unix-entries.patch b/SOURCES/0001-wayland-Do-not-fail-on-stalled-.X11-unix-entries.patch deleted file mode 100644 index d90a588..0000000 --- a/SOURCES/0001-wayland-Do-not-fail-on-stalled-.X11-unix-entries.patch +++ /dev/null @@ -1,37 +0,0 @@ -From 9826eae9f091d461bd117c254ba8e255dd084797 Mon Sep 17 00:00:00 2001 -From: Olivier Fourdan -Date: Fri, 2 Feb 2018 16:35:26 +0100 -Subject: [PATCH] wayland: Do not fail on stalled .X11-unix entries - -If for whatever reason, there are stalled files in /tmp/.X11-unix/ the -bind() to the abstract socket will succeed but not the bind() to the -to the UNIX socket. - -This causes gnome-shell/mutter to fail because it cannot start Xwayland -(while it could actually, by using a different display). - -In case of failure to bind to the UNIX socket, try the next display -instead of failing, to avoid stalled entries in /tmp/.X11-unix. - -Closes: https://gitlab.gnome.org/GNOME/mutter/issues/13 ---- - src/wayland/meta-xwayland.c | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - -diff --git a/src/wayland/meta-xwayland.c b/src/wayland/meta-xwayland.c -index 50cfc7c57..ce21fe5ee 100644 ---- a/src/wayland/meta-xwayland.c -+++ b/src/wayland/meta-xwayland.c -@@ -458,7 +458,8 @@ choose_xdisplay (MetaXWaylandManager *manager) - { - unlink (lock_file); - close (manager->abstract_fd); -- return FALSE; -+ display++; -+ continue; - } - - break; --- -2.14.3 - diff --git a/SOURCES/0003-window-wayland-Handle-resizing-when-headless.patch b/SOURCES/0003-window-wayland-Handle-resizing-when-headless.patch deleted file mode 100644 index 32756c0..0000000 --- a/SOURCES/0003-window-wayland-Handle-resizing-when-headless.patch +++ /dev/null @@ -1,50 +0,0 @@ -From 07e5f7ef29b5567e090221d5da9415e8b84c0ebb Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Mon, 16 Oct 2017 17:02:51 +0800 -Subject: [PATCH 3/4] window/wayland: Handle resizing when headless - -We tried to get the geometry scale, which may depend on the main -logical monitor assigned to the window. To avoid dereferencing a NULL -logical monitor when headless, instead assume the geometry scale is 1. - -https://bugzilla.gnome.org/show_bug.cgi?id=788764 ---- - src/wayland/meta-window-wayland.c | 8 ++++++-- - 1 file changed, 6 insertions(+), 2 deletions(-) - -diff --git a/src/wayland/meta-window-wayland.c b/src/wayland/meta-window-wayland.c -index ed6e34b43..f3f0e1688 100644 ---- a/src/wayland/meta-window-wayland.c -+++ b/src/wayland/meta-window-wayland.c -@@ -67,6 +67,8 @@ G_DEFINE_TYPE (MetaWindowWayland, meta_window_wayland, META_TYPE_WINDOW) - static int - get_window_geometry_scale_for_logical_monitor (MetaLogicalMonitor *logical_monitor) - { -+ g_assert (logical_monitor); -+ - if (meta_is_stage_views_scaled ()) - return 1; - else -@@ -79,8 +81,7 @@ meta_window_wayland_manage (MetaWindow *window) - MetaWindowWayland *wl_window = META_WINDOW_WAYLAND (window); - MetaDisplay *display = window->display; - -- wl_window->geometry_scale = -- get_window_geometry_scale_for_logical_monitor (window->monitor); -+ wl_window->geometry_scale = meta_window_wayland_get_geometry_scale (window); - - meta_display_register_wayland_window (display, window); - -@@ -634,6 +635,9 @@ should_do_pending_move (MetaWindowWayland *wl_window, - int - meta_window_wayland_get_geometry_scale (MetaWindow *window) - { -+ if (!window->monitor) -+ return 1; -+ - return get_window_geometry_scale_for_logical_monitor (window->monitor); - } - --- -2.14.2 - diff --git a/SOURCES/0008-Add-support-for-quad-buffer-stereo.patch b/SOURCES/0008-Add-support-for-quad-buffer-stereo.patch index 82fe332..e5b861e 100644 --- a/SOURCES/0008-Add-support-for-quad-buffer-stereo.patch +++ b/SOURCES/0008-Add-support-for-quad-buffer-stereo.patch @@ -1,7 +1,7 @@ -From 7940ea62307044c056c16f1534e3e8e94cc7a352 Mon Sep 17 00:00:00 2001 +From 77b95bdac1b3cca4d06480e1d7fe1b6c86a32d2f Mon Sep 17 00:00:00 2001 From: "Owen W. Taylor" Date: Thu, 8 May 2014 18:44:15 -0400 -Subject: [PATCH 7/8] Add support for quad-buffer stereo +Subject: [PATCH] Add support for quad-buffer stereo Track the stereo status of windows using the new EXT_stereo_tree GLX extension. @@ -37,10 +37,10 @@ texture_from_pixmap. create mode 100644 src/core/stereo.h diff --git a/src/Makefile.am b/src/Makefile.am -index 6aef50de8..8c680602c 100644 +index 5bbac70..8b21d2f 100644 --- a/src/Makefile.am +++ b/src/Makefile.am -@@ -281,6 +281,8 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \ +@@ -308,6 +308,8 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \ core/stack.h \ core/stack-tracker.c \ core/stack-tracker.h \ @@ -50,7 +50,7 @@ index 6aef50de8..8c680602c 100644 meta/util.h \ core/util-private.h \ diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h -index ba58bf175..1c257b5ee 100644 +index 40c0344..25cab92 100644 --- a/src/compositor/compositor-private.h +++ b/src/compositor/compositor-private.h @@ -21,6 +21,10 @@ struct _MetaCompositor @@ -77,11 +77,11 @@ index ba58bf175..1c257b5ee 100644 MetaWindow *window); diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c -index 17e8a55dd..a1bf1a8f8 100644 +index 8c924d2..e12fb7b 100644 --- a/src/compositor/compositor.c +++ b/src/compositor/compositor.c @@ -70,6 +70,8 @@ - #include "meta-window-group.h" + #include "meta-window-group-private.h" #include "window-private.h" /* to check window->hidden */ #include "display-private.h" /* for meta_display_lookup_x_window() and meta_display_cancel_touch() */ +#include "stack-tracker.h" @@ -89,7 +89,7 @@ index 17e8a55dd..a1bf1a8f8 100644 #include "util-private.h" #include "backends/meta-dnd-private.h" #include "frame.h" -@@ -482,6 +484,97 @@ redirect_windows (MetaScreen *screen) +@@ -487,6 +489,97 @@ redirect_windows (MetaScreen *screen) } } @@ -187,7 +187,7 @@ index 17e8a55dd..a1bf1a8f8 100644 void meta_compositor_manage (MetaCompositor *compositor) { -@@ -490,6 +583,8 @@ meta_compositor_manage (MetaCompositor *compositor) +@@ -495,6 +588,8 @@ meta_compositor_manage (MetaCompositor *compositor) MetaScreen *screen = display->screen; MetaBackend *backend = meta_get_backend (); @@ -196,7 +196,7 @@ index 17e8a55dd..a1bf1a8f8 100644 meta_screen_set_cm_selection (display->screen); compositor->stage = meta_backend_get_stage (backend); -@@ -757,6 +852,23 @@ meta_compositor_process_event (MetaCompositor *compositor, +@@ -759,6 +854,23 @@ meta_compositor_process_event (MetaCompositor *compositor, if (window) process_damage (compositor, (XDamageNotifyEvent *) event, window); } @@ -220,7 +220,7 @@ index 17e8a55dd..a1bf1a8f8 100644 if (compositor->have_x11_sync_object) meta_sync_ring_handle_event (event); -@@ -957,6 +1069,7 @@ meta_compositor_sync_stack (MetaCompositor *compositor, +@@ -969,6 +1081,7 @@ meta_compositor_sync_stack (MetaCompositor *compositor, GList *stack) { GList *old_stack; @@ -228,7 +228,7 @@ index 17e8a55dd..a1bf1a8f8 100644 /* 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 -@@ -1032,6 +1145,8 @@ meta_compositor_sync_stack (MetaCompositor *compositor, +@@ -1044,6 +1157,8 @@ meta_compositor_sync_stack (MetaCompositor *compositor, * near the front of the other.) */ compositor->windows = g_list_prepend (compositor->windows, actor); @@ -237,16 +237,16 @@ index 17e8a55dd..a1bf1a8f8 100644 stack = g_list_remove (stack, window); old_stack = g_list_remove (old_stack, actor); -@@ -1039,6 +1154,8 @@ meta_compositor_sync_stack (MetaCompositor *compositor, +@@ -1051,6 +1166,8 @@ meta_compositor_sync_stack (MetaCompositor *compositor, sync_actor_stacking (compositor); + meta_stereo_set_have_stereo_windows (stereo_window_count > 0); + - compositor->top_window_actor = get_top_visible_window_actor (compositor); - } - -@@ -1237,6 +1354,17 @@ meta_compositor_new (MetaDisplay *display) + if (compositor->top_window_actor) + g_signal_handlers_disconnect_by_func (compositor->top_window_actor, + on_top_window_actor_destroyed, +@@ -1259,6 +1376,17 @@ meta_compositor_new (MetaDisplay *display) meta_post_paint_func, compositor, NULL); @@ -265,7 +265,7 @@ index 17e8a55dd..a1bf1a8f8 100644 } diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h -index 5b3f283c2..189a95312 100644 +index 5b3f283..189a953 100644 --- a/src/compositor/meta-shaped-texture-private.h +++ b/src/compositor/meta-shaped-texture-private.h @@ -30,8 +30,9 @@ @@ -281,7 +281,7 @@ index 5b3f283c2..189a95312 100644 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 98346c6ae..b89de03a3 100644 +index 98346c6..b89de03 100644 --- a/src/compositor/meta-shaped-texture.c +++ b/src/compositor/meta-shaped-texture.c @@ -74,8 +74,10 @@ static guint signals[LAST_SIGNAL]; @@ -550,10 +550,10 @@ index 98346c6ae..b89de03a3 100644 /** diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c -index 551322573..6ca68eb64 100644 +index 7505b7d..9475c20 100644 --- a/src/compositor/meta-surface-actor-wayland.c +++ b/src/compositor/meta-surface-actor-wayland.c -@@ -403,7 +403,7 @@ meta_surface_actor_wayland_dispose (GObject *object) +@@ -187,7 +187,7 @@ meta_surface_actor_wayland_dispose (GObject *object) MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); @@ -562,7 +562,7 @@ index 551322573..6ca68eb64 100644 if (priv->surface) { g_object_remove_weak_pointer (G_OBJECT (priv->surface), -@@ -462,6 +462,14 @@ meta_surface_actor_wayland_new (MetaWaylandSurface *surface) +@@ -246,6 +246,14 @@ meta_surface_actor_wayland_new (MetaWaylandSurface *surface) return META_SURFACE_ACTOR (self); } @@ -578,7 +578,7 @@ index 551322573..6ca68eb64 100644 meta_surface_actor_wayland_get_surface (MetaSurfaceActorWayland *self) { diff --git a/src/compositor/meta-surface-actor-x11.c b/src/compositor/meta-surface-actor-x11.c -index d32aeb68a..52db3808e 100644 +index d32aeb6..52db380 100644 --- a/src/compositor/meta-surface-actor-x11.c +++ b/src/compositor/meta-surface-actor-x11.c @@ -31,6 +31,7 @@ @@ -716,7 +716,7 @@ index d32aeb68a..52db3808e 100644 + return priv->stereo; +} diff --git a/src/compositor/meta-surface-actor-x11.h b/src/compositor/meta-surface-actor-x11.h -index 0e692ee0f..4b2ecccb1 100644 +index 0e692ee..4b2eccc 100644 --- a/src/compositor/meta-surface-actor-x11.h +++ b/src/compositor/meta-surface-actor-x11.h @@ -64,6 +64,11 @@ MetaSurfaceActor * meta_surface_actor_x11_new (MetaWindow *window); @@ -732,12 +732,12 @@ index 0e692ee0f..4b2ecccb1 100644 #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 72dcd1451..035d756b2 100644 +index ce5e7ea..5b011ce 100644 --- a/src/compositor/meta-window-actor-private.h +++ b/src/compositor/meta-window-actor-private.h -@@ -59,4 +59,9 @@ void meta_window_actor_effect_completed (MetaWindowActor *actor, - MetaSurfaceActor *meta_window_actor_get_surface (MetaWindowActor *self); +@@ -60,4 +60,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); @@ -746,12 +746,12 @@ index 72dcd1451..035d756b2 100644 + #endif /* META_WINDOW_ACTOR_PRIVATE_H */ diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c -index 1184cd422..773e6d09d 100644 +index 120b043..b2c7725 100644 --- a/src/compositor/meta-window-actor.c +++ b/src/compositor/meta-window-actor.c -@@ -2150,3 +2150,25 @@ meta_window_actor_sync_updates_frozen (MetaWindowActor *self) - - meta_window_actor_set_updates_frozen (self, meta_window_updates_are_frozen (window)); +@@ -2189,3 +2189,25 @@ meta_window_actor_from_window (MetaWindow *window) + { + return META_WINDOW_ACTOR (meta_window_get_compositor_private (window)); } + +void @@ -776,7 +776,7 @@ index 1184cd422..773e6d09d 100644 + return FALSE; +} diff --git a/src/core/main.c b/src/core/main.c -index dc1f1c4f6..2c1160711 100644 +index 04a42c7..faa2081 100644 --- a/src/core/main.c +++ b/src/core/main.c @@ -47,6 +47,7 @@ @@ -787,7 +787,7 @@ index dc1f1c4f6..2c1160711 100644 #include #include "ui.h" #include -@@ -566,6 +567,9 @@ meta_init (void) +@@ -580,6 +581,9 @@ meta_init (void) meta_init_backend (backend_gtype); @@ -799,7 +799,7 @@ index dc1f1c4f6..2c1160711 100644 #ifdef HAVE_WAYLAND diff --git a/src/core/stereo.c b/src/core/stereo.c new file mode 100644 -index 000000000..5a232b67c +index 0000000..5a232b6 --- /dev/null +++ b/src/core/stereo.c @@ -0,0 +1,153 @@ @@ -958,7 +958,7 @@ index 000000000..5a232b67c +} diff --git a/src/core/stereo.h b/src/core/stereo.h new file mode 100644 -index 000000000..ccd1d702a +index 0000000..ccd1d70 --- /dev/null +++ b/src/core/stereo.h @@ -0,0 +1,28 @@ @@ -991,10 +991,10 @@ index 000000000..ccd1d702a + +#endif diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c -index 6f9df37da..d353ae5d0 100644 +index 899f777..f8f7fc5 100644 --- a/src/wayland/meta-wayland-surface.c +++ b/src/wayland/meta-wayland-surface.c -@@ -789,7 +789,7 @@ apply_pending_state (MetaWaylandSurface *surface, +@@ -667,7 +667,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); @@ -1004,5 +1004,5 @@ index 6f9df37da..d353ae5d0 100644 meta_shaped_texture_set_is_y_inverted (stex, is_y_inverted); g_clear_pointer (&snippet, cogl_object_unref); -- -2.14.2 +1.8.3.1 diff --git a/SOURCES/fix-crash-when-modal-closes-during-drag.patch b/SOURCES/fix-crash-when-modal-closes-during-drag.patch new file mode 100644 index 0000000..598a574 --- /dev/null +++ b/SOURCES/fix-crash-when-modal-closes-during-drag.patch @@ -0,0 +1,71 @@ +From 33bf5319baec86e6caef5b94c71db8101fb94343 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Fri, 25 May 2018 20:18:23 +0200 +Subject: [PATCH 1/2] window: Don't refuse to move focus to the grab window + +We refuse to move focus while a grab operation is in place. While this +generally makes sense, there's no reason why the window that owns the +grab shouldn't be given the regular input focus as well - we pretty +much assume that the grab window is also the focus window anyway. + +In fact there's a strong reason for allowing the focus change here: +If the grab window isn't the focus window, it probably has a modal +transient that is focused instead, and a likely reason for the focus +request is that the transient is being unmanaged and we must move +the focus elsewhere. + +https://gitlab.gnome.org/GNOME/mutter/issues/15 +--- + src/core/window.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/core/window.c b/src/core/window.c +index 743326c60..5b1eb5b68 100644 +--- a/src/core/window.c ++++ b/src/core/window.c +@@ -4620,6 +4620,7 @@ meta_window_focus (MetaWindow *window, + window->desc, window->input, window->take_focus); + + if (window->display->grab_window && ++ window->display->grab_window != window && + window->display->grab_window->all_keys_grabbed && + !window->display->grab_window->unmanaging) + { +-- +2.17.1 + + +From 149ae05df628480e8226f035044e6020305a8aeb Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Fri, 25 May 2018 21:24:17 +0200 +Subject: [PATCH 2/2] window: Explicitly exclude unmanaging window from focus + again + +Since commit b3b9d9e16 we no longer have to pass the unmanaging window +to make sure we don't try to focus it again, however the parameter also +influences the focus policy by giving ancestors preference over the normal +stack order. + +https://gitlab.gnome.org/GNOME/mutter/issues/15 +--- + src/core/window.c | 4 +++- + 1 file changed, 3 insertions(+), 1 deletion(-) + +diff --git a/src/core/window.c b/src/core/window.c +index 5b1eb5b68..cc0813ac4 100644 +--- a/src/core/window.c ++++ b/src/core/window.c +@@ -1469,7 +1469,9 @@ meta_window_unmanage (MetaWindow *window, + meta_topic (META_DEBUG_FOCUS, + "Focusing default window since we're unmanaging %s\n", + window->desc); +- meta_workspace_focus_default_window (window->screen->active_workspace, NULL, timestamp); ++ meta_workspace_focus_default_window (window->screen->active_workspace, ++ window, ++ timestamp); + } + else + { +-- +2.17.1 + diff --git a/SOURCES/fix-session-save-crash.patch b/SOURCES/fix-session-save-crash.patch deleted file mode 100644 index 99534ae..0000000 --- a/SOURCES/fix-session-save-crash.patch +++ /dev/null @@ -1,92 +0,0 @@ -From 0c9cb02111908409285991e4b0f44a4fdcf91eed Mon Sep 17 00:00:00 2001 -From: Olivier Fourdan -Date: Tue, 23 Jan 2018 11:43:09 +0100 -Subject: [PATCH 1/2] session: use initial workspace if no workspace set -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -Having “on_all_workspaces_requested” FALSE on a window does not imply a -workspace is set. - -If the X11 window is placed on a secondary monitor while workspaces -applies on primary monitor only (“workspaces-only-on-primary” set) then -“on_all_workspaces_requested” is FALSE while “on_all_workspaces“ is TRUE -and the associated workspace is NULL, leading to a crash when saving the -gnome-shell/mutter session. - -So if no workspace is set, use the “initial_workspace” instead to avoid -a NULL pointer dereference. - -https://bugzilla.gnome.org/show_bug.cgi?id=792818 ---- - src/x11/session.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - -diff --git a/src/x11/session.c b/src/x11/session.c -index af64270a6..8b2a89f1c 100644 ---- a/src/x11/session.c -+++ b/src/x11/session.c -@@ -950,7 +950,10 @@ save_state (void) - fputs (" \n", outfile); - } else { - int n; -- n = meta_workspace_index (window->workspace); -+ if (window->workspace) -+ n = meta_workspace_index (window->workspace); -+ else -+ n = window->initial_workspace; - fprintf (outfile, - " \n", n); - } --- -2.14.3 - - -From e2269448dcebd24f23bb8872590204819abc3ac0 Mon Sep 17 00:00:00 2001 -From: Olivier Fourdan -Date: Mon, 29 Jan 2018 16:58:46 +0100 -Subject: [PATCH 2/2] =?UTF-8?q?x11/window:=20Mark=20restored=20workspace?= - =?UTF-8?q?=20as=20=E2=80=9Cset=E2=80=9D?= -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit - -When a window's workspace is not NULL, on_all_workspace should be FALSE. -Similarly, when on_all_workspace is TRUE, the window workspace should be -NULL. - -This is an assumption in multiple places in the code, including when -setting the workspace state, the window is either added or removed from -all workspaces only if the window's workspace is NULL. - -This rule is initially enforced at creation in _meta_window_shared_new() -when a initial workspace is set. However, when the initial workspace is -set from the session info, the initial workspace is not marked as “set” -which leads to an assertion failure when unmanaging windows, because the -window is not removed from all the workspaces. - -When applying the session info to a window, mark the workspace as “set”. - -https://gitlab.gnome.org/GNOME/mutter/issues/4 - -Closes: #4 ---- - src/x11/window-x11.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/x11/window-x11.c b/src/x11/window-x11.c -index 36a5e70a3..9c8ef5d75 100644 ---- a/src/x11/window-x11.c -+++ b/src/x11/window-x11.c -@@ -466,6 +466,7 @@ meta_window_apply_session_info (MetaWindow *window, - MetaWorkspace *workspace = spaces->data; - - meta_window_change_workspace (window, workspace); -+ window->initial_workspace_set = TRUE; - - meta_topic (META_DEBUG_SM, - "Restoring saved window %s to workspace %d\n", --- -2.14.3 - diff --git a/SOURCES/fix-transient-close-crash.patch b/SOURCES/fix-transient-close-crash.patch deleted file mode 100644 index 0d2da5e..0000000 --- a/SOURCES/fix-transient-close-crash.patch +++ /dev/null @@ -1,71 +0,0 @@ -From 2e3ae76207d9367fa15a3e759e797a0bea5eea71 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Fri, 25 May 2018 20:18:23 +0200 -Subject: [PATCH 1/2] window: Don't refuse to move focus to the grab window - -We refuse to move focus while a grab operation is in place. While this -generally makes sense, there's no reason why the window that owns the -grab shouldn't be given the regular input focus as well - we pretty -much assume that the grab window is also the focus window anyway. - -In fact there's a strong reason for allowing the focus change here: -If the grab window isn't the focus window, it probably has a modal -transient that is focused instead, and a likely reason for the focus -request is that the transient is being unmanaged and we must move -the focus elsewhere. - -https://gitlab.gnome.org/GNOME/mutter/issues/15 ---- - src/core/window.c | 1 + - 1 file changed, 1 insertion(+) - -diff --git a/src/core/window.c b/src/core/window.c -index c2d9869d2..80144cc63 100644 ---- a/src/core/window.c -+++ b/src/core/window.c -@@ -4601,6 +4601,7 @@ meta_window_focus (MetaWindow *window, - window->desc, window->input, window->take_focus); - - if (window->display->grab_window && -+ window->display->grab_window != window && - window->display->grab_window->all_keys_grabbed && - !window->display->grab_window->unmanaging) - { --- -2.17.1 - - -From ba49c5298b1ae3a1e1ba52ec16d5a739115e6967 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Florian=20M=C3=BCllner?= -Date: Fri, 25 May 2018 21:24:17 +0200 -Subject: [PATCH 2/2] window: Explicitly exclude unmanaging window from focus - again - -Since commit b3b9d9e16 we no longer have to pass the unmanaging window -to make sure we don't try to focus it again, however the parameter also -influences the focus policy by giving ancestors preference over the normal -stack order. - -https://gitlab.gnome.org/GNOME/mutter/issues/15 ---- - src/core/window.c | 4 +++- - 1 file changed, 3 insertions(+), 1 deletion(-) - -diff --git a/src/core/window.c b/src/core/window.c -index 80144cc63..0b71744d5 100644 ---- a/src/core/window.c -+++ b/src/core/window.c -@@ -1466,7 +1466,9 @@ meta_window_unmanage (MetaWindow *window, - meta_topic (META_DEBUG_FOCUS, - "Focusing default window since we're unmanaging %s\n", - window->desc); -- meta_workspace_focus_default_window (window->screen->active_workspace, NULL, timestamp); -+ meta_workspace_focus_default_window (window->screen->active_workspace, -+ window, -+ timestamp); - } - else - { --- -2.17.1 - diff --git a/SOURCES/hw-cursor-on-demand-gnome-3-28.patch b/SOURCES/hw-cursor-on-demand-gnome-3-28.patch new file mode 100644 index 0000000..ae3db81 --- /dev/null +++ b/SOURCES/hw-cursor-on-demand-gnome-3-28.patch @@ -0,0 +1,3006 @@ +diff --git a/src/Makefile.am b/src/Makefile.am +index bcb3505c7..5bbac70e8 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -114,6 +114,8 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \ + backends/meta-cursor-tracker-private.h \ + backends/meta-cursor-renderer.c \ + backends/meta-cursor-renderer.h \ ++ backends/meta-cursor-sprite-xcursor.c \ ++ backends/meta-cursor-sprite-xcursor.h \ + backends/meta-dnd-private.h \ + backends/meta-egl.c \ + backends/meta-egl.h \ +@@ -176,6 +178,8 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \ + backends/x11/meta-gpu-xrandr.h \ + backends/x11/cm/meta-backend-x11-cm.c \ + backends/x11/cm/meta-backend-x11-cm.h \ ++ backends/x11/cm/meta-cursor-sprite-xfixes.c \ ++ backends/x11/cm/meta-cursor-sprite-xfixes.h \ + backends/x11/cm/meta-renderer-x11-cm.c \ + backends/x11/cm/meta-renderer-x11-cm.h \ + backends/x11/nested/meta-backend-x11-nested.c \ +@@ -370,6 +374,8 @@ if HAVE_WAYLAND + libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES += \ + compositor/meta-surface-actor-wayland.c \ + compositor/meta-surface-actor-wayland.h \ ++ wayland/meta-cursor-sprite-wayland.c \ ++ wayland/meta-cursor-sprite-wayland.h \ + wayland/meta-wayland.c \ + wayland/meta-wayland.h \ + wayland/meta-wayland-private.h \ +@@ -431,10 +437,10 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES += \ + wayland/meta-wayland-touch.h \ + wayland/meta-wayland-surface.c \ + wayland/meta-wayland-surface.h \ +- wayland/meta-wayland-surface-role-cursor.c \ +- wayland/meta-wayland-surface-role-cursor.h \ +- wayland/meta-wayland-surface-role-tablet-cursor.c \ +- wayland/meta-wayland-surface-role-tablet-cursor.h \ ++ wayland/meta-wayland-cursor-surface.c \ ++ wayland/meta-wayland-cursor-surface.h \ ++ wayland/meta-wayland-tablet-cursor-surface.c \ ++ wayland/meta-wayland-tablet-cursor-surface.h \ + wayland/meta-wayland-actor-surface.c \ + wayland/meta-wayland-actor-surface.h \ + wayland/meta-wayland-subsurface.c \ +diff --git a/src/backends/meta-cursor-renderer.c b/src/backends/meta-cursor-renderer.c +index f6470e66a..eb79737f1 100644 +--- a/src/backends/meta-cursor-renderer.c ++++ b/src/backends/meta-cursor-renderer.c +@@ -193,8 +193,8 @@ meta_cursor_renderer_calculate_rect (MetaCursorRenderer *renderer, + } + + static void +-update_cursor (MetaCursorRenderer *renderer, +- MetaCursorSprite *cursor_sprite) ++meta_cursor_renderer_update_cursor (MetaCursorRenderer *renderer, ++ MetaCursorSprite *cursor_sprite) + { + MetaCursorRendererPrivate *priv = meta_cursor_renderer_get_instance_private (renderer); + gboolean handled_by_backend; +@@ -237,7 +237,7 @@ meta_cursor_renderer_set_cursor (MetaCursorRenderer *renderer, + return; + priv->displayed_cursor = cursor_sprite; + +- update_cursor (renderer, cursor_sprite); ++ meta_cursor_renderer_update_cursor (renderer, cursor_sprite); + } + + void +@@ -246,7 +246,7 @@ meta_cursor_renderer_force_update (MetaCursorRenderer *renderer) + MetaCursorRendererPrivate *priv = + meta_cursor_renderer_get_instance_private (renderer); + +- update_cursor (renderer, priv->displayed_cursor); ++ meta_cursor_renderer_update_cursor (renderer, priv->displayed_cursor); + } + + void +@@ -261,7 +261,7 @@ meta_cursor_renderer_set_position (MetaCursorRenderer *renderer, + priv->current_x = x; + priv->current_y = y; + +- update_cursor (renderer, priv->displayed_cursor); ++ meta_cursor_renderer_update_cursor (renderer, priv->displayed_cursor); + } + + ClutterPoint +@@ -283,28 +283,3 @@ meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer) + + return priv->displayed_cursor; + } +- +-#ifdef HAVE_WAYLAND +-void +-meta_cursor_renderer_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer, +- MetaCursorSprite *cursor_sprite, +- struct wl_resource *buffer) +-{ +- +- MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_GET_CLASS (renderer); +- +- if (renderer_class->realize_cursor_from_wl_buffer) +- renderer_class->realize_cursor_from_wl_buffer (renderer, cursor_sprite, buffer); +-} +-#endif +- +-void +-meta_cursor_renderer_realize_cursor_from_xcursor (MetaCursorRenderer *renderer, +- MetaCursorSprite *cursor_sprite, +- XcursorImage *xc_image) +-{ +- MetaCursorRendererClass *renderer_class = META_CURSOR_RENDERER_GET_CLASS (renderer); +- +- if (renderer_class->realize_cursor_from_xcursor) +- renderer_class->realize_cursor_from_xcursor (renderer, cursor_sprite, xc_image); +-} +diff --git a/src/backends/meta-cursor-renderer.h b/src/backends/meta-cursor-renderer.h +index 1691f4471..830d16ef6 100644 +--- a/src/backends/meta-cursor-renderer.h ++++ b/src/backends/meta-cursor-renderer.h +@@ -26,10 +26,6 @@ + #define META_CURSOR_RENDERER_H + + #include +-#include +-#ifdef HAVE_WAYLAND +-#include +-#endif + + #include + #include "meta-cursor.h" +@@ -44,14 +40,6 @@ struct _MetaCursorRendererClass + + gboolean (* update_cursor) (MetaCursorRenderer *renderer, + MetaCursorSprite *cursor_sprite); +-#ifdef HAVE_WAYLAND +- void (* realize_cursor_from_wl_buffer) (MetaCursorRenderer *renderer, +- MetaCursorSprite *cursor_sprite, +- struct wl_resource *buffer); +-#endif +- void (* realize_cursor_from_xcursor) (MetaCursorRenderer *renderer, +- MetaCursorSprite *cursor_sprite, +- XcursorImage *xc_image); + }; + + MetaCursorRenderer * meta_cursor_renderer_new (void); +@@ -70,16 +58,6 @@ MetaCursorSprite * meta_cursor_renderer_get_cursor (MetaCursorRenderer *renderer + ClutterRect meta_cursor_renderer_calculate_rect (MetaCursorRenderer *renderer, + MetaCursorSprite *cursor_sprite); + +-#ifdef HAVE_WAYLAND +-void meta_cursor_renderer_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer, +- MetaCursorSprite *cursor_sprite, +- struct wl_resource *buffer); +-#endif +- +-void meta_cursor_renderer_realize_cursor_from_xcursor (MetaCursorRenderer *renderer, +- MetaCursorSprite *cursor_sprite, +- XcursorImage *xc_image); +- + void meta_cursor_renderer_emit_painted (MetaCursorRenderer *renderer, + MetaCursorSprite *cursor_sprite); + +diff --git a/src/backends/meta-cursor-sprite-xcursor.c b/src/backends/meta-cursor-sprite-xcursor.c +new file mode 100644 +index 000000000..657c1dae8 +--- /dev/null ++++ b/src/backends/meta-cursor-sprite-xcursor.c +@@ -0,0 +1,292 @@ ++/* ++ * Copyright 2013, 2018 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 . ++ * ++ */ ++ ++#include "config.h" ++ ++#include "backends/meta-cursor-sprite-xcursor.h" ++ ++#include "backends/meta-cursor.h" ++#include "backends/meta-cursor-renderer.h" ++#include "clutter/clutter.h" ++#include "cogl/cogl.h" ++#include "meta/prefs.h" ++ ++struct _MetaCursorSpriteXcursor ++{ ++ MetaCursorSprite parent; ++ ++ MetaCursor cursor; ++ ++ int current_frame; ++ XcursorImages *xcursor_images; ++ ++ int theme_scale; ++ gboolean theme_dirty; ++}; ++ ++G_DEFINE_TYPE (MetaCursorSpriteXcursor, meta_cursor_sprite_xcursor, ++ META_TYPE_CURSOR_SPRITE) ++ ++static const char * ++translate_meta_cursor (MetaCursor cursor) ++{ ++ switch (cursor) ++ { ++ case META_CURSOR_DEFAULT: ++ return "left_ptr"; ++ case META_CURSOR_NORTH_RESIZE: ++ return "top_side"; ++ case META_CURSOR_SOUTH_RESIZE: ++ return "bottom_side"; ++ case META_CURSOR_WEST_RESIZE: ++ return "left_side"; ++ case META_CURSOR_EAST_RESIZE: ++ return "right_side"; ++ case META_CURSOR_SE_RESIZE: ++ return "bottom_right_corner"; ++ case META_CURSOR_SW_RESIZE: ++ return "bottom_left_corner"; ++ case META_CURSOR_NE_RESIZE: ++ return "top_right_corner"; ++ case META_CURSOR_NW_RESIZE: ++ return "top_left_corner"; ++ case META_CURSOR_MOVE_OR_RESIZE_WINDOW: ++ return "fleur"; ++ case META_CURSOR_BUSY: ++ return "watch"; ++ case META_CURSOR_DND_IN_DRAG: ++ return "dnd-none"; ++ case META_CURSOR_DND_MOVE: ++ return "dnd-move"; ++ case META_CURSOR_DND_COPY: ++ return "dnd-copy"; ++ case META_CURSOR_DND_UNSUPPORTED_TARGET: ++ return "dnd-none"; ++ case META_CURSOR_POINTING_HAND: ++ return "hand2"; ++ case META_CURSOR_CROSSHAIR: ++ return "crosshair"; ++ case META_CURSOR_IBEAM: ++ return "xterm"; ++ default: ++ break; ++ } ++ ++ g_assert_not_reached (); ++} ++ ++MetaCursor ++meta_cursor_sprite_xcursor_get_cursor (MetaCursorSpriteXcursor *sprite_xcursor) ++{ ++ return sprite_xcursor->cursor; ++} ++ ++Cursor ++meta_create_x_cursor (Display *xdisplay, ++ MetaCursor cursor) ++{ ++ return XcursorLibraryLoadCursor (xdisplay, translate_meta_cursor (cursor)); ++} ++ ++static XcursorImages * ++load_cursor_on_client (MetaCursor cursor, int scale) ++{ ++ return XcursorLibraryLoadImages (translate_meta_cursor (cursor), ++ meta_prefs_get_cursor_theme (), ++ meta_prefs_get_cursor_size () * scale); ++} ++ ++static void ++load_from_current_xcursor_image (MetaCursorSpriteXcursor *sprite_xcursor) ++{ ++ MetaCursorSprite *sprite = META_CURSOR_SPRITE (sprite_xcursor); ++ XcursorImage *xc_image; ++ int width, height, rowstride; ++ CoglPixelFormat cogl_format; ++ ClutterBackend *clutter_backend; ++ CoglContext *cogl_context; ++ CoglTexture2D *texture; ++ CoglError *error = NULL; ++ ++ g_assert (!meta_cursor_sprite_get_cogl_texture (sprite)); ++ ++ xc_image = meta_cursor_sprite_xcursor_get_current_image (sprite_xcursor); ++ width = (int) xc_image->width; ++ height = (int) xc_image->height; ++ rowstride = width * 4; ++ ++#if G_BYTE_ORDER == G_LITTLE_ENDIAN ++ cogl_format = COGL_PIXEL_FORMAT_BGRA_8888; ++#else ++ cogl_format = COGL_PIXEL_FORMAT_ARGB_8888; ++#endif ++ ++ clutter_backend = clutter_get_default_backend (); ++ cogl_context = clutter_backend_get_cogl_context (clutter_backend); ++ texture = cogl_texture_2d_new_from_data (cogl_context, ++ width, height, ++ cogl_format, ++ rowstride, ++ (uint8_t *) xc_image->pixels, ++ &error); ++ if (!texture) ++ { ++ g_warning ("Failed to allocate cursor texture: %s\n", error->message); ++ cogl_error_free (error); ++ } ++ ++ meta_cursor_sprite_set_texture (sprite, ++ COGL_TEXTURE (texture), ++ xc_image->xhot, xc_image->yhot); ++ ++ if (texture) ++ cogl_object_unref (texture); ++} ++ ++void ++meta_cursor_sprite_xcursor_set_theme_scale (MetaCursorSpriteXcursor *sprite_xcursor, ++ int theme_scale) ++{ ++ if (sprite_xcursor->theme_scale != theme_scale) ++ sprite_xcursor->theme_dirty = TRUE; ++ sprite_xcursor->theme_scale = theme_scale; ++} ++ ++ ++static gboolean ++meta_cursor_sprite_xcursor_is_animated (MetaCursorSprite *sprite) ++{ ++ MetaCursorSpriteXcursor *sprite_xcursor = META_CURSOR_SPRITE_XCURSOR (sprite); ++ ++ return (sprite_xcursor->xcursor_images && ++ sprite_xcursor->xcursor_images->nimage > 1); ++} ++ ++XcursorImage * ++meta_cursor_sprite_xcursor_get_current_image (MetaCursorSpriteXcursor *sprite_xcursor) ++{ ++ return sprite_xcursor->xcursor_images->images[sprite_xcursor->current_frame]; ++} ++ ++static void ++meta_cursor_sprite_xcursor_tick_frame (MetaCursorSprite *sprite) ++{ ++ MetaCursorSpriteXcursor *sprite_xcursor = META_CURSOR_SPRITE_XCURSOR (sprite); ++ ++ if (!meta_cursor_sprite_is_animated (sprite)) ++ return; ++ ++ sprite_xcursor->current_frame++; ++ ++ if (sprite_xcursor->current_frame >= sprite_xcursor->xcursor_images->nimage) ++ sprite_xcursor->current_frame = 0; ++ ++ meta_cursor_sprite_clear_texture (sprite); ++ load_from_current_xcursor_image (sprite_xcursor); ++} ++ ++static unsigned int ++meta_cursor_sprite_xcursor_get_current_frame_time (MetaCursorSprite *sprite) ++{ ++ MetaCursorSpriteXcursor *sprite_xcursor = META_CURSOR_SPRITE_XCURSOR (sprite); ++ XcursorImages *xcursor_images; ++ ++ g_return_val_if_fail (meta_cursor_sprite_is_animated (sprite), 0); ++ ++ xcursor_images = sprite_xcursor->xcursor_images; ++ return xcursor_images->images[sprite_xcursor->current_frame]->delay; ++} ++ ++static void ++load_cursor_from_theme (MetaCursorSprite *sprite) ++{ ++ MetaCursorSpriteXcursor *sprite_xcursor = META_CURSOR_SPRITE_XCURSOR (sprite); ++ ++ g_assert (sprite_xcursor->cursor != META_CURSOR_NONE); ++ ++ sprite_xcursor->theme_dirty = FALSE; ++ ++ /* We might be reloading with a different scale. If so clear the old data. */ ++ if (sprite_xcursor->xcursor_images) ++ { ++ meta_cursor_sprite_clear_texture (sprite); ++ XcursorImagesDestroy (sprite_xcursor->xcursor_images); ++ } ++ ++ sprite_xcursor->current_frame = 0; ++ sprite_xcursor->xcursor_images = ++ load_cursor_on_client (sprite_xcursor->cursor, ++ sprite_xcursor->theme_scale); ++ if (!sprite_xcursor->xcursor_images) ++ g_error ("Could not find cursor. Perhaps set XCURSOR_PATH?"); ++ ++ load_from_current_xcursor_image (sprite_xcursor); ++} ++ ++static void ++meta_cursor_sprite_xcursor_realize_texture (MetaCursorSprite *sprite) ++{ ++ MetaCursorSpriteXcursor *sprite_xcursor = META_CURSOR_SPRITE_XCURSOR (sprite); ++ ++ if (sprite_xcursor->theme_dirty) ++ load_cursor_from_theme (sprite); ++} ++ ++MetaCursorSpriteXcursor * ++meta_cursor_sprite_xcursor_new (MetaCursor cursor) ++{ ++ MetaCursorSpriteXcursor *sprite_xcursor; ++ ++ sprite_xcursor = g_object_new (META_TYPE_CURSOR_SPRITE_XCURSOR, NULL); ++ sprite_xcursor->cursor = cursor; ++ ++ return sprite_xcursor; ++} ++ ++static void ++meta_cursor_sprite_xcursor_finalize (GObject *object) ++{ ++ MetaCursorSpriteXcursor *sprite_xcursor = META_CURSOR_SPRITE_XCURSOR (object); ++ ++ g_clear_pointer (&sprite_xcursor->xcursor_images, ++ XcursorImagesDestroy); ++ ++ G_OBJECT_CLASS (meta_cursor_sprite_xcursor_parent_class)->finalize (object); ++} ++ ++static void ++meta_cursor_sprite_xcursor_init (MetaCursorSpriteXcursor *sprite_xcursor) ++{ ++ sprite_xcursor->theme_dirty = TRUE; ++} ++ ++static void ++meta_cursor_sprite_xcursor_class_init (MetaCursorSpriteXcursorClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ MetaCursorSpriteClass *cursor_sprite_class = META_CURSOR_SPRITE_CLASS (klass); ++ ++ object_class->finalize = meta_cursor_sprite_xcursor_finalize; ++ ++ cursor_sprite_class->realize_texture = ++ meta_cursor_sprite_xcursor_realize_texture; ++ cursor_sprite_class->is_animated = meta_cursor_sprite_xcursor_is_animated; ++ cursor_sprite_class->tick_frame = meta_cursor_sprite_xcursor_tick_frame; ++ cursor_sprite_class->get_current_frame_time = ++ meta_cursor_sprite_xcursor_get_current_frame_time; ++} +diff --git a/src/backends/meta-cursor-sprite-xcursor.h b/src/backends/meta-cursor-sprite-xcursor.h +new file mode 100644 +index 000000000..dbc927484 +--- /dev/null ++++ b/src/backends/meta-cursor-sprite-xcursor.h +@@ -0,0 +1,43 @@ ++/* ++ * Copyright 2013, 2018 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_CURSOR_SPRITE_XCURSOR_H ++#define META_CURSOR_SPRITE_XCURSOR_H ++ ++#include ++#include ++ ++#include "backends/meta-cursor.h" ++ ++#define META_TYPE_CURSOR_SPRITE_XCURSOR meta_cursor_sprite_xcursor_get_type () ++G_DECLARE_FINAL_TYPE (MetaCursorSpriteXcursor, meta_cursor_sprite_xcursor, ++ META, CURSOR_SPRITE_XCURSOR, MetaCursorSprite) ++ ++MetaCursorSpriteXcursor * meta_cursor_sprite_xcursor_new (MetaCursor cursor); ++ ++void meta_cursor_sprite_xcursor_set_theme_scale (MetaCursorSpriteXcursor *sprite_xcursor, ++ int scale); ++ ++MetaCursor meta_cursor_sprite_xcursor_get_cursor (MetaCursorSpriteXcursor *sprite_xcusror); ++ ++XcursorImage * meta_cursor_sprite_xcursor_get_current_image (MetaCursorSpriteXcursor *sprite_xcursor); ++ ++Cursor meta_create_x_cursor (Display *xdisplay, ++ MetaCursor cursor); ++ ++#endif /* META_CURSOR_SPRITE_XCURSOR_H */ +diff --git a/src/backends/meta-cursor-tracker-private.h b/src/backends/meta-cursor-tracker-private.h +index 2ec946847..6f4f84b83 100644 +--- a/src/backends/meta-cursor-tracker-private.h ++++ b/src/backends/meta-cursor-tracker-private.h +@@ -26,6 +26,7 @@ + + #include "meta-cursor.h" + #include "meta-cursor-renderer.h" ++#include "backends/x11/cm/meta-cursor-sprite-xfixes.h" + + struct _MetaCursorTracker { + GObject parent_instance; +@@ -46,7 +47,7 @@ struct _MetaCursorTracker { + MetaCursorSprite *root_cursor; + + /* The cursor from the X11 server. */ +- MetaCursorSprite *xfixes_cursor; ++ MetaCursorSpriteXfixes *xfixes_cursor; + }; + + struct _MetaCursorTrackerClass { +diff --git a/src/backends/meta-cursor-tracker.c b/src/backends/meta-cursor-tracker.c +index 74fa4351d..6244f11ee 100644 +--- a/src/backends/meta-cursor-tracker.c ++++ b/src/backends/meta-cursor-tracker.c +@@ -40,9 +40,9 @@ + + #include + #include +-#include + + #include "meta-backend-private.h" ++#include "backends/x11/cm/meta-cursor-sprite-xfixes.h" + + G_DEFINE_TYPE (MetaCursorTracker, meta_cursor_tracker, G_TYPE_OBJECT); + +@@ -218,75 +218,14 @@ static void + ensure_xfixes_cursor (MetaCursorTracker *tracker) + { + MetaDisplay *display = meta_get_display (); +- XFixesCursorImage *cursor_image; +- CoglTexture2D *sprite; +- guint8 *cursor_data; +- gboolean free_cursor_data; +- CoglContext *ctx; +- CoglError *error = NULL; ++ g_autoptr (GError) error = NULL; + + if (tracker->xfixes_cursor) + return; + +- cursor_image = XFixesGetCursorImage (display->xdisplay); +- if (!cursor_image) +- return; +- +- /* Like all X APIs, XFixesGetCursorImage() returns arrays of 32-bit +- * quantities as arrays of long; we need to convert on 64 bit */ +- if (sizeof(long) == 4) +- { +- cursor_data = (guint8 *)cursor_image->pixels; +- free_cursor_data = FALSE; +- } +- else +- { +- int i, j; +- guint32 *cursor_words; +- gulong *p; +- guint32 *q; +- +- cursor_words = g_new (guint32, cursor_image->width * cursor_image->height); +- cursor_data = (guint8 *)cursor_words; +- +- p = cursor_image->pixels; +- q = cursor_words; +- for (j = 0; j < cursor_image->height; j++) +- for (i = 0; i < cursor_image->width; i++) +- *(q++) = *(p++); +- +- free_cursor_data = TRUE; +- } +- +- ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); +- sprite = cogl_texture_2d_new_from_data (ctx, +- cursor_image->width, +- cursor_image->height, +- CLUTTER_CAIRO_FORMAT_ARGB32, +- cursor_image->width * 4, /* stride */ +- cursor_data, +- &error); +- +- if (free_cursor_data) +- g_free (cursor_data); +- +- if (error != NULL) +- { +- meta_warning ("Failed to allocate cursor sprite texture: %s\n", error->message); +- cogl_error_free (error); +- } +- +- if (sprite != NULL) +- { +- MetaCursorSprite *cursor_sprite = meta_cursor_sprite_new (); +- meta_cursor_sprite_set_texture (cursor_sprite, +- COGL_TEXTURE (sprite), +- cursor_image->xhot, +- cursor_image->yhot); +- cogl_object_unref (sprite); +- tracker->xfixes_cursor = cursor_sprite; +- } +- XFree (cursor_image); ++ tracker->xfixes_cursor = meta_cursor_sprite_xfixes_new (display, &error); ++ if (!tracker->xfixes_cursor) ++ g_warning ("Failed to create XFIXES cursor: %s", error->message); + } + + /** +@@ -308,7 +247,7 @@ meta_cursor_tracker_get_sprite (MetaCursorTracker *tracker) + else + { + ensure_xfixes_cursor (tracker); +- cursor_sprite = tracker->xfixes_cursor; ++ cursor_sprite = META_CURSOR_SPRITE (tracker->xfixes_cursor); + } + + if (cursor_sprite) +@@ -345,7 +284,7 @@ meta_cursor_tracker_get_hot (MetaCursorTracker *tracker, + else + { + ensure_xfixes_cursor (tracker); +- cursor_sprite = tracker->xfixes_cursor; ++ cursor_sprite = META_CURSOR_SPRITE (tracker->xfixes_cursor); + } + + if (cursor_sprite) +diff --git a/src/backends/meta-cursor.c b/src/backends/meta-cursor.c +index beeee765b..9750dc00b 100644 +--- a/src/backends/meta-cursor.c ++++ b/src/backends/meta-cursor.c +@@ -23,19 +23,12 @@ + + #include "meta-cursor.h" + +-#include ++#include "backends/meta-backend-private.h" ++#include "cogl/cogl.h" ++#include "meta/common.h" + +-#include "display-private.h" +-#include "screen-private.h" +-#include "meta-backend-private.h" +- +-#include +- +-#include +-#include +-#include +- +-enum { ++enum ++{ + PREPARE_AT, + TEXTURE_CHANGED, + +@@ -44,316 +37,148 @@ enum { + + static guint signals[LAST_SIGNAL]; + +-struct _MetaCursorSprite ++typedef struct _MetaCursorSpritePrivate + { + GObject parent; + +- MetaCursor cursor; +- + CoglTexture2D *texture; + float texture_scale; + int hot_x, hot_y; ++} MetaCursorSpritePrivate; + +- int current_frame; +- XcursorImages *xcursor_images; +- +- int theme_scale; +- gboolean theme_dirty; +-}; +- +-G_DEFINE_TYPE (MetaCursorSprite, meta_cursor_sprite, G_TYPE_OBJECT) ++G_DEFINE_ABSTRACT_TYPE_WITH_PRIVATE (MetaCursorSprite, ++ meta_cursor_sprite, ++ G_TYPE_OBJECT) + +-static const char * +-translate_meta_cursor (MetaCursor cursor) +-{ +- switch (cursor) +- { +- case META_CURSOR_DEFAULT: +- return "left_ptr"; +- case META_CURSOR_NORTH_RESIZE: +- return "top_side"; +- case META_CURSOR_SOUTH_RESIZE: +- return "bottom_side"; +- case META_CURSOR_WEST_RESIZE: +- return "left_side"; +- case META_CURSOR_EAST_RESIZE: +- return "right_side"; +- case META_CURSOR_SE_RESIZE: +- return "bottom_right_corner"; +- case META_CURSOR_SW_RESIZE: +- return "bottom_left_corner"; +- case META_CURSOR_NE_RESIZE: +- return "top_right_corner"; +- case META_CURSOR_NW_RESIZE: +- return "top_left_corner"; +- case META_CURSOR_MOVE_OR_RESIZE_WINDOW: +- return "fleur"; +- case META_CURSOR_BUSY: +- return "watch"; +- case META_CURSOR_DND_IN_DRAG: +- return "dnd-none"; +- case META_CURSOR_DND_MOVE: +- return "dnd-move"; +- case META_CURSOR_DND_COPY: +- return "dnd-copy"; +- case META_CURSOR_DND_UNSUPPORTED_TARGET: +- return "dnd-none"; +- case META_CURSOR_POINTING_HAND: +- return "hand2"; +- case META_CURSOR_CROSSHAIR: +- return "crosshair"; +- case META_CURSOR_IBEAM: +- return "xterm"; +- default: +- break; +- } +- +- g_assert_not_reached (); +-} +- +-Cursor +-meta_cursor_create_x_cursor (Display *xdisplay, +- MetaCursor cursor) +-{ +- return XcursorLibraryLoadCursor (xdisplay, translate_meta_cursor (cursor)); +-} +- +-static XcursorImages * +-load_cursor_on_client (MetaCursor cursor, int scale) +-{ +- return XcursorLibraryLoadImages (translate_meta_cursor (cursor), +- meta_prefs_get_cursor_theme (), +- meta_prefs_get_cursor_size () * scale); +-} +- +-static void +-meta_cursor_sprite_load_from_xcursor_image (MetaCursorSprite *self, +- XcursorImage *xc_image) ++gboolean ++meta_cursor_sprite_is_animated (MetaCursorSprite *sprite) + { +- MetaBackend *meta_backend = meta_get_backend (); +- MetaCursorRenderer *renderer = meta_backend_get_cursor_renderer (meta_backend); +- uint width, height, rowstride; +- CoglPixelFormat cogl_format; +- ClutterBackend *clutter_backend; +- CoglContext *cogl_context; +- CoglTexture2D *texture; +- CoglError *error = NULL; +- +- g_assert (self->texture == NULL); +- +- width = xc_image->width; +- height = xc_image->height; +- rowstride = width * 4; +- +-#if G_BYTE_ORDER == G_LITTLE_ENDIAN +- cogl_format = COGL_PIXEL_FORMAT_BGRA_8888; +-#else +- cogl_format = COGL_PIXEL_FORMAT_ARGB_8888; +-#endif +- +- clutter_backend = clutter_get_default_backend (); +- cogl_context = clutter_backend_get_cogl_context (clutter_backend); +- texture = cogl_texture_2d_new_from_data (cogl_context, +- width, height, +- cogl_format, +- rowstride, +- (uint8_t *) xc_image->pixels, +- &error); +- +- if (error) +- { +- meta_warning ("Failed to allocate cursor texture: %s\n", error->message); +- cogl_error_free (error); +- } +- +- meta_cursor_sprite_set_texture (self, COGL_TEXTURE (texture), +- xc_image->xhot, xc_image->yhot); ++ MetaCursorSpriteClass *klass = META_CURSOR_SPRITE_GET_CLASS (sprite); + +- if (texture) +- cogl_object_unref (texture); +- +- meta_cursor_renderer_realize_cursor_from_xcursor (renderer, self, xc_image); +-} +- +-static XcursorImage * +-meta_cursor_sprite_get_current_frame_image (MetaCursorSprite *self) +-{ +- return self->xcursor_images->images[self->current_frame]; ++ if (klass->is_animated) ++ return klass->is_animated (sprite); ++ else ++ return FALSE; + } + + void +-meta_cursor_sprite_tick_frame (MetaCursorSprite *self) +-{ +- XcursorImage *image; +- +- if (!meta_cursor_sprite_is_animated (self)) +- return; +- +- self->current_frame++; +- +- if (self->current_frame >= self->xcursor_images->nimage) +- self->current_frame = 0; +- +- image = meta_cursor_sprite_get_current_frame_image (self); +- +- g_clear_pointer (&self->texture, cogl_object_unref); +- meta_cursor_sprite_load_from_xcursor_image (self, image); +-} +- +-guint +-meta_cursor_sprite_get_current_frame_time (MetaCursorSprite *self) +-{ +- if (!meta_cursor_sprite_is_animated (self)) +- return 0; +- +- return self->xcursor_images->images[self->current_frame]->delay; +-} +- +-gboolean +-meta_cursor_sprite_is_animated (MetaCursorSprite *self) ++meta_cursor_sprite_tick_frame (MetaCursorSprite *sprite) + { +- return (self->xcursor_images && +- self->xcursor_images->nimage > 1); ++ return META_CURSOR_SPRITE_GET_CLASS (sprite)->tick_frame (sprite); + } + +-MetaCursorSprite * +-meta_cursor_sprite_new (void) ++unsigned int ++meta_cursor_sprite_get_current_frame_time (MetaCursorSprite *sprite) + { +- return g_object_new (META_TYPE_CURSOR_SPRITE, NULL); ++ return META_CURSOR_SPRITE_GET_CLASS (sprite)->get_current_frame_time (sprite); + } + +-static void +-meta_cursor_sprite_load_from_theme (MetaCursorSprite *self) +-{ +- XcursorImage *image; +- +- g_assert (self->cursor != META_CURSOR_NONE); +- +- self->theme_dirty = FALSE; +- +- /* We might be reloading with a different scale. If so clear the old data. */ +- if (self->xcursor_images) +- { +- g_clear_pointer (&self->texture, cogl_object_unref); +- XcursorImagesDestroy (self->xcursor_images); +- } +- +- self->current_frame = 0; +- self->xcursor_images = load_cursor_on_client (self->cursor, +- self->theme_scale); +- if (!self->xcursor_images) +- meta_fatal ("Could not find cursor. Perhaps set XCURSOR_PATH?"); +- +- image = meta_cursor_sprite_get_current_frame_image (self); +- meta_cursor_sprite_load_from_xcursor_image (self, image); +-} +- +-MetaCursorSprite * +-meta_cursor_sprite_from_theme (MetaCursor cursor) ++void ++meta_cursor_sprite_clear_texture (MetaCursorSprite *sprite) + { +- MetaCursorSprite *self; +- +- self = meta_cursor_sprite_new (); +- +- self->cursor = cursor; +- self->theme_dirty = TRUE; ++ MetaCursorSpritePrivate *priv = ++ meta_cursor_sprite_get_instance_private (sprite); + +- return self; ++ g_clear_pointer (&priv->texture, cogl_object_unref); + } + + void +-meta_cursor_sprite_set_texture (MetaCursorSprite *self, ++meta_cursor_sprite_set_texture (MetaCursorSprite *sprite, + CoglTexture *texture, + int hot_x, + int hot_y) + { +- if (self->texture == COGL_TEXTURE_2D (texture) && +- self->hot_x == hot_x && +- self->hot_y == hot_y) ++ MetaCursorSpritePrivate *priv = ++ meta_cursor_sprite_get_instance_private (sprite); ++ ++ if (priv->texture == COGL_TEXTURE_2D (texture) && ++ priv->hot_x == hot_x && ++ priv->hot_y == hot_y) + return; + +- g_clear_pointer (&self->texture, cogl_object_unref); ++ g_clear_pointer (&priv->texture, cogl_object_unref); + if (texture) +- self->texture = cogl_object_ref (texture); +- self->hot_x = hot_x; +- self->hot_y = hot_y; ++ priv->texture = cogl_object_ref (texture); ++ priv->hot_x = hot_x; ++ priv->hot_y = hot_y; + +- g_signal_emit (self, signals[TEXTURE_CHANGED], 0); ++ g_signal_emit (sprite, signals[TEXTURE_CHANGED], 0); + } + + void +-meta_cursor_sprite_set_texture_scale (MetaCursorSprite *self, ++meta_cursor_sprite_set_texture_scale (MetaCursorSprite *sprite, + float scale) + { +- self->texture_scale = scale; +-} ++ MetaCursorSpritePrivate *priv = ++ meta_cursor_sprite_get_instance_private (sprite); + +-void +-meta_cursor_sprite_set_theme_scale (MetaCursorSprite *self, +- int theme_scale) +-{ +- if (self->theme_scale != theme_scale) +- self->theme_dirty = TRUE; +- self->theme_scale = theme_scale; ++ priv->texture_scale = scale; + } + + CoglTexture * +-meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *self) ++meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *sprite) + { +- return COGL_TEXTURE (self->texture); +-} ++ MetaCursorSpritePrivate *priv = ++ meta_cursor_sprite_get_instance_private (sprite); + +-MetaCursor +-meta_cursor_sprite_get_meta_cursor (MetaCursorSprite *self) +-{ +- return self->cursor; ++ return COGL_TEXTURE (priv->texture); + } + + void +-meta_cursor_sprite_get_hotspot (MetaCursorSprite *self, ++meta_cursor_sprite_get_hotspot (MetaCursorSprite *sprite, + int *hot_x, + int *hot_y) + { +- *hot_x = self->hot_x; +- *hot_y = self->hot_y; ++ MetaCursorSpritePrivate *priv = ++ meta_cursor_sprite_get_instance_private (sprite); ++ ++ *hot_x = priv->hot_x; ++ *hot_y = priv->hot_y; + } + + float +-meta_cursor_sprite_get_texture_scale (MetaCursorSprite *self) ++meta_cursor_sprite_get_texture_scale (MetaCursorSprite *sprite) + { +- return self->texture_scale; ++ MetaCursorSpritePrivate *priv = ++ meta_cursor_sprite_get_instance_private (sprite); ++ ++ return priv->texture_scale; + } + + void +-meta_cursor_sprite_prepare_at (MetaCursorSprite *self, ++meta_cursor_sprite_prepare_at (MetaCursorSprite *sprite, + int x, + int y) + { +- g_signal_emit (self, signals[PREPARE_AT], 0, x, y); ++ g_signal_emit (sprite, signals[PREPARE_AT], 0, x, y); + } + + void +-meta_cursor_sprite_realize_texture (MetaCursorSprite *self) ++meta_cursor_sprite_realize_texture (MetaCursorSprite *sprite) + { +- if (self->theme_dirty) +- meta_cursor_sprite_load_from_theme (self); ++ MetaCursorSpriteClass *klass = META_CURSOR_SPRITE_GET_CLASS (sprite); ++ ++ if (klass->realize_texture) ++ klass->realize_texture (sprite); + } + + static void +-meta_cursor_sprite_init (MetaCursorSprite *self) ++meta_cursor_sprite_init (MetaCursorSprite *sprite) + { +- self->texture_scale = 1.0f; ++ MetaCursorSpritePrivate *priv = ++ meta_cursor_sprite_get_instance_private (sprite); ++ ++ priv->texture_scale = 1.0f; + } + + static void + meta_cursor_sprite_finalize (GObject *object) + { +- MetaCursorSprite *self = META_CURSOR_SPRITE (object); +- +- if (self->xcursor_images) +- XcursorImagesDestroy (self->xcursor_images); ++ MetaCursorSprite *sprite = META_CURSOR_SPRITE (object); ++ MetaCursorSpritePrivate *priv = ++ meta_cursor_sprite_get_instance_private (sprite); + +- g_clear_pointer (&self->texture, cogl_object_unref); ++ g_clear_pointer (&priv->texture, cogl_object_unref); + + G_OBJECT_CLASS (meta_cursor_sprite_parent_class)->finalize (object); + } +diff --git a/src/backends/meta-cursor.h b/src/backends/meta-cursor.h +index 6087df69c..3051fdee6 100644 +--- a/src/backends/meta-cursor.h ++++ b/src/backends/meta-cursor.h +@@ -25,51 +25,50 @@ + #include + #include + +-typedef struct _MetaCursorSprite MetaCursorSprite; +- + #define META_TYPE_CURSOR_SPRITE (meta_cursor_sprite_get_type ()) +-G_DECLARE_FINAL_TYPE (MetaCursorSprite, +- meta_cursor_sprite, +- META, CURSOR_SPRITE, +- GObject); +- +-MetaCursorSprite * meta_cursor_sprite_new (void); +- +-MetaCursorSprite * meta_cursor_sprite_from_theme (MetaCursor cursor); +- +- +-void meta_cursor_sprite_set_theme_scale (MetaCursorSprite *self, +- int scale); +- +-MetaCursor meta_cursor_sprite_get_meta_cursor (MetaCursorSprite *self); +- +-Cursor meta_cursor_create_x_cursor (Display *xdisplay, +- MetaCursor cursor); +- +-void meta_cursor_sprite_prepare_at (MetaCursorSprite *self, ++G_DECLARE_DERIVABLE_TYPE (MetaCursorSprite, ++ meta_cursor_sprite, ++ META, CURSOR_SPRITE, ++ GObject) ++ ++struct _MetaCursorSpriteClass ++{ ++ GObjectClass parent_class; ++ ++ void (* realize_texture) (MetaCursorSprite *sprite); ++ gboolean (* is_animated) (MetaCursorSprite *sprite); ++ void (* tick_frame) (MetaCursorSprite *sprite); ++ unsigned int (* get_current_frame_time) (MetaCursorSprite *sprite); ++}; ++ ++void meta_cursor_sprite_prepare_at (MetaCursorSprite *sprite, + int x, + int y); + +-void meta_cursor_sprite_realize_texture (MetaCursorSprite *self); ++void meta_cursor_sprite_realize_texture (MetaCursorSprite *sprite); ++ ++void meta_cursor_sprite_clear_texture (MetaCursorSprite *sprite); + +-void meta_cursor_sprite_set_texture (MetaCursorSprite *self, ++void meta_cursor_sprite_set_texture (MetaCursorSprite *sprite, + CoglTexture *texture, + int hot_x, + int hot_y); + +-void meta_cursor_sprite_set_texture_scale (MetaCursorSprite *self, ++void meta_cursor_sprite_set_texture_scale (MetaCursorSprite *sprite, + float scale); + +-CoglTexture *meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *self); ++CoglTexture *meta_cursor_sprite_get_cogl_texture (MetaCursorSprite *sprite); + +-void meta_cursor_sprite_get_hotspot (MetaCursorSprite *self, ++void meta_cursor_sprite_get_hotspot (MetaCursorSprite *sprite, + int *hot_x, + int *hot_y); + +-float meta_cursor_sprite_get_texture_scale (MetaCursorSprite *self); ++float meta_cursor_sprite_get_texture_scale (MetaCursorSprite *sprite); ++ ++gboolean meta_cursor_sprite_is_animated (MetaCursorSprite *sprite); ++ ++void meta_cursor_sprite_tick_frame (MetaCursorSprite *sprite); + +-gboolean meta_cursor_sprite_is_animated (MetaCursorSprite *self); +-void meta_cursor_sprite_tick_frame (MetaCursorSprite *self); +-guint meta_cursor_sprite_get_current_frame_time (MetaCursorSprite *self); ++unsigned int meta_cursor_sprite_get_current_frame_time (MetaCursorSprite *sprite); + + #endif /* META_CURSOR_H */ +diff --git a/src/backends/native/meta-backend-native.c b/src/backends/native/meta-backend-native.c +index a29f593ea..042d96ec6 100644 +--- a/src/backends/native/meta-backend-native.c ++++ b/src/backends/native/meta-backend-native.c +@@ -645,8 +645,6 @@ void meta_backend_native_resume (MetaBackendNative *native) + meta_backend_get_monitor_manager (backend); + MetaMonitorManagerKms *monitor_manager_kms = + META_MONITOR_MANAGER_KMS (monitor_manager); +- MetaCursorRenderer *cursor_renderer; +- MetaCursorRendererNative *cursor_renderer_native; + ClutterActor *stage; + MetaIdleMonitor *idle_monitor; + +@@ -658,10 +656,6 @@ void meta_backend_native_resume (MetaBackendNative *native) + stage = meta_backend_get_stage (backend); + clutter_actor_queue_redraw (stage); + +- cursor_renderer = meta_backend_get_cursor_renderer (backend); +- cursor_renderer_native = META_CURSOR_RENDERER_NATIVE (cursor_renderer); +- meta_cursor_renderer_native_force_update (cursor_renderer_native); +- + idle_monitor = meta_backend_get_idle_monitor (backend, 0); + meta_idle_monitor_reset_idletime (idle_monitor); + } +diff --git a/src/backends/native/meta-cursor-renderer-native.c b/src/backends/native/meta-cursor-renderer-native.c +index c7326af42..29800953b 100644 +--- a/src/backends/native/meta-cursor-renderer-native.c ++++ b/src/backends/native/meta-cursor-renderer-native.c +@@ -35,6 +35,7 @@ + #include + + #include "backends/meta-backend-private.h" ++#include "backends/meta-cursor-sprite-xcursor.h" + #include "backends/meta-logical-monitor.h" + #include "backends/meta-monitor.h" + #include "backends/meta-monitor-manager-private.h" +@@ -43,6 +44,11 @@ + #include "core/boxes-private.h" + #include "meta/boxes.h" + ++#ifdef HAVE_WAYLAND ++#include "wayland/meta-cursor-sprite-wayland.h" ++#include "wayland/meta-wayland-buffer.h" ++#endif ++ + #ifndef DRM_CAP_CURSOR_WIDTH + #define DRM_CAP_CURSOR_WIDTH 0x8 + #endif +@@ -113,6 +119,11 @@ static GQuark quark_cursor_renderer_native_gpu_data = 0; + + G_DEFINE_TYPE_WITH_PRIVATE (MetaCursorRendererNative, meta_cursor_renderer_native, META_TYPE_CURSOR_RENDERER); + ++static void ++realize_cursor_sprite (MetaCursorRenderer *renderer, ++ MetaCursorSprite *cursor_sprite, ++ GList *gpus); ++ + static MetaCursorNativeGpuState * + get_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv, + MetaGpuKms *gpu_kms); +@@ -152,7 +163,8 @@ static void + meta_cursor_renderer_native_finalize (GObject *object) + { + MetaCursorRendererNative *renderer = META_CURSOR_RENDERER_NATIVE (object); +- MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (renderer); ++ MetaCursorRendererNativePrivate *priv = ++ meta_cursor_renderer_native_get_instance_private (renderer); + + if (priv->animation_timeout_id) + g_source_remove (priv->animation_timeout_id); +@@ -203,7 +215,8 @@ set_crtc_cursor (MetaCursorRendererNative *native, + MetaCrtc *crtc, + MetaCursorSprite *cursor_sprite) + { +- MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); ++ MetaCursorRendererNativePrivate *priv = ++ meta_cursor_renderer_native_get_instance_private (native); + MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data; + MetaGpuKms *gpu_kms; + int kms_fd; +@@ -371,7 +384,8 @@ static void + update_hw_cursor (MetaCursorRendererNative *native, + MetaCursorSprite *cursor_sprite) + { +- MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); ++ MetaCursorRendererNativePrivate *priv = ++ meta_cursor_renderer_native_get_instance_private (native); + MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native); + MetaMonitorManager *monitor_manager = priv->monitor_manager; + GList *logical_monitors; +@@ -564,18 +578,15 @@ can_draw_cursor_unscaled (MetaCursorRenderer *renderer, + + static gboolean + should_have_hw_cursor (MetaCursorRenderer *renderer, +- MetaCursorSprite *cursor_sprite) ++ MetaCursorSprite *cursor_sprite, ++ GList *gpus) + { +- MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); +- MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); +- GList *gpus; + GList *l; + CoglTexture *texture; + + if (!cursor_sprite) + return FALSE; + +- gpus = meta_monitor_manager_get_gpus (priv->monitor_manager); + for (l = gpus; l; l = l->next) + { + MetaGpuKms *gpu_kms = l->data; +@@ -609,7 +620,8 @@ should_have_hw_cursor (MetaCursorRenderer *renderer, + static gboolean + meta_cursor_renderer_native_update_animation (MetaCursorRendererNative *native) + { +- MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); ++ MetaCursorRendererNativePrivate *priv = ++ meta_cursor_renderer_native_get_instance_private (native); + MetaCursorRenderer *renderer = META_CURSOR_RENDERER (native); + MetaCursorSprite *cursor_sprite = meta_cursor_renderer_get_cursor (renderer); + +@@ -621,10 +633,11 @@ meta_cursor_renderer_native_update_animation (MetaCursorRendererNative *native) + } + + static void +-meta_cursor_renderer_native_trigger_frame (MetaCursorRendererNative *native, +- MetaCursorSprite *cursor_sprite) ++maybe_schedule_cursor_sprite_animation_frame (MetaCursorRendererNative *native, ++ MetaCursorSprite *cursor_sprite) + { +- MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); ++ MetaCursorRendererNativePrivate *priv = ++ meta_cursor_renderer_native_get_instance_private (native); + gboolean cursor_change; + guint delay; + +@@ -656,21 +669,78 @@ meta_cursor_renderer_native_trigger_frame (MetaCursorRendererNative *native, + } + } + ++static GList * ++calculate_cursor_sprite_gpus (MetaCursorRenderer *renderer, ++ MetaCursorSprite *cursor_sprite) ++{ ++ MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); ++ MetaCursorRendererNativePrivate *priv = ++ meta_cursor_renderer_native_get_instance_private (native); ++ MetaMonitorManager *monitor_manager = priv->monitor_manager; ++ GList *gpus = NULL; ++ GList *logical_monitors; ++ GList *l; ++ ClutterRect cursor_rect; ++ ++ cursor_rect = meta_cursor_renderer_calculate_rect (renderer, cursor_sprite); ++ ++ logical_monitors = ++ meta_monitor_manager_get_logical_monitors (monitor_manager); ++ for (l = logical_monitors; l; l = l->next) ++ { ++ MetaLogicalMonitor *logical_monitor = l->data; ++ MetaRectangle logical_monitor_layout; ++ ClutterRect logical_monitor_rect; ++ GList *monitors, *l_mon; ++ ++ logical_monitor_layout = ++ meta_logical_monitor_get_layout (logical_monitor); ++ logical_monitor_rect = ++ meta_rectangle_to_clutter_rect (&logical_monitor_layout); ++ ++ if (!clutter_rect_intersection (&cursor_rect, &logical_monitor_rect, ++ NULL)) ++ continue; ++ ++ monitors = meta_logical_monitor_get_monitors (logical_monitor); ++ for (l_mon = monitors; l_mon; l_mon = l_mon->next) ++ { ++ MetaMonitor *monitor = l_mon->data; ++ MetaGpu *gpu; ++ ++ gpu = meta_monitor_get_gpu (monitor); ++ if (!g_list_find (gpus, gpu)) ++ gpus = g_list_prepend (gpus, gpu); ++ } ++ } ++ ++ return gpus; ++} ++ + static gboolean + meta_cursor_renderer_native_update_cursor (MetaCursorRenderer *renderer, + MetaCursorSprite *cursor_sprite) + { + MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); +- MetaCursorRendererNativePrivate *priv = meta_cursor_renderer_native_get_instance_private (native); ++ MetaCursorRendererNativePrivate *priv = ++ meta_cursor_renderer_native_get_instance_private (native); ++ g_autoptr (GList) gpus = NULL; + + if (cursor_sprite) +- meta_cursor_sprite_realize_texture (cursor_sprite); ++ { ++ meta_cursor_sprite_realize_texture (cursor_sprite); ++ gpus = calculate_cursor_sprite_gpus (renderer, cursor_sprite); ++ realize_cursor_sprite (renderer, cursor_sprite, gpus); ++ } + +- meta_cursor_renderer_native_trigger_frame (native, cursor_sprite); ++ maybe_schedule_cursor_sprite_animation_frame (native, cursor_sprite); + +- priv->has_hw_cursor = should_have_hw_cursor (renderer, cursor_sprite); ++ priv->has_hw_cursor = should_have_hw_cursor (renderer, cursor_sprite, gpus); + update_hw_cursor (native, cursor_sprite); +- return priv->has_hw_cursor; ++ ++ return (priv->has_hw_cursor || ++ !cursor_sprite || ++ !meta_cursor_sprite_get_cogl_texture (cursor_sprite)); + } + + static void +@@ -706,6 +776,24 @@ ensure_cursor_gpu_state (MetaCursorNativePrivate *cursor_priv, + return cursor_gpu_state; + } + ++static void ++on_cursor_sprite_texture_changed (MetaCursorSprite *cursor_sprite) ++{ ++ MetaCursorNativePrivate *cursor_priv = get_cursor_priv (cursor_sprite); ++ GHashTableIter iter; ++ MetaCursorNativeGpuState *cursor_gpu_state; ++ ++ g_hash_table_iter_init (&iter, cursor_priv->gpu_states); ++ while (g_hash_table_iter_next (&iter, NULL, (gpointer *) &cursor_gpu_state)) ++ { ++ guint pending_bo; ++ pending_bo = get_pending_cursor_sprite_gbm_bo_index (cursor_gpu_state); ++ g_clear_pointer (&cursor_gpu_state->bos[pending_bo], ++ (GDestroyNotify) gbm_bo_destroy); ++ cursor_gpu_state->pending_bo_state = META_CURSOR_GBM_BO_STATE_INVALIDATED; ++ } ++} ++ + static void + cursor_priv_free (MetaCursorNativePrivate *cursor_priv) + { +@@ -738,6 +826,9 @@ ensure_cursor_priv (MetaCursorSprite *cursor_sprite) + cursor_priv, + (GDestroyNotify) cursor_priv_free); + ++ g_signal_connect (cursor_sprite, "texture-changed", ++ G_CALLBACK (on_cursor_sprite_texture_changed), NULL); ++ + return cursor_priv; + } + +@@ -805,57 +896,71 @@ load_cursor_sprite_gbm_buffer_for_gpu (MetaCursorRendererNative *native, + } + } + +-static void +-invalidate_pending_cursor_sprite_gbm_bo (MetaCursorSprite *cursor_sprite, +- MetaGpuKms *gpu_kms) ++static gboolean ++is_cursor_hw_state_valid (MetaCursorSprite *cursor_sprite, ++ MetaGpuKms *gpu_kms) + { + MetaCursorNativePrivate *cursor_priv; + MetaCursorNativeGpuState *cursor_gpu_state; +- guint pending_bo; + + cursor_priv = get_cursor_priv (cursor_sprite); + if (!cursor_priv) +- return; ++ return FALSE; + + cursor_gpu_state = get_cursor_gpu_state (cursor_priv, gpu_kms); + if (!cursor_gpu_state) +- return; ++ return FALSE; + +- pending_bo = get_pending_cursor_sprite_gbm_bo_index (cursor_gpu_state); +- g_clear_pointer (&cursor_gpu_state->bos[pending_bo], +- (GDestroyNotify) gbm_bo_destroy); +- cursor_gpu_state->pending_bo_state = META_CURSOR_GBM_BO_STATE_INVALIDATED; ++ switch (cursor_gpu_state->pending_bo_state) ++ { ++ case META_CURSOR_GBM_BO_STATE_SET: ++ case META_CURSOR_GBM_BO_STATE_NONE: ++ return TRUE; ++ case META_CURSOR_GBM_BO_STATE_INVALIDATED: ++ return FALSE; ++ } ++ ++ g_assert_not_reached (); + } + + #ifdef HAVE_WAYLAND + static void +-meta_cursor_renderer_native_realize_cursor_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer, +- MetaGpuKms *gpu_kms, +- MetaCursorSprite *cursor_sprite, +- struct wl_resource *buffer) ++realize_cursor_sprite_from_wl_buffer_for_gpu (MetaCursorRenderer *renderer, ++ MetaGpuKms *gpu_kms, ++ MetaCursorSpriteWayland *sprite_wayland) + { + MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); ++ MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_wayland); + MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data; + uint32_t gbm_format; + uint64_t cursor_width, cursor_height; + CoglTexture *texture; + uint width, height; ++ MetaWaylandBuffer *buffer; ++ struct wl_resource *buffer_resource; ++ struct wl_shm_buffer *shm_buffer; + + cursor_renderer_gpu_data = + meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms); + if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken) + return; + +- /* Destroy any previous pending cursor buffer; we'll always either fail (which +- * should unset, or succeed, which will set new buffer. +- */ +- invalidate_pending_cursor_sprite_gbm_bo (cursor_sprite, gpu_kms); ++ if (is_cursor_hw_state_valid (cursor_sprite, gpu_kms)) ++ return; + + texture = meta_cursor_sprite_get_cogl_texture (cursor_sprite); + width = cogl_texture_get_width (texture); + height = cogl_texture_get_height (texture); + +- struct wl_shm_buffer *shm_buffer = wl_shm_buffer_get (buffer); ++ buffer = meta_cursor_sprite_wayland_get_buffer (sprite_wayland); ++ if (!buffer) ++ return; ++ ++ buffer_resource = meta_wayland_buffer_get_resource (buffer); ++ if (!buffer_resource) ++ return; ++ ++ shm_buffer = wl_shm_buffer_get (buffer_resource); + if (shm_buffer) + { + int rowstride = wl_shm_buffer_get_stride (shm_buffer); +@@ -929,47 +1034,27 @@ meta_cursor_renderer_native_realize_cursor_from_wl_buffer_for_gpu (MetaCursorRen + set_pending_cursor_sprite_gbm_bo (cursor_sprite, gpu_kms, bo); + } + } +- +-static void +-meta_cursor_renderer_native_realize_cursor_from_wl_buffer (MetaCursorRenderer *renderer, +- MetaCursorSprite *cursor_sprite, +- struct wl_resource *buffer) +-{ +- MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); +- MetaCursorRendererNativePrivate *priv = +- meta_cursor_renderer_native_get_instance_private (native); +- GList *gpus; +- GList *l; +- +- gpus = meta_monitor_manager_get_gpus (priv->monitor_manager); +- for (l = gpus; l; l = l->next) +- { +- MetaGpuKms *gpu_kms = l->data; +- +- meta_cursor_renderer_native_realize_cursor_from_wl_buffer_for_gpu ( +- renderer, +- gpu_kms, +- cursor_sprite, +- buffer); +- } +-} + #endif + + static void +-meta_cursor_renderer_native_realize_cursor_from_xcursor_for_gpu (MetaCursorRenderer *renderer, +- MetaGpuKms *gpu_kms, +- MetaCursorSprite *cursor_sprite, +- XcursorImage *xc_image) ++realize_cursor_sprite_from_xcursor_for_gpu (MetaCursorRenderer *renderer, ++ MetaGpuKms *gpu_kms, ++ MetaCursorSpriteXcursor *sprite_xcursor) + { + MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); + MetaCursorRendererNativeGpuData *cursor_renderer_gpu_data; ++ MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_xcursor); ++ XcursorImage *xc_image; + + cursor_renderer_gpu_data = + meta_cursor_renderer_native_gpu_data_from_gpu (gpu_kms); + if (!cursor_renderer_gpu_data || cursor_renderer_gpu_data->hw_cursor_broken) + return; + +- invalidate_pending_cursor_sprite_gbm_bo (cursor_sprite, gpu_kms); ++ if (is_cursor_hw_state_valid (cursor_sprite, gpu_kms)) ++ return; ++ ++ xc_image = meta_cursor_sprite_xcursor_get_current_image (sprite_xcursor); + + load_cursor_sprite_gbm_buffer_for_gpu (native, + gpu_kms, +@@ -982,26 +1067,45 @@ meta_cursor_renderer_native_realize_cursor_from_xcursor_for_gpu (MetaCursorRende + } + + static void +-meta_cursor_renderer_native_realize_cursor_from_xcursor (MetaCursorRenderer *renderer, +- MetaCursorSprite *cursor_sprite, +- XcursorImage *xc_image) ++realize_cursor_sprite_for_gpu (MetaCursorRenderer *renderer, ++ MetaGpuKms *gpu_kms, ++ MetaCursorSprite *cursor_sprite) ++{ ++#ifdef HAVE_WAYLAND ++ if (META_IS_CURSOR_SPRITE_WAYLAND (cursor_sprite)) ++ { ++ MetaCursorSpriteWayland *sprite_wayland = ++ META_CURSOR_SPRITE_WAYLAND (cursor_sprite); ++ ++ realize_cursor_sprite_from_wl_buffer_for_gpu (renderer, ++ gpu_kms, ++ sprite_wayland); ++ } ++ else ++#endif ++ if (META_IS_CURSOR_SPRITE_XCURSOR (cursor_sprite)) ++ { ++ MetaCursorSpriteXcursor *sprite_xcursor = ++ META_CURSOR_SPRITE_XCURSOR (cursor_sprite); ++ ++ realize_cursor_sprite_from_xcursor_for_gpu (renderer, ++ gpu_kms, ++ sprite_xcursor); ++ } ++} ++ ++static void ++realize_cursor_sprite (MetaCursorRenderer *renderer, ++ MetaCursorSprite *cursor_sprite, ++ GList *gpus) + { +- MetaCursorRendererNative *native = META_CURSOR_RENDERER_NATIVE (renderer); +- MetaCursorRendererNativePrivate *priv = +- meta_cursor_renderer_native_get_instance_private (native); +- GList *gpus; + GList *l; + +- gpus = meta_monitor_manager_get_gpus (priv->monitor_manager); + for (l = gpus; l; l = l->next) + { + MetaGpuKms *gpu_kms = l->data; + +- meta_cursor_renderer_native_realize_cursor_from_xcursor_for_gpu ( +- renderer, +- gpu_kms, +- cursor_sprite, +- xc_image); ++ realize_cursor_sprite_for_gpu (renderer, gpu_kms, cursor_sprite); + } + } + +@@ -1013,12 +1117,6 @@ meta_cursor_renderer_native_class_init (MetaCursorRendererNativeClass *klass) + + object_class->finalize = meta_cursor_renderer_native_finalize; + renderer_class->update_cursor = meta_cursor_renderer_native_update_cursor; +-#ifdef HAVE_WAYLAND +- renderer_class->realize_cursor_from_wl_buffer = +- meta_cursor_renderer_native_realize_cursor_from_wl_buffer; +-#endif +- renderer_class->realize_cursor_from_xcursor = +- meta_cursor_renderer_native_realize_cursor_from_xcursor; + + quark_cursor_sprite = g_quark_from_static_string ("-meta-cursor-native"); + quark_cursor_renderer_native_gpu_data = +@@ -1033,14 +1131,13 @@ force_update_hw_cursor (MetaCursorRendererNative *native) + meta_cursor_renderer_native_get_instance_private (native); + + priv->hw_state_invalidated = TRUE; +- update_hw_cursor (native, meta_cursor_renderer_get_cursor (renderer)); ++ meta_cursor_renderer_force_update (renderer); + } + + static void + on_monitors_changed (MetaMonitorManager *monitors, + MetaCursorRendererNative *native) + { +- /* Our tracking is all messed up, so force an update. */ + force_update_hw_cursor (native); + } + +@@ -1112,9 +1209,3 @@ static void + meta_cursor_renderer_native_init (MetaCursorRendererNative *native) + { + } +- +-void +-meta_cursor_renderer_native_force_update (MetaCursorRendererNative *native) +-{ +- force_update_hw_cursor (native); +-} +diff --git a/src/backends/native/meta-cursor-renderer-native.h b/src/backends/native/meta-cursor-renderer-native.h +index 09203a5f7..fb4c8edc7 100644 +--- a/src/backends/native/meta-cursor-renderer-native.h ++++ b/src/backends/native/meta-cursor-renderer-native.h +@@ -32,8 +32,6 @@ G_DECLARE_FINAL_TYPE (MetaCursorRendererNative, meta_cursor_renderer_native, + META, CURSOR_RENDERER_NATIVE, + MetaCursorRenderer) + +-void meta_cursor_renderer_native_force_update (MetaCursorRendererNative *renderer); +- + MetaCursorRendererNative * meta_cursor_renderer_native_new (MetaBackend *backend); + + #endif /* META_CURSOR_RENDERER_NATIVE_H */ +diff --git a/src/backends/x11/cm/meta-cursor-sprite-xfixes.c b/src/backends/x11/cm/meta-cursor-sprite-xfixes.c +new file mode 100644 +index 000000000..143ebb791 +--- /dev/null ++++ b/src/backends/x11/cm/meta-cursor-sprite-xfixes.c +@@ -0,0 +1,226 @@ ++/* ++ * Copyright 2013, 2018 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 . ++ * ++ */ ++ ++#include "config.h" ++ ++#include "backends/x11/cm/meta-cursor-sprite-xfixes.h" ++ ++#include ++ ++#include "core/display-private.h" ++ ++enum ++{ ++ PROP_0, ++ ++ PROP_DISPLAY, ++ ++ N_PROPS ++}; ++ ++static GParamSpec *obj_props[N_PROPS]; ++ ++struct _MetaCursorSpriteXfixes ++{ ++ MetaCursorSprite parent; ++ ++ MetaDisplay *display; ++}; ++ ++static void ++meta_screen_cast_xfixes_init_initable_iface (GInitableIface *iface); ++ ++G_DEFINE_TYPE_WITH_CODE (MetaCursorSpriteXfixes, ++ meta_cursor_sprite_xfixes, ++ META_TYPE_CURSOR_SPRITE, ++ G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, ++ meta_screen_cast_xfixes_init_initable_iface)) ++ ++static void ++meta_cursor_sprite_xfixes_realize_texture (MetaCursorSprite *sprite) ++{ ++} ++ ++static gboolean ++meta_cursor_sprite_xfixes_is_animated (MetaCursorSprite *sprite) ++{ ++ return FALSE; ++} ++ ++static void ++meta_cursor_sprite_xfixes_get_property (GObject *object, ++ guint prop_id, ++ GValue *value, ++ GParamSpec *pspec) ++{ ++ MetaCursorSpriteXfixes *sprite_xfixes = META_CURSOR_SPRITE_XFIXES (object); ++ ++ switch (prop_id) ++ { ++ case PROP_DISPLAY: ++ g_value_set_object (value, sprite_xfixes->display); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ ++static void ++meta_cursor_sprite_xfixes_set_property (GObject *object, ++ guint prop_id, ++ const GValue *value, ++ GParamSpec *pspec) ++{ ++ MetaCursorSpriteXfixes *sprite_xfixes = META_CURSOR_SPRITE_XFIXES (object); ++ ++ switch (prop_id) ++ { ++ case PROP_DISPLAY: ++ sprite_xfixes->display = g_value_get_object (value); ++ break; ++ default: ++ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); ++ break; ++ } ++} ++ ++MetaCursorSpriteXfixes * ++meta_cursor_sprite_xfixes_new (MetaDisplay *display, ++ GError **error) ++{ ++ return g_initable_new (META_TYPE_CURSOR_SPRITE_XFIXES, ++ NULL, error, ++ "display", display, ++ NULL); ++} ++ ++static gboolean ++meta_cursor_sprite_xfixes_initable_init (GInitable *initable, ++ GCancellable *cancellable, ++ GError **error) ++{ ++ MetaCursorSpriteXfixes *sprite_xfixes = ++ META_CURSOR_SPRITE_XFIXES (initable); ++ MetaCursorSprite *sprite = META_CURSOR_SPRITE (sprite_xfixes); ++ XFixesCursorImage *cursor_image; ++ CoglTexture2D *texture; ++ uint8_t *cursor_data; ++ gboolean free_cursor_data; ++ ClutterBackend *clutter_backend; ++ CoglContext *cogl_context; ++ ++ cursor_image = XFixesGetCursorImage (sprite_xfixes->display->xdisplay); ++ if (!cursor_image) ++ { ++ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, ++ "Failed to get cursor image"); ++ return FALSE; ++ } ++ ++ /* ++ * Like all X APIs, XFixesGetCursorImage() returns arrays of 32-bit ++ * quantities as arrays of long; we need to convert on 64 bit ++ */ ++ if (sizeof (long) == 4) ++ { ++ cursor_data = (uint8_t *) cursor_image->pixels; ++ free_cursor_data = FALSE; ++ } ++ else ++ { ++ int i, j; ++ uint32_t *cursor_words; ++ unsigned long *p; ++ uint32_t *q; ++ ++ cursor_words = g_new (uint32_t, ++ cursor_image->width * cursor_image->height); ++ cursor_data = (uint8_t *) cursor_words; ++ ++ p = cursor_image->pixels; ++ q = cursor_words; ++ for (j = 0; j < cursor_image->height; j++) ++ { ++ for (i = 0; i < cursor_image->width; i++) ++ *(q++) = *(p++); ++ } ++ ++ free_cursor_data = TRUE; ++ } ++ ++ clutter_backend = clutter_get_default_backend (); ++ cogl_context = clutter_backend_get_cogl_context (clutter_backend); ++ texture = cogl_texture_2d_new_from_data (cogl_context, ++ cursor_image->width, ++ cursor_image->height, ++ CLUTTER_CAIRO_FORMAT_ARGB32, ++ cursor_image->width * 4, /* stride */ ++ cursor_data, ++ error); ++ ++ if (free_cursor_data) ++ g_free (cursor_data); ++ ++ if (!sprite) ++ return FALSE; ++ ++ meta_cursor_sprite_set_texture (sprite, ++ COGL_TEXTURE (texture), ++ cursor_image->xhot, ++ cursor_image->yhot); ++ cogl_object_unref (texture); ++ XFree (cursor_image); ++ ++ return TRUE; ++} ++ ++static void ++meta_screen_cast_xfixes_init_initable_iface (GInitableIface *iface) ++{ ++ iface->init = meta_cursor_sprite_xfixes_initable_init; ++} ++ ++static void ++meta_cursor_sprite_xfixes_init (MetaCursorSpriteXfixes *sprite_xfixes) ++{ ++} ++ ++static void ++meta_cursor_sprite_xfixes_class_init (MetaCursorSpriteXfixesClass *klass) ++{ ++ GObjectClass *object_class = G_OBJECT_CLASS (klass); ++ MetaCursorSpriteClass *cursor_sprite_class = META_CURSOR_SPRITE_CLASS (klass); ++ ++ object_class->get_property = meta_cursor_sprite_xfixes_get_property; ++ object_class->set_property = meta_cursor_sprite_xfixes_set_property; ++ ++ cursor_sprite_class->realize_texture = ++ meta_cursor_sprite_xfixes_realize_texture; ++ cursor_sprite_class->is_animated = meta_cursor_sprite_xfixes_is_animated; ++ ++ obj_props[PROP_DISPLAY] = ++ g_param_spec_object ("display", ++ "display", ++ "MetaDisplay", ++ META_TYPE_DISPLAY, ++ G_PARAM_READWRITE | ++ G_PARAM_CONSTRUCT_ONLY | ++ G_PARAM_STATIC_STRINGS); ++ g_object_class_install_properties (object_class, N_PROPS, obj_props); ++} +diff --git a/src/backends/x11/cm/meta-cursor-sprite-xfixes.h b/src/backends/x11/cm/meta-cursor-sprite-xfixes.h +new file mode 100644 +index 000000000..c7073fc2c +--- /dev/null ++++ b/src/backends/x11/cm/meta-cursor-sprite-xfixes.h +@@ -0,0 +1,36 @@ ++/* ++ * Copyright 2013, 2018 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_CURSOR_SPRITE_XFIXES_H ++#define META_CURSOR_SPRITE_XFIXES_H ++ ++#include ++ ++#include "backends/meta-cursor.h" ++#include "meta/types.h" ++ ++#define META_TYPE_CURSOR_SPRITE_XFIXES (meta_cursor_sprite_xfixes_get_type ()) ++G_DECLARE_FINAL_TYPE (MetaCursorSpriteXfixes, ++ meta_cursor_sprite_xfixes, ++ META, CURSOR_SPRITE_XFIXES, ++ MetaCursorSprite) ++ ++MetaCursorSpriteXfixes * meta_cursor_sprite_xfixes_new (MetaDisplay *display, ++ GError **error); ++ ++#endif /* META_CURSOR_SPRITE_XFIXES_H */ +diff --git a/src/backends/x11/meta-cursor-renderer-x11.c b/src/backends/x11/meta-cursor-renderer-x11.c +index 82109f1f3..bb3100a91 100644 +--- a/src/backends/x11/meta-cursor-renderer-x11.c ++++ b/src/backends/x11/meta-cursor-renderer-x11.c +@@ -30,6 +30,7 @@ + + #include "meta-backend-x11.h" + #include "meta-stage-private.h" ++#include "backends/meta-cursor-sprite-xcursor.h" + + struct _MetaCursorRendererX11Private + { +@@ -59,13 +60,18 @@ meta_cursor_renderer_x11_update_cursor (MetaCursorRenderer *renderer, + + gboolean has_server_cursor = FALSE; + +- if (cursor_sprite) ++ if (cursor_sprite && META_IS_CURSOR_SPRITE_XCURSOR (cursor_sprite)) + { +- MetaCursor cursor = meta_cursor_sprite_get_meta_cursor (cursor_sprite); ++ MetaCursorSpriteXcursor *sprite_xcursor = ++ META_CURSOR_SPRITE_XCURSOR (cursor_sprite); ++ MetaCursor cursor; + ++ cursor = meta_cursor_sprite_xcursor_get_cursor (sprite_xcursor); + if (cursor != META_CURSOR_NONE) + { +- Cursor xcursor = meta_cursor_create_x_cursor (xdisplay, cursor); ++ Cursor xcursor; ++ ++ xcursor = meta_create_x_cursor (xdisplay, cursor); + XDefineCursor (xdisplay, xwindow, xcursor); + XFlush (xdisplay); + XFreeCursor (xdisplay, xcursor); +diff --git a/src/backends/x11/nested/meta-cursor-renderer-x11-nested.c b/src/backends/x11/nested/meta-cursor-renderer-x11-nested.c +index da1a56038..0daae683c 100644 +--- a/src/backends/x11/nested/meta-cursor-renderer-x11-nested.c ++++ b/src/backends/x11/nested/meta-cursor-renderer-x11-nested.c +@@ -26,6 +26,8 @@ + + #include "backends/x11/nested/meta-cursor-renderer-x11-nested.h" + ++#include ++ + #include "backends/x11/meta-backend-x11.h" + + struct _MetaCursorRendererX11Nested +diff --git a/src/core/display.c b/src/core/display.c +index d6da84b30..e7dd4534b 100644 +--- a/src/core/display.c ++++ b/src/core/display.c +@@ -3018,7 +3018,7 @@ Cursor + meta_display_create_x_cursor (MetaDisplay *display, + MetaCursor cursor) + { +- return meta_cursor_create_x_cursor (display->xdisplay, cursor); ++ return meta_create_x_cursor (display->xdisplay, cursor); + } + + MetaGestureTracker * +diff --git a/src/core/screen.c b/src/core/screen.c +index c14bba0cf..048104150 100644 +--- a/src/core/screen.c ++++ b/src/core/screen.c +@@ -60,6 +60,7 @@ + #include "x11/xprops.h" + + #include "backends/x11/meta-backend-x11.h" ++#include "backends/meta-cursor-sprite-xcursor.h" + + static char* get_screen_name (MetaDisplay *display, + int number); +@@ -1323,12 +1324,13 @@ find_highest_logical_monitor_scale (MetaBackend *backend, + } + + static void +-root_cursor_prepare_at (MetaCursorSprite *cursor_sprite, +- int x, +- int y, +- MetaScreen *screen) ++root_cursor_prepare_at (MetaCursorSpriteXcursor *sprite_xcursor, ++ int x, ++ int y, ++ MetaScreen *screen) + { + MetaBackend *backend = meta_get_backend (); ++ MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (sprite_xcursor); + + if (meta_is_stage_views_scaled ()) + { +@@ -1337,7 +1339,7 @@ root_cursor_prepare_at (MetaCursorSprite *cursor_sprite, + scale = find_highest_logical_monitor_scale (backend, cursor_sprite); + if (scale != 0.0) + { +- meta_cursor_sprite_set_theme_scale (cursor_sprite, scale); ++ meta_cursor_sprite_xcursor_set_theme_scale (sprite_xcursor, scale); + meta_cursor_sprite_set_texture_scale (cursor_sprite, 1.0 / scale); + } + } +@@ -1353,18 +1355,18 @@ root_cursor_prepare_at (MetaCursorSprite *cursor_sprite, + /* Reload the cursor texture if the scale has changed. */ + if (logical_monitor) + { +- meta_cursor_sprite_set_theme_scale (cursor_sprite, +- logical_monitor->scale); ++ meta_cursor_sprite_xcursor_set_theme_scale (sprite_xcursor, ++ logical_monitor->scale); + meta_cursor_sprite_set_texture_scale (cursor_sprite, 1.0); + } + } + } + + static void +-manage_root_cursor_sprite_scale (MetaScreen *screen, +- MetaCursorSprite *cursor_sprite) ++manage_root_cursor_sprite_scale (MetaScreen *screen, ++ MetaCursorSpriteXcursor *sprite_xcursor) + { +- g_signal_connect_object (cursor_sprite, ++ g_signal_connect_object (sprite_xcursor, + "prepare-at", + G_CALLBACK (root_cursor_prepare_at), + screen, +@@ -1377,17 +1379,18 @@ meta_screen_update_cursor (MetaScreen *screen) + MetaDisplay *display = screen->display; + MetaCursor cursor = screen->current_cursor; + Cursor xcursor; +- MetaCursorSprite *cursor_sprite; ++ MetaCursorSpriteXcursor *sprite_xcursor; + MetaBackend *backend = meta_get_backend (); + MetaCursorTracker *cursor_tracker = meta_backend_get_cursor_tracker (backend); + +- cursor_sprite = meta_cursor_sprite_from_theme (cursor); ++ sprite_xcursor = meta_cursor_sprite_xcursor_new (cursor); + + if (meta_is_wayland_compositor ()) +- manage_root_cursor_sprite_scale (screen, cursor_sprite); ++ manage_root_cursor_sprite_scale (screen, sprite_xcursor); + +- meta_cursor_tracker_set_root_cursor (cursor_tracker, cursor_sprite); +- g_object_unref (cursor_sprite); ++ meta_cursor_tracker_set_root_cursor (cursor_tracker, ++ META_CURSOR_SPRITE (sprite_xcursor)); ++ g_object_unref (sprite_xcursor); + + /* Set a cursor for X11 applications that don't specify their own */ + xcursor = meta_display_create_x_cursor (display, cursor); +diff --git a/src/wayland/meta-cursor-sprite-wayland.c b/src/wayland/meta-cursor-sprite-wayland.c +new file mode 100644 +index 000000000..7c14960ff +--- /dev/null ++++ b/src/wayland/meta-cursor-sprite-wayland.c +@@ -0,0 +1,75 @@ ++/* ++ * Copyright 2015, 2018 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 . ++ * ++ */ ++ ++#include "config.h" ++ ++#include "wayland/meta-cursor-sprite-wayland.h" ++ ++struct _MetaCursorSpriteWayland ++{ ++ MetaCursorSprite parent; ++ ++ MetaWaylandSurface *surface; ++}; ++ ++G_DEFINE_TYPE (MetaCursorSpriteWayland, ++ meta_cursor_sprite_wayland, ++ META_TYPE_CURSOR_SPRITE) ++ ++static void ++meta_cursor_sprite_wayland_realize_texture (MetaCursorSprite *sprite) ++{ ++} ++ ++static gboolean ++meta_cursor_sprite_wayland_is_animated (MetaCursorSprite *sprite) ++{ ++ return FALSE; ++} ++ ++MetaCursorSpriteWayland * ++meta_cursor_sprite_wayland_new (MetaWaylandSurface *surface) ++{ ++ MetaCursorSpriteWayland *sprite_wayland; ++ ++ sprite_wayland = g_object_new (META_TYPE_CURSOR_SPRITE_WAYLAND, NULL); ++ sprite_wayland->surface = surface; ++ ++ return sprite_wayland; ++} ++ ++MetaWaylandBuffer * ++meta_cursor_sprite_wayland_get_buffer (MetaCursorSpriteWayland *sprite_wayland) ++{ ++ return meta_wayland_surface_get_buffer (sprite_wayland->surface); ++} ++ ++static void ++meta_cursor_sprite_wayland_init (MetaCursorSpriteWayland *sprite_wayland) ++{ ++} ++ ++static void ++meta_cursor_sprite_wayland_class_init (MetaCursorSpriteWaylandClass *klass) ++{ ++ MetaCursorSpriteClass *cursor_sprite_class = META_CURSOR_SPRITE_CLASS (klass); ++ ++ cursor_sprite_class->realize_texture = ++ meta_cursor_sprite_wayland_realize_texture; ++ cursor_sprite_class->is_animated = meta_cursor_sprite_wayland_is_animated; ++} +diff --git a/src/wayland/meta-cursor-sprite-wayland.h b/src/wayland/meta-cursor-sprite-wayland.h +new file mode 100644 +index 000000000..107698f3f +--- /dev/null ++++ b/src/wayland/meta-cursor-sprite-wayland.h +@@ -0,0 +1,35 @@ ++/* ++ * Copyright 2013, 2018 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_CURSOR_SPRITE_WAYLAND_H ++#define META_CURSOR_SPRITE_WAYLAND_H ++ ++#include ++ ++#include "backends/meta-cursor.h" ++#include "wayland/meta-wayland-surface.h" ++ ++#define META_TYPE_CURSOR_SPRITE_WAYLAND meta_cursor_sprite_wayland_get_type () ++G_DECLARE_FINAL_TYPE (MetaCursorSpriteWayland, meta_cursor_sprite_wayland, ++ META, CURSOR_SPRITE_WAYLAND, MetaCursorSprite) ++ ++MetaCursorSpriteWayland * meta_cursor_sprite_wayland_new (MetaWaylandSurface *surface); ++ ++MetaWaylandBuffer * meta_cursor_sprite_wayland_get_buffer (MetaCursorSpriteWayland *sprite_wayland); ++ ++#endif /* META_CURSOR_SPRITE_WAYLAND_H */ +diff --git a/src/wayland/meta-wayland-buffer.c b/src/wayland/meta-wayland-buffer.c +index 55564492a..c759eefc1 100644 +--- a/src/wayland/meta-wayland-buffer.c ++++ b/src/wayland/meta-wayland-buffer.c +@@ -88,6 +88,12 @@ meta_wayland_buffer_from_resource (struct wl_resource *resource) + return buffer; + } + ++struct wl_resource * ++meta_wayland_buffer_get_resource (MetaWaylandBuffer *buffer) ++{ ++ return buffer->resource; ++} ++ + static gboolean + meta_wayland_buffer_is_realized (MetaWaylandBuffer *buffer) + { +diff --git a/src/wayland/meta-wayland-buffer.h b/src/wayland/meta-wayland-buffer.h +index 5345033c2..e00a41e09 100644 +--- a/src/wayland/meta-wayland-buffer.h ++++ b/src/wayland/meta-wayland-buffer.h +@@ -68,6 +68,7 @@ G_DECLARE_FINAL_TYPE (MetaWaylandBuffer, meta_wayland_buffer, + META, WAYLAND_BUFFER, GObject); + + MetaWaylandBuffer * meta_wayland_buffer_from_resource (struct wl_resource *resource); ++struct wl_resource * meta_wayland_buffer_get_resource (MetaWaylandBuffer *buffer); + gboolean meta_wayland_buffer_attach (MetaWaylandBuffer *buffer, + GError **error); + CoglTexture * meta_wayland_buffer_get_texture (MetaWaylandBuffer *buffer); +diff --git a/src/wayland/meta-wayland-surface-role-cursor.c b/src/wayland/meta-wayland-cursor-surface.c +similarity index 52% +rename from src/wayland/meta-wayland-surface-role-cursor.c +rename to src/wayland/meta-wayland-cursor-surface.c +index d118a8917..d08af9e8c 100644 +--- a/src/wayland/meta-wayland-surface-role-cursor.c ++++ b/src/wayland/meta-wayland-cursor-surface.c +@@ -23,7 +23,7 @@ + + #include + #include +-#include "meta-wayland-surface-role-cursor.h" ++#include "meta-wayland-cursor-surface.h" + #include "meta-wayland-buffer.h" + #include "meta-xwayland.h" + #include "screen-private.h" +@@ -31,35 +31,38 @@ + #include "backends/meta-backend-private.h" + #include "backends/meta-logical-monitor.h" + #include "core/boxes-private.h" ++#include "wayland/meta-cursor-sprite-wayland.h" + +-typedef struct _MetaWaylandSurfaceRoleCursorPrivate MetaWaylandSurfaceRoleCursorPrivate; ++typedef struct _MetaWaylandCursorSurfacePrivate MetaWaylandCursorSurfacePrivate; + +-struct _MetaWaylandSurfaceRoleCursorPrivate ++struct _MetaWaylandCursorSurfacePrivate + { + int hot_x; + int hot_y; +- MetaCursorSprite *cursor_sprite; ++ MetaCursorSpriteWayland *cursor_sprite; + MetaCursorRenderer *cursor_renderer; + MetaWaylandBuffer *buffer; + struct wl_list frame_callbacks; + gulong cursor_painted_handler_id; + }; + +-G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandSurfaceRoleCursor, +- meta_wayland_surface_role_cursor, ++G_DEFINE_TYPE_WITH_PRIVATE (MetaWaylandCursorSurface, ++ meta_wayland_cursor_surface, + META_TYPE_WAYLAND_SURFACE_ROLE) + + static void +-update_cursor_sprite_texture (MetaWaylandSurfaceRoleCursor *cursor_role) ++update_cursor_sprite_texture (MetaWaylandCursorSurface *cursor_surface) + { +- MetaWaylandSurfaceRoleCursorPrivate *priv = meta_wayland_surface_role_cursor_get_instance_private (cursor_role); +- MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (cursor_role)); ++ MetaWaylandCursorSurfacePrivate *priv = ++ meta_wayland_cursor_surface_get_instance_private (cursor_surface); ++ MetaWaylandSurface *surface = ++ meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (cursor_surface)); + MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface); +- MetaCursorSprite *cursor_sprite = priv->cursor_sprite; ++ MetaCursorSprite *cursor_sprite = META_CURSOR_SPRITE (priv->cursor_sprite); + + g_return_if_fail (!buffer || buffer->texture); + +- if (!priv->cursor_renderer || !cursor_sprite) ++ if (!priv->cursor_renderer) + return; + + if (buffer) +@@ -68,20 +71,6 @@ update_cursor_sprite_texture (MetaWaylandSurfaceRoleCursor *cursor_role) + buffer->texture, + priv->hot_x * surface->scale, + priv->hot_y * surface->scale); +- +- if (priv->buffer) +- { +- struct wl_resource *buffer_resource; +- +- g_assert (priv->buffer == buffer); +- buffer_resource = buffer->resource; +- meta_cursor_renderer_realize_cursor_from_wl_buffer (priv->cursor_renderer, +- cursor_sprite, +- buffer_resource); +- +- meta_wayland_surface_unref_buffer_use_count (surface); +- g_clear_object (&priv->buffer); +- } + } + else + { +@@ -92,12 +81,12 @@ update_cursor_sprite_texture (MetaWaylandSurfaceRoleCursor *cursor_role) + } + + static void +-cursor_sprite_prepare_at (MetaCursorSprite *cursor_sprite, +- int x, +- int y, +- MetaWaylandSurfaceRoleCursor *cursor_role) ++cursor_sprite_prepare_at (MetaCursorSprite *cursor_sprite, ++ int x, ++ int y, ++ MetaWaylandCursorSurface *cursor_surface) + { +- MetaWaylandSurfaceRole *role = META_WAYLAND_SURFACE_ROLE (cursor_role); ++ MetaWaylandSurfaceRole *role = META_WAYLAND_SURFACE_ROLE (cursor_surface); + MetaWaylandSurface *surface = meta_wayland_surface_role_get_surface (role); + + if (!meta_xwayland_is_xwayland_surface (surface)) +@@ -126,14 +115,14 @@ cursor_sprite_prepare_at (MetaCursorSprite *cursor_sprite, + } + + static void +-cursor_surface_role_assigned (MetaWaylandSurfaceRole *surface_role) ++meta_wayland_cursor_surface_assigned (MetaWaylandSurfaceRole *surface_role) + { + MetaWaylandSurface *surface = + meta_wayland_surface_role_get_surface (surface_role); +- MetaWaylandSurfaceRoleCursor *cursor_role = +- META_WAYLAND_SURFACE_ROLE_CURSOR (surface_role); +- MetaWaylandSurfaceRoleCursorPrivate *priv = +- meta_wayland_surface_role_cursor_get_instance_private (cursor_role); ++ MetaWaylandCursorSurface *cursor_surface = ++ META_WAYLAND_CURSOR_SURFACE (surface_role); ++ MetaWaylandCursorSurfacePrivate *priv = ++ meta_wayland_cursor_surface_get_instance_private (cursor_surface); + + wl_list_insert_list (&priv->frame_callbacks, + &surface->pending_frame_callback_list); +@@ -141,13 +130,13 @@ cursor_surface_role_assigned (MetaWaylandSurfaceRole *surface_role) + } + + static void +-cursor_surface_role_pre_commit (MetaWaylandSurfaceRole *surface_role, +- MetaWaylandPendingState *pending) ++meta_wayland_cursor_surface_pre_commit (MetaWaylandSurfaceRole *surface_role, ++ MetaWaylandPendingState *pending) + { +- MetaWaylandSurfaceRoleCursor *cursor_role = +- META_WAYLAND_SURFACE_ROLE_CURSOR (surface_role); +- MetaWaylandSurfaceRoleCursorPrivate *priv = +- meta_wayland_surface_role_cursor_get_instance_private (cursor_role); ++ MetaWaylandCursorSurface *cursor_surface = ++ META_WAYLAND_CURSOR_SURFACE (surface_role); ++ MetaWaylandCursorSurfacePrivate *priv = ++ meta_wayland_cursor_surface_get_instance_private (cursor_surface); + MetaWaylandSurface *surface = + meta_wayland_surface_role_get_surface (surface_role); + +@@ -159,13 +148,13 @@ cursor_surface_role_pre_commit (MetaWaylandSurfaceRole *surface_role, + } + + static void +-cursor_surface_role_commit (MetaWaylandSurfaceRole *surface_role, +- MetaWaylandPendingState *pending) ++meta_wayland_cursor_surface_commit (MetaWaylandSurfaceRole *surface_role, ++ MetaWaylandPendingState *pending) + { +- MetaWaylandSurfaceRoleCursor *cursor_role = +- META_WAYLAND_SURFACE_ROLE_CURSOR (surface_role); +- MetaWaylandSurfaceRoleCursorPrivate *priv = +- meta_wayland_surface_role_cursor_get_instance_private (cursor_role); ++ MetaWaylandCursorSurface *cursor_surface = ++ META_WAYLAND_CURSOR_SURFACE (surface_role); ++ MetaWaylandCursorSurfacePrivate *priv = ++ meta_wayland_cursor_surface_get_instance_private (cursor_surface); + MetaWaylandSurface *surface = + meta_wayland_surface_role_get_surface (surface_role); + MetaWaylandBuffer *buffer = meta_wayland_surface_get_buffer (surface); +@@ -182,19 +171,19 @@ cursor_surface_role_commit (MetaWaylandSurfaceRole *surface_role, + wl_list_init (&pending->frame_callback_list); + + if (pending->newly_attached) +- update_cursor_sprite_texture (META_WAYLAND_SURFACE_ROLE_CURSOR (surface_role)); ++ update_cursor_sprite_texture (META_WAYLAND_CURSOR_SURFACE (surface_role)); + } + + static gboolean +-cursor_surface_role_is_on_logical_monitor (MetaWaylandSurfaceRole *role, +- MetaLogicalMonitor *logical_monitor) ++meta_wayland_cursor_surface_is_on_logical_monitor (MetaWaylandSurfaceRole *role, ++ MetaLogicalMonitor *logical_monitor) + { + MetaWaylandSurface *surface = + meta_wayland_surface_role_get_surface (role); +- MetaWaylandSurfaceRoleCursor *cursor_role = +- META_WAYLAND_SURFACE_ROLE_CURSOR (surface->role); +- MetaWaylandSurfaceRoleCursorPrivate *priv = +- meta_wayland_surface_role_cursor_get_instance_private (cursor_role); ++ MetaWaylandCursorSurface *cursor_surface = ++ META_WAYLAND_CURSOR_SURFACE (surface->role); ++ MetaWaylandCursorSurfacePrivate *priv = ++ meta_wayland_cursor_surface_get_instance_private (cursor_surface); + ClutterPoint point; + ClutterRect logical_monitor_rect; + +@@ -207,12 +196,12 @@ cursor_surface_role_is_on_logical_monitor (MetaWaylandSurfaceRole *role, + } + + static void +-cursor_surface_role_dispose (GObject *object) ++meta_wayland_cursor_surface_dispose (GObject *object) + { +- MetaWaylandSurfaceRoleCursor *cursor_role = +- META_WAYLAND_SURFACE_ROLE_CURSOR (object); +- MetaWaylandSurfaceRoleCursorPrivate *priv = +- meta_wayland_surface_role_cursor_get_instance_private (cursor_role); ++ MetaWaylandCursorSurface *cursor_surface = ++ META_WAYLAND_CURSOR_SURFACE (object); ++ MetaWaylandCursorSurfacePrivate *priv = ++ meta_wayland_cursor_surface_get_instance_private (cursor_surface); + MetaWaylandSurface *surface = + meta_wayland_surface_role_get_surface (META_WAYLAND_SURFACE_ROLE (object)); + MetaWaylandFrameCallback *cb, *next; +@@ -221,7 +210,7 @@ cursor_surface_role_dispose (GObject *object) + wl_resource_destroy (cb->resource); + + g_signal_handlers_disconnect_by_func (priv->cursor_sprite, +- cursor_sprite_prepare_at, cursor_role); ++ cursor_sprite_prepare_at, cursor_surface); + + g_clear_object (&priv->cursor_renderer); + g_clear_object (&priv->cursor_sprite); +@@ -232,18 +221,18 @@ cursor_surface_role_dispose (GObject *object) + g_clear_object (&priv->buffer); + } + +- G_OBJECT_CLASS (meta_wayland_surface_role_cursor_parent_class)->dispose (object); ++ G_OBJECT_CLASS (meta_wayland_cursor_surface_parent_class)->dispose (object); + } + + static void +-cursor_surface_role_constructed (GObject *object) ++meta_wayland_cursor_surface_constructed (GObject *object) + { +- MetaWaylandSurfaceRoleCursor *cursor_role = +- META_WAYLAND_SURFACE_ROLE_CURSOR (object); +- MetaWaylandSurfaceRoleCursorPrivate *priv = +- meta_wayland_surface_role_cursor_get_instance_private (cursor_role); ++ MetaWaylandCursorSurface *cursor_surface = ++ META_WAYLAND_CURSOR_SURFACE (object); ++ MetaWaylandCursorSurfacePrivate *priv = ++ meta_wayland_cursor_surface_get_instance_private (cursor_surface); + MetaWaylandSurfaceRole *surface_role = +- META_WAYLAND_SURFACE_ROLE (cursor_role); ++ META_WAYLAND_SURFACE_ROLE (cursor_surface); + MetaWaylandSurface *surface = + meta_wayland_surface_role_get_surface (surface_role); + MetaWaylandBuffer *buffer; +@@ -257,55 +246,57 @@ cursor_surface_role_constructed (GObject *object) + g_set_object (&priv->buffer, buffer); + meta_wayland_surface_ref_buffer_use_count (surface); + } +-} + +-static void +-meta_wayland_surface_role_cursor_init (MetaWaylandSurfaceRoleCursor *role) +-{ +- MetaWaylandSurfaceRoleCursorPrivate *priv = +- meta_wayland_surface_role_cursor_get_instance_private (role); +- +- priv->cursor_sprite = meta_cursor_sprite_new (); ++ priv->cursor_sprite = meta_cursor_sprite_wayland_new (surface); + g_signal_connect_object (priv->cursor_sprite, + "prepare-at", + G_CALLBACK (cursor_sprite_prepare_at), +- role, ++ cursor_surface, + 0); ++} ++ ++static void ++meta_wayland_cursor_surface_init (MetaWaylandCursorSurface *role) ++{ ++ MetaWaylandCursorSurfacePrivate *priv = ++ meta_wayland_cursor_surface_get_instance_private (role); ++ + wl_list_init (&priv->frame_callbacks); + } + + static void +-meta_wayland_surface_role_cursor_class_init (MetaWaylandSurfaceRoleCursorClass *klass) ++meta_wayland_cursor_surface_class_init (MetaWaylandCursorSurfaceClass *klass) + { + MetaWaylandSurfaceRoleClass *surface_role_class = + META_WAYLAND_SURFACE_ROLE_CLASS (klass); + GObjectClass *object_class = G_OBJECT_CLASS (klass); + +- surface_role_class->assigned = cursor_surface_role_assigned; +- surface_role_class->pre_commit = cursor_surface_role_pre_commit; +- surface_role_class->commit = cursor_surface_role_commit; +- surface_role_class->is_on_logical_monitor = cursor_surface_role_is_on_logical_monitor; ++ surface_role_class->assigned = meta_wayland_cursor_surface_assigned; ++ surface_role_class->pre_commit = meta_wayland_cursor_surface_pre_commit; ++ surface_role_class->commit = meta_wayland_cursor_surface_commit; ++ surface_role_class->is_on_logical_monitor = ++ meta_wayland_cursor_surface_is_on_logical_monitor; + +- object_class->constructed = cursor_surface_role_constructed; +- object_class->dispose = cursor_surface_role_dispose; ++ object_class->constructed = meta_wayland_cursor_surface_constructed; ++ object_class->dispose = meta_wayland_cursor_surface_dispose; + } + + MetaCursorSprite * +-meta_wayland_surface_role_cursor_get_sprite (MetaWaylandSurfaceRoleCursor *cursor_role) ++meta_wayland_cursor_surface_get_sprite (MetaWaylandCursorSurface *cursor_surface) + { +- MetaWaylandSurfaceRoleCursorPrivate *priv = +- meta_wayland_surface_role_cursor_get_instance_private (cursor_role); ++ MetaWaylandCursorSurfacePrivate *priv = ++ meta_wayland_cursor_surface_get_instance_private (cursor_surface); + +- return priv->cursor_sprite; ++ return META_CURSOR_SPRITE (priv->cursor_sprite); + } + + void +-meta_wayland_surface_role_cursor_set_hotspot (MetaWaylandSurfaceRoleCursor *cursor_role, +- gint hotspot_x, +- gint hotspot_y) ++meta_wayland_cursor_surface_set_hotspot (MetaWaylandCursorSurface *cursor_surface, ++ int hotspot_x, ++ int hotspot_y) + { +- MetaWaylandSurfaceRoleCursorPrivate *priv = +- meta_wayland_surface_role_cursor_get_instance_private (cursor_role); ++ MetaWaylandCursorSurfacePrivate *priv = ++ meta_wayland_cursor_surface_get_instance_private (cursor_surface); + + if (priv->hot_x == hotspot_x && + priv->hot_y == hotspot_y) +@@ -313,16 +304,16 @@ meta_wayland_surface_role_cursor_set_hotspot (MetaWaylandSurfaceRoleCursor *curs + + priv->hot_x = hotspot_x; + priv->hot_y = hotspot_y; +- update_cursor_sprite_texture (cursor_role); ++ update_cursor_sprite_texture (cursor_surface); + } + + void +-meta_wayland_surface_role_cursor_get_hotspot (MetaWaylandSurfaceRoleCursor *cursor_role, +- gint *hotspot_x, +- gint *hotspot_y) ++meta_wayland_cursor_surface_get_hotspot (MetaWaylandCursorSurface *cursor_surface, ++ int *hotspot_x, ++ int *hotspot_y) + { +- MetaWaylandSurfaceRoleCursorPrivate *priv = +- meta_wayland_surface_role_cursor_get_instance_private (cursor_role); ++ MetaWaylandCursorSurfacePrivate *priv = ++ meta_wayland_cursor_surface_get_instance_private (cursor_surface); + + if (hotspot_x) + *hotspot_x = priv->hot_x; +@@ -331,15 +322,15 @@ meta_wayland_surface_role_cursor_get_hotspot (MetaWaylandSurfaceRoleCursor *curs + } + + static void +-on_cursor_painted (MetaCursorRenderer *renderer, +- MetaCursorSprite *displayed_sprite, +- MetaWaylandSurfaceRoleCursor *cursor_role) ++on_cursor_painted (MetaCursorRenderer *renderer, ++ MetaCursorSprite *displayed_sprite, ++ MetaWaylandCursorSurface *cursor_surface) + { +- MetaWaylandSurfaceRoleCursorPrivate *priv = +- meta_wayland_surface_role_cursor_get_instance_private (cursor_role); ++ MetaWaylandCursorSurfacePrivate *priv = ++ meta_wayland_cursor_surface_get_instance_private (cursor_surface); + guint32 time = (guint32) (g_get_monotonic_time () / 1000); + +- if (displayed_sprite != priv->cursor_sprite) ++ if (displayed_sprite != META_CURSOR_SPRITE (priv->cursor_sprite)) + return; + + while (!wl_list_empty (&priv->frame_callbacks)) +@@ -353,11 +344,11 @@ on_cursor_painted (MetaCursorRenderer *renderer, + } + + void +-meta_wayland_surface_role_cursor_set_renderer (MetaWaylandSurfaceRoleCursor *cursor_role, +- MetaCursorRenderer *renderer) ++meta_wayland_cursor_surface_set_renderer (MetaWaylandCursorSurface *cursor_surface, ++ MetaCursorRenderer *renderer) + { +- MetaWaylandSurfaceRoleCursorPrivate *priv = +- meta_wayland_surface_role_cursor_get_instance_private (cursor_role); ++ MetaWaylandCursorSurfacePrivate *priv = ++ meta_wayland_cursor_surface_get_instance_private (cursor_surface); + + if (priv->cursor_renderer == renderer) + return; +@@ -373,19 +364,19 @@ meta_wayland_surface_role_cursor_set_renderer (MetaWaylandSurfaceRoleCursor *cur + { + priv->cursor_painted_handler_id = + g_signal_connect_object (renderer, "cursor-painted", +- G_CALLBACK (on_cursor_painted), cursor_role, 0); ++ G_CALLBACK (on_cursor_painted), cursor_surface, 0); + g_object_ref (renderer); + } + + priv->cursor_renderer = renderer; +- update_cursor_sprite_texture (cursor_role); ++ update_cursor_sprite_texture (cursor_surface); + } + + MetaCursorRenderer * +-meta_wayland_surface_role_cursor_get_renderer (MetaWaylandSurfaceRoleCursor *cursor_role) ++meta_wayland_cursor_surface_get_renderer (MetaWaylandCursorSurface *cursor_surface) + { +- MetaWaylandSurfaceRoleCursorPrivate *priv = +- meta_wayland_surface_role_cursor_get_instance_private (cursor_role); ++ MetaWaylandCursorSurfacePrivate *priv = ++ meta_wayland_cursor_surface_get_instance_private (cursor_surface); + + return priv->cursor_renderer; + } +diff --git a/src/wayland/meta-wayland-cursor-surface.h b/src/wayland/meta-wayland-cursor-surface.h +new file mode 100644 +index 000000000..2461a85b3 +--- /dev/null ++++ b/src/wayland/meta-wayland-cursor-surface.h +@@ -0,0 +1,52 @@ ++/* ++ * Wayland Support ++ * ++ * Copyright (C) 2015 Red Hat, Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, write to the Free Software ++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA ++ * 02111-1307, USA. ++ */ ++ ++#ifndef META_WAYLAND_CURSOR_SURFACE_H ++#define META_WAYLAND_CURSOR_SURFACE_H ++ ++#include "meta-wayland-surface.h" ++#include "backends/meta-cursor-renderer.h" ++ ++struct _MetaWaylandCursorSurfaceClass ++{ ++ MetaWaylandSurfaceRoleClass parent_class; ++}; ++ ++#define META_TYPE_WAYLAND_CURSOR_SURFACE (meta_wayland_cursor_surface_get_type ()) ++G_DECLARE_DERIVABLE_TYPE (MetaWaylandCursorSurface, ++ meta_wayland_cursor_surface, ++ META, WAYLAND_CURSOR_SURFACE, ++ MetaWaylandSurfaceRole); ++ ++MetaCursorSprite * meta_wayland_cursor_surface_get_sprite (MetaWaylandCursorSurface *cursor_surface); ++ ++void meta_wayland_cursor_surface_set_hotspot (MetaWaylandCursorSurface *cursor_surface, ++ int hotspot_x, ++ int hotspot_y); ++void meta_wayland_cursor_surface_get_hotspot (MetaWaylandCursorSurface *cursor_surface, ++ int *hotspot_x, ++ int *hotspot_y); ++void meta_wayland_cursor_surface_set_renderer (MetaWaylandCursorSurface *cursor_surface, ++ MetaCursorRenderer *renderer); ++MetaCursorRenderer * meta_wayland_cursor_surface_get_renderer (MetaWaylandCursorSurface *cursor_surface); ++ ++ ++#endif /* META_WAYLAND_CURSOR_SURFACE_H */ +diff --git a/src/wayland/meta-wayland-pointer.c b/src/wayland/meta-wayland-pointer.c +index d5c90c169..e8138576e 100644 +--- a/src/wayland/meta-wayland-pointer.c ++++ b/src/wayland/meta-wayland-pointer.c +@@ -55,7 +55,7 @@ + #include "meta-wayland-seat.h" + #include "meta-wayland-surface.h" + #include "meta-wayland-buffer.h" +-#include "meta-wayland-surface-role-cursor.h" ++#include "meta-wayland-cursor-surface.h" + #include "meta-xwayland.h" + #include "meta-cursor.h" + #include "meta-cursor-tracker-private.h" +@@ -1025,10 +1025,10 @@ meta_wayland_pointer_update_cursor_surface (MetaWaylandPointer *pointer) + + if (pointer->cursor_surface) + { +- MetaWaylandSurfaceRoleCursor *cursor_role = +- META_WAYLAND_SURFACE_ROLE_CURSOR (pointer->cursor_surface->role); ++ MetaWaylandCursorSurface *cursor_surface = ++ META_WAYLAND_CURSOR_SURFACE (pointer->cursor_surface->role); + +- cursor_sprite = meta_wayland_surface_role_cursor_get_sprite (cursor_role); ++ cursor_sprite = meta_wayland_cursor_surface_get_sprite (cursor_surface); + } + + meta_cursor_tracker_set_window_cursor (cursor_tracker, cursor_sprite); +@@ -1102,7 +1102,7 @@ pointer_set_cursor (struct wl_client *client, + + if (surface && + !meta_wayland_surface_assign_role (surface, +- META_TYPE_WAYLAND_SURFACE_ROLE_CURSOR, ++ META_TYPE_WAYLAND_CURSOR_SURFACE, + NULL)) + { + wl_resource_post_error (resource, WL_POINTER_ERROR_ROLE, +@@ -1115,13 +1115,13 @@ pointer_set_cursor (struct wl_client *client, + { + MetaCursorRenderer *cursor_renderer = + meta_backend_get_cursor_renderer (meta_get_backend ()); +- MetaWaylandSurfaceRoleCursor *cursor_role; ++ MetaWaylandCursorSurface *cursor_surface; + +- cursor_role = META_WAYLAND_SURFACE_ROLE_CURSOR (surface->role); +- meta_wayland_surface_role_cursor_set_renderer (cursor_role, +- cursor_renderer); +- meta_wayland_surface_role_cursor_set_hotspot (cursor_role, +- hot_x, hot_y); ++ cursor_surface = META_WAYLAND_CURSOR_SURFACE (surface->role); ++ meta_wayland_cursor_surface_set_renderer (cursor_surface, ++ cursor_renderer); ++ meta_wayland_cursor_surface_set_hotspot (cursor_surface, ++ hot_x, hot_y); + } + + meta_wayland_pointer_set_cursor_surface (pointer, surface); +diff --git a/src/wayland/meta-wayland-surface-role-cursor.h b/src/wayland/meta-wayland-surface-role-cursor.h +deleted file mode 100644 +index b6d6d4a6a..000000000 +--- a/src/wayland/meta-wayland-surface-role-cursor.h ++++ /dev/null +@@ -1,52 +0,0 @@ +-/* +- * Wayland Support +- * +- * Copyright (C) 2015 Red Hat, Inc. +- * +- * This program is free software; you can redistribute it and/or +- * modify it under the terms of the GNU General Public License as +- * published by the Free Software Foundation; either version 2 of the +- * License, or (at your option) any later version. +- * +- * This program is distributed in the hope that it will be useful, but +- * WITHOUT ANY WARRANTY; without even the implied warranty of +- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +- * General Public License for more details. +- * +- * You should have received a copy of the GNU General Public License +- * along with this program; if not, write to the Free Software +- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA +- * 02111-1307, USA. +- */ +- +-#ifndef META_WAYLAND_SURFACE_ROLE_CURSOR_H +-#define META_WAYLAND_SURFACE_ROLE_CURSOR_H +- +-#include "meta-wayland-surface.h" +-#include "backends/meta-cursor-renderer.h" +- +-struct _MetaWaylandSurfaceRoleCursorClass +-{ +- MetaWaylandSurfaceRoleClass parent_class; +-}; +- +-#define META_TYPE_WAYLAND_SURFACE_ROLE_CURSOR (meta_wayland_surface_role_cursor_get_type ()) +-G_DECLARE_DERIVABLE_TYPE (MetaWaylandSurfaceRoleCursor, +- meta_wayland_surface_role_cursor, +- META, WAYLAND_SURFACE_ROLE_CURSOR, +- MetaWaylandSurfaceRole); +- +-MetaCursorSprite * meta_wayland_surface_role_cursor_get_sprite (MetaWaylandSurfaceRoleCursor *cursor_role); +- +-void meta_wayland_surface_role_cursor_set_hotspot (MetaWaylandSurfaceRoleCursor *cursor_role, +- gint hotspot_x, +- gint hotspot_y); +-void meta_wayland_surface_role_cursor_get_hotspot (MetaWaylandSurfaceRoleCursor *cursor_role, +- gint *hotspot_x, +- gint *hotspot_y); +-void meta_wayland_surface_role_cursor_set_renderer (MetaWaylandSurfaceRoleCursor *cursor_role, +- MetaCursorRenderer *renderer); +-MetaCursorRenderer * meta_wayland_surface_role_cursor_get_renderer (MetaWaylandSurfaceRoleCursor *cursor_role); +- +- +-#endif /* META_WAYLAND_SURFACE_ROLE_CURSOR_H */ +diff --git a/src/wayland/meta-wayland-surface-role-tablet-cursor.c b/src/wayland/meta-wayland-tablet-cursor-surface.c +similarity index 63% +rename from src/wayland/meta-wayland-surface-role-tablet-cursor.c +rename to src/wayland/meta-wayland-tablet-cursor-surface.c +index 075a5e4f6..808bf2820 100644 +--- a/src/wayland/meta-wayland-surface-role-tablet-cursor.c ++++ b/src/wayland/meta-wayland-tablet-cursor-surface.c +@@ -20,23 +20,24 @@ + */ + + #include "config.h" +-#include "meta-wayland-surface-role-tablet-cursor.h" + +-struct _MetaWaylandSurfaceRoleTabletCursor ++#include "meta-wayland-tablet-cursor-surface.h" ++ ++struct _MetaWaylandTabletCursorSurface + { +- MetaWaylandSurfaceRoleCursor parent; ++ MetaWaylandCursorSurface parent; + }; + +-G_DEFINE_TYPE (MetaWaylandSurfaceRoleTabletCursor, +- meta_wayland_surface_role_tablet_cursor, +- META_TYPE_WAYLAND_SURFACE_ROLE_CURSOR) ++G_DEFINE_TYPE (MetaWaylandTabletCursorSurface, ++ meta_wayland_tablet_cursor_surface, ++ META_TYPE_WAYLAND_CURSOR_SURFACE) + + static void +-meta_wayland_surface_role_tablet_cursor_init (MetaWaylandSurfaceRoleTabletCursor *role) ++meta_wayland_tablet_cursor_surface_init (MetaWaylandTabletCursorSurface *role) + { + } + + static void +-meta_wayland_surface_role_tablet_cursor_class_init (MetaWaylandSurfaceRoleTabletCursorClass *klass) ++meta_wayland_tablet_cursor_surface_class_init (MetaWaylandTabletCursorSurfaceClass *klass) + { + } +diff --git a/src/wayland/meta-wayland-surface-role-tablet-cursor.h b/src/wayland/meta-wayland-tablet-cursor-surface.h +similarity index 59% +rename from src/wayland/meta-wayland-surface-role-tablet-cursor.h +rename to src/wayland/meta-wayland-tablet-cursor-surface.h +index 69fc6cf0f..5c5c198f5 100644 +--- a/src/wayland/meta-wayland-surface-role-tablet-cursor.h ++++ b/src/wayland/meta-wayland-tablet-cursor-surface.h +@@ -19,15 +19,15 @@ + * 02111-1307, USA. + */ + +-#ifndef META_WAYLAND_SURFACE_ROLE_TABLET_CURSOR_H +-#define META_WAYLAND_SURFACE_ROLE_TABLET_CURSOR_H ++#ifndef META_WAYLAND_TABLET_CURSOR_SURFACE_H ++#define META_WAYLAND_TABLET_CURSOR_SURFACE_H + +-#include "meta-wayland-surface-role-cursor.h" ++#include "meta-wayland-cursor-surface.h" + +-#define META_TYPE_WAYLAND_SURFACE_ROLE_TABLET_CURSOR (meta_wayland_surface_role_tablet_cursor_get_type ()) +-G_DECLARE_FINAL_TYPE (MetaWaylandSurfaceRoleTabletCursor, +- meta_wayland_surface_role_tablet_cursor, +- META, WAYLAND_SURFACE_ROLE_TABLET_CURSOR, +- MetaWaylandSurfaceRoleCursor); ++#define META_TYPE_WAYLAND_TABLET_CURSOR_SURFACE (meta_wayland_tablet_cursor_surface_get_type ()) ++G_DECLARE_FINAL_TYPE (MetaWaylandTabletCursorSurface, ++ meta_wayland_tablet_cursor_surface, ++ META, WAYLAND_TABLET_CURSOR_SURFACE, ++ MetaWaylandCursorSurface) + +-#endif /* META_WAYLAND_SURFACE_ROLE_TABLET_CURSOR_H */ ++#endif /* META_WAYLAND_TABLET_CURSOR_SURFACE_H */ +diff --git a/src/wayland/meta-wayland-tablet-tool.c b/src/wayland/meta-wayland-tablet-tool.c +index 4b57d4156..d373f8d25 100644 +--- a/src/wayland/meta-wayland-tablet-tool.c ++++ b/src/wayland/meta-wayland-tablet-tool.c +@@ -31,7 +31,7 @@ + #include + #include "tablet-unstable-v2-server-protocol.h" + #include "meta-wayland-private.h" +-#include "meta-wayland-surface-role-tablet-cursor.h" ++#include "meta-wayland-tablet-cursor-surface.h" + #include "meta-surface-actor-wayland.h" + #include "meta-wayland-tablet.h" + #include "meta-wayland-tablet-seat.h" +@@ -90,16 +90,16 @@ meta_wayland_tablet_tool_update_cursor_surface (MetaWaylandTabletTool *tool) + if (tool->cursor_surface && + meta_wayland_surface_get_buffer (tool->cursor_surface)) + { +- MetaWaylandSurfaceRoleCursor *cursor_role = +- META_WAYLAND_SURFACE_ROLE_CURSOR (tool->cursor_surface->role); ++ MetaWaylandCursorSurface *cursor_surface = ++ META_WAYLAND_CURSOR_SURFACE (tool->cursor_surface->role); + +- cursor = meta_wayland_surface_role_cursor_get_sprite (cursor_role); ++ cursor = meta_wayland_cursor_surface_get_sprite (cursor_surface); + } + else + cursor = NULL; + } + else if (tool->current_tablet) +- cursor = tool->default_sprite; ++ cursor = META_CURSOR_SPRITE (tool->default_sprite); + else + cursor = NULL; + +@@ -382,10 +382,10 @@ tablet_tool_handle_cursor_surface_destroy (struct wl_listener *listener, + } + + static void +-tool_cursor_prepare_at (MetaCursorSprite *cursor_sprite, +- int x, +- int y, +- MetaWaylandTabletTool *tool) ++tool_cursor_prepare_at (MetaCursorSpriteXcursor *sprite_xcursor, ++ int x, ++ int y, ++ MetaWaylandTabletTool *tool) + { + MetaBackend *backend = meta_get_backend (); + MetaMonitorManager *monitor_manager = +@@ -397,7 +397,8 @@ tool_cursor_prepare_at (MetaCursorSprite *cursor_sprite, + + /* Reload the cursor texture if the scale has changed. */ + if (logical_monitor) +- meta_cursor_sprite_set_theme_scale (cursor_sprite, logical_monitor->scale); ++ meta_cursor_sprite_xcursor_set_theme_scale (sprite_xcursor, ++ logical_monitor->scale); + } + + MetaWaylandTabletTool * +@@ -417,7 +418,7 @@ meta_wayland_tablet_tool_new (MetaWaylandTabletSeat *seat, + tool->focus_surface_destroy_listener.notify = tablet_tool_handle_focus_surface_destroy; + tool->cursor_surface_destroy_listener.notify = tablet_tool_handle_cursor_surface_destroy; + +- tool->default_sprite = meta_cursor_sprite_from_theme (META_CURSOR_CROSSHAIR); ++ tool->default_sprite = meta_cursor_sprite_xcursor_new (META_CURSOR_CROSSHAIR); + tool->prepare_at_signal_id = + g_signal_connect (tool->default_sprite, "prepare-at", + G_CALLBACK (tool_cursor_prepare_at), tool); +@@ -471,7 +472,7 @@ tool_set_cursor (struct wl_client *client, + + if (surface && + !meta_wayland_surface_assign_role (surface, +- META_TYPE_WAYLAND_SURFACE_ROLE_TABLET_CURSOR, ++ META_TYPE_WAYLAND_TABLET_CURSOR_SURFACE, + NULL)) + { + wl_resource_post_error (resource, WL_POINTER_ERROR_ROLE, +@@ -482,13 +483,13 @@ tool_set_cursor (struct wl_client *client, + + if (surface) + { +- MetaWaylandSurfaceRoleCursor *cursor_role; ++ MetaWaylandCursorSurface *cursor_surface; + +- cursor_role = META_WAYLAND_SURFACE_ROLE_CURSOR (surface->role); +- meta_wayland_surface_role_cursor_set_renderer (cursor_role, +- tool->cursor_renderer); +- meta_wayland_surface_role_cursor_set_hotspot (cursor_role, +- hotspot_x, hotspot_y); ++ cursor_surface = META_WAYLAND_CURSOR_SURFACE (surface->role); ++ meta_wayland_cursor_surface_set_renderer (cursor_surface, ++ tool->cursor_renderer); ++ meta_wayland_cursor_surface_set_hotspot (cursor_surface, ++ hotspot_x, hotspot_y); + } + + meta_wayland_tablet_tool_set_cursor_surface (tool, surface); +diff --git a/src/wayland/meta-wayland-tablet-tool.h b/src/wayland/meta-wayland-tablet-tool.h +index 8cd930086..011972fc2 100644 +--- a/src/wayland/meta-wayland-tablet-tool.h ++++ b/src/wayland/meta-wayland-tablet-tool.h +@@ -28,6 +28,7 @@ + + #include "meta-wayland-types.h" + #include "meta-cursor-renderer.h" ++#include "backends/meta-cursor-sprite-xcursor.h" + + struct _MetaWaylandTabletTool + { +@@ -43,7 +44,7 @@ struct _MetaWaylandTabletTool + MetaWaylandSurface *cursor_surface; + struct wl_listener cursor_surface_destroy_listener; + MetaCursorRenderer *cursor_renderer; +- MetaCursorSprite *default_sprite; ++ MetaCursorSpriteXcursor *default_sprite; + guint prepare_at_signal_id; + + MetaWaylandSurface *current; diff --git a/SOURCES/mutter-3.26.0-hybrid-gpus.patch b/SOURCES/mutter-3.26.0-hybrid-gpus.patch deleted file mode 100644 index e0c314a..0000000 --- a/SOURCES/mutter-3.26.0-hybrid-gpus.patch +++ /dev/null @@ -1,12 +0,0 @@ -diff -up mutter-3.26.0/src/backends/native/meta-launcher.c.hybrid mutter-3.26.0/src/backends/native/meta-launcher.c ---- mutter-3.26.0/src/backends/native/meta-launcher.c.hybrid 2017-09-18 15:55:56.673262947 +0100 -+++ mutter-3.26.0/src/backends/native/meta-launcher.c 2017-09-18 15:56:21.383167768 +0100 -@@ -363,7 +363,7 @@ get_primary_gpu_path (const gchar *seat_ - guint num_devices; - - num_devices = count_devices_with_connectors (seat_name, devices); -- if (num_devices != 1) -+ if (num_devices > 1) - goto out; - } - diff --git a/SOURCES/remember-saved-multi-monitor-configuration.patch b/SOURCES/remember-saved-multi-monitor-configuration.patch deleted file mode 100644 index f658b0d..0000000 --- a/SOURCES/remember-saved-multi-monitor-configuration.patch +++ /dev/null @@ -1,160 +0,0 @@ -From 702f204a281c6525da6bfcd2286d70b1ab6eab13 Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Fri, 3 Nov 2017 15:58:02 +0800 -Subject: [PATCH 1/4] monitor-config-manager: Don't include closed laptop panel - in config key - -When deriving the list of disabled monitors when creating new monitors -configs, don't include the laptop panel if the lid is currently closed, -as we consider the laptop panel nonexistent when the laptop lid is -closed when it comes to configuration. - -The laptop panel connector(s) will either way be appropriately disabled -anyway, as the field listing disabled monitors in the configuration do -not affect actual CRTC/connector assignments. - -https://bugzilla.gnome.org/show_bug.cgi?id=788915 ---- - src/backends/meta-monitor-config-manager.c | 4 ++++ - 1 file changed, 4 insertions(+) - -diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c -index 2fe620767..2a7287778 100644 ---- a/src/backends/meta-monitor-config-manager.c -+++ b/src/backends/meta-monitor-config-manager.c -@@ -1308,6 +1308,10 @@ meta_monitors_config_new (MetaMonitorManager *monitor_manager, - MetaMonitor *monitor = l->data; - MetaMonitorSpec *monitor_spec; - -+ if (meta_monitor_manager_is_lid_closed (monitor_manager) && -+ meta_monitor_is_laptop_panel (monitor)) -+ continue; -+ - monitor_spec = meta_monitor_get_spec (monitor); - if (meta_logical_monitor_configs_have_monitor (logical_monitor_configs, - monitor_spec)) --- -2.14.2 - -From 584e2b93d9f28557cfe8a6ff720b4c3e45c458ab Mon Sep 17 00:00:00 2001 -From: =?UTF-8?q?Jonas=20=C3=85dahl?= -Date: Fri, 3 Nov 2017 16:03:23 +0800 -Subject: [PATCH 2/4] monitor-manager: Compare keys when checking whether a - config is complete - -We only counted configured monitors and whether the config was -applicable (could be assigned), howeverwe didn't include disabled -monitors when comparing. This could caused incorrect configurations to -be applied when trying to use the previous configuration. - -One scenario where this happened was one a system with one laptop -screen and one external monitor that was hot plugged some point after -start up. When the laptop lid was closed, the 'previous configuration' -being the configuration where only the laptop panel was enabled, passed -'is-complete' check as the number of configured monitors were correct, -and the configuration was applicable. - -Avoid this issue by simply comparing the configuration key of the -previous configuration and the configuration key of the current state. -This correctly identifies a laptop panel with the lid closed as -inaccessible, thus doesn't incorrectly revert to the previous -configuration. - -https://bugzilla.gnome.org/show_bug.cgi?id=788915 ---- - src/backends/meta-monitor-config-manager.c | 7 +++--- - src/backends/meta-monitor-config-manager.h | 2 ++ - src/backends/meta-monitor-manager.c | 36 +++++++++--------------------- - 3 files changed, 16 insertions(+), 29 deletions(-) - -diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c -index 2a7287778..bdf863055 100644 ---- a/src/backends/meta-monitor-config-manager.c -+++ b/src/backends/meta-monitor-config-manager.c -@@ -326,8 +326,8 @@ meta_monitor_config_manager_assign (MetaMonitorManager *manager, - return TRUE; - } - --static MetaMonitorsConfigKey * --create_key_for_current_state (MetaMonitorManager *monitor_manager) -+MetaMonitorsConfigKey * -+meta_create_monitors_config_key_for_current_state (MetaMonitorManager *monitor_manager) - { - MetaMonitorsConfigKey *config_key; - GList *l; -@@ -369,7 +369,8 @@ meta_monitor_config_manager_get_stored (MetaMonitorConfigManager *config_manager - MetaMonitorsConfig *config; - GError *error = NULL; - -- config_key = create_key_for_current_state (monitor_manager); -+ config_key = -+ meta_create_monitors_config_key_for_current_state (monitor_manager); - if (!config_key) - return NULL; - -diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h -index 516909dd7..c36df38e6 100644 ---- a/src/backends/meta-monitor-config-manager.h -+++ b/src/backends/meta-monitor-config-manager.h -@@ -136,6 +136,8 @@ void meta_logical_monitor_config_free (MetaLogicalMonitorConfig *logical_monitor - - void meta_monitor_config_free (MetaMonitorConfig *monitor_config); - -+MetaMonitorsConfigKey * meta_create_monitors_config_key_for_current_state (MetaMonitorManager *monitor_manager); -+ - gboolean meta_logical_monitor_configs_have_monitor (GList *logical_monitor_configs, - MetaMonitorSpec *monitor_spec); - -diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c -index 8b548fd68..eb3612cf0 100644 ---- a/src/backends/meta-monitor-manager.c -+++ b/src/backends/meta-monitor-manager.c -@@ -1551,35 +1551,19 @@ static gboolean - meta_monitor_manager_is_config_complete (MetaMonitorManager *manager, - MetaMonitorsConfig *config) - { -- GList *l; -- unsigned int configured_monitor_count = 0; -- unsigned int expected_monitor_count = 0; -- -- for (l = config->logical_monitor_configs; l; l = l->next) -- { -- MetaLogicalMonitorConfig *logical_monitor_config = l->data; -- GList *k; -+ MetaMonitorsConfigKey *current_state_key; -+ gboolean is_config_complete; - -- for (k = logical_monitor_config->monitor_configs; k; k = k->next) -- configured_monitor_count++; -- } -- -- for (l = manager->monitors; l; l = l->next) -- { -- MetaMonitor *monitor = l->data; -+ current_state_key = -+ meta_create_monitors_config_key_for_current_state (manager); -+ if (!current_state_key) -+ return FALSE; - -- if (meta_monitor_is_laptop_panel (monitor)) -- { -- if (!meta_monitor_manager_is_lid_closed (manager)) -- expected_monitor_count++; -- } -- else -- { -- expected_monitor_count++; -- } -- } -+ is_config_complete = meta_monitors_config_key_equal (current_state_key, -+ config->key); -+ meta_monitors_config_key_free (current_state_key); - -- if (configured_monitor_count != expected_monitor_count) -+ if (!is_config_complete) - return FALSE; - - return meta_monitor_manager_is_config_applicable (manager, config, NULL); --- -2.14.2 - diff --git a/SOURCES/wacom-pro-pen-3d.patch b/SOURCES/wacom-pro-pen-3d.patch deleted file mode 100644 index f3d155a..0000000 --- a/SOURCES/wacom-pro-pen-3d.patch +++ /dev/null @@ -1,159 +0,0 @@ -From 42a526581d1216d835dbbbeab5a7bdb75b349179 Mon Sep 17 00:00:00 2001 -From: Jason Gerecke -Date: Tue, 10 Oct 2017 09:18:25 -0700 -Subject: [PATCH 1/2] clutter/evdev: Add support for BTN_STYLUS3 - -BTN_STYLUS3 is defined by the Linux 4.15 kernel and is sent when the -third button on a stylus is pressed. At the moment, only Wacom's "Pro -Pen 3D" has three stylus buttons. Pressing this button triggers a button -8 event to be sent under X11, so we use the same mapping here. - -https://bugzilla.gnome.org/show_bug.cgi?id=790033 ---- - clutter/clutter/evdev/clutter-seat-evdev.c | 8 ++++++++ - 1 file changed, 8 insertions(+) - -diff --git a/clutter/clutter/evdev/clutter-seat-evdev.c b/clutter/clutter/evdev/clutter-seat-evdev.c -index e8524da..f98f85a 100644 ---- a/clutter/clutter/evdev/clutter-seat-evdev.c -+++ b/clutter/clutter/evdev/clutter-seat-evdev.c -@@ -45,6 +45,10 @@ - - #define DISCRETE_SCROLL_STEP 10.0 - -+#ifndef BTN_STYLUS3 -+#define BTN_STYLUS3 0x149 /* Linux 4.15 */ -+#endif -+ - void - clutter_seat_evdev_set_libinput_seat (ClutterSeatEvdev *seat, - struct libinput_seat *libinput_seat) -@@ -492,6 +496,10 @@ clutter_seat_evdev_notify_button (ClutterSeatEvdev *seat, - button_nr = CLUTTER_BUTTON_MIDDLE; - break; - -+ case 0x149: /* BTN_STYLUS3 */ -+ button_nr = 8; -+ break; -+ - default: - /* For compatibility reasons, all additional buttons go after the old 4-7 scroll ones */ - if (clutter_input_device_get_device_type (input_device) == CLUTTER_TABLET_DEVICE) --- -2.17.0 - - -From c42c5294d0ca3d27001f217974cad72a40ffae60 Mon Sep 17 00:00:00 2001 -From: Jason Gerecke -Date: Tue, 10 Oct 2017 08:55:41 -0700 -Subject: [PATCH 2/2] backends: Add support for Wacom stylus - tertiary-button-action - -The tertiary-button-action (see bug 790028) is a place for g-c-c to store -the action which should be performed when a stylus' third button is pressed. -Pressing this button is signaled as a BTN_STYLUS3 event from the kernel or -X11 button 8. - -https://bugzilla.gnome.org/show_bug.cgi?id=790033 ---- - src/backends/meta-input-settings-private.h | 3 ++- - src/backends/meta-input-settings.c | 5 +++-- - src/backends/native/meta-input-settings-native.c | 5 ++++- - src/backends/x11/meta-input-settings-x11.c | 10 ++++++++-- - 4 files changed, 17 insertions(+), 6 deletions(-) - -diff --git a/src/backends/meta-input-settings-private.h b/src/backends/meta-input-settings-private.h -index 605690e..893d4ec 100644 ---- a/src/backends/meta-input-settings-private.h -+++ b/src/backends/meta-input-settings-private.h -@@ -111,7 +111,8 @@ struct _MetaInputSettingsClass - ClutterInputDevice *device, - ClutterInputDeviceTool *tool, - GDesktopStylusButtonAction primary, -- GDesktopStylusButtonAction secondary); -+ GDesktopStylusButtonAction secondary, -+ GDesktopStylusButtonAction tertiary); - gboolean (* has_two_finger_scroll) (MetaInputSettings *settings, - ClutterInputDevice *device); - }; -diff --git a/src/backends/meta-input-settings.c b/src/backends/meta-input-settings.c -index ec0fc9f..989f9e3 100644 ---- a/src/backends/meta-input-settings.c -+++ b/src/backends/meta-input-settings.c -@@ -1453,7 +1453,7 @@ update_stylus_buttonmap (MetaInputSettings *input_settings, - ClutterInputDeviceTool *tool) - { - MetaInputSettingsClass *input_settings_class; -- GDesktopStylusButtonAction primary, secondary; -+ GDesktopStylusButtonAction primary, secondary, tertiary; - GSettings *tool_settings; - - if (clutter_input_device_get_device_type (device) != CLUTTER_TABLET_DEVICE && -@@ -1468,10 +1468,11 @@ update_stylus_buttonmap (MetaInputSettings *input_settings, - - primary = g_settings_get_enum (tool_settings, "button-action"); - secondary = g_settings_get_enum (tool_settings, "secondary-button-action"); -+ tertiary = g_settings_get_enum (tool_settings, "tertiary-button-action"); - - input_settings_class = META_INPUT_SETTINGS_GET_CLASS (input_settings); - input_settings_class->set_stylus_button_map (input_settings, device, tool, -- primary, secondary); -+ primary, secondary, tertiary); - } - - static void -diff --git a/src/backends/native/meta-input-settings-native.c b/src/backends/native/meta-input-settings-native.c -index beb7217..7450725 100644 ---- a/src/backends/native/meta-input-settings-native.c -+++ b/src/backends/native/meta-input-settings-native.c -@@ -547,12 +547,15 @@ meta_input_settings_native_set_stylus_button_map (MetaInputSettings *se - ClutterInputDevice *device, - ClutterInputDeviceTool *tool, - GDesktopStylusButtonAction primary, -- GDesktopStylusButtonAction secondary) -+ GDesktopStylusButtonAction secondary, -+ GDesktopStylusButtonAction tertiary) - { - clutter_evdev_input_device_tool_set_button_code (tool, CLUTTER_BUTTON_MIDDLE, - action_to_evcode (primary)); - clutter_evdev_input_device_tool_set_button_code (tool, CLUTTER_BUTTON_SECONDARY, - action_to_evcode (secondary)); -+ clutter_evdev_input_device_tool_set_button_code (tool, 8, /* Back */ -+ action_to_evcode (tertiary)); - } - - static void -diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c -index 4867b6b..7d5239f 100644 ---- a/src/backends/x11/meta-input-settings-x11.c -+++ b/src/backends/x11/meta-input-settings-x11.c -@@ -1031,7 +1031,8 @@ meta_input_settings_x11_set_stylus_button_map (MetaInputSettings *setti - ClutterInputDevice *device, - ClutterInputDeviceTool *tool, - GDesktopStylusButtonAction primary, -- GDesktopStylusButtonAction secondary) -+ GDesktopStylusButtonAction secondary, -+ GDesktopStylusButtonAction tertiary) - { - MetaDisplay *display = meta_get_display (); - MetaBackend *backend = meta_get_backend (); -@@ -1046,10 +1047,15 @@ meta_input_settings_x11_set_stylus_button_map (MetaInputSettings *setti - xdev = device_ensure_xdevice (device); - if (xdev) - { -- guchar map[3] = { -+ guchar map[8] = { - CLUTTER_BUTTON_PRIMARY, - action_to_button (primary, CLUTTER_BUTTON_MIDDLE), - action_to_button (secondary, CLUTTER_BUTTON_SECONDARY), -+ 4, -+ 5, -+ 6, -+ 7, -+ action_to_button (tertiary, 8), /* "Back" */ - }; - - XSetDeviceButtonMapping (xdisplay, xdev, map, G_N_ELEMENTS (map)); --- -2.17.0 - diff --git a/SPECS/mutter.spec b/SPECS/mutter.spec index 52c9c6c..0b9d366 100644 --- a/SPECS/mutter.spec +++ b/SPECS/mutter.spec @@ -3,27 +3,28 @@ %global gsettings_desktop_schemas_version 3.21.4 %global json_glib_version 0.12.0 %global libinput_version 1.4 -%global wayland_protocols_version 1.9.0 %ifarch s390 s390x %global disable_wayland --disable-wayland-egl-server --disable-wayland --disable-native-backend %endif Name: mutter -Version: 3.26.2 -Release: 17%{?dist} +Version: 3.28.3 +Release: 4%{?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.26/%{name}-%{version}.tar.xz +Source0: http://download.gnome.org/sources/%{name}/3.28/%{name}-%{version}.tar.xz Patch0: startup-notification.patch Patch1: deal-more-gracefully-with-oversized-windows.patch +# Work-around for Xvnc resizing (#1265511) Patch2: 0001-monitor-manager-xrandr-Work-around-spurious-hotplugs.patch + Patch3: 0001-monitor-manager-xrandr-Force-an-update-when-resuming.patch Patch4: 0001-monitor-manager-Consider-external-layout-before-defa.patch @@ -32,35 +33,31 @@ Patch6: 0001-backends-x11-Support-synaptics-configuration.patch Patch7: 0001-window-actor-Special-case-shaped-Java-windows.patch -Patch8: 0001-backends-x11-Preserve-XI1-XDevice-throughout-Clutter.patch Patch9: 0001-clutter-Extend-touchpad-device-property-check-for-Sy.patch -Patch10: 0001-backends-x11-wacom-pressure-curve-is-a-32-bit-proper.patch - -Patch11: 0001-renderer-x11-Enable-GPU-memory-purge-error-extension.patch -Patch12: 0001-backends-Monitor-changes-in-active-tools-settings.patch -Patch13: 0001-clutter-x11-Implement-missing-ClutterInputDevice-pad.patch -Patch14: wacom-pro-pen-3d.patch +Patch10: 0001-clutter-x11-Implement-keycode-lookup-from-keysyms-on.patch # http://bugzilla.gnome.org/show_bug.cgi?id=733277 Patch20: 0008-Add-support-for-quad-buffer-stereo.patch Patch21: 0001-build-Lower-automake-requirement.patch -Patch23: 0001-backends-x11-Fix-time-comparison-bug-causing-hang.patch -Patch24: fix-transient-close-crash.patch +# https://bugzilla.redhat.com/show_bug.cgi?id=1618632 +# https://bugzilla.redhat.com/show_bug.cgi?id=1497303 +Patch31: 0001-monitor-manager-only-reuse-initial-config-if-monitor.patch # el7 patches Patch100: 0001-Revert-build-Require-libgudev-232.patch Patch101: 0001-rhel7-Fix-build-for-el7.patch -Patch102: mutter-3.26.0-hybrid-gpus.patch Patch103: 0001-wayland-enable-scale-monitor-framebuffer-by-default.patch Patch104: add-support-for-plain-old-x-device-configuration.patch -Patch105: remember-saved-multi-monitor-configuration.patch -Patch106: 0003-window-wayland-Handle-resizing-when-headless.patch -Patch107: fix-session-save-crash.patch -Patch108: 0001-wayland-Do-not-fail-on-stalled-.X11-unix-entries.patch Patch109: 0001-main-be-more-aggressive-in-assuming-X11-backend.patch +Patch110: 0001-clutter-Only-reset-scroll-axes-on-slave-devices.patch +Patch111: fix-crash-when-modal-closes-during-drag.patch -Patch500: 0001-clutter-stage-don-t-use-deprecated-api.patch +# Fedora patches: +# Upload HW cursor on demand, avoiding stuttering on hybrid GPU laptops +Patch201: hw-cursor-on-demand-gnome-3-28.patch +# Check hw support for calculated view transform +Patch202: 0001-renderer-native-Check-calculated-transform-when-crea.patch BuildRequires: chrpath BuildRequires: pango-devel @@ -91,6 +88,7 @@ BuildRequires: mesa-libGLES-devel BuildRequires: mesa-libGL-devel BuildRequires: mesa-libgbm-devel BuildRequires: pam-devel +BuildRequires: systemd-devel BuildRequires: upower-devel BuildRequires: xkeyboard-config-devel BuildRequires: zenity @@ -110,7 +108,6 @@ BuildRequires: libgudev1-devel %ifnarch s390 s390x BuildRequires: libwayland-server-devel BuildRequires: libinput-devel >= %{libinput_version} -BuildRequires: wayland-protocols-devel >= %{wayland_protocols_version} %endif Obsoletes: mutter-wayland < 3.13.0 @@ -128,7 +125,6 @@ Requires: dbus-x11 Requires: zenity Requires: json-glib%{?_isa} >= %{json_glib_version} - %ifnarch s390 s390x Requires: libinput%{?_isa} >= %{libinput_version} %endif @@ -218,21 +214,47 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : %{_libdir}/pkgconfig/* %changelog -* Tue Aug 28 2018 Florian Müllner - 3.26.2-17 -- Fix crash when transient dialog closes during drag operation -- Resolves: #1622036 +* Fri Sep 21 2018 Ray Strode - 3.28.3-4 +- Fix crasher introduced in the previous build + Related: #1497303 1618632 + +* Wed Sep 19 2018 Ray Strode - 3.28.3-3 +- ensure monitor hotplugged after start up is activated + Resolves: #1497303 1618632 + +* Tue Sep 04 2018 Florian Müllner - 3.28.3-2 +- Fix non-lowercase letters on virtual key devices +- Resolves: #1521077 -* Wed Aug 08 2018 Florian Müllner - 3.26.2-16 +* Wed Aug 01 2018 Kalev Lember - 3.28.3-1 +- Update to 3.28.3 +- Apply HW cursor on-demand patches +- Apply monitor transform regression patch +- Resolves: #1569736 + +* Thu Jul 26 2018 Florian Müllner - 3.28.2-5 +- Fix crash when modal closes during drag + Resolves: #1581454 + +* Wed Jul 18 2018 Ray Strode - 3.28.2-4 +- rebuild against correct gnome-desktop + Related: #1593782 + +* Fri Jun 22 2018 Florian Müllner - 3.28.2-3 - Fix support for external monitor configurations -- Resolves: #1622000 +- Resolves: #1585230 + +* Tue Jun 19 2018 Carlos Garnacho - 3.28.2-2 +- Update scroll axes only in slave devices +- Resolves: #1423374 -* Tue Jul 17 2018 Florian Müllner - 3.26.2-15 -- Fix time comparison bug causing hang - Resolves: #1601948 +* Mon May 07 2018 Florian Müllner - 3.28.2-1 +- Update to 3.28.2 +- Resolves: #1569736 * Tue Apr 17 2018 Carlos Garnacho - 3.26.2-14 - Add support for Wacom Pro Pen 3D styli - Resolves: #1568702 + Resolves: #1564063 * Fri Feb 23 2018 Carlos Garnacho - 3.26.2-13 - Fix pad ring/strip modes