From b8efaf5e639c5971ea33180d970485a1bdc7e82d Mon Sep 17 00:00:00 2001 From: guibuilder_pel7x64builder0 Date: Mon, 26 Nov 2018 11:35:18 +0100 Subject: [PATCH] mutter package update Signed-off-by: guibuilder_pel7x64builder0 --- ...01-Revert-build-Require-libgudev-232.patch | 37 +- ...y-reset-scroll-axes-on-slave-devices.patch | 27 + ...ement-keycode-lookup-from-keysyms-on.patch | 317 ++ ...Consider-external-layout-before-defa.patch | 30 +- ...only-reuse-initial-config-if-monitor.patch | 505 +++ ...xrandr-Force-an-update-when-resuming.patch | 807 ++++- ...xrandr-Work-around-spurious-hotplugs.patch | 48 +- ...8-Add-support-for-quad-buffer-stereo.patch | 76 +- ...-crash-when-modal-closes-during-drag.patch | 71 + SOURCES/hw-cursor-on-demand-gnome-3-28.patch | 3006 +++++++++++++++++ SPECS/mutter.spec | 79 +- 11 files changed, 4755 insertions(+), 248 deletions(-) create mode 100644 SOURCES/0001-clutter-Only-reset-scroll-axes-on-slave-devices.patch create mode 100644 SOURCES/0001-clutter-x11-Implement-keycode-lookup-from-keysyms-on.patch create mode 100644 SOURCES/0001-monitor-manager-only-reuse-initial-config-if-monitor.patch create mode 100644 SOURCES/fix-crash-when-modal-closes-during-drag.patch create mode 100644 SOURCES/hw-cursor-on-demand-gnome-3-28.patch 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-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-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-monitor-manager-Consider-external-layout-before-defa.patch b/SOURCES/0001-monitor-manager-Consider-external-layout-before-defa.patch index 3a67aa8..5ef6094 100644 --- a/SOURCES/0001-monitor-manager-Consider-external-layout-before-defa.patch +++ b/SOURCES/0001-monitor-manager-Consider-external-layout-before-defa.patch @@ -1,4 +1,4 @@ -From 679644180338527648d7856640c2021b4f4daf30 Mon Sep 17 00:00:00 2001 +From 648f1ce9350fcab0ebaecccb115b5021c632e7b5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Florian=20M=C3=BCllner?= Date: Thu, 28 Jan 2016 15:26:33 +0100 Subject: [PATCH] monitor-manager: Consider external layout before default @@ -11,16 +11,16 @@ which is not desirable. Instead, base the initial configuration on the existing layout if it passes some sanity checks before falling back to the default linear config. --- - src/backends/meta-monitor-config-manager.c | 71 ++++++++++++++++++++++++++++++ + 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, 91 insertions(+) + 3 files changed, 97 insertions(+) diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c -index cdc9fb775..2fe620767 100644 +index 197892bf2..ae988f64a 100644 --- a/src/backends/meta-monitor-config-manager.c +++ b/src/backends/meta-monitor-config-manager.c -@@ -558,6 +558,77 @@ 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 cdc9fb775..2fe620767 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); +} @@ -92,14 +94,18 @@ index cdc9fb775..2fe620767 100644 + logical_monitor_configs = g_list_append (logical_monitor_configs, + logical_monitor_config); + } -+ return NULL; ++ ++ return meta_monitors_config_new (monitor_manager, ++ logical_monitor_configs, ++ layout_mode, ++ META_MONITORS_CONFIG_FLAG_NONE); +} + MetaMonitorsConfig * meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_manager) { diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h -index b99cdaba2..516909dd7 100644 +index 269d8e1b7..c36df38e6 100644 --- a/src/backends/meta-monitor-config-manager.h +++ b/src/backends/meta-monitor-config-manager.h @@ -87,6 +87,7 @@ gboolean meta_monitor_config_manager_assign (MetaMonitorManager *manager, @@ -111,10 +117,10 @@ index b99cdaba2..516909dd7 100644 MetaMonitorsConfig * meta_monitor_config_manager_create_fallback (MetaMonitorConfigManager *config_manager); diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c -index f2ad3f3d0..8b548fd68 100644 +index 0b5e54c48..263e93941 100644 --- a/src/backends/meta-monitor-manager.c +++ b/src/backends/meta-monitor-manager.c -@@ -553,6 +553,25 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager) +@@ -576,6 +576,25 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager) g_clear_object (&config); } @@ -141,5 +147,5 @@ index f2ad3f3d0..8b548fd68 100644 if (config) { -- -2.14.2 +2.17.1 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/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/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/SPECS/mutter.spec b/SPECS/mutter.spec index af086a5..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: 13%{?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,32 +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 +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 +# 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 @@ -88,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 @@ -107,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 @@ -125,7 +125,6 @@ Requires: dbus-x11 Requires: zenity Requires: json-glib%{?_isa} >= %{json_glib_version} - %ifnarch s390 s390x Requires: libinput%{?_isa} >= %{libinput_version} %endif @@ -215,6 +214,48 @@ glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : %{_libdir}/pkgconfig/* %changelog +* 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 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: #1585230 + +* Tue Jun 19 2018 Carlos Garnacho - 3.28.2-2 +- Update scroll axes only in slave devices +- Resolves: #1423374 + +* 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: #1564063 + * Fri Feb 23 2018 Carlos Garnacho - 3.26.2-13 - Fix pad ring/strip modes Resolves: #1543633