diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f2ae9b2 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +SOURCES/mutter-3.28.3.tar.xz diff --git a/.mutter.metadata b/.mutter.metadata new file mode 100644 index 0000000..6b4e4ce --- /dev/null +++ b/.mutter.metadata @@ -0,0 +1 @@ +a7a01f50c75dc6c1e0fe708656cfce1546624568 SOURCES/mutter-3.28.3.tar.xz diff --git a/SOURCES/0001-Revert-build-Require-libgudev-232.patch b/SOURCES/0001-Revert-build-Require-libgudev-232.patch new file mode 100644 index 0000000..e55d8bb --- /dev/null +++ b/SOURCES/0001-Revert-build-Require-libgudev-232.patch @@ -0,0 +1,59 @@ +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 | 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 e6b2bf8..2fde187 100644 +--- a/configure.ac ++++ b/configure.ac +@@ -227,10 +227,10 @@ AC_MSG_CHECKING([gudev]) + if test x$with_gudev = xno ; then + AC_MSG_RESULT([disabled]) + else +- if $PKG_CONFIG --exists "gudev-1.0 >= 232"; then ++ if $PKG_CONFIG --exists gudev-1.0; then + have_gudev=yes + AC_MSG_RESULT(yes) +- MUTTER_PC_MODULES="$MUTTER_PC_MODULES gudev-1.0 >= 232" ++ MUTTER_PC_MODULES="$MUTTER_PC_MODULES gudev-1.0" + AC_DEFINE([HAVE_LIBGUDEV], 1, [Building with gudev for device type detection]) + else + AC_MSG_RESULT(no) +diff --git a/src/backends/native/meta-launcher.c b/src/backends/native/meta-launcher.c +index 8b066c9..22ea2ad 100644 +--- a/src/backends/native/meta-launcher.c ++++ b/src/backends/native/meta-launcher.c +@@ -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(GUdevEnumerator, g_object_unref) ++ + typedef struct + { + GSource source; +-- +1.8.3.1 + diff --git a/SOURCES/0001-backends-x11-Support-synaptics-configuration.patch b/SOURCES/0001-backends-x11-Support-synaptics-configuration.patch new file mode 100644 index 0000000..b6f21e1 --- /dev/null +++ b/SOURCES/0001-backends-x11-Support-synaptics-configuration.patch @@ -0,0 +1,342 @@ +From 647de5a802627809486fe760c657b05297470683 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Thu, 19 Jan 2017 15:03:41 +0100 +Subject: [PATCH] backends/x11: Support synaptics configuration + +The code is taken mostly as-is from g-s-d, so we can drag the +dead horse a bit longer. +--- + src/backends/x11/meta-input-settings-x11.c | 261 +++++++++++++++++++++++++++++ + 1 file changed, 261 insertions(+) + +diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c +index 7a876ef..467a9b7 100644 +--- a/src/backends/x11/meta-input-settings-x11.c ++++ b/src/backends/x11/meta-input-settings-x11.c +@@ -26,6 +26,7 @@ + #include "meta-backend-x11.h" + #include "meta-input-settings-x11.h" + ++#include + #include + #include + #include +@@ -159,6 +160,173 @@ change_property (ClutterInputDevice *device, + meta_XFree (data_ret); + } + ++static gboolean ++is_device_synaptics (ClutterInputDevice *device) ++{ ++ guchar *has_setting; ++ ++ /* We just need looking for a synaptics-specific property */ ++ has_setting = get_property (device, "Synaptics Off", XA_INTEGER, 8, 1); ++ if (!has_setting) ++ return FALSE; ++ ++ meta_XFree (has_setting); ++ return TRUE; ++} ++ ++static void ++change_synaptics_tap_left_handed (ClutterInputDevice *device, ++ gboolean tap_enabled, ++ gboolean left_handed) ++{ ++ MetaDisplay *display = meta_get_display (); ++ MetaBackend *backend = meta_get_backend (); ++ Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); ++ XDevice *xdevice; ++ guchar *tap_action, *buttons; ++ guint buttons_capacity = 16, n_buttons; ++ ++ xdevice = device_ensure_xdevice (device); ++ if (!xdevice) ++ return; ++ ++ tap_action = get_property (device, "Synaptics Tap Action", ++ XA_INTEGER, 8, 7); ++ if (!tap_action) ++ return; ++ ++ tap_action[4] = tap_enabled ? (left_handed ? 3 : 1) : 0; ++ tap_action[5] = tap_enabled ? (left_handed ? 1 : 3) : 0; ++ tap_action[6] = tap_enabled ? 2 : 0; ++ ++ change_property (device, "Synaptics Tap Action", ++ XA_INTEGER, 8, tap_action, 7); ++ meta_XFree (tap_action); ++ ++ if (display) ++ meta_error_trap_push (display); ++ buttons = g_new (guchar, buttons_capacity); ++ n_buttons = XGetDeviceButtonMapping (xdisplay, xdevice, ++ buttons, buttons_capacity); ++ ++ while (n_buttons > buttons_capacity) ++ { ++ buttons_capacity = n_buttons; ++ buttons = (guchar *) g_realloc (buttons, ++ buttons_capacity * sizeof (guchar)); ++ ++ n_buttons = XGetDeviceButtonMapping (xdisplay, xdevice, ++ buttons, buttons_capacity); ++ } ++ ++ buttons[0] = left_handed ? 3 : 1; ++ buttons[2] = left_handed ? 1 : 3; ++ XSetDeviceButtonMapping (xdisplay, xdevice, buttons, n_buttons); ++ ++ if (display && meta_error_trap_pop_with_return (display)) ++ { ++ g_warning ("Could not set synaptics touchpad left-handed for %s", ++ clutter_input_device_get_device_name (device)); ++ } ++} ++ ++static void ++change_synaptics_speed (ClutterInputDevice *device, ++ gdouble speed) ++{ ++ MetaDisplay *display = meta_get_display (); ++ MetaBackend *backend = meta_get_backend (); ++ Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); ++ XDevice *xdevice; ++ XPtrFeedbackControl feedback; ++ XFeedbackState *states, *state; ++ int i, num_feedbacks, motion_threshold, numerator, denominator; ++ gfloat motion_acceleration; ++ ++ xdevice = device_ensure_xdevice (device); ++ if (!xdevice) ++ return; ++ /* Get the list of feedbacks for the device */ ++ states = XGetFeedbackControl (xdisplay, xdevice, &num_feedbacks); ++ if (!states) ++ return; ++ ++ /* Calculate acceleration and threshold */ ++ motion_acceleration = (speed + 1) * 5; /* speed is [-1..1], map to [0..10] */ ++ motion_threshold = CLAMP (10 - floor (motion_acceleration), 1, 10); ++ ++ if (motion_acceleration >= 1.0) ++ { ++ /* we want to get the acceleration, with a resolution of 0.5 ++ */ ++ if ((motion_acceleration - floor (motion_acceleration)) < 0.25) ++ { ++ numerator = floor (motion_acceleration); ++ denominator = 1; ++ } ++ else if ((motion_acceleration - floor (motion_acceleration)) < 0.5) ++ { ++ numerator = ceil (2.0 * motion_acceleration); ++ denominator = 2; ++ } ++ else if ((motion_acceleration - floor (motion_acceleration)) < 0.75) ++ { ++ numerator = floor (2.0 *motion_acceleration); ++ denominator = 2; ++ } ++ else ++ { ++ numerator = ceil (motion_acceleration); ++ denominator = 1; ++ } ++ } ++ else if (motion_acceleration < 1.0 && motion_acceleration > 0) ++ { ++ /* This we do to 1/10ths */ ++ numerator = floor (motion_acceleration * 10) + 1; ++ denominator= 10; ++ } ++ else ++ { ++ numerator = -1; ++ denominator = -1; ++ } ++ ++ if (display) ++ meta_error_trap_push (display); ++ ++ state = (XFeedbackState *) states; ++ ++ for (i = 0; i < num_feedbacks; i++) ++ { ++ if (state->class == PtrFeedbackClass) ++ { ++ /* And tell the device */ ++ feedback.class = PtrFeedbackClass; ++ feedback.length = sizeof (XPtrFeedbackControl); ++ feedback.id = state->id; ++ feedback.threshold = motion_threshold; ++ feedback.accelNum = numerator; ++ feedback.accelDenom = denominator; ++ ++ XChangeFeedbackControl (xdisplay, xdevice, ++ DvAccelNum | DvAccelDenom | DvThreshold, ++ (XFeedbackControl *) &feedback); ++ break; ++ } ++ ++ state = (XFeedbackState *) ((char *) state + state->length); ++ } ++ ++ if (display && meta_error_trap_pop_with_return (display)) ++ { ++ g_warning ("Could not set synaptics touchpad acceleration for %s", ++ clutter_input_device_get_device_name (device)); ++ } ++ ++ XFreeFeedbackList (states); ++} ++ + static void + meta_input_settings_x11_set_send_events (MetaInputSettings *settings, + ClutterInputDevice *device, +@@ -167,6 +335,13 @@ meta_input_settings_x11_set_send_events (MetaInputSettings *settings, + guchar values[2] = { 0 }; /* disabled, disabled-on-external-mouse */ + guchar *available; + ++ if (is_device_synaptics (device)) ++ { ++ values[0] = mode != G_DESKTOP_DEVICE_SEND_EVENTS_ENABLED; ++ change_property (device, "Synaptics Off", XA_INTEGER, 8, &values, 1); ++ return; ++ } ++ + available = get_property (device, "libinput Send Events Modes Available", + XA_INTEGER, 8, 2); + if (!available) +@@ -219,6 +394,12 @@ meta_input_settings_x11_set_speed (MetaInputSettings *settings, + Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); + gfloat value = speed; + ++ if (is_device_synaptics (device)) ++ { ++ change_synaptics_speed (device, speed); ++ return; ++ } ++ + change_property (device, "libinput Accel Speed", + XInternAtom (xdisplay, "FLOAT", False), + 32, &value, 1); +@@ -245,6 +426,19 @@ meta_input_settings_x11_set_left_handed (MetaInputSettings *settings, + else + { + value = enabled ? 1 : 0; ++ ++ if (is_device_synaptics (device)) ++ { ++ GSettings *settings; ++ ++ settings = g_settings_new ("org.gnome.desktop.peripherals.touchpad"); ++ change_synaptics_tap_left_handed (device, ++ g_settings_get_boolean (settings, "tap-to-click"), ++ enabled); ++ g_object_unref (settings); ++ return; ++ } ++ + change_property (device, "libinput Left Handed Enabled", + XA_INTEGER, 8, &value, 1); + } +@@ -268,6 +462,20 @@ meta_input_settings_x11_set_tap_enabled (MetaInputSettings *settings, + { + guchar value = (enabled) ? 1 : 0; + ++ if (is_device_synaptics (device)) ++ { ++ GDesktopTouchpadHandedness handedness; ++ GSettings *settings; ++ ++ settings = g_settings_new ("org.gnome.desktop.peripherals.touchpad"); ++ handedness = g_settings_get_enum (settings, "left-handed"); ++ g_object_unref (settings); ++ ++ change_synaptics_tap_left_handed (device, enabled, ++ handedness == G_DESKTOP_TOUCHPAD_HANDEDNESS_LEFT); ++ return; ++ } ++ + change_property (device, "libinput Tapping Enabled", + XA_INTEGER, 8, &value, 1); + } +@@ -290,6 +498,27 @@ meta_input_settings_x11_set_invert_scroll (MetaInputSettings *settings, + { + guchar value = (inverted) ? 1 : 0; + ++ if (is_device_synaptics (device)) ++ { ++ gint32 *scrolling_distance; ++ ++ scrolling_distance = get_property (device, "Synaptics Scrolling Distance", ++ XA_INTEGER, 32, 2); ++ if (scrolling_distance) ++ { ++ scrolling_distance[0] = inverted ? ++ -abs (scrolling_distance[0]) : abs (scrolling_distance[0]); ++ scrolling_distance[1] = inverted ? ++ -abs (scrolling_distance[1]) : abs (scrolling_distance[1]); ++ ++ change_property (device, "Synaptics Scrolling Distance", ++ XA_INTEGER, 32, scrolling_distance, 2); ++ meta_XFree (scrolling_distance); ++ } ++ ++ return; ++ } ++ + change_property (device, "libinput Natural Scrolling Enabled", + XA_INTEGER, 8, &value, 1); + } +@@ -303,6 +532,22 @@ meta_input_settings_x11_set_edge_scroll (MetaInputSettings *settings, + guchar *current = NULL; + guchar *available = NULL; + ++ if (is_device_synaptics (device)) ++ { ++ current = get_property (device, "Synaptics Edge Scrolling", ++ XA_INTEGER, 8, 3); ++ if (current) ++ { ++ current[0] = !!edge_scroll_enabled; ++ current[1] = !!edge_scroll_enabled; ++ change_property (device, "Synaptics Edge Scrolling", ++ XA_INTEGER, 8, current, 3); ++ meta_XFree (current); ++ } ++ ++ return; ++ } ++ + available = get_property (device, "libinput Scroll Methods Available", + XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS); + if (!available || !available[SCROLL_METHOD_FIELD_EDGE]) +@@ -332,6 +577,22 @@ meta_input_settings_x11_set_two_finger_scroll (MetaInputSettings *set + guchar *current = NULL; + guchar *available = NULL; + ++ if (is_device_synaptics (device)) ++ { ++ current = get_property (device, "Synaptics Two-Finger Scrolling", ++ XA_INTEGER, 8, 2); ++ if (current) ++ { ++ current[0] = !!two_finger_scroll_enabled; ++ current[1] = !!two_finger_scroll_enabled; ++ change_property (device, "Synaptics Two-Finger Scrolling", ++ XA_INTEGER, 8, current, 2); ++ meta_XFree (current); ++ } ++ ++ return; ++ } ++ + available = get_property (device, "libinput Scroll Methods Available", + XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS); + if (!available || !available[SCROLL_METHOD_FIELD_2FG]) +-- +1.8.3.1 + diff --git a/SOURCES/0001-build-Lower-automake-requirement.patch b/SOURCES/0001-build-Lower-automake-requirement.patch new file mode 100644 index 0000000..f7c7af6 --- /dev/null +++ b/SOURCES/0001-build-Lower-automake-requirement.patch @@ -0,0 +1,25 @@ +From e19b0723e829a102f930af735c9ff6d08ec9232f Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Fri, 17 Mar 2017 16:44:11 +0100 +Subject: [PATCH] build: Lower automake requirement + +--- + cogl/configure.ac | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/cogl/configure.ac b/cogl/configure.ac +index 3ed761c57..1b259af58 100644 +--- a/cogl/configure.ac ++++ b/cogl/configure.ac +@@ -113,7 +113,7 @@ AC_SUBST([WAYLAND_SERVER_REQ_VERSION], [wayland_server_req_version]) + # want to know if the user specified custom cflags or not. + cflags_set=${CFLAGS+set} + +-AM_INIT_AUTOMAKE([1.14 foreign -Wno-portability no-define no-dist-gzip dist-xz tar-ustar subdir-objects]) ++AM_INIT_AUTOMAKE([1.11 foreign -Wno-portability no-define no-dist-gzip dist-xz tar-ustar]) + AM_SILENT_RULES([yes]) + + AH_BOTTOM([#include "config-custom.h"]) +-- +2.12.0 + diff --git a/SOURCES/0001-clutter-Do-not-latch-modifiers-on-modifier-keys.patch b/SOURCES/0001-clutter-Do-not-latch-modifiers-on-modifier-keys.patch new file mode 100644 index 0000000..7a9604e --- /dev/null +++ b/SOURCES/0001-clutter-Do-not-latch-modifiers-on-modifier-keys.patch @@ -0,0 +1,44 @@ +From 67aab7c13812befde061f0d2068b431b04dcbc98 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Wed, 3 Oct 2018 22:43:21 +0200 +Subject: [PATCH] clutter: Do not latch modifiers on modifier keys + +If the user maps eg. Alt+F2 to a pad button, the MetaInputSettings will +send the full Alt press, F2 press, F2 release, Alt release sequence. +However the keycode corresponding to Alt is found in level 1, so the +Shift modifier gets unintendedly latched in addition to the Alt key +press/release pair. + +We could probably improve keycode lookup heuristics so level=0 (and +no modifier latching) is preferred, but we can do without it altogether +for modifier keys. +--- + clutter/clutter/x11/clutter-virtual-input-device-x11.c | 6 ++++-- + 1 file changed, 4 insertions(+), 2 deletions(-) + +diff --git a/clutter/clutter/x11/clutter-virtual-input-device-x11.c b/clutter/clutter/x11/clutter-virtual-input-device-x11.c +index b86ded0d0..e16ba3fd0 100644 +--- a/clutter/clutter/x11/clutter-virtual-input-device-x11.c ++++ b/clutter/clutter/x11/clutter-virtual-input-device-x11.c +@@ -147,14 +147,16 @@ clutter_virtual_input_device_x11_notify_keyval (ClutterVirtualInputDevice *virtu + return; + } + +- if (key_state == CLUTTER_KEY_STATE_PRESSED) ++ if (!_clutter_keymap_x11_get_is_modifier (keymap, keycode) && ++ key_state == CLUTTER_KEY_STATE_PRESSED) + clutter_keymap_x11_latch_modifiers (keymap, level, TRUE); + + XTestFakeKeyEvent (clutter_x11_get_default_display (), + (KeyCode) keycode, + key_state == CLUTTER_KEY_STATE_PRESSED, 0); + +- if (key_state == CLUTTER_KEY_STATE_RELEASED) ++ if (!_clutter_keymap_x11_get_is_modifier (keymap, keycode) && ++ key_state == CLUTTER_KEY_STATE_RELEASED) + clutter_keymap_x11_latch_modifiers (keymap, level, FALSE); + } + +-- +2.19.0 + diff --git a/SOURCES/0001-clutter-Extend-touchpad-device-property-check-for-Sy.patch b/SOURCES/0001-clutter-Extend-touchpad-device-property-check-for-Sy.patch new file mode 100644 index 0000000..3ae0f20 --- /dev/null +++ b/SOURCES/0001-clutter-Extend-touchpad-device-property-check-for-Sy.patch @@ -0,0 +1,61 @@ +From 424e37231a0930594d4363477e7515e006b3dac1 Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Tue, 13 Feb 2018 11:44:40 +0100 +Subject: [PATCH] clutter: Extend touchpad device property check for Synaptics + +So we reliably get CLUTTER_TOUCHPAD_DEVICE for those. The other heuristics +to get the device type may fall short. +--- + clutter/clutter/x11/clutter-device-manager-xi2.c | 22 +++++++++++++++++++--- + 1 file changed, 19 insertions(+), 3 deletions(-) + +diff --git a/clutter/clutter/x11/clutter-device-manager-xi2.c b/clutter/clutter/x11/clutter-device-manager-xi2.c +index d2610cc..fcba55c 100644 +--- a/clutter/clutter/x11/clutter-device-manager-xi2.c ++++ b/clutter/clutter/x11/clutter-device-manager-xi2.c +@@ -267,8 +267,9 @@ is_touch_device (XIAnyClassInfo **classes, + } + + static gboolean +-is_touchpad_device (ClutterBackendX11 *backend_x11, +- XIDeviceInfo *info) ++query_exists_device_property (ClutterBackendX11 *backend_x11, ++ XIDeviceInfo *info, ++ const gchar *property) + { + gulong nitems, bytes_after; + guint32 *data = NULL; +@@ -276,7 +277,7 @@ is_touchpad_device (ClutterBackendX11 *backend_x11, + Atom type; + Atom prop; + +- prop = XInternAtom (backend_x11->xdpy, "libinput Tapping Enabled", True); ++ prop = XInternAtom (backend_x11->xdpy, property, True); + if (prop == None) + return FALSE; + +@@ -298,6 +299,21 @@ is_touchpad_device (ClutterBackendX11 *backend_x11, + } + + static gboolean ++is_touchpad_device (ClutterBackendX11 *backend_x11, ++ XIDeviceInfo *info) ++{ ++ if (query_exists_device_property (backend_x11, info, ++ "libinput Tapping Enabled")) ++ return TRUE; ++ ++ if (query_exists_device_property (backend_x11, info, ++ "Synaptics Off")) ++ return TRUE; ++ ++ return FALSE; ++} ++ ++static gboolean + get_device_ids (ClutterBackendX11 *backend_x11, + XIDeviceInfo *info, + gchar **vendor_id, +-- +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-input-device-xi2-Check-for-null-group_modes-.patch b/SOURCES/0001-clutter-input-device-xi2-Check-for-null-group_modes-.patch new file mode 100644 index 0000000..5f6473c --- /dev/null +++ b/SOURCES/0001-clutter-input-device-xi2-Check-for-null-group_modes-.patch @@ -0,0 +1,27 @@ +From 2a45b7de7cf5955b81cc1778dbb5085bfabb1c56 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Corentin=20No=C3=ABl?= +Date: Sat, 2 Jun 2018 19:16:32 +0100 +Subject: [PATCH] clutter-input-device-xi2: Check for null group_modes before + unref + +--- + clutter/clutter/x11/clutter-input-device-xi2.c | 3 ++- + 1 file changed, 2 insertions(+), 1 deletion(-) + +diff --git a/clutter/clutter/x11/clutter-input-device-xi2.c b/clutter/clutter/x11/clutter-input-device-xi2.c +index f62ba85dcb..1254aca3ae 100644 +--- a/clutter/clutter/x11/clutter-input-device-xi2.c ++++ b/clutter/clutter/x11/clutter-input-device-xi2.c +@@ -110,7 +110,8 @@ clutter_input_device_xi2_finalize (GObject *object) + if (device_xi2->wacom_device) + libwacom_destroy (device_xi2->wacom_device); + +- g_array_unref (device_xi2->group_modes); ++ if (device_xi2->group_modes) ++ g_array_unref (device_xi2->group_modes); + #endif + + G_OBJECT_CLASS (clutter_input_device_xi2_parent_class)->finalize (object); +-- +2.23.0.rc1 + 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-compositor-Don-t-emit-size-changed-when-only-positio.patch b/SOURCES/0001-compositor-Don-t-emit-size-changed-when-only-positio.patch new file mode 100644 index 0000000..0e04185 --- /dev/null +++ b/SOURCES/0001-compositor-Don-t-emit-size-changed-when-only-positio.patch @@ -0,0 +1,140 @@ +From a8d0870c6e9c9d2269c2b856cd2d83949fef4154 Mon Sep 17 00:00:00 2001 +From: Daniel van Vugt +Date: Tue, 7 May 2019 18:08:13 +0800 +Subject: [PATCH 1/2] compositor: Don't emit size-changed when only position + changes + +Waking up gnome-shell and triggering JavaScript listeners of +`size-changed` every time a window was only moved was wasting a lot +of CPU. + +This cuts the CPU requirement for dragging windows by around 22%. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/568 +--- + src/compositor/compositor.c | 8 +++- + src/compositor/meta-window-actor-private.h | 12 +++++- + src/compositor/meta-window-actor.c | 43 ++++++++++++++++++---- + 3 files changed, 52 insertions(+), 11 deletions(-) + +diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c +index 8c924d256..abf7de57d 100644 +--- a/src/compositor/compositor.c ++++ b/src/compositor/compositor.c +@@ -1070,8 +1070,12 @@ meta_compositor_sync_window_geometry (MetaCompositor *compositor, + gboolean did_placement) + { + MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window)); +- meta_window_actor_sync_actor_geometry (window_actor, did_placement); +- meta_plugin_manager_event_size_changed (compositor->plugin_mgr, window_actor); ++ MetaWindowActorChanges changes; ++ ++ changes = meta_window_actor_sync_actor_geometry (window_actor, did_placement); ++ ++ if (changes & META_WINDOW_ACTOR_CHANGE_SIZE) ++ meta_plugin_manager_event_size_changed (compositor->plugin_mgr, window_actor); + } + + static void +diff --git a/src/compositor/meta-window-actor-private.h b/src/compositor/meta-window-actor-private.h +index ce5e7eadc..acd649d07 100644 +--- a/src/compositor/meta-window-actor-private.h ++++ b/src/compositor/meta-window-actor-private.h +@@ -12,6 +12,12 @@ + + MetaWindowActor *meta_window_actor_new (MetaWindow *window); + ++typedef enum ++{ ++ META_WINDOW_ACTOR_CHANGE_SIZE = 1 << 0, ++ META_WINDOW_ACTOR_CHANGE_POSITION = 1 << 1 ++} MetaWindowActorChanges; ++ + void meta_window_actor_queue_destroy (MetaWindowActor *self); + + void meta_window_actor_show (MetaWindowActor *self, +@@ -43,8 +49,10 @@ void meta_window_actor_set_unredirected (MetaWindowActor *self, + gboolean unredirected); + + gboolean meta_window_actor_effect_in_progress (MetaWindowActor *self); +-void meta_window_actor_sync_actor_geometry (MetaWindowActor *self, +- gboolean did_placement); ++ ++MetaWindowActorChanges meta_window_actor_sync_actor_geometry (MetaWindowActor *self, ++ gboolean did_placement); ++ + void meta_window_actor_update_shape (MetaWindowActor *self); + void meta_window_actor_update_opacity (MetaWindowActor *self); + void meta_window_actor_mapped (MetaWindowActor *self); +diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c +index 120b0432c..afe2bab6e 100644 +--- a/src/compositor/meta-window-actor.c ++++ b/src/compositor/meta-window-actor.c +@@ -1299,12 +1299,14 @@ meta_window_actor_queue_destroy (MetaWindowActor *self) + clutter_actor_destroy (CLUTTER_ACTOR (self)); + } + +-void ++MetaWindowActorChanges + meta_window_actor_sync_actor_geometry (MetaWindowActor *self, + gboolean did_placement) + { + MetaWindowActorPrivate *priv = self->priv; + MetaRectangle window_rect; ++ ClutterActor *actor = CLUTTER_ACTOR (self); ++ MetaWindowActorChanges changes = 0; + + meta_window_get_buffer_rect (priv->window, &window_rect); + +@@ -1322,15 +1324,42 @@ meta_window_actor_sync_actor_geometry (MetaWindowActor *self, + * updates. + */ + if (is_frozen (self) && !did_placement) +- return; ++ return META_WINDOW_ACTOR_CHANGE_POSITION | META_WINDOW_ACTOR_CHANGE_SIZE; + + if (meta_window_actor_effect_in_progress (self)) +- return; ++ return META_WINDOW_ACTOR_CHANGE_POSITION | META_WINDOW_ACTOR_CHANGE_SIZE; ++ ++ if (clutter_actor_has_allocation (actor)) ++ { ++ ClutterActorBox box; ++ float old_x, old_y; ++ float old_width, old_height; ++ ++ clutter_actor_get_allocation_box (actor, &box); ++ ++ old_x = box.x1; ++ old_y = box.y1; ++ old_width = box.x2 - box.x1; ++ old_height = box.y2 - box.y1; ++ ++ if (old_x != window_rect.x || old_y != window_rect.y) ++ changes |= META_WINDOW_ACTOR_CHANGE_POSITION; ++ ++ if (old_width != window_rect.width || old_height != window_rect.height) ++ changes |= META_WINDOW_ACTOR_CHANGE_SIZE; ++ } ++ else ++ { ++ changes = META_WINDOW_ACTOR_CHANGE_POSITION | META_WINDOW_ACTOR_CHANGE_SIZE; ++ } ++ ++ if (changes & META_WINDOW_ACTOR_CHANGE_POSITION) ++ clutter_actor_set_position (actor, window_rect.x, window_rect.y); ++ ++ if (changes & META_WINDOW_ACTOR_CHANGE_SIZE) ++ clutter_actor_set_size (actor, window_rect.width, window_rect.height); + +- clutter_actor_set_position (CLUTTER_ACTOR (self), +- window_rect.x, window_rect.y); +- clutter_actor_set_size (CLUTTER_ACTOR (self), +- window_rect.width, window_rect.height); ++ return changes; + } + + void +-- +2.21.0 + diff --git a/SOURCES/0001-constraints-Fix-titlebars-going-off-the-bottom.patch b/SOURCES/0001-constraints-Fix-titlebars-going-off-the-bottom.patch new file mode 100644 index 0000000..bc199e1 --- /dev/null +++ b/SOURCES/0001-constraints-Fix-titlebars-going-off-the-bottom.patch @@ -0,0 +1,39 @@ +From 2fd734c349ab00f2f460af97f7c383678407f620 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 16 Jan 2019 01:09:26 +0100 +Subject: [PATCH] constraints: Fix titlebars going off the bottom + +The "current" rect includes the frame, so in order to keep the +titlebar on screen, window movement must be restricted to at +most (height - titlebar_height) past the work area bottom. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/391 +--- + src/core/constraints.c | 4 ++-- + 1 file changed, 2 insertions(+), 2 deletions(-) + +diff --git a/src/core/constraints.c b/src/core/constraints.c +index 3b6203d6b..92b146ce3 100644 +--- a/src/core/constraints.c ++++ b/src/core/constraints.c +@@ -1570,7 +1570,7 @@ constrain_titlebar_visible (MetaWindow *window, + MetaFrameBorders borders; + meta_frame_calc_borders (window->frame, &borders); + +- bottom_amount = info->current.height + borders.visible.bottom; ++ bottom_amount = info->current.height - borders.visible.top; + vert_amount_onscreen = borders.visible.top; + } + else +@@ -1649,7 +1649,7 @@ constrain_partially_onscreen (MetaWindow *window, + MetaFrameBorders borders; + meta_frame_calc_borders (window->frame, &borders); + +- bottom_amount = info->current.height + borders.visible.bottom; ++ bottom_amount = info->current.height - borders.visible.top; + vert_amount_onscreen = borders.visible.top; + } + else +-- +2.20.1 + diff --git a/SOURCES/0001-events-Don-t-move-sloppy-focus-while-buttons-are-pre.patch b/SOURCES/0001-events-Don-t-move-sloppy-focus-while-buttons-are-pre.patch new file mode 100644 index 0000000..4eeb33e --- /dev/null +++ b/SOURCES/0001-events-Don-t-move-sloppy-focus-while-buttons-are-pre.patch @@ -0,0 +1,43 @@ +From 887537360c3c3b0ae5d0ef0222fad4d0a3bc41c9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Thu, 21 Jul 2016 15:43:12 +0200 +Subject: [PATCH 5/8] events: Don't move (sloppy) focus while buttons are + pressed + +(https://bugzilla.redhat.com/show_bug.cgi?id=1358535) +--- + src/x11/events.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/src/x11/events.c b/src/x11/events.c +index 49f2569f3..ecb4de53d 100644 +--- a/src/x11/events.c ++++ b/src/x11/events.c +@@ -830,6 +830,16 @@ crossing_serial_is_ignored (MetaDisplay *display, + return FALSE; + } + ++static gboolean ++event_has_button_mask (XIEnterEvent *enter_event) ++{ ++ int i; ++ for (i = 0; i < enter_event->buttons.mask_len; i++) ++ if (enter_event->buttons.mask[i] != '\0') ++ return TRUE; ++ return FALSE; ++} ++ + static gboolean + handle_input_xevent (MetaDisplay *display, + XIEvent *input_event, +@@ -871,6 +881,7 @@ handle_input_xevent (MetaDisplay *display, + * avoid races. + */ + if (window && !crossing_serial_is_ignored (display, serial) && ++ !event_has_button_mask (enter_event) && + enter_event->mode != XINotifyGrab && + enter_event->mode != XINotifyUngrab && + enter_event->detail != XINotifyInferior && +-- +2.14.2 + diff --git a/SOURCES/0001-events-Sync-pending-pointer-events-without-a-window.patch b/SOURCES/0001-events-Sync-pending-pointer-events-without-a-window.patch new file mode 100644 index 0000000..14878a7 --- /dev/null +++ b/SOURCES/0001-events-Sync-pending-pointer-events-without-a-window.patch @@ -0,0 +1,122 @@ +From 3582d1780c9bf3fc93604963a11b9b60d9895178 Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Wed, 2 Oct 2019 16:49:28 +0200 +Subject: [PATCH] events: Sync pending pointer events without a window + +Mutter issues a synchronous grab on the pointer for unfocused client +windows to be able to catch the button events first and raise/focus +client windows accordingly. + +When there is a synchronous grab in effect, all events are queued until +the grabbing client releases the event queue as it processes the events. + +Mutter does release the events in its event handler function but does so +only if it is able to find the window matching the event. If the window +is a shell widget, that matching may fail and therefore Mutter will not +release the events, hence causing a freeze in pointer events delivery. + +To avoid the issue, make sure we sync the pointer events in case we +can't find a matching window. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/821 +--- + src/core/events.c | 62 ++++++++++++++++++++++++++++++++++++++--------- + 1 file changed, 51 insertions(+), 11 deletions(-) + +diff --git a/src/core/events.c b/src/core/events.c +index 92503a168..9b19065fb 100644 +--- a/src/core/events.c ++++ b/src/core/events.c +@@ -51,6 +51,12 @@ + #define IS_KEY_EVENT(e) ((e)->type == CLUTTER_KEY_PRESS || \ + (e)->type == CLUTTER_KEY_RELEASE) + ++typedef enum ++{ ++ EVENTS_UNFREEZE_SYNC, ++ EVENTS_UNFREEZE_REPLAY, ++} EventsUnfreezeMethod; ++ + static gboolean + stage_has_key_focus (void) + { +@@ -167,6 +173,43 @@ sequence_is_pointer_emulated (MetaDisplay *display, + return FALSE; + } + ++static void ++maybe_unfreeze_pointer_events (MetaBackend *backend, ++ const ClutterEvent *event, ++ EventsUnfreezeMethod unfreeze_method) ++{ ++ Display *xdisplay; ++ int event_mode; ++ int device_id; ++ ++ if (event->type != CLUTTER_BUTTON_PRESS) ++ return; ++ ++ if (!META_IS_BACKEND_X11 (backend)) ++ return; ++ ++ device_id = clutter_event_get_device_id (event); ++ switch (unfreeze_method) ++ { ++ case EVENTS_UNFREEZE_SYNC: ++ event_mode = XISyncDevice; ++ meta_verbose ("Syncing events time %u device %i\n", ++ (unsigned int) event->button.time, device_id); ++ break; ++ case EVENTS_UNFREEZE_REPLAY: ++ event_mode = XIReplayDevice; ++ meta_verbose ("Replaying events time %u device %i\n", ++ (unsigned int) event->button.time, device_id); ++ break; ++ default: ++ g_assert_not_reached (); ++ return; ++ } ++ ++ xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); ++ XIAllowEvents (xdisplay, device_id, event_mode, event->button.time); ++} ++ + static gboolean + meta_display_handle_event (MetaDisplay *display, + const ClutterEvent *event) +@@ -366,17 +409,7 @@ meta_display_handle_event (MetaDisplay *display, + { + /* Only replay button press events, since that's where we + * have the synchronous grab. */ +- if (event->type == CLUTTER_BUTTON_PRESS) +- { +- if (META_IS_BACKEND_X11 (backend)) +- { +- Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); +- meta_verbose ("Allowing events time %u\n", +- (unsigned int)event->button.time); +- XIAllowEvents (xdisplay, clutter_event_get_device_id (event), +- XIReplayDevice, event->button.time); +- } +- } ++ maybe_unfreeze_pointer_events (backend, event, EVENTS_UNFREEZE_REPLAY); + + /* If the focus window has an active close dialog let clutter + * events go through, so fancy clutter dialogs can get to handle +@@ -392,6 +425,13 @@ meta_display_handle_event (MetaDisplay *display, + + goto out; + } ++ else ++ { ++ /* We could not match the event with a window, make sure we sync ++ * the pointer to discard the sequence and don't keep events frozen. ++ */ ++ maybe_unfreeze_pointer_events (backend, event, EVENTS_UNFREEZE_SYNC); ++ } + + out: + /* If the compositor has a grab, don't pass that through to Wayland */ +-- +2.23.0 + diff --git a/SOURCES/0001-gpu-xrandr-Move-dpms-state-and-screen-size-updating-.patch b/SOURCES/0001-gpu-xrandr-Move-dpms-state-and-screen-size-updating-.patch new file mode 100644 index 0000000..e448785 --- /dev/null +++ b/SOURCES/0001-gpu-xrandr-Move-dpms-state-and-screen-size-updating-.patch @@ -0,0 +1,114 @@ +From 7ce6f10f6966ec6e66549a6878ae333d0fe1e84c Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Wed, 3 Oct 2018 10:50:07 +0200 +Subject: [PATCH 1/2] gpu/xrandr: Move dpms state and screen size updating into + helpers + +To be used by no-Xrandr fallback path. +--- + src/backends/x11/meta-gpu-xrandr.c | 70 ++++++++++++++++++++---------- + 1 file changed, 46 insertions(+), 24 deletions(-) + +diff --git a/src/backends/x11/meta-gpu-xrandr.c b/src/backends/x11/meta-gpu-xrandr.c +index add80c0d2d..a4e187a49a 100644 +--- a/src/backends/x11/meta-gpu-xrandr.c ++++ b/src/backends/x11/meta-gpu-xrandr.c +@@ -91,31 +91,15 @@ meta_gpu_xrandr_poll_hardware (MetaGpu *gpu) + gpu_xrandr->need_hardware_poll = TRUE; + } + +-static gboolean +-meta_gpu_xrandr_read_current (MetaGpu *gpu, +- GError **error) ++static void ++update_dpms_state (MetaMonitorManagerXrandr *monitor_manager_xrandr) + { +- 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); ++ MetaMonitorManager *monitor_manager = ++ META_MONITOR_MANAGER (monitor_manager_xrandr); + 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); + +@@ -146,6 +130,47 @@ meta_gpu_xrandr_read_current (MetaGpu *gpu, + { + monitor_manager->power_save_mode = META_POWER_SAVE_UNSUPPORTED; + } ++} ++ ++static void ++update_screen_size (MetaMonitorManagerXrandr *monitor_manager_xrandr) ++{ ++ MetaMonitorManager *monitor_manager = ++ META_MONITOR_MANAGER (monitor_manager_xrandr); ++ Display *xdisplay = ++ meta_monitor_manager_xrandr_get_xdisplay (monitor_manager_xrandr); ++ Screen *screen; ++ ++ screen = ScreenOfDisplay (xdisplay, DefaultScreen (xdisplay)); ++ ++ monitor_manager->screen_width = WidthOfScreen (screen); ++ monitor_manager->screen_height = HeightOfScreen (screen); ++} ++ ++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; ++ GList *outputs = NULL; ++ GList *modes = NULL; ++ GList *crtcs = NULL; ++ ++ if (gpu_xrandr->resources) ++ XRRFreeScreenResources (gpu_xrandr->resources); ++ gpu_xrandr->resources = NULL; ++ ++ update_dpms_state (monitor_manager_xrandr); + + XRRGetScreenSizeRange (xdisplay, DefaultRootWindow (xdisplay), + &min_width, +@@ -153,10 +178,7 @@ meta_gpu_xrandr_read_current (MetaGpu *gpu, + &gpu_xrandr->max_screen_width, + &gpu_xrandr->max_screen_height); + +- screen = ScreenOfDisplay (xdisplay, DefaultScreen (xdisplay)); +- /* This is updated because we called XRRUpdateConfiguration. */ +- monitor_manager->screen_width = WidthOfScreen (screen); +- monitor_manager->screen_height = HeightOfScreen (screen); ++ update_screen_size (monitor_manager_xrandr); + + if (gpu_xrandr->need_hardware_poll) + { +-- +2.17.1 + diff --git a/SOURCES/0001-idle-monitor-Use-G_SOURCE_CONTINUE-instead-of-TRUE.patch b/SOURCES/0001-idle-monitor-Use-G_SOURCE_CONTINUE-instead-of-TRUE.patch new file mode 100644 index 0000000..ac3c785 --- /dev/null +++ b/SOURCES/0001-idle-monitor-Use-G_SOURCE_CONTINUE-instead-of-TRUE.patch @@ -0,0 +1,28 @@ +From 0ac0bc55cf69579834b28d99729cefd1157624c3 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Tue, 16 Apr 2019 18:06:54 +0200 +Subject: [PATCH 1/2] idle-monitor: Use G_SOURCE_CONTINUE instead of TRUE + +Returning TRUE is confusing, as it doesn't carry any relevant meaning. +Use G_SOURCE_CONTINUE to make it clearer that the source is here to +stay. +--- + src/backends/meta-idle-monitor.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/src/backends/meta-idle-monitor.c b/src/backends/meta-idle-monitor.c +index 46cf8cd76..2b634f59a 100644 +--- a/src/backends/meta-idle-monitor.c ++++ b/src/backends/meta-idle-monitor.c +@@ -315,7 +315,7 @@ idle_monitor_dispatch_timeout (GSource *source, + _meta_idle_monitor_watch_fire (watch); + g_source_set_ready_time (watch->timeout_source, -1); + +- return TRUE; ++ return G_SOURCE_CONTINUE; + } + + static GSourceFuncs idle_monitor_source_funcs = { +-- +2.20.1 + diff --git a/SOURCES/0001-main-be-more-aggressive-in-assuming-X11-backend.patch b/SOURCES/0001-main-be-more-aggressive-in-assuming-X11-backend.patch new file mode 100644 index 0000000..8fcef03 --- /dev/null +++ b/SOURCES/0001-main-be-more-aggressive-in-assuming-X11-backend.patch @@ -0,0 +1,132 @@ +From 5e3a6efd0e2bbea040e203b996e7d00ab3431cfa Mon Sep 17 00:00:00 2001 +From: Ray Strode +Date: Tue, 13 Feb 2018 09:44:50 -0500 +Subject: [PATCH] main: be more aggressive in assuming X11 backend + +If the session is started by vncserver right now, the +XDG_SESSION_TYPE won't be X11. Ideally that would be +fixed, but for backward compatibility we should default +to X11 if the session type isn't set to wayland explicitly. +--- + src/core/main.c | 8 +++----- + 1 file changed, 3 insertions(+), 5 deletions(-) + +diff --git a/src/core/main.c b/src/core/main.c +index 079f6a9ef..8e8bc3f77 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -304,108 +304,106 @@ meta_finalize (void) + + #ifdef HAVE_WAYLAND + if (meta_is_wayland_compositor ()) + meta_wayland_finalize (); + #endif + } + + static gboolean + on_sigterm (gpointer user_data) + { + meta_quit (EXIT_SUCCESS); + + return G_SOURCE_REMOVE; + } + + #if defined(HAVE_WAYLAND) && defined(HAVE_NATIVE_BACKEND) + static gboolean + session_type_is_supported (const char *session_type) + { + return (g_strcmp0 (session_type, "x11") == 0) || + (g_strcmp0 (session_type, "wayland") == 0); + } + + static char * + find_session_type (void) + { + char **sessions = NULL; + char *session_id; + char *session_type; + const char *session_type_env; +- gboolean is_tty = FALSE; + int ret, i; + + ret = sd_pid_get_session (0, &session_id); + if (ret == 0 && session_id != NULL) + { + ret = sd_session_get_type (session_id, &session_type); + free (session_id); + + if (ret == 0) + { + if (session_type_is_supported (session_type)) + goto out; +- else +- is_tty = g_strcmp0 (session_type, "tty") == 0; ++ + free (session_type); + } + } + else if (sd_uid_get_sessions (getuid (), 1, &sessions) > 0) + { + for (i = 0; sessions[i] != NULL; i++) + { + ret = sd_session_get_type (sessions[i], &session_type); + + if (ret < 0) + continue; + + if (session_type_is_supported (session_type)) + { + g_strfreev (sessions); + goto out; + } + + free (session_type); + } + } + g_strfreev (sessions); + + session_type_env = g_getenv ("XDG_SESSION_TYPE"); + if (session_type_is_supported (session_type_env)) + { + /* The string should be freeable */ + session_type = strdup (session_type_env); + goto out; + } + +- /* Legacy support for starting through xinit */ +- if (is_tty && (g_getenv ("MUTTER_DISPLAY") || g_getenv ("DISPLAY"))) ++ /* Legacy support for starting through xinit or vncserver */ ++ if (g_getenv ("MUTTER_DISPLAY") || g_getenv ("DISPLAY")) + { + session_type = strdup ("x11"); + goto out; + } + + meta_warning ("Unsupported session type\n"); + meta_exit (META_EXIT_ERROR); + + out: + return session_type; + } + + static gboolean + check_for_wayland_session_type (void) + { + char *session_type; + gboolean is_wayland; + + session_type = find_session_type (); + is_wayland = g_strcmp0 (session_type, "wayland") == 0; + free (session_type); + + return is_wayland; + } + #endif + + /* + * Determine the compositor configuration, i.e. whether to run as a Wayland + * compositor, as well as what backend to use. + * +-- +2.14.3 + diff --git a/SOURCES/0001-monitor-Use-current-monitor-mode-to-check-whether-ac.patch b/SOURCES/0001-monitor-Use-current-monitor-mode-to-check-whether-ac.patch new file mode 100644 index 0000000..c5819df --- /dev/null +++ b/SOURCES/0001-monitor-Use-current-monitor-mode-to-check-whether-ac.patch @@ -0,0 +1,85 @@ +From 22d626580cd84136b54ca1154852da6f990c00a2 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Tue, 31 Jul 2018 11:18:51 +0000 +Subject: [PATCH 1/2] monitor: Use current monitor mode to check whether active + +For historical reasons meta_monitor_is_active() checked whether it is +active by checking whether the main output have a CRTC assigned and +whether that CRTC has a current mode. At a later point, the MetaMonitor +got its own mode abstraction (MetaMonitorMode), but +meta_monitor_is_active() was never updated to use this. + +An issue with checking the main output's CRTC state is that, if there is +some CRTC mode combination that for some reason isn't properly detected +by the MetaMonitorMode abstraction (e.g. some tiling configuration not +yet handled), meta_monitor_is_active() would return TRUE, even though no +(abstracted) mode was set. This would cause confusion here and there, +leading to NULL pointer dereferences due to the assumption that if a +monitor is active, it has an active mode. + +Instead, change meta_monitor_is_active() to directly check the current +monitor mode, and log a warning if the main output still happen to have +a CRTC with a mode assigned to it. This way, when an not undrestood CRTC +mode combination is encountered, instead of dereferencing NULL pointers, +simply assume the monitor is not active, which means that it will not be +managed or rendered by mutter at all. + +https://gitlab.gnome.org/GNOME/mutter/issues/130 + + +(cherry picked from commit 4d465eac0806eb1ead375e2852d4a9d6bc24524f) +--- + src/backends/meta-monitor.c | 22 ++++++++++++++++------ + 1 file changed, 16 insertions(+), 6 deletions(-) + +diff --git a/src/backends/meta-monitor.c b/src/backends/meta-monitor.c +index 98330661e..9a412a612 100644 +--- a/src/backends/meta-monitor.c ++++ b/src/backends/meta-monitor.c +@@ -203,13 +203,9 @@ meta_monitor_get_main_output (MetaMonitor *monitor) + gboolean + meta_monitor_is_active (MetaMonitor *monitor) + { +- MetaOutput *output; +- MetaCrtc *crtc; +- +- output = meta_monitor_get_main_output (monitor); +- crtc = meta_output_get_assigned_crtc (output); ++ MetaMonitorPrivate *priv = meta_monitor_get_instance_private (monitor); + +- return crtc && crtc->current_mode; ++ return !!priv->current_mode; + } + + gboolean +@@ -1411,6 +1407,18 @@ meta_monitor_get_current_mode (MetaMonitor *monitor) + return priv->current_mode; + } + ++static gboolean ++is_current_mode_known (MetaMonitor *monitor) ++{ ++ MetaOutput *output; ++ MetaCrtc *crtc; ++ ++ output = meta_monitor_get_main_output (monitor); ++ crtc = meta_output_get_assigned_crtc (output); ++ ++ return meta_monitor_is_active (monitor) == (crtc && crtc->current_mode); ++} ++ + void + meta_monitor_derive_current_mode (MetaMonitor *monitor) + { +@@ -1430,6 +1438,8 @@ meta_monitor_derive_current_mode (MetaMonitor *monitor) + } + + priv->current_mode = current_mode; ++ ++ g_warn_if_fail (is_current_mode_known (monitor)); + } + + void +-- +2.21.0 + diff --git a/SOURCES/0001-monitor-config-store-Read-system-wide-config-files.patch b/SOURCES/0001-monitor-config-store-Read-system-wide-config-files.patch new file mode 100644 index 0000000..4fea4d0 --- /dev/null +++ b/SOURCES/0001-monitor-config-store-Read-system-wide-config-files.patch @@ -0,0 +1,186 @@ +From f7de692a87e4bf46bc005567fe0475c1208f0969 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Fri, 5 Oct 2018 18:52:03 +0200 +Subject: [PATCH] monitor-config-store: Read system wide config files + +Before introducing the new config store, the old monitor configuration +system read system wide monitor configuration files. Add back that +feature. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/253 +--- + src/backends/meta-monitor-config-manager.h | 1 + + src/backends/meta-monitor-config-store.c | 72 +++++++++++++++++++--- + 2 files changed, 65 insertions(+), 8 deletions(-) + +diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h +index 29ef8f8ce..16dff6d6a 100644 +--- a/src/backends/meta-monitor-config-manager.h ++++ b/src/backends/meta-monitor-config-manager.h +@@ -55,6 +55,7 @@ typedef enum _MetaMonitorsConfigFlag + { + META_MONITORS_CONFIG_FLAG_NONE = 0, + META_MONITORS_CONFIG_FLAG_MIGRATED = (1 << 0), ++ META_MONITORS_CONFIG_FLAG_SYSTEM_CONFIG = (1 << 1), + } MetaMonitorsConfigFlag; + + struct _MetaMonitorsConfig +diff --git a/src/backends/meta-monitor-config-store.c b/src/backends/meta-monitor-config-store.c +index ed0ce34f0..770bef734 100644 +--- a/src/backends/meta-monitor-config-store.c ++++ b/src/backends/meta-monitor-config-store.c +@@ -179,6 +179,8 @@ typedef struct + MetaMonitorConfig *current_monitor_config; + MetaLogicalMonitorConfig *current_logical_monitor_config; + GList *current_disabled_monitor_specs; ++ ++ MetaMonitorsConfigFlag extra_config_flags; + } ConfigParser; + + G_DEFINE_TYPE (MetaMonitorConfigStore, meta_monitor_config_store, +@@ -766,6 +768,8 @@ handle_end_element (GMarkupParseContext *context, + if (parser->current_was_migrated) + config_flags |= META_MONITORS_CONFIG_FLAG_MIGRATED; + ++ config_flags |= parser->extra_config_flags; ++ + config = + meta_monitors_config_new_full (parser->current_logical_monitor_configs, + parser->current_disabled_monitor_specs, +@@ -1078,9 +1082,10 @@ static const GMarkupParser config_parser = { + }; + + static gboolean +-read_config_file (MetaMonitorConfigStore *config_store, +- GFile *file, +- GError **error) ++read_config_file (MetaMonitorConfigStore *config_store, ++ GFile *file, ++ MetaMonitorsConfigFlag extra_config_flags, ++ GError **error) + { + char *buffer; + gsize size; +@@ -1092,7 +1097,8 @@ read_config_file (MetaMonitorConfigStore *config_store, + + parser = (ConfigParser) { + .state = STATE_INITIAL, +- .config_store = config_store ++ .config_store = config_store, ++ .extra_config_flags = extra_config_flags, + }; + + parse_context = g_markup_parse_context_new (&config_parser, +@@ -1274,6 +1280,9 @@ generate_config_xml (MetaMonitorConfigStore *config_store) + { + GList *l; + ++ if (config->flags & META_MONITORS_CONFIG_FLAG_SYSTEM_CONFIG) ++ continue; ++ + g_string_append (buffer, " \n"); + + if (config->flags & META_MONITORS_CONFIG_FLAG_MIGRATED) +@@ -1425,6 +1434,12 @@ maybe_save_configs (MetaMonitorConfigStore *config_store) + meta_monitor_config_store_save (config_store); + } + ++static gboolean ++is_system_config (MetaMonitorsConfig *config) ++{ ++ return !!(config->flags & META_MONITORS_CONFIG_FLAG_SYSTEM_CONFIG); ++} ++ + void + meta_monitor_config_store_add (MetaMonitorConfigStore *config_store, + MetaMonitorsConfig *config) +@@ -1432,7 +1447,8 @@ meta_monitor_config_store_add (MetaMonitorConfigStore *config_store, + g_hash_table_replace (config_store->configs, + config->key, g_object_ref (config)); + +- maybe_save_configs (config_store); ++ if (!is_system_config (config)) ++ maybe_save_configs (config_store); + } + + void +@@ -1441,7 +1457,8 @@ meta_monitor_config_store_remove (MetaMonitorConfigStore *config_store, + { + g_hash_table_remove (config_store->configs, config->key); + +- maybe_save_configs (config_store); ++ if (!is_system_config (config)) ++ maybe_save_configs (config_store); + } + + gboolean +@@ -1458,7 +1475,10 @@ meta_monitor_config_store_set_custom (MetaMonitorConfigStore *config_store, + if (write_path) + config_store->custom_write_file = g_file_new_for_path (write_path); + +- return read_config_file (config_store, config_store->custom_read_file, error); ++ return read_config_file (config_store, ++ config_store->custom_read_file, ++ META_MONITORS_CONFIG_FLAG_NONE, ++ error); + } + + int +@@ -1485,9 +1505,42 @@ static void + meta_monitor_config_store_constructed (GObject *object) + { + MetaMonitorConfigStore *config_store = META_MONITOR_CONFIG_STORE (object); ++ const char * const *system_dirs; + char *user_file_path; + GError *error = NULL; + ++ for (system_dirs = g_get_system_config_dirs (); ++ system_dirs && *system_dirs; ++ system_dirs++) ++ { ++ g_autofree char *system_file_path = NULL; ++ ++ system_file_path = g_build_filename (*system_dirs, "monitors.xml", NULL); ++ if (g_file_test (system_file_path, G_FILE_TEST_EXISTS)) ++ { ++ g_autoptr (GFile) system_file = NULL; ++ ++ system_file = g_file_new_for_path (system_file_path); ++ if (!read_config_file (config_store, ++ system_file, ++ META_MONITORS_CONFIG_FLAG_SYSTEM_CONFIG, ++ &error)) ++ { ++ if (g_error_matches (error, ++ META_MONITOR_CONFIG_STORE_ERROR, ++ META_MONITOR_CONFIG_STORE_ERROR_NEEDS_MIGRATION)) ++ g_warning ("System monitor configuration file (%s) is " ++ "incompatible; ask your administrator to migrate " ++ "the system monitor configuation.", ++ system_file_path); ++ else ++ g_warning ("Failed to read monitors config file '%s': %s", ++ system_file_path, error->message); ++ g_clear_error (&error); ++ } ++ } ++ } ++ + user_file_path = g_build_filename (g_get_user_config_dir (), + "monitors.xml", + NULL); +@@ -1495,7 +1548,10 @@ meta_monitor_config_store_constructed (GObject *object) + + if (g_file_test (user_file_path, G_FILE_TEST_EXISTS)) + { +- if (!read_config_file (config_store, config_store->user_file, &error)) ++ if (!read_config_file (config_store, ++ config_store->user_file, ++ META_MONITORS_CONFIG_FLAG_NONE, ++ &error)) + { + if (error->domain == META_MONITOR_CONFIG_STORE_ERROR && + error->code == META_MONITOR_CONFIG_STORE_ERROR_NEEDS_MIGRATION) +-- +2.20.1 + diff --git a/SOURCES/0001-monitor-manager-Consider-external-layout-before-defa.patch b/SOURCES/0001-monitor-manager-Consider-external-layout-before-defa.patch new file mode 100644 index 0000000..5ef6094 --- /dev/null +++ b/SOURCES/0001-monitor-manager-Consider-external-layout-before-defa.patch @@ -0,0 +1,151 @@ +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 + linear config + +In case of no existing configuration, we use a default layout of +aligning attached displays horizontally. This sidesteps any layout +configuration that is done externally, for instance via xorg.conf, +which is not desirable. Instead, base the initial configuration on +the existing layout if it passes some sanity checks before falling +back to the default linear config. +--- + src/backends/meta-monitor-config-manager.c | 75 ++++++++++++++++++++++ + src/backends/meta-monitor-config-manager.h | 1 + + src/backends/meta-monitor-manager.c | 19 ++++++++ + 3 files changed, 97 insertions(+) + +diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c +index 197892bf2..ae988f64a 100644 +--- a/src/backends/meta-monitor-config-manager.c ++++ b/src/backends/meta-monitor-config-manager.c +@@ -559,6 +559,83 @@ create_preferred_logical_monitor_config (MetaMonitorManager *monitor_ma + return logical_monitor_config; + } + ++static MetaLogicalMonitorConfig * ++create_logical_monitor_config_from_output (MetaMonitorManager *monitor_manager, ++ MetaMonitor *monitor, ++ MetaLogicalMonitorConfig *primary_logical_monitor_config, ++ MetaLogicalMonitorLayoutMode layout_mode) ++{ ++ MetaOutput *output; ++ MetaCrtc *crtc; ++ ++ output = meta_monitor_get_main_output (monitor); ++ crtc = meta_output_get_assigned_crtc (output); ++ return create_preferred_logical_monitor_config (monitor_manager, ++ monitor, ++ crtc->rect.x, ++ crtc->rect.y, ++ primary_logical_monitor_config, ++ layout_mode); ++} ++ ++MetaMonitorsConfig * ++meta_monitor_config_manager_create_current (MetaMonitorConfigManager *config_manager) ++{ ++ MetaMonitorManager *monitor_manager = config_manager->monitor_manager; ++ GList *logical_monitor_configs; ++ MetaMonitor *primary_monitor; ++ MetaLogicalMonitorLayoutMode layout_mode; ++ MetaLogicalMonitorConfig *primary_logical_monitor_config; ++ GList *monitors; ++ GList *l; ++ ++ if (meta_monitor_config_store_get_config_count (config_manager->config_store) > 0) ++ return NULL; ++ ++ primary_monitor = find_primary_monitor (monitor_manager); ++ if (!primary_monitor || !meta_monitor_is_active (primary_monitor)) ++ return NULL; ++ ++ layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager); ++ ++ primary_logical_monitor_config = ++ create_logical_monitor_config_from_output (monitor_manager, ++ primary_monitor, ++ NULL, ++ layout_mode); ++ ++ primary_logical_monitor_config->is_primary = TRUE; ++ logical_monitor_configs = g_list_append (NULL, ++ primary_logical_monitor_config); ++ ++ monitors = meta_monitor_manager_get_monitors (monitor_manager); ++ for (l = monitors; l; l = l->next) ++ { ++ MetaMonitor *monitor = l->data; ++ MetaLogicalMonitorConfig *logical_monitor_config; ++ ++ if (monitor == primary_monitor) ++ continue; ++ ++ if (!meta_monitor_is_active (monitor)) ++ continue; ++ ++ logical_monitor_config = ++ create_logical_monitor_config_from_output (monitor_manager, ++ monitor, ++ primary_logical_monitor_config, ++ layout_mode); ++ ++ logical_monitor_configs = g_list_append (logical_monitor_configs, ++ logical_monitor_config); ++ } ++ ++ return meta_monitors_config_new (monitor_manager, ++ logical_monitor_configs, ++ layout_mode, ++ META_MONITORS_CONFIG_FLAG_NONE); ++} ++ + MetaMonitorsConfig * + meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_manager) + { +diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h +index 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, + + 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_linear (MetaMonitorConfigManager *config_manager); + + 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 0b5e54c48..263e93941 100644 +--- a/src/backends/meta-monitor-manager.c ++++ b/src/backends/meta-monitor-manager.c +@@ -576,6 +576,25 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager) + g_clear_object (&config); + } + ++ config = meta_monitor_config_manager_create_current (manager->config_manager); ++ if (config) ++ { ++ if (!meta_monitor_manager_apply_monitors_config (manager, ++ config, ++ method, ++ &error)) ++ { ++ g_clear_object (&config); ++ g_warning ("Failed to use current monitor configuration: %s", ++ error->message); ++ g_clear_error (&error); ++ } ++ else ++ { ++ goto done; ++ } ++ } ++ + config = meta_monitor_config_manager_create_linear (manager->config_manager); + if (config) + { +-- +2.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 new file mode 100644 index 0000000..857ab93 --- /dev/null +++ b/SOURCES/0001-monitor-manager-xrandr-Force-an-update-when-resuming.patch @@ -0,0 +1,776 @@ +From 100795c2729305f919ff9611c877ea3e74d528b7 Mon Sep 17 00:00:00 2001 +From: Rui Matos +Date: Mon, 4 Jun 2018 16:35:04 -0400 +Subject: [PATCH] monitor-manager-xrandr: Force an update when resuming from + suspend + +The stack below us isn't as reliable as we'd like and in some cases +doesn't generate RRScreenChangeNotify events when e.g. resuming a +laptop on a dock, meaning that we'd miss newly attached outputs. +--- + src/backends/meta-gpu.c | 7 ++ + src/backends/meta-gpu.h | 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/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]; + + typedef struct _MetaGpuPrivate + { + MetaMonitorManager *monitor_manager; + + GList *outputs; + GList *crtcs; + GList *modes; + } MetaGpuPrivate; + + 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; + } + ++void ++meta_gpu_poll_hardware (MetaGpu *gpu) ++{ ++ if (META_GPU_GET_CLASS (gpu)->poll_hardware) ++ META_GPU_GET_CLASS (gpu)->poll_hardware (gpu); ++} ++ + gboolean + meta_gpu_read_current (MetaGpu *gpu, + GError **error) + { + 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_gpu_xrandr_poll_hardware (MetaGpu *gpu) ++{ ++ MetaGpuXrandr *gpu_xrandr = META_GPU_XRANDR (gpu); ++ ++ gpu_xrandr->need_hardware_poll = TRUE; ++} ++ + static gboolean + meta_gpu_xrandr_read_current (MetaGpu *gpu, + GError **error) + { + 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) ++ { ++ resources = XRRGetScreenResources (xdisplay, ++ DefaultRootWindow (xdisplay)); ++ gpu_xrandr->need_hardware_poll = FALSE; ++ } ++ else ++ { ++ resources = XRRGetScreenResourcesCurrent (xdisplay, ++ DefaultRootWindow (xdisplay)); ++ } ++ + if (!resources) + { + g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, + "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; ++ ++ guint logind_watch_id; ++ guint logind_signal_sub_id; ++ + 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, ++ const gchar *object_path, ++ const gchar *interface_name, ++ const gchar *signal_name, ++ GVariant *parameters, ++ gpointer user_data) ++{ ++ MetaMonitorManagerXrandr *manager_xrandr = user_data; ++ gboolean suspending; ++ ++ if (!g_str_equal (signal_name, "PrepareForSleep")) ++ return; ++ ++ g_variant_get (parameters, "(b)", &suspending); ++ if (!suspending) ++ { ++ meta_gpu_poll_hardware (manager_xrandr->gpu); ++ meta_monitor_manager_xrandr_update (manager_xrandr); ++ } ++} ++ ++static void ++logind_appeared (GDBusConnection *connection, ++ const gchar *name, ++ const gchar *name_owner, ++ gpointer user_data) ++{ ++ MetaMonitorManagerXrandr *manager_xrandr = user_data; ++ ++ manager_xrandr->logind_signal_sub_id = g_dbus_connection_signal_subscribe (connection, ++ "org.freedesktop.login1", ++ "org.freedesktop.login1.Manager", ++ "PrepareForSleep", ++ "/org/freedesktop/login1", ++ NULL, ++ G_DBUS_SIGNAL_FLAGS_NONE, ++ logind_signal_handler, ++ manager_xrandr, ++ NULL); ++} ++ ++static void ++logind_vanished (GDBusConnection *connection, ++ const gchar *name, ++ gpointer user_data) ++{ ++ MetaMonitorManagerXrandr *manager_xrandr = user_data; ++ ++ if (connection && manager_xrandr->logind_signal_sub_id > 0) ++ g_dbus_connection_signal_unsubscribe (connection, manager_xrandr->logind_signal_sub_id); ++ ++ manager_xrandr->logind_signal_sub_id = 0; ++} ++ + static void + meta_monitor_manager_xrandr_constructed (GObject *object) + { + 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 + } + + G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->constructed (object); + } + + static void + 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); + ++ if (manager_xrandr->logind_watch_id > 0) ++ g_bus_unwatch_name (manager_xrandr->logind_watch_id); ++ manager_xrandr->logind_watch_id = 0; ++ + G_OBJECT_CLASS (meta_monitor_manager_xrandr_parent_class)->finalize (object); + } + + static void + meta_monitor_manager_xrandr_init (MetaMonitorManagerXrandr *manager_xrandr) + { ++ manager_xrandr->logind_watch_id = g_bus_watch_name (G_BUS_TYPE_SYSTEM, ++ "org.freedesktop.login1", ++ G_BUS_NAME_WATCHER_FLAGS_NONE, ++ logind_appeared, ++ logind_vanished, ++ manager_xrandr, ++ NULL); + } + + static void + 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) + { + MetaMonitorManagerXrandr *manager_xrandr = + META_MONITOR_MANAGER_XRANDR (manager); + GList *l; + + 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; + } + +-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; +- +- XRRUpdateConfiguration (event); +- + 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.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 new file mode 100644 index 0000000..ff9cd9f --- /dev/null +++ b/SOURCES/0001-monitor-manager-xrandr-Work-around-spurious-hotplugs.patch @@ -0,0 +1,67 @@ +From ad61347e9d92380fbbb4effd8a19349777d76715 Mon Sep 17 00:00:00 2001 +From: Rui Matos +Date: Tue, 6 Oct 2015 21:16:18 +0200 +Subject: [PATCH] monitor-manager-xrandr: Work around spurious hotplugs on Xvnc + +Xvnc turns its outputs off/on on every mode set which makes us believe +there was an hotplug when there actually wasn't. Work around this by +requiring new randr configuration timestamps to be ahead of the last +set timestamp by at least 100 ms for us to consider them an actual +hotplug. +--- + .../x11/meta-monitor-manager-xrandr.c | 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 dbe3e4e3b..90a3952db 100644 +--- a/src/backends/x11/meta-monitor-manager-xrandr.c ++++ b/src/backends/x11/meta-monitor-manager-xrandr.c +@@ -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) ++{ ++ MetaMonitorManagerXrandr *manager_xrandr = ++ META_MONITOR_MANAGER_XRANDR (manager); ++ GList *l; ++ ++ 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; ++} ++ + gboolean + meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager_xrandr, + XEvent *event) +@@ -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; +@@ -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 = resources->timestamp < resources->configTimestamp; ++ timestamp = resources->timestamp; ++ if (is_xvnc (manager)) ++ timestamp += 100; ++ ++ is_hotplug = timestamp < resources->configTimestamp; + is_our_configuration = (resources->timestamp == + manager_xrandr->last_xrandr_set_timestamp); + if (is_hotplug) +-- +2.17.0 + diff --git a/SOURCES/0001-renderer-native-Check-calculated-transform-when-crea.patch b/SOURCES/0001-renderer-native-Check-calculated-transform-when-crea.patch new file mode 100644 index 0000000..1079d4c --- /dev/null +++ b/SOURCES/0001-renderer-native-Check-calculated-transform-when-crea.patch @@ -0,0 +1,88 @@ +From 91c5c94434b22895f97b3ae47a889ccb902b86aa Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Mon, 23 Jul 2018 21:36:57 +0200 +Subject: [PATCH] renderer/native: Check calculated transform when creating + view + +The "backends: Move MetaOutput::crtc field into private struct" +accidentally changed the view transform calculation code to assume that +"MetaCrtc::transform" corresponds to the transform of the CRTC; so is +not the case yet; one must calculate the transform from the logical +monitor, and check whether it is supported by the CRTC using +meta_monitor_manager_is_transform_handled(). This commit restores the +old behaviour that doesn't use MetaCrtc::transform when calculating the +view transform. + +Fixes: https://gitlab.gnome.org/GNOME/mutter/issues/216 +--- + src/backends/native/meta-renderer-native.c | 9 +++++++-- + src/backends/x11/nested/meta-renderer-x11-nested.c | 8 ++++++-- + 2 files changed, 13 insertions(+), 4 deletions(-) + +diff --git a/src/backends/native/meta-renderer-native.c b/src/backends/native/meta-renderer-native.c +index fc6b223026..8dc0da7104 100644 +--- a/src/backends/native/meta-renderer-native.c ++++ b/src/backends/native/meta-renderer-native.c +@@ -2720,9 +2720,14 @@ calculate_view_transform (MetaMonitorManager *monitor_manager, + MetaMonitor *main_monitor; + MetaOutput *main_output; + MetaCrtc *crtc; ++ MetaMonitorTransform crtc_transform; ++ + main_monitor = meta_logical_monitor_get_monitors (logical_monitor)->data; + main_output = meta_monitor_get_main_output (main_monitor); + crtc = meta_output_get_assigned_crtc (main_output); ++ crtc_transform = ++ meta_monitor_logical_to_crtc_transform (main_monitor, ++ logical_monitor->transform); + + /* + * Pick any monitor and output and check; all CRTCs of a logical monitor will +@@ -2731,10 +2736,10 @@ calculate_view_transform (MetaMonitorManager *monitor_manager, + + if (meta_monitor_manager_is_transform_handled (monitor_manager, + crtc, +- crtc->transform)) ++ crtc_transform)) + return META_MONITOR_TRANSFORM_NORMAL; + else +- return crtc->transform; ++ return crtc_transform; + } + + static MetaRendererView * +diff --git a/src/backends/x11/nested/meta-renderer-x11-nested.c b/src/backends/x11/nested/meta-renderer-x11-nested.c +index 8fdf46b0b5..b29b9c69e2 100644 +--- a/src/backends/x11/nested/meta-renderer-x11-nested.c ++++ b/src/backends/x11/nested/meta-renderer-x11-nested.c +@@ -51,10 +51,14 @@ calculate_view_transform (MetaMonitorManager *monitor_manager, + MetaMonitor *main_monitor; + MetaOutput *main_output; + MetaCrtc *crtc; ++ MetaMonitorTransform crtc_transform; + + main_monitor = meta_logical_monitor_get_monitors (logical_monitor)->data; + main_output = meta_monitor_get_main_output (main_monitor); + crtc = meta_output_get_assigned_crtc (main_output); ++ crtc_transform = ++ meta_monitor_logical_to_crtc_transform (main_monitor, ++ logical_monitor->transform); + /* + * Pick any monitor and output and check; all CRTCs of a logical monitor will + * always have the same transform assigned to them. +@@ -62,10 +66,10 @@ calculate_view_transform (MetaMonitorManager *monitor_manager, + + if (meta_monitor_manager_is_transform_handled (monitor_manager, + crtc, +- crtc->transform)) ++ crtc_transform)) + return META_MONITOR_TRANSFORM_NORMAL; + else +- return crtc->transform; ++ return crtc_transform; + } + + static MetaRendererView * +-- +2.17.1 + diff --git a/SOURCES/0001-rhel7-Fix-build-for-el7.patch b/SOURCES/0001-rhel7-Fix-build-for-el7.patch new file mode 100644 index 0000000..5b9ac0f --- /dev/null +++ b/SOURCES/0001-rhel7-Fix-build-for-el7.patch @@ -0,0 +1,898 @@ +From 6be34265a67e9ca1e30fe42993d5743b01d3b010 Mon Sep 17 00:00:00 2001 +From: rpm-build +Date: Fri, 15 Sep 2017 08:55:44 +0100 +Subject: [PATCH] rhel7: Fix build for el7 + +--- + .../evdev/clutter-virtual-input-device-evdev.c | 1 + + clutter/clutter/evdev/linux/input-event-codes.h | 838 +++++++++++++++++++++ + src/backends/native/meta-input-settings-native.c | 2 +- + src/wayland/meta-wayland-tablet-tool.c | 2 +- + 4 files changed, 841 insertions(+), 2 deletions(-) + create mode 100644 clutter/clutter/evdev/linux/input-event-codes.h + +diff --git a/clutter/clutter/evdev/clutter-virtual-input-device-evdev.c b/clutter/clutter/evdev/clutter-virtual-input-device-evdev.c +index e487708..8443c0a 100644 +--- a/clutter/clutter/evdev/clutter-virtual-input-device-evdev.c ++++ b/clutter/clutter/evdev/clutter-virtual-input-device-evdev.c +@@ -33,6 +33,7 @@ + #include "evdev/clutter-input-device-evdev.h" + #include "evdev/clutter-seat-evdev.h" + #include "evdev/clutter-virtual-input-device-evdev.h" ++#include "evdev/linux/input-event-codes.h" + + enum + { +diff --git a/clutter/clutter/evdev/linux/input-event-codes.h b/clutter/clutter/evdev/linux/input-event-codes.h +new file mode 100644 +index 0000000..e2b5c75 +--- /dev/null ++++ b/clutter/clutter/evdev/linux/input-event-codes.h +@@ -0,0 +1,838 @@ ++/* ++ * Input event codes ++ * ++ * *** IMPORTANT *** ++ * This file is not only included from C-code but also from devicetree source ++ * files. As such this file MUST only contain comments and defines. ++ * ++ * Copyright (c) 1999-2002 Vojtech Pavlik ++ * Copyright (c) 2015 Hans de Goede ++ * ++ * This program is free software; you can redistribute it and/or modify it ++ * under the terms of the GNU General Public License version 2 as published by ++ * the Free Software Foundation. ++ */ ++#ifndef _INPUT_EVENT_CODES_H ++#define _INPUT_EVENT_CODES_H ++ ++/* ++ * Device properties and quirks ++ */ ++ ++#define INPUT_PROP_POINTER 0x00 /* needs a pointer */ ++#define INPUT_PROP_DIRECT 0x01 /* direct input devices */ ++#define INPUT_PROP_BUTTONPAD 0x02 /* has button(s) under pad */ ++#define INPUT_PROP_SEMI_MT 0x03 /* touch rectangle only */ ++#define INPUT_PROP_TOPBUTTONPAD 0x04 /* softbuttons at top of pad */ ++#define INPUT_PROP_POINTING_STICK 0x05 /* is a pointing stick */ ++#define INPUT_PROP_ACCELEROMETER 0x06 /* has accelerometer */ ++ ++#define INPUT_PROP_MAX 0x1f ++#define INPUT_PROP_CNT (INPUT_PROP_MAX + 1) ++ ++/* ++ * Event types ++ */ ++ ++#define EV_SYN 0x00 ++#define EV_KEY 0x01 ++#define EV_REL 0x02 ++#define EV_ABS 0x03 ++#define EV_MSC 0x04 ++#define EV_SW 0x05 ++#define EV_LED 0x11 ++#define EV_SND 0x12 ++#define EV_REP 0x14 ++#define EV_FF 0x15 ++#define EV_PWR 0x16 ++#define EV_FF_STATUS 0x17 ++#define EV_MAX 0x1f ++#define EV_CNT (EV_MAX+1) ++ ++/* ++ * Synchronization events. ++ */ ++ ++#define SYN_REPORT 0 ++#define SYN_CONFIG 1 ++#define SYN_MT_REPORT 2 ++#define SYN_DROPPED 3 ++#define SYN_MAX 0xf ++#define SYN_CNT (SYN_MAX+1) ++ ++/* ++ * Keys and buttons ++ * ++ * Most of the keys/buttons are modeled after USB HUT 1.12 ++ * (see http://www.usb.org/developers/hidpage). ++ * Abbreviations in the comments: ++ * AC - Application Control ++ * AL - Application Launch Button ++ * SC - System Control ++ */ ++ ++#define KEY_RESERVED 0 ++#define KEY_ESC 1 ++#define KEY_1 2 ++#define KEY_2 3 ++#define KEY_3 4 ++#define KEY_4 5 ++#define KEY_5 6 ++#define KEY_6 7 ++#define KEY_7 8 ++#define KEY_8 9 ++#define KEY_9 10 ++#define KEY_0 11 ++#define KEY_MINUS 12 ++#define KEY_EQUAL 13 ++#define KEY_BACKSPACE 14 ++#define KEY_TAB 15 ++#define KEY_Q 16 ++#define KEY_W 17 ++#define KEY_E 18 ++#define KEY_R 19 ++#define KEY_T 20 ++#define KEY_Y 21 ++#define KEY_U 22 ++#define KEY_I 23 ++#define KEY_O 24 ++#define KEY_P 25 ++#define KEY_LEFTBRACE 26 ++#define KEY_RIGHTBRACE 27 ++#define KEY_ENTER 28 ++#define KEY_LEFTCTRL 29 ++#define KEY_A 30 ++#define KEY_S 31 ++#define KEY_D 32 ++#define KEY_F 33 ++#define KEY_G 34 ++#define KEY_H 35 ++#define KEY_J 36 ++#define KEY_K 37 ++#define KEY_L 38 ++#define KEY_SEMICOLON 39 ++#define KEY_APOSTROPHE 40 ++#define KEY_GRAVE 41 ++#define KEY_LEFTSHIFT 42 ++#define KEY_BACKSLASH 43 ++#define KEY_Z 44 ++#define KEY_X 45 ++#define KEY_C 46 ++#define KEY_V 47 ++#define KEY_B 48 ++#define KEY_N 49 ++#define KEY_M 50 ++#define KEY_COMMA 51 ++#define KEY_DOT 52 ++#define KEY_SLASH 53 ++#define KEY_RIGHTSHIFT 54 ++#define KEY_KPASTERISK 55 ++#define KEY_LEFTALT 56 ++#define KEY_SPACE 57 ++#define KEY_CAPSLOCK 58 ++#define KEY_F1 59 ++#define KEY_F2 60 ++#define KEY_F3 61 ++#define KEY_F4 62 ++#define KEY_F5 63 ++#define KEY_F6 64 ++#define KEY_F7 65 ++#define KEY_F8 66 ++#define KEY_F9 67 ++#define KEY_F10 68 ++#define KEY_NUMLOCK 69 ++#define KEY_SCROLLLOCK 70 ++#define KEY_KP7 71 ++#define KEY_KP8 72 ++#define KEY_KP9 73 ++#define KEY_KPMINUS 74 ++#define KEY_KP4 75 ++#define KEY_KP5 76 ++#define KEY_KP6 77 ++#define KEY_KPPLUS 78 ++#define KEY_KP1 79 ++#define KEY_KP2 80 ++#define KEY_KP3 81 ++#define KEY_KP0 82 ++#define KEY_KPDOT 83 ++ ++#define KEY_ZENKAKUHANKAKU 85 ++#define KEY_102ND 86 ++#define KEY_F11 87 ++#define KEY_F12 88 ++#define KEY_RO 89 ++#define KEY_KATAKANA 90 ++#define KEY_HIRAGANA 91 ++#define KEY_HENKAN 92 ++#define KEY_KATAKANAHIRAGANA 93 ++#define KEY_MUHENKAN 94 ++#define KEY_KPJPCOMMA 95 ++#define KEY_KPENTER 96 ++#define KEY_RIGHTCTRL 97 ++#define KEY_KPSLASH 98 ++#define KEY_SYSRQ 99 ++#define KEY_RIGHTALT 100 ++#define KEY_LINEFEED 101 ++#define KEY_HOME 102 ++#define KEY_UP 103 ++#define KEY_PAGEUP 104 ++#define KEY_LEFT 105 ++#define KEY_RIGHT 106 ++#define KEY_END 107 ++#define KEY_DOWN 108 ++#define KEY_PAGEDOWN 109 ++#define KEY_INSERT 110 ++#define KEY_DELETE 111 ++#define KEY_MACRO 112 ++#define KEY_MUTE 113 ++#define KEY_VOLUMEDOWN 114 ++#define KEY_VOLUMEUP 115 ++#define KEY_POWER 116 /* SC System Power Down */ ++#define KEY_KPEQUAL 117 ++#define KEY_KPPLUSMINUS 118 ++#define KEY_PAUSE 119 ++#define KEY_SCALE 120 /* AL Compiz Scale (Expose) */ ++ ++#define KEY_KPCOMMA 121 ++#define KEY_HANGEUL 122 ++#define KEY_HANGUEL KEY_HANGEUL ++#define KEY_HANJA 123 ++#define KEY_YEN 124 ++#define KEY_LEFTMETA 125 ++#define KEY_RIGHTMETA 126 ++#define KEY_COMPOSE 127 ++ ++#define KEY_STOP 128 /* AC Stop */ ++#define KEY_AGAIN 129 ++#define KEY_PROPS 130 /* AC Properties */ ++#define KEY_UNDO 131 /* AC Undo */ ++#define KEY_FRONT 132 ++#define KEY_COPY 133 /* AC Copy */ ++#define KEY_OPEN 134 /* AC Open */ ++#define KEY_PASTE 135 /* AC Paste */ ++#define KEY_FIND 136 /* AC Search */ ++#define KEY_CUT 137 /* AC Cut */ ++#define KEY_HELP 138 /* AL Integrated Help Center */ ++#define KEY_MENU 139 /* Menu (show menu) */ ++#define KEY_CALC 140 /* AL Calculator */ ++#define KEY_SETUP 141 ++#define KEY_SLEEP 142 /* SC System Sleep */ ++#define KEY_WAKEUP 143 /* System Wake Up */ ++#define KEY_FILE 144 /* AL Local Machine Browser */ ++#define KEY_SENDFILE 145 ++#define KEY_DELETEFILE 146 ++#define KEY_XFER 147 ++#define KEY_PROG1 148 ++#define KEY_PROG2 149 ++#define KEY_WWW 150 /* AL Internet Browser */ ++#define KEY_MSDOS 151 ++#define KEY_COFFEE 152 /* AL Terminal Lock/Screensaver */ ++#define KEY_SCREENLOCK KEY_COFFEE ++#define KEY_ROTATE_DISPLAY 153 /* Display orientation for e.g. tablets */ ++#define KEY_DIRECTION KEY_ROTATE_DISPLAY ++#define KEY_CYCLEWINDOWS 154 ++#define KEY_MAIL 155 ++#define KEY_BOOKMARKS 156 /* AC Bookmarks */ ++#define KEY_COMPUTER 157 ++#define KEY_BACK 158 /* AC Back */ ++#define KEY_FORWARD 159 /* AC Forward */ ++#define KEY_CLOSECD 160 ++#define KEY_EJECTCD 161 ++#define KEY_EJECTCLOSECD 162 ++#define KEY_NEXTSONG 163 ++#define KEY_PLAYPAUSE 164 ++#define KEY_PREVIOUSSONG 165 ++#define KEY_STOPCD 166 ++#define KEY_RECORD 167 ++#define KEY_REWIND 168 ++#define KEY_PHONE 169 /* Media Select Telephone */ ++#define KEY_ISO 170 ++#define KEY_CONFIG 171 /* AL Consumer Control Configuration */ ++#define KEY_HOMEPAGE 172 /* AC Home */ ++#define KEY_REFRESH 173 /* AC Refresh */ ++#define KEY_EXIT 174 /* AC Exit */ ++#define KEY_MOVE 175 ++#define KEY_EDIT 176 ++#define KEY_SCROLLUP 177 ++#define KEY_SCROLLDOWN 178 ++#define KEY_KPLEFTPAREN 179 ++#define KEY_KPRIGHTPAREN 180 ++#define KEY_NEW 181 /* AC New */ ++#define KEY_REDO 182 /* AC Redo/Repeat */ ++ ++#define KEY_F13 183 ++#define KEY_F14 184 ++#define KEY_F15 185 ++#define KEY_F16 186 ++#define KEY_F17 187 ++#define KEY_F18 188 ++#define KEY_F19 189 ++#define KEY_F20 190 ++#define KEY_F21 191 ++#define KEY_F22 192 ++#define KEY_F23 193 ++#define KEY_F24 194 ++ ++#define KEY_PLAYCD 200 ++#define KEY_PAUSECD 201 ++#define KEY_PROG3 202 ++#define KEY_PROG4 203 ++#define KEY_DASHBOARD 204 /* AL Dashboard */ ++#define KEY_SUSPEND 205 ++#define KEY_CLOSE 206 /* AC Close */ ++#define KEY_PLAY 207 ++#define KEY_FASTFORWARD 208 ++#define KEY_BASSBOOST 209 ++#define KEY_PRINT 210 /* AC Print */ ++#define KEY_HP 211 ++#define KEY_CAMERA 212 ++#define KEY_SOUND 213 ++#define KEY_QUESTION 214 ++#define KEY_EMAIL 215 ++#define KEY_CHAT 216 ++#define KEY_SEARCH 217 ++#define KEY_CONNECT 218 ++#define KEY_FINANCE 219 /* AL Checkbook/Finance */ ++#define KEY_SPORT 220 ++#define KEY_SHOP 221 ++#define KEY_ALTERASE 222 ++#define KEY_CANCEL 223 /* AC Cancel */ ++#define KEY_BRIGHTNESSDOWN 224 ++#define KEY_BRIGHTNESSUP 225 ++#define KEY_MEDIA 226 ++ ++#define KEY_SWITCHVIDEOMODE 227 /* Cycle between available video ++ outputs (Monitor/LCD/TV-out/etc) */ ++#define KEY_KBDILLUMTOGGLE 228 ++#define KEY_KBDILLUMDOWN 229 ++#define KEY_KBDILLUMUP 230 ++ ++#define KEY_SEND 231 /* AC Send */ ++#define KEY_REPLY 232 /* AC Reply */ ++#define KEY_FORWARDMAIL 233 /* AC Forward Msg */ ++#define KEY_SAVE 234 /* AC Save */ ++#define KEY_DOCUMENTS 235 ++ ++#define KEY_BATTERY 236 ++ ++#define KEY_BLUETOOTH 237 ++#define KEY_WLAN 238 ++#define KEY_UWB 239 ++ ++#define KEY_UNKNOWN 240 ++ ++#define KEY_VIDEO_NEXT 241 /* drive next video source */ ++#define KEY_VIDEO_PREV 242 /* drive previous video source */ ++#define KEY_BRIGHTNESS_CYCLE 243 /* brightness up, after max is min */ ++#define KEY_BRIGHTNESS_AUTO 244 /* Set Auto Brightness: manual ++ brightness control is off, ++ rely on ambient */ ++#define KEY_BRIGHTNESS_ZERO KEY_BRIGHTNESS_AUTO ++#define KEY_DISPLAY_OFF 245 /* display device to off state */ ++ ++#define KEY_WWAN 246 /* Wireless WAN (LTE, UMTS, GSM, etc.) */ ++#define KEY_WIMAX KEY_WWAN ++#define KEY_RFKILL 247 /* Key that controls all radios */ ++ ++#define KEY_MICMUTE 248 /* Mute / unmute the microphone */ ++ ++/* Code 255 is reserved for special needs of AT keyboard driver */ ++ ++#define BTN_MISC 0x100 ++#define BTN_0 0x100 ++#define BTN_1 0x101 ++#define BTN_2 0x102 ++#define BTN_3 0x103 ++#define BTN_4 0x104 ++#define BTN_5 0x105 ++#define BTN_6 0x106 ++#define BTN_7 0x107 ++#define BTN_8 0x108 ++#define BTN_9 0x109 ++ ++#define BTN_MOUSE 0x110 ++#define BTN_LEFT 0x110 ++#define BTN_RIGHT 0x111 ++#define BTN_MIDDLE 0x112 ++#define BTN_SIDE 0x113 ++#define BTN_EXTRA 0x114 ++#define BTN_FORWARD 0x115 ++#define BTN_BACK 0x116 ++#define BTN_TASK 0x117 ++ ++#define BTN_JOYSTICK 0x120 ++#define BTN_TRIGGER 0x120 ++#define BTN_THUMB 0x121 ++#define BTN_THUMB2 0x122 ++#define BTN_TOP 0x123 ++#define BTN_TOP2 0x124 ++#define BTN_PINKIE 0x125 ++#define BTN_BASE 0x126 ++#define BTN_BASE2 0x127 ++#define BTN_BASE3 0x128 ++#define BTN_BASE4 0x129 ++#define BTN_BASE5 0x12a ++#define BTN_BASE6 0x12b ++#define BTN_DEAD 0x12f ++ ++#define BTN_GAMEPAD 0x130 ++#define BTN_SOUTH 0x130 ++#define BTN_A BTN_SOUTH ++#define BTN_EAST 0x131 ++#define BTN_B BTN_EAST ++#define BTN_C 0x132 ++#define BTN_NORTH 0x133 ++#define BTN_X BTN_NORTH ++#define BTN_WEST 0x134 ++#define BTN_Y BTN_WEST ++#define BTN_Z 0x135 ++#define BTN_TL 0x136 ++#define BTN_TR 0x137 ++#define BTN_TL2 0x138 ++#define BTN_TR2 0x139 ++#define BTN_SELECT 0x13a ++#define BTN_START 0x13b ++#define BTN_MODE 0x13c ++#define BTN_THUMBL 0x13d ++#define BTN_THUMBR 0x13e ++ ++#define BTN_DIGI 0x140 ++#define BTN_TOOL_PEN 0x140 ++#define BTN_TOOL_RUBBER 0x141 ++#define BTN_TOOL_BRUSH 0x142 ++#define BTN_TOOL_PENCIL 0x143 ++#define BTN_TOOL_AIRBRUSH 0x144 ++#define BTN_TOOL_FINGER 0x145 ++#define BTN_TOOL_MOUSE 0x146 ++#define BTN_TOOL_LENS 0x147 ++#define BTN_TOOL_QUINTTAP 0x148 /* Five fingers on trackpad */ ++#define BTN_TOUCH 0x14a ++#define BTN_STYLUS 0x14b ++#define BTN_STYLUS2 0x14c ++#define BTN_TOOL_DOUBLETAP 0x14d ++#define BTN_TOOL_TRIPLETAP 0x14e ++#define BTN_TOOL_QUADTAP 0x14f /* Four fingers on trackpad */ ++ ++#define BTN_WHEEL 0x150 ++#define BTN_GEAR_DOWN 0x150 ++#define BTN_GEAR_UP 0x151 ++ ++#define KEY_OK 0x160 ++#define KEY_SELECT 0x161 ++#define KEY_GOTO 0x162 ++#define KEY_CLEAR 0x163 ++#define KEY_POWER2 0x164 ++#define KEY_OPTION 0x165 ++#define KEY_INFO 0x166 /* AL OEM Features/Tips/Tutorial */ ++#define KEY_TIME 0x167 ++#define KEY_VENDOR 0x168 ++#define KEY_ARCHIVE 0x169 ++#define KEY_PROGRAM 0x16a /* Media Select Program Guide */ ++#define KEY_CHANNEL 0x16b ++#define KEY_FAVORITES 0x16c ++#define KEY_EPG 0x16d ++#define KEY_PVR 0x16e /* Media Select Home */ ++#define KEY_MHP 0x16f ++#define KEY_LANGUAGE 0x170 ++#define KEY_TITLE 0x171 ++#define KEY_SUBTITLE 0x172 ++#define KEY_ANGLE 0x173 ++#define KEY_ZOOM 0x174 ++#define KEY_MODE 0x175 ++#define KEY_KEYBOARD 0x176 ++#define KEY_SCREEN 0x177 ++#define KEY_PC 0x178 /* Media Select Computer */ ++#define KEY_TV 0x179 /* Media Select TV */ ++#define KEY_TV2 0x17a /* Media Select Cable */ ++#define KEY_VCR 0x17b /* Media Select VCR */ ++#define KEY_VCR2 0x17c /* VCR Plus */ ++#define KEY_SAT 0x17d /* Media Select Satellite */ ++#define KEY_SAT2 0x17e ++#define KEY_CD 0x17f /* Media Select CD */ ++#define KEY_TAPE 0x180 /* Media Select Tape */ ++#define KEY_RADIO 0x181 ++#define KEY_TUNER 0x182 /* Media Select Tuner */ ++#define KEY_PLAYER 0x183 ++#define KEY_TEXT 0x184 ++#define KEY_DVD 0x185 /* Media Select DVD */ ++#define KEY_AUX 0x186 ++#define KEY_MP3 0x187 ++#define KEY_AUDIO 0x188 /* AL Audio Browser */ ++#define KEY_VIDEO 0x189 /* AL Movie Browser */ ++#define KEY_DIRECTORY 0x18a ++#define KEY_LIST 0x18b ++#define KEY_MEMO 0x18c /* Media Select Messages */ ++#define KEY_CALENDAR 0x18d ++#define KEY_RED 0x18e ++#define KEY_GREEN 0x18f ++#define KEY_YELLOW 0x190 ++#define KEY_BLUE 0x191 ++#define KEY_CHANNELUP 0x192 /* Channel Increment */ ++#define KEY_CHANNELDOWN 0x193 /* Channel Decrement */ ++#define KEY_FIRST 0x194 ++#define KEY_LAST 0x195 /* Recall Last */ ++#define KEY_AB 0x196 ++#define KEY_NEXT 0x197 ++#define KEY_RESTART 0x198 ++#define KEY_SLOW 0x199 ++#define KEY_SHUFFLE 0x19a ++#define KEY_BREAK 0x19b ++#define KEY_PREVIOUS 0x19c ++#define KEY_DIGITS 0x19d ++#define KEY_TEEN 0x19e ++#define KEY_TWEN 0x19f ++#define KEY_VIDEOPHONE 0x1a0 /* Media Select Video Phone */ ++#define KEY_GAMES 0x1a1 /* Media Select Games */ ++#define KEY_ZOOMIN 0x1a2 /* AC Zoom In */ ++#define KEY_ZOOMOUT 0x1a3 /* AC Zoom Out */ ++#define KEY_ZOOMRESET 0x1a4 /* AC Zoom */ ++#define KEY_WORDPROCESSOR 0x1a5 /* AL Word Processor */ ++#define KEY_EDITOR 0x1a6 /* AL Text Editor */ ++#define KEY_SPREADSHEET 0x1a7 /* AL Spreadsheet */ ++#define KEY_GRAPHICSEDITOR 0x1a8 /* AL Graphics Editor */ ++#define KEY_PRESENTATION 0x1a9 /* AL Presentation App */ ++#define KEY_DATABASE 0x1aa /* AL Database App */ ++#define KEY_NEWS 0x1ab /* AL Newsreader */ ++#define KEY_VOICEMAIL 0x1ac /* AL Voicemail */ ++#define KEY_ADDRESSBOOK 0x1ad /* AL Contacts/Address Book */ ++#define KEY_MESSENGER 0x1ae /* AL Instant Messaging */ ++#define KEY_DISPLAYTOGGLE 0x1af /* Turn display (LCD) on and off */ ++#define KEY_BRIGHTNESS_TOGGLE KEY_DISPLAYTOGGLE ++#define KEY_SPELLCHECK 0x1b0 /* AL Spell Check */ ++#define KEY_LOGOFF 0x1b1 /* AL Logoff */ ++ ++#define KEY_DOLLAR 0x1b2 ++#define KEY_EURO 0x1b3 ++ ++#define KEY_FRAMEBACK 0x1b4 /* Consumer - transport controls */ ++#define KEY_FRAMEFORWARD 0x1b5 ++#define KEY_CONTEXT_MENU 0x1b6 /* GenDesc - system context menu */ ++#define KEY_MEDIA_REPEAT 0x1b7 /* Consumer - transport control */ ++#define KEY_10CHANNELSUP 0x1b8 /* 10 channels up (10+) */ ++#define KEY_10CHANNELSDOWN 0x1b9 /* 10 channels down (10-) */ ++#define KEY_IMAGES 0x1ba /* AL Image Browser */ ++ ++#define KEY_DEL_EOL 0x1c0 ++#define KEY_DEL_EOS 0x1c1 ++#define KEY_INS_LINE 0x1c2 ++#define KEY_DEL_LINE 0x1c3 ++ ++#define KEY_FN 0x1d0 ++#define KEY_FN_ESC 0x1d1 ++#define KEY_FN_F1 0x1d2 ++#define KEY_FN_F2 0x1d3 ++#define KEY_FN_F3 0x1d4 ++#define KEY_FN_F4 0x1d5 ++#define KEY_FN_F5 0x1d6 ++#define KEY_FN_F6 0x1d7 ++#define KEY_FN_F7 0x1d8 ++#define KEY_FN_F8 0x1d9 ++#define KEY_FN_F9 0x1da ++#define KEY_FN_F10 0x1db ++#define KEY_FN_F11 0x1dc ++#define KEY_FN_F12 0x1dd ++#define KEY_FN_1 0x1de ++#define KEY_FN_2 0x1df ++#define KEY_FN_D 0x1e0 ++#define KEY_FN_E 0x1e1 ++#define KEY_FN_F 0x1e2 ++#define KEY_FN_S 0x1e3 ++#define KEY_FN_B 0x1e4 ++ ++#define KEY_BRL_DOT1 0x1f1 ++#define KEY_BRL_DOT2 0x1f2 ++#define KEY_BRL_DOT3 0x1f3 ++#define KEY_BRL_DOT4 0x1f4 ++#define KEY_BRL_DOT5 0x1f5 ++#define KEY_BRL_DOT6 0x1f6 ++#define KEY_BRL_DOT7 0x1f7 ++#define KEY_BRL_DOT8 0x1f8 ++#define KEY_BRL_DOT9 0x1f9 ++#define KEY_BRL_DOT10 0x1fa ++ ++#define KEY_NUMERIC_0 0x200 /* used by phones, remote controls, */ ++#define KEY_NUMERIC_1 0x201 /* and other keypads */ ++#define KEY_NUMERIC_2 0x202 ++#define KEY_NUMERIC_3 0x203 ++#define KEY_NUMERIC_4 0x204 ++#define KEY_NUMERIC_5 0x205 ++#define KEY_NUMERIC_6 0x206 ++#define KEY_NUMERIC_7 0x207 ++#define KEY_NUMERIC_8 0x208 ++#define KEY_NUMERIC_9 0x209 ++#define KEY_NUMERIC_STAR 0x20a ++#define KEY_NUMERIC_POUND 0x20b ++#define KEY_NUMERIC_A 0x20c /* Phone key A - HUT Telephony 0xb9 */ ++#define KEY_NUMERIC_B 0x20d ++#define KEY_NUMERIC_C 0x20e ++#define KEY_NUMERIC_D 0x20f ++ ++#define KEY_CAMERA_FOCUS 0x210 ++#define KEY_WPS_BUTTON 0x211 /* WiFi Protected Setup key */ ++ ++#define KEY_TOUCHPAD_TOGGLE 0x212 /* Request switch touchpad on or off */ ++#define KEY_TOUCHPAD_ON 0x213 ++#define KEY_TOUCHPAD_OFF 0x214 ++ ++#define KEY_CAMERA_ZOOMIN 0x215 ++#define KEY_CAMERA_ZOOMOUT 0x216 ++#define KEY_CAMERA_UP 0x217 ++#define KEY_CAMERA_DOWN 0x218 ++#define KEY_CAMERA_LEFT 0x219 ++#define KEY_CAMERA_RIGHT 0x21a ++ ++#define KEY_ATTENDANT_ON 0x21b ++#define KEY_ATTENDANT_OFF 0x21c ++#define KEY_ATTENDANT_TOGGLE 0x21d /* Attendant call on or off */ ++#define KEY_LIGHTS_TOGGLE 0x21e /* Reading light on or off */ ++ ++#define BTN_DPAD_UP 0x220 ++#define BTN_DPAD_DOWN 0x221 ++#define BTN_DPAD_LEFT 0x222 ++#define BTN_DPAD_RIGHT 0x223 ++ ++#define KEY_ALS_TOGGLE 0x230 /* Ambient light sensor */ ++ ++#define KEY_BUTTONCONFIG 0x240 /* AL Button Configuration */ ++#define KEY_TASKMANAGER 0x241 /* AL Task/Project Manager */ ++#define KEY_JOURNAL 0x242 /* AL Log/Journal/Timecard */ ++#define KEY_CONTROLPANEL 0x243 /* AL Control Panel */ ++#define KEY_APPSELECT 0x244 /* AL Select Task/Application */ ++#define KEY_SCREENSAVER 0x245 /* AL Screen Saver */ ++#define KEY_VOICECOMMAND 0x246 /* Listening Voice Command */ ++ ++#define KEY_BRIGHTNESS_MIN 0x250 /* Set Brightness to Minimum */ ++#define KEY_BRIGHTNESS_MAX 0x251 /* Set Brightness to Maximum */ ++ ++#define KEY_KBDINPUTASSIST_PREV 0x260 ++#define KEY_KBDINPUTASSIST_NEXT 0x261 ++#define KEY_KBDINPUTASSIST_PREVGROUP 0x262 ++#define KEY_KBDINPUTASSIST_NEXTGROUP 0x263 ++#define KEY_KBDINPUTASSIST_ACCEPT 0x264 ++#define KEY_KBDINPUTASSIST_CANCEL 0x265 ++ ++/* Diagonal movement keys */ ++#define KEY_RIGHT_UP 0x266 ++#define KEY_RIGHT_DOWN 0x267 ++#define KEY_LEFT_UP 0x268 ++#define KEY_LEFT_DOWN 0x269 ++ ++#define KEY_ROOT_MENU 0x26a /* Show Device's Root Menu */ ++/* Show Top Menu of the Media (e.g. DVD) */ ++#define KEY_MEDIA_TOP_MENU 0x26b ++#define KEY_NUMERIC_11 0x26c ++#define KEY_NUMERIC_12 0x26d ++/* ++ * Toggle Audio Description: refers to an audio service that helps blind and ++ * visually impaired consumers understand the action in a program. Note: in ++ * some countries this is referred to as "Video Description". ++ */ ++#define KEY_AUDIO_DESC 0x26e ++#define KEY_3D_MODE 0x26f ++#define KEY_NEXT_FAVORITE 0x270 ++#define KEY_STOP_RECORD 0x271 ++#define KEY_PAUSE_RECORD 0x272 ++#define KEY_VOD 0x273 /* Video on Demand */ ++#define KEY_UNMUTE 0x274 ++#define KEY_FASTREVERSE 0x275 ++#define KEY_SLOWREVERSE 0x276 ++/* ++ * Control a data application associated with the currently viewed channel, ++ * e.g. teletext or data broadcast application (MHEG, MHP, HbbTV, etc.) ++ */ ++#define KEY_DATA 0x277 ++#define KEY_ONSCREEN_KEYBOARD 0x278 ++ ++#define BTN_TRIGGER_HAPPY 0x2c0 ++#define BTN_TRIGGER_HAPPY1 0x2c0 ++#define BTN_TRIGGER_HAPPY2 0x2c1 ++#define BTN_TRIGGER_HAPPY3 0x2c2 ++#define BTN_TRIGGER_HAPPY4 0x2c3 ++#define BTN_TRIGGER_HAPPY5 0x2c4 ++#define BTN_TRIGGER_HAPPY6 0x2c5 ++#define BTN_TRIGGER_HAPPY7 0x2c6 ++#define BTN_TRIGGER_HAPPY8 0x2c7 ++#define BTN_TRIGGER_HAPPY9 0x2c8 ++#define BTN_TRIGGER_HAPPY10 0x2c9 ++#define BTN_TRIGGER_HAPPY11 0x2ca ++#define BTN_TRIGGER_HAPPY12 0x2cb ++#define BTN_TRIGGER_HAPPY13 0x2cc ++#define BTN_TRIGGER_HAPPY14 0x2cd ++#define BTN_TRIGGER_HAPPY15 0x2ce ++#define BTN_TRIGGER_HAPPY16 0x2cf ++#define BTN_TRIGGER_HAPPY17 0x2d0 ++#define BTN_TRIGGER_HAPPY18 0x2d1 ++#define BTN_TRIGGER_HAPPY19 0x2d2 ++#define BTN_TRIGGER_HAPPY20 0x2d3 ++#define BTN_TRIGGER_HAPPY21 0x2d4 ++#define BTN_TRIGGER_HAPPY22 0x2d5 ++#define BTN_TRIGGER_HAPPY23 0x2d6 ++#define BTN_TRIGGER_HAPPY24 0x2d7 ++#define BTN_TRIGGER_HAPPY25 0x2d8 ++#define BTN_TRIGGER_HAPPY26 0x2d9 ++#define BTN_TRIGGER_HAPPY27 0x2da ++#define BTN_TRIGGER_HAPPY28 0x2db ++#define BTN_TRIGGER_HAPPY29 0x2dc ++#define BTN_TRIGGER_HAPPY30 0x2dd ++#define BTN_TRIGGER_HAPPY31 0x2de ++#define BTN_TRIGGER_HAPPY32 0x2df ++#define BTN_TRIGGER_HAPPY33 0x2e0 ++#define BTN_TRIGGER_HAPPY34 0x2e1 ++#define BTN_TRIGGER_HAPPY35 0x2e2 ++#define BTN_TRIGGER_HAPPY36 0x2e3 ++#define BTN_TRIGGER_HAPPY37 0x2e4 ++#define BTN_TRIGGER_HAPPY38 0x2e5 ++#define BTN_TRIGGER_HAPPY39 0x2e6 ++#define BTN_TRIGGER_HAPPY40 0x2e7 ++ ++/* We avoid low common keys in module aliases so they don't get huge. */ ++#define KEY_MIN_INTERESTING KEY_MUTE ++#define KEY_MAX 0x2ff ++#define KEY_CNT (KEY_MAX+1) ++ ++/* ++ * Relative axes ++ */ ++ ++#define REL_X 0x00 ++#define REL_Y 0x01 ++#define REL_Z 0x02 ++#define REL_RX 0x03 ++#define REL_RY 0x04 ++#define REL_RZ 0x05 ++#define REL_HWHEEL 0x06 ++#define REL_DIAL 0x07 ++#define REL_WHEEL 0x08 ++#define REL_MISC 0x09 ++#define REL_MAX 0x0f ++#define REL_CNT (REL_MAX+1) ++ ++/* ++ * Absolute axes ++ */ ++ ++#define ABS_X 0x00 ++#define ABS_Y 0x01 ++#define ABS_Z 0x02 ++#define ABS_RX 0x03 ++#define ABS_RY 0x04 ++#define ABS_RZ 0x05 ++#define ABS_THROTTLE 0x06 ++#define ABS_RUDDER 0x07 ++#define ABS_WHEEL 0x08 ++#define ABS_GAS 0x09 ++#define ABS_BRAKE 0x0a ++#define ABS_HAT0X 0x10 ++#define ABS_HAT0Y 0x11 ++#define ABS_HAT1X 0x12 ++#define ABS_HAT1Y 0x13 ++#define ABS_HAT2X 0x14 ++#define ABS_HAT2Y 0x15 ++#define ABS_HAT3X 0x16 ++#define ABS_HAT3Y 0x17 ++#define ABS_PRESSURE 0x18 ++#define ABS_DISTANCE 0x19 ++#define ABS_TILT_X 0x1a ++#define ABS_TILT_Y 0x1b ++#define ABS_TOOL_WIDTH 0x1c ++ ++#define ABS_VOLUME 0x20 ++ ++#define ABS_MISC 0x28 ++ ++#define ABS_MT_SLOT 0x2f /* MT slot being modified */ ++#define ABS_MT_TOUCH_MAJOR 0x30 /* Major axis of touching ellipse */ ++#define ABS_MT_TOUCH_MINOR 0x31 /* Minor axis (omit if circular) */ ++#define ABS_MT_WIDTH_MAJOR 0x32 /* Major axis of approaching ellipse */ ++#define ABS_MT_WIDTH_MINOR 0x33 /* Minor axis (omit if circular) */ ++#define ABS_MT_ORIENTATION 0x34 /* Ellipse orientation */ ++#define ABS_MT_POSITION_X 0x35 /* Center X touch position */ ++#define ABS_MT_POSITION_Y 0x36 /* Center Y touch position */ ++#define ABS_MT_TOOL_TYPE 0x37 /* Type of touching device */ ++#define ABS_MT_BLOB_ID 0x38 /* Group a set of packets as a blob */ ++#define ABS_MT_TRACKING_ID 0x39 /* Unique ID of initiated contact */ ++#define ABS_MT_PRESSURE 0x3a /* Pressure on contact area */ ++#define ABS_MT_DISTANCE 0x3b /* Contact hover distance */ ++#define ABS_MT_TOOL_X 0x3c /* Center X tool position */ ++#define ABS_MT_TOOL_Y 0x3d /* Center Y tool position */ ++ ++ ++#define ABS_MAX 0x3f ++#define ABS_CNT (ABS_MAX+1) ++ ++/* ++ * Switch events ++ */ ++ ++#define SW_LID 0x00 /* set = lid shut */ ++#define SW_TABLET_MODE 0x01 /* set = tablet mode */ ++#define SW_HEADPHONE_INSERT 0x02 /* set = inserted */ ++#define SW_RFKILL_ALL 0x03 /* rfkill master switch, type "any" ++ set = radio enabled */ ++#define SW_RADIO SW_RFKILL_ALL /* deprecated */ ++#define SW_MICROPHONE_INSERT 0x04 /* set = inserted */ ++#define SW_DOCK 0x05 /* set = plugged into dock */ ++#define SW_LINEOUT_INSERT 0x06 /* set = inserted */ ++#define SW_JACK_PHYSICAL_INSERT 0x07 /* set = mechanical switch set */ ++#define SW_VIDEOOUT_INSERT 0x08 /* set = inserted */ ++#define SW_CAMERA_LENS_COVER 0x09 /* set = lens covered */ ++#define SW_KEYPAD_SLIDE 0x0a /* set = keypad slide out */ ++#define SW_FRONT_PROXIMITY 0x0b /* set = front proximity sensor active */ ++#define SW_ROTATE_LOCK 0x0c /* set = rotate locked/disabled */ ++#define SW_LINEIN_INSERT 0x0d /* set = inserted */ ++#define SW_MUTE_DEVICE 0x0e /* set = device disabled */ ++#define SW_PEN_INSERTED 0x0f /* set = pen inserted */ ++#define SW_MAX 0x0f ++#define SW_CNT (SW_MAX+1) ++ ++/* ++ * Misc events ++ */ ++ ++#define MSC_SERIAL 0x00 ++#define MSC_PULSELED 0x01 ++#define MSC_GESTURE 0x02 ++#define MSC_RAW 0x03 ++#define MSC_SCAN 0x04 ++#define MSC_TIMESTAMP 0x05 ++#define MSC_MAX 0x07 ++#define MSC_CNT (MSC_MAX+1) ++ ++/* ++ * LEDs ++ */ ++ ++#define LED_NUML 0x00 ++#define LED_CAPSL 0x01 ++#define LED_SCROLLL 0x02 ++#define LED_COMPOSE 0x03 ++#define LED_KANA 0x04 ++#define LED_SLEEP 0x05 ++#define LED_SUSPEND 0x06 ++#define LED_MUTE 0x07 ++#define LED_MISC 0x08 ++#define LED_MAIL 0x09 ++#define LED_CHARGING 0x0a ++#define LED_MAX 0x0f ++#define LED_CNT (LED_MAX+1) ++ ++/* ++ * Autorepeat values ++ */ ++ ++#define REP_DELAY 0x00 ++#define REP_PERIOD 0x01 ++#define REP_MAX 0x01 ++#define REP_CNT (REP_MAX+1) ++ ++/* ++ * Sounds ++ */ ++ ++#define SND_CLICK 0x00 ++#define SND_BELL 0x01 ++#define SND_TONE 0x02 ++#define SND_MAX 0x07 ++#define SND_CNT (SND_MAX+1) ++ ++#endif +diff --git a/src/backends/native/meta-input-settings-native.c b/src/backends/native/meta-input-settings-native.c +index 8a62bb3..8a5ff5b 100644 +--- a/src/backends/native/meta-input-settings-native.c ++++ b/src/backends/native/meta-input-settings-native.c +@@ -24,7 +24,7 @@ + #include "config.h" + + #include +-#include ++#include + #include + + #include "meta-backend-native.h" +diff --git a/src/wayland/meta-wayland-tablet-tool.c b/src/wayland/meta-wayland-tablet-tool.c +index 4b57d41..5675f48 100644 +--- a/src/wayland/meta-wayland-tablet-tool.c ++++ b/src/wayland/meta-wayland-tablet-tool.c +@@ -41,7 +41,7 @@ + + #ifdef HAVE_NATIVE_BACKEND + #include "backends/native/meta-backend-native.h" +-#include ++#include + #endif + + #define TABLET_AXIS_MAX 65535 +-- +1.8.3.1 + diff --git a/SOURCES/0001-screen-Expose-workspace-layout-properties.patch b/SOURCES/0001-screen-Expose-workspace-layout-properties.patch new file mode 100644 index 0000000..bc7ed96 --- /dev/null +++ b/SOURCES/0001-screen-Expose-workspace-layout-properties.patch @@ -0,0 +1,80 @@ +From 6b8e2636911c79d77d95aaac62336dd4f4063f63 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Tue, 4 Jun 2019 21:21:37 +0200 +Subject: [PATCH] screen: Expose workspace layout properties + +gnome-shell hardcodes a vertical one-column workspace layout, and +while not supporting arbitrary grids is very much by design, it +currently doesn't have a choice: We simply don't expose the workspace +layout we use. + +Change that to allow gnome-shell to be a bit more flexible with the +workspace layouts it supports. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/618 +--- + src/core/screen.c | 27 +++++++++++++++++++++++++++ + 1 file changed, 27 insertions(+) + +diff --git a/src/core/screen.c b/src/core/screen.c +index c14bba0cf..4fac02cdb 100644 +--- a/src/core/screen.c ++++ b/src/core/screen.c +@@ -81,6 +81,9 @@ static void on_monitors_changed (MetaMonitorManager *manager, + enum + { + PROP_N_WORKSPACES = 1, ++ ++ PROP_LAYOUT_COLUMNS, ++ PROP_LAYOUT_ROWS, + }; + + enum +@@ -138,6 +141,12 @@ meta_screen_get_property (GObject *object, + + switch (prop_id) + { ++ case PROP_LAYOUT_COLUMNS: ++ g_value_set_int (value, screen->columns_of_workspaces); ++ break; ++ case PROP_LAYOUT_ROWS: ++ g_value_set_int (value, screen->rows_of_workspaces); ++ break; + case PROP_N_WORKSPACES: + g_value_set_int (value, meta_screen_get_n_workspaces (screen)); + break; +@@ -261,6 +270,22 @@ meta_screen_class_init (MetaScreenClass *klass) + NULL, NULL, NULL, + G_TYPE_NONE, 0); + ++ g_object_class_install_property (object_class, ++ PROP_LAYOUT_COLUMNS, ++ g_param_spec_int ("layout-columns", ++ "Layout columns", ++ "Number of columns in layout", ++ -1, G_MAXINT, 1, ++ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); ++ ++ g_object_class_install_property (object_class, ++ PROP_LAYOUT_ROWS, ++ g_param_spec_int ("layout-rows", ++ "Layout rows", ++ "Number of rows in layout", ++ -1, G_MAXINT, 1, ++ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); ++ + g_object_class_install_property (object_class, + PROP_N_WORKSPACES, + pspec); +@@ -1753,6 +1778,8 @@ meta_screen_update_workspace_layout (MetaScreen *screen) + screen->columns_of_workspaces, + screen->vertical_workspaces, + screen->starting_corner); ++ g_object_notify (G_OBJECT (screen), "layout-columns"); ++ g_object_notify (G_OBJECT (screen), "layout-rows"); + } + + /** +-- +2.21.0 + diff --git a/SOURCES/0001-wayland-enable-scale-monitor-framebuffer-by-default.patch b/SOURCES/0001-wayland-enable-scale-monitor-framebuffer-by-default.patch new file mode 100644 index 0000000..46c940b --- /dev/null +++ b/SOURCES/0001-wayland-enable-scale-monitor-framebuffer-by-default.patch @@ -0,0 +1,25 @@ +From 85968e1d0996b7f3a7453076c88ed6d5e0113369 Mon Sep 17 00:00:00 2001 +From: Olivier Fourdan +Date: Wed, 20 Sep 2017 12:17:23 +0200 +Subject: [PATCH] wayland: enable scale-monitor-framebuffer by default + +--- + data/org.gnome.mutter.gschema.xml.in | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/data/org.gnome.mutter.gschema.xml.in b/data/org.gnome.mutter.gschema.xml.in +index d926312c8..bec5585bd 100644 +--- a/data/org.gnome.mutter.gschema.xml.in ++++ b/data/org.gnome.mutter.gschema.xml.in +@@ -103,7 +103,7 @@ + + + +- [] ++ ['scale-monitor-framebuffer'] + Enable experimental features + + To enable experimental features, add the feature keyword to the list. +-- +2.13.5 + diff --git a/SOURCES/0001-window-actor-Special-case-shaped-Java-windows.patch b/SOURCES/0001-window-actor-Special-case-shaped-Java-windows.patch new file mode 100644 index 0000000..f20fc6c --- /dev/null +++ b/SOURCES/0001-window-actor-Special-case-shaped-Java-windows.patch @@ -0,0 +1,35 @@ +From 97f5f9bdc1c5cb1a2e02ec04750b5db9a4b4fdf1 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Fri, 12 May 2017 13:40:31 +0200 +Subject: [PATCH 8/8] window-actor: Special-case shaped Java windows + +OpenJDK wrongly assumes that shaping a window implies no shadows. +They got lucky until commit b975676c changed the fallback case, +but now their compliance tests are broken. Make them happy again +by special-casing shaped Java windows. +--- + src/compositor/meta-window-actor.c | 8 ++++++++ + 1 file changed, 8 insertions(+) + +diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c +index 773e6d09d..ac072997c 100644 +--- a/src/compositor/meta-window-actor.c ++++ b/src/compositor/meta-window-actor.c +@@ -843,6 +843,14 @@ meta_window_actor_has_shadow (MetaWindowActor *self) + if (priv->window->has_custom_frame_extents) + return FALSE; + ++ /* ++ * OpenJDK wrongly assumes that shaping a window implies no compositor ++ * shadows; make its compliance tests happy to give it what it wants ... ++ */ ++ if (g_strcmp0 (priv->window->res_name, "sun-awt-X11-XWindowPeer") == 0 && ++ priv->window->shape_region != NULL) ++ return FALSE; ++ + /* + * Generate shadows for all other windows. + */ +-- +2.14.2 + diff --git a/SOURCES/0001-x11-window-props-Do-not-convert-WM_NAME.patch b/SOURCES/0001-x11-window-props-Do-not-convert-WM_NAME.patch new file mode 100644 index 0000000..f7ce445 --- /dev/null +++ b/SOURCES/0001-x11-window-props-Do-not-convert-WM_NAME.patch @@ -0,0 +1,38 @@ +From ad1a395707f7c37b26ce446f0fd73ac7fbb9d0fd Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Tue, 9 Oct 2018 00:40:33 +0200 +Subject: [PATCH 1/2] x11/window-props: Do not convert WM_NAME + +The WM_NAME property is of type TEXT_PROPERTY, which is supposed to be +returned as UTF-8. Commit 840378ae68 broke that assumption, resulting +in crashes with non-UTF8 locales; however the "fix" of converting from +LATIN1 to UTF8 is wrong as well, as the conversion will spit out garbage +when the input encoding isn't actually LATIN1. + +Now that the original issue in text_property_to_utf8() has been fixed, +we can simply revert the relevant bits of commit d62491f46eba748e. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/227 +--- + src/x11/window-props.c | 5 +---- + 1 file changed, 1 insertion(+), 4 deletions(-) + +diff --git a/src/x11/window-props.c b/src/x11/window-props.c +index 2f4dfeb31..7c6b25fdb 100644 +--- a/src/x11/window-props.c ++++ b/src/x11/window-props.c +@@ -645,10 +645,7 @@ reload_wm_name (MetaWindow *window, + + if (value->type != META_PROP_VALUE_INVALID) + { +- g_autofree gchar *title = g_convert (value->v.str, -1, +- "UTF-8", "LATIN1", +- NULL, NULL, NULL); +- set_window_title (window, title); ++ set_window_title (window, value->v.str); + + meta_verbose ("Using WM_NAME for new title of %s: \"%s\"\n", + window->desc, window->title); +-- +2.21.0 + diff --git a/SOURCES/0002-clutter-Avoid-relayouts-when-raising-lowering-childr.patch b/SOURCES/0002-clutter-Avoid-relayouts-when-raising-lowering-childr.patch new file mode 100644 index 0000000..3bdd6e8 --- /dev/null +++ b/SOURCES/0002-clutter-Avoid-relayouts-when-raising-lowering-childr.patch @@ -0,0 +1,60 @@ +From dcf0717d7d90ff525c4f87cf633353caabf0eeeb Mon Sep 17 00:00:00 2001 +From: Carlos Garnacho +Date: Fri, 10 Aug 2018 21:30:58 +0200 +Subject: [PATCH 2/2] clutter: Avoid relayouts when raising/lowering children + +These calls don't actually affect the layout, but the paint order. +It seems safe to skip the full relayout/repaint of the parent actor, +and redraw only the area occupied by the affected child. +--- + clutter/clutter/clutter-actor.c | 20 ++++++++++++++++++-- + 1 file changed, 18 insertions(+), 2 deletions(-) + +diff --git a/clutter/clutter/clutter-actor.c b/clutter/clutter/clutter-actor.c +index 6954f0396..7a9da7257 100644 +--- a/clutter/clutter/clutter-actor.c ++++ b/clutter/clutter/clutter-actor.c +@@ -1713,6 +1713,22 @@ set_show_on_set_parent (ClutterActor *self, + } + } + ++static void ++clutter_actor_queue_redraw_on_parent (ClutterActor *self) ++{ ++ const ClutterPaintVolume *pv; ++ ++ if (!self->priv->parent) ++ return; ++ ++ /* A relayout/redraw is underway */ ++ if (self->priv->needs_allocation) ++ return; ++ ++ pv = clutter_actor_get_transformed_paint_volume (self, self->priv->parent); ++ _clutter_actor_queue_redraw_with_clip (self->priv->parent, 0, pv); ++} ++ + /** + * clutter_actor_show: + * @self: A #ClutterActor +@@ -13618,7 +13634,7 @@ clutter_actor_set_child_above_sibling (ClutterActor *self, + sibling); + g_object_unref(child); + +- clutter_actor_queue_relayout (self); ++ clutter_actor_queue_redraw_on_parent (child); + } + + /** +@@ -13665,7 +13681,7 @@ clutter_actor_set_child_below_sibling (ClutterActor *self, + sibling); + g_object_unref(child); + +- clutter_actor_queue_relayout (self); ++ clutter_actor_queue_redraw_on_parent (child); + } + + /** +-- +2.21.0 + diff --git a/SOURCES/0002-idle-monitor-Postpone-dispatching-of-idle-timeout-if.patch b/SOURCES/0002-idle-monitor-Postpone-dispatching-of-idle-timeout-if.patch new file mode 100644 index 0000000..54879c6 --- /dev/null +++ b/SOURCES/0002-idle-monitor-Postpone-dispatching-of-idle-timeout-if.patch @@ -0,0 +1,41 @@ +From 22879378393c21a1a1e5307dc457233bd40ef877 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Tue, 16 Apr 2019 18:07:31 +0200 +Subject: [PATCH 2/2] idle-monitor: Postpone dispatching of idle timeout if not + ready + +If we update the ready time while the source is already in the +to-dispatch list, changing the ready time doesn't have any effect, and +the source will still be dispatched. This could cause incorrect idle +watch firing causing the power management plugin in +gnome-settings-daemon to sometimes turn off monitors due to it believing +the user had been idle for some time, while in fact, they just logged +back in. + +Fix this by not actually dispatching the idle timeout if the ready time +is in the future when actually dispatching. +--- + src/backends/meta-idle-monitor.c | 7 +++++++ + 1 file changed, 7 insertions(+) + +diff --git a/src/backends/meta-idle-monitor.c b/src/backends/meta-idle-monitor.c +index 2b634f59a..2c06ee73c 100644 +--- a/src/backends/meta-idle-monitor.c ++++ b/src/backends/meta-idle-monitor.c +@@ -311,6 +311,13 @@ idle_monitor_dispatch_timeout (GSource *source, + gpointer user_data) + { + MetaIdleMonitorWatch *watch = (MetaIdleMonitorWatch *) user_data; ++ int64_t now; ++ int64_t ready_time; ++ ++ now = g_source_get_time (source); ++ ready_time = g_source_get_ready_time (source); ++ if (ready_time > now) ++ return G_SOURCE_CONTINUE; + + _meta_idle_monitor_watch_fire (watch); + g_source_set_ready_time (watch->timeout_source, -1); +-- +2.20.1 + diff --git a/SOURCES/0002-monitor-manager-xrandr-Create-dummy-screen-sized-mon.patch b/SOURCES/0002-monitor-manager-xrandr-Create-dummy-screen-sized-mon.patch new file mode 100644 index 0000000..a676cf6 --- /dev/null +++ b/SOURCES/0002-monitor-manager-xrandr-Create-dummy-screen-sized-mon.patch @@ -0,0 +1,171 @@ +From 8950fc632bcf4c3eca2be1c347acaa16b4b8d0c5 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Wed, 3 Oct 2018 10:50:47 +0200 +Subject: [PATCH 2/2] monitor-manager/xrandr: Create dummy screen sized monitor + if no RANDR + +When there is no RANDR support enabled in the X server, we wont get +notified of any monitors, resulting in mutter believing we're being +headless. To get at least something working, although with no way +configuration ability, lets pretend the whole screen is just a single +monitor with a single output, crtc and mode. +--- + src/backends/x11/meta-gpu-xrandr.c | 60 +++++++++++++++++++ + .../x11/meta-monitor-manager-xrandr.c | 20 +++++++ + .../x11/meta-monitor-manager-xrandr.h | 2 + + 3 files changed, 82 insertions(+) + +diff --git a/src/backends/x11/meta-gpu-xrandr.c b/src/backends/x11/meta-gpu-xrandr.c +index a4e187a49a..9397c1f64d 100644 +--- a/src/backends/x11/meta-gpu-xrandr.c ++++ b/src/backends/x11/meta-gpu-xrandr.c +@@ -147,6 +147,63 @@ update_screen_size (MetaMonitorManagerXrandr *monitor_manager_xrandr) + monitor_manager->screen_height = HeightOfScreen (screen); + } + ++static gboolean ++read_current_fallback (MetaGpuXrandr *gpu_xrandr, ++ MetaMonitorManagerXrandr *monitor_manager_xrandr) ++{ ++ MetaGpu *gpu = META_GPU (gpu_xrandr); ++ MetaMonitorManager *monitor_manager = ++ META_MONITOR_MANAGER (monitor_manager_xrandr); ++ MetaCrtcMode *mode; ++ MetaCrtc *crtc; ++ MetaOutput *output; ++ ++ update_dpms_state (monitor_manager_xrandr); ++ update_screen_size (monitor_manager_xrandr); ++ ++ mode = g_object_new (META_TYPE_CRTC_MODE, NULL); ++ mode->mode_id = 0; ++ mode->width = monitor_manager->screen_width; ++ mode->height = monitor_manager->screen_height; ++ mode->refresh_rate = 60.0; ++ mode->name = g_strdup_printf ("%dx%d", mode->width, mode->height); ++ ++ meta_gpu_take_modes (gpu, g_list_prepend (NULL, mode)); ++ ++ crtc = g_object_new (META_TYPE_CRTC, NULL); ++ crtc->gpu = gpu; ++ crtc->crtc_id = 0; ++ crtc->rect = (MetaRectangle) { .width = mode->width, .height = mode->height }; ++ crtc->current_mode = mode; ++ ++ meta_gpu_take_crtcs (gpu, g_list_prepend (NULL, crtc)); ++ ++ output = g_object_new (META_TYPE_OUTPUT, NULL); ++ output->gpu = gpu; ++ output->winsys_id = 0; ++ output->name = g_strdup ("X11 Screen"); ++ output->vendor = g_strdup ("unknown"); ++ output->product = g_strdup ("unknown"); ++ output->serial = g_strdup ("unknown"); ++ output->hotplug_mode_update = TRUE; ++ output->suggested_x = -1; ++ output->suggested_y = -1; ++ output->connector_type = META_CONNECTOR_TYPE_Unknown; ++ output->modes = g_new0 (MetaCrtcMode *, 1); ++ output->modes[0] = mode; ++ output->n_modes = 1; ++ output->preferred_mode = mode; ++ output->possible_crtcs = g_new0 (MetaCrtc *, 1); ++ output->possible_crtcs[0] = crtc; ++ output->n_possible_crtcs = 1; ++ meta_output_assign_crtc (output, crtc); ++ output->is_primary = TRUE; ++ ++ meta_gpu_take_outputs (gpu, g_list_prepend (NULL, output)); ++ ++ return TRUE; ++} ++ + static gboolean + meta_gpu_xrandr_read_current (MetaGpu *gpu, + GError **error) +@@ -166,6 +223,9 @@ meta_gpu_xrandr_read_current (MetaGpu *gpu, + GList *modes = NULL; + GList *crtcs = NULL; + ++ if (!meta_monitor_manager_xrandr_has_randr (monitor_manager_xrandr)) ++ return read_current_fallback (gpu_xrandr, monitor_manager_xrandr); ++ + if (gpu_xrandr->resources) + XRRFreeScreenResources (gpu_xrandr->resources); + gpu_xrandr->resources = NULL; +diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c +index d0da2c539e..26b057a559 100644 +--- a/src/backends/x11/meta-monitor-manager-xrandr.c ++++ b/src/backends/x11/meta-monitor-manager-xrandr.c +@@ -64,6 +64,7 @@ struct _MetaMonitorManagerXrandr + guint logind_watch_id; + guint logind_signal_sub_id; + ++ gboolean has_randr; + gboolean has_randr15; + + /* +@@ -107,6 +108,12 @@ meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *manager_xran + return manager_xrandr->xdisplay; + } + ++gboolean ++meta_monitor_manager_xrandr_has_randr (MetaMonitorManagerXrandr *manager_xrandr) ++{ ++ return manager_xrandr->has_randr; ++} ++ + gboolean + meta_monitor_manager_xrandr_has_randr15 (MetaMonitorManagerXrandr *manager_xrandr) + { +@@ -577,9 +584,18 @@ meta_monitor_manager_xrandr_apply_monitors_config (MetaMonitorManager *mana + MetaMonitorsConfigMethod method, + GError **error) + { ++ MetaMonitorManagerXrandr *manager_xrandr = ++ META_MONITOR_MANAGER_XRANDR (manager); + GPtrArray *crtc_infos; + GPtrArray *output_infos; + ++ if (!manager_xrandr->has_randr) ++ { ++ g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, ++ "Tried to change configuration without XRANDR support"); ++ return FALSE; ++ } ++ + if (!config) + { + meta_monitor_manager_xrandr_rebuild_derived (manager, NULL); +@@ -1046,11 +1062,15 @@ meta_monitor_manager_xrandr_constructed (GObject *object) + &manager_xrandr->rr_event_base, + &manager_xrandr->rr_error_base)) + { ++ g_warning ("No RANDR support, monitor configuration disabled"); + return; + } + else + { + int major_version, minor_version; ++ ++ manager_xrandr->has_randr = TRUE; ++ + /* We only use ScreenChangeNotify, but GDK uses the others, + and we don't want to step on its toes */ + XRRSelectInput (manager_xrandr->xdisplay, +diff --git a/src/backends/x11/meta-monitor-manager-xrandr.h b/src/backends/x11/meta-monitor-manager-xrandr.h +index f09cbfd83a..343c8131ee 100644 +--- a/src/backends/x11/meta-monitor-manager-xrandr.h ++++ b/src/backends/x11/meta-monitor-manager-xrandr.h +@@ -33,6 +33,8 @@ G_DECLARE_FINAL_TYPE (MetaMonitorManagerXrandr, meta_monitor_manager_xrandr, + + Display * meta_monitor_manager_xrandr_get_xdisplay (MetaMonitorManagerXrandr *manager_xrandr); + ++gboolean meta_monitor_manager_xrandr_has_randr (MetaMonitorManagerXrandr *manager_xrandr); ++ + gboolean meta_monitor_manager_xrandr_has_randr15 (MetaMonitorManagerXrandr *manager_xrandr); + + gboolean meta_monitor_manager_xrandr_handle_xevent (MetaMonitorManagerXrandr *manager, +-- +2.17.1 + diff --git a/SOURCES/0002-window-Return-1-if-meta_window_get_monitor-is-called.patch b/SOURCES/0002-window-Return-1-if-meta_window_get_monitor-is-called.patch new file mode 100644 index 0000000..76191d9 --- /dev/null +++ b/SOURCES/0002-window-Return-1-if-meta_window_get_monitor-is-called.patch @@ -0,0 +1,38 @@ +From 760e22fd301df35a4bca9e0453a3877f1840a819 Mon Sep 17 00:00:00 2001 +From: Sam Spilsbury +Date: Wed, 11 Oct 2017 00:39:40 +0800 +Subject: [PATCH 2/2] window: Return -1 if meta_window_get_monitor is called on + an unmanaged window + +As opposed to crashing. In this case, letting the caller deal with +it is the best policy, since this is public API. + +https://bugzilla.gnome.org/show_bug.cgi?id=788834 +--- + src/core/window.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/core/window.c b/src/core/window.c +index cc0813ac4..79f0d6bc0 100644 +--- a/src/core/window.c ++++ b/src/core/window.c +@@ -3752,11 +3752,15 @@ maybe_move_attached_dialog (MetaWindow *window, + * + * Gets index of the monitor that this window is on. + * +- * Return Value: The index of the monitor in the screens monitor list ++ * Return Value: The index of the monitor in the screens monitor list, or -1 ++ * if the window has been recently unmanaged and does not have a monitor. + */ + int + meta_window_get_monitor (MetaWindow *window) + { ++ if (!window->monitor) ++ return -1; ++ + return window->monitor->number; + } + +-- +2.21.0 + diff --git a/SOURCES/0002-xprops-Make-sure-text_property_to_utf8-returns-UTF8.patch b/SOURCES/0002-xprops-Make-sure-text_property_to_utf8-returns-UTF8.patch new file mode 100644 index 0000000..6178049 --- /dev/null +++ b/SOURCES/0002-xprops-Make-sure-text_property_to_utf8-returns-UTF8.patch @@ -0,0 +1,44 @@ +From 5881b87be4432ca1c50ee0652634883110b487de Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Tue, 9 Oct 2018 00:29:01 +0200 +Subject: [PATCH 2/2] xprops: Make sure text_property_to_utf8() returns UTF8 + +Commit 840378ae682 changed the code to use XmbTextPropertyToTextList() +instead of gdk_text_property_to_utf8_list_for_display(), but didn't +take into account that the replacement returns text in the current +locale's encoding, while any callers (rightfully) expect UTF8. + +Fix this by converting the text if necessary. + +https://gitlab.gnome.org/GNOME/mutter/merge_requests/227 +--- + src/x11/xprops.c | 6 +++++- + 1 file changed, 5 insertions(+), 1 deletion(-) + +diff --git a/src/x11/xprops.c b/src/x11/xprops.c +index cffa5958a..ca686b2fa 100644 +--- a/src/x11/xprops.c ++++ b/src/x11/xprops.c +@@ -637,6 +637,7 @@ text_property_to_utf8 (Display *xdisplay, + { + char *ret = NULL; + char **local_list = NULL; ++ const char *charset = NULL; + int count = 0; + int res; + +@@ -647,7 +648,10 @@ text_property_to_utf8 (Display *xdisplay, + if (count == 0) + goto out; + +- ret = g_strdup (local_list[0]); ++ if (g_get_charset (&charset)) ++ ret = g_strdup (local_list[0]); ++ else ++ ret = g_convert (local_list[0], -1, "UTF-8", charset, NULL, NULL, NULL); + + out: + XFreeStringList (local_list); +-- +2.21.0 + diff --git a/SOURCES/0008-Add-support-for-quad-buffer-stereo.patch b/SOURCES/0008-Add-support-for-quad-buffer-stereo.patch new file mode 100644 index 0000000..e5b861e --- /dev/null +++ b/SOURCES/0008-Add-support-for-quad-buffer-stereo.patch @@ -0,0 +1,1008 @@ +From 77b95bdac1b3cca4d06480e1d7fe1b6c86a32d2f Mon Sep 17 00:00:00 2001 +From: "Owen W. Taylor" +Date: Thu, 8 May 2014 18:44:15 -0400 +Subject: [PATCH] Add support for quad-buffer stereo + +Track the stereo status of windows using the new EXT_stereo_tree +GLX extension. + +When stereo is enabled or disabled, a restart is triggered via +meta_restart() after a timeout, setting a _META_ENABLE_STEREO +property on the root window to indicate whether we should +turn on a stereo stage for clutter. The property avoids a loop, +since we need to enable stereo *before* initializing Clutter and GL, +but we need GL to figure out whether we have stereo windows. + +Stereo windows are drawn to the stage using new functionality +in Cogl to setup a stereo context, select which buffer to draw +to, and draw either the left or right buffer of a stereo +texture_from_pixmap. +--- + src/Makefile.am | 2 + + src/compositor/compositor-private.h | 9 ++ + src/compositor/compositor.c | 128 ++++++++++++++++++++++ + src/compositor/meta-shaped-texture-private.h | 5 +- + src/compositor/meta-shaped-texture.c | 157 ++++++++++++++++++++------- + src/compositor/meta-surface-actor-wayland.c | 10 +- + src/compositor/meta-surface-actor-x11.c | 56 ++++++++-- + src/compositor/meta-surface-actor-x11.h | 5 + + src/compositor/meta-window-actor-private.h | 5 + + src/compositor/meta-window-actor.c | 22 ++++ + src/core/main.c | 4 + + src/core/stereo.c | 153 ++++++++++++++++++++++++++ + src/core/stereo.h | 28 +++++ + src/wayland/meta-wayland-surface.c | 2 +- + 14 files changed, 535 insertions(+), 51 deletions(-) + create mode 100644 src/core/stereo.c + create mode 100644 src/core/stereo.h + +diff --git a/src/Makefile.am b/src/Makefile.am +index 5bbac70..8b21d2f 100644 +--- a/src/Makefile.am ++++ b/src/Makefile.am +@@ -308,6 +308,8 @@ libmutter_@LIBMUTTER_API_VERSION@_la_SOURCES = \ + core/stack.h \ + core/stack-tracker.c \ + core/stack-tracker.h \ ++ core/stereo.c \ ++ core/stereo.h \ + core/util.c \ + meta/util.h \ + core/util-private.h \ +diff --git a/src/compositor/compositor-private.h b/src/compositor/compositor-private.h +index 40c0344..25cab92 100644 +--- a/src/compositor/compositor-private.h ++++ b/src/compositor/compositor-private.h +@@ -21,6 +21,10 @@ struct _MetaCompositor + gint64 server_time_query_time; + gint64 server_time_offset; + ++ int glx_opcode; ++ guint stereo_tree_ext : 1; ++ guint have_stereo_windows : 1; ++ + guint server_time_is_monotonic_time : 1; + guint no_mipmaps : 1; + +@@ -61,6 +65,11 @@ void meta_end_modal_for_plugin (MetaCompositor *compositor, + gint64 meta_compositor_monotonic_time_to_server_time (MetaDisplay *display, + gint64 monotonic_time); + ++gboolean meta_compositor_window_is_stereo (MetaScreen *screen, ++ Window xwindow); ++void meta_compositor_select_stereo_notify (MetaScreen *screen, ++ Window xwindow); ++ + void meta_compositor_flash_window (MetaCompositor *compositor, + MetaWindow *window); + +diff --git a/src/compositor/compositor.c b/src/compositor/compositor.c +index 8c924d2..e12fb7b 100644 +--- a/src/compositor/compositor.c ++++ b/src/compositor/compositor.c +@@ -70,6 +70,8 @@ + #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" ++#include "stereo.h" + #include "util-private.h" + #include "backends/meta-dnd-private.h" + #include "frame.h" +@@ -487,6 +489,97 @@ redirect_windows (MetaScreen *screen) + } + } + ++#define GLX_STEREO_TREE_EXT 0x20F5 ++#define GLX_STEREO_NOTIFY_MASK_EXT 0x00000001 ++#define GLX_STEREO_NOTIFY_EXT 0x00000000 ++ ++typedef struct { ++ int type; ++ unsigned long serial; ++ Bool send_event; ++ Display *display; ++ int extension; ++ int evtype; ++ Drawable window; ++ Bool stereo_tree; ++} StereoNotifyEvent; ++ ++static gboolean ++screen_has_stereo_tree_ext (MetaScreen *screen) ++{ ++ MetaDisplay *display = meta_screen_get_display (screen); ++ Display *xdisplay = meta_display_get_xdisplay (display); ++ const char *extensions_string; ++ ++ static const char * (*query_extensions_string) (Display *display, ++ int screen); ++ ++ if (query_extensions_string == NULL) ++ query_extensions_string = ++ (const char * (*) (Display *, int)) ++ cogl_get_proc_address ("glXQueryExtensionsString"); ++ ++ extensions_string = query_extensions_string (xdisplay, ++ meta_screen_get_screen_number (screen)); ++ ++ return extensions_string && strstr (extensions_string, "EXT_stereo_tree") != 0; ++} ++ ++#include ++ ++gboolean ++meta_compositor_window_is_stereo (MetaScreen *screen, ++ Window xwindow) ++{ ++ MetaCompositor *compositor = get_compositor_for_screen (screen); ++ MetaDisplay *display = meta_screen_get_display (screen); ++ Display *xdisplay = meta_display_get_xdisplay (display); ++ ++ static int (*query_drawable) (Display *dpy, ++ Drawable draw, ++ int attribute, ++ unsigned int *value); ++ ++ if (compositor->stereo_tree_ext) ++ { ++ unsigned int stereo_tree = 0; ++ ++ if (query_drawable == NULL) ++ query_drawable = ++ (int (*) (Display *, Drawable, int, unsigned int *)) ++ cogl_get_proc_address ("glXQueryDrawable"); ++ ++ query_drawable (xdisplay, xwindow, GLX_STEREO_TREE_EXT, &stereo_tree); ++ ++ return stereo_tree != 0; ++ } ++ else ++ return FALSE; ++} ++ ++void ++meta_compositor_select_stereo_notify (MetaScreen *screen, ++ Window xwindow) ++{ ++ MetaCompositor *compositor = get_compositor_for_screen (screen); ++ MetaDisplay *display = meta_screen_get_display (screen); ++ Display *xdisplay = meta_display_get_xdisplay (display); ++ ++ static void (*select_event) (Display *dpy, ++ Drawable draw, ++ unsigned long event_mask); ++ ++ if (compositor->stereo_tree_ext) ++ { ++ if (select_event == NULL) ++ select_event = ++ (void (*) (Display *, Drawable, unsigned long)) ++ cogl_get_proc_address ("glXSelectEvent"); ++ ++ select_event (xdisplay, xwindow, GLX_STEREO_NOTIFY_MASK_EXT); ++ } ++} ++ + void + meta_compositor_manage (MetaCompositor *compositor) + { +@@ -495,6 +588,8 @@ meta_compositor_manage (MetaCompositor *compositor) + MetaScreen *screen = display->screen; + MetaBackend *backend = meta_get_backend (); + ++ compositor->stereo_tree_ext = screen_has_stereo_tree_ext (screen); ++ + meta_screen_set_cm_selection (display->screen); + + compositor->stage = meta_backend_get_stage (backend); +@@ -759,6 +854,23 @@ meta_compositor_process_event (MetaCompositor *compositor, + if (window) + process_damage (compositor, (XDamageNotifyEvent *) event, window); + } ++ else if (!meta_is_wayland_compositor () && ++ event->type == GenericEvent && ++ event->xcookie.extension == compositor->glx_opcode) ++ { ++ if (event->xcookie.evtype == GLX_STEREO_NOTIFY_EXT) ++ { ++ StereoNotifyEvent *stereo_event = (StereoNotifyEvent *)(event->xcookie.data); ++ window = meta_display_lookup_x_window (compositor->display, stereo_event->window); ++ ++ if (window != NULL) ++ { ++ MetaWindowActor *window_actor = META_WINDOW_ACTOR (meta_window_get_compositor_private (window)); ++ meta_window_actor_stereo_notify (window_actor, stereo_event->stereo_tree); ++ meta_stack_tracker_queue_sync_stack (window->screen->stack_tracker); ++ } ++ } ++ } + + if (compositor->have_x11_sync_object) + meta_sync_ring_handle_event (event); +@@ -969,6 +1081,7 @@ meta_compositor_sync_stack (MetaCompositor *compositor, + GList *stack) + { + GList *old_stack; ++ int stereo_window_count = 0; + + /* This is painful because hidden windows that we are in the process + * of animating out of existence. They'll be at the bottom of the +@@ -1044,6 +1157,8 @@ meta_compositor_sync_stack (MetaCompositor *compositor, + * near the front of the other.) + */ + compositor->windows = g_list_prepend (compositor->windows, actor); ++ if (meta_window_actor_is_stereo (actor)) ++ stereo_window_count++; + + stack = g_list_remove (stack, window); + old_stack = g_list_remove (old_stack, actor); +@@ -1051,6 +1166,8 @@ meta_compositor_sync_stack (MetaCompositor *compositor, + + sync_actor_stacking (compositor); + ++ meta_stereo_set_have_stereo_windows (stereo_window_count > 0); ++ + if (compositor->top_window_actor) + g_signal_handlers_disconnect_by_func (compositor->top_window_actor, + on_top_window_actor_destroyed, +@@ -1259,6 +1376,17 @@ meta_compositor_new (MetaDisplay *display) + meta_post_paint_func, + compositor, + NULL); ++ if (!meta_is_wayland_compositor ()) ++ { ++ Display *xdisplay = meta_display_get_xdisplay (display); ++ int glx_major_opcode, glx_first_event, glx_first_error; ++ ++ if (XQueryExtension (xdisplay, ++ "GLX", ++ &glx_major_opcode, &glx_first_event, &glx_first_error)) ++ compositor->glx_opcode = glx_major_opcode; ++ } ++ + return compositor; + } + +diff --git a/src/compositor/meta-shaped-texture-private.h b/src/compositor/meta-shaped-texture-private.h +index 5b3f283..189a953 100644 +--- a/src/compositor/meta-shaped-texture-private.h ++++ b/src/compositor/meta-shaped-texture-private.h +@@ -30,8 +30,9 @@ + #include + + ClutterActor *meta_shaped_texture_new (void); +-void meta_shaped_texture_set_texture (MetaShapedTexture *stex, +- CoglTexture *texture); ++void meta_shaped_texture_set_textures (MetaShapedTexture *stex, ++ CoglTexture *texture, ++ CoglTexture *texture_right); + void meta_shaped_texture_set_is_y_inverted (MetaShapedTexture *stex, + gboolean is_y_inverted); + void meta_shaped_texture_set_snippet (MetaShapedTexture *stex, +diff --git a/src/compositor/meta-shaped-texture.c b/src/compositor/meta-shaped-texture.c +index 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]; + struct _MetaShapedTexturePrivate + { + MetaTextureTower *paint_tower; ++ MetaTextureTower *paint_tower_right; + + CoglTexture *texture; ++ CoglTexture *texture_right; + CoglTexture *mask_texture; + CoglSnippet *snippet; + +@@ -129,8 +131,10 @@ meta_shaped_texture_init (MetaShapedTexture *self) + priv = self->priv = META_SHAPED_TEXTURE_GET_PRIVATE (self); + + priv->paint_tower = meta_texture_tower_new (); ++ priv->paint_tower_right = NULL; /* demand create */ + + priv->texture = NULL; ++ priv->texture_right = NULL; + priv->mask_texture = NULL; + priv->create_mipmaps = TRUE; + priv->is_y_inverted = TRUE; +@@ -191,11 +195,11 @@ meta_shaped_texture_dispose (GObject *object) + MetaShapedTexture *self = (MetaShapedTexture *) object; + MetaShapedTexturePrivate *priv = self->priv; + +- if (priv->paint_tower) +- meta_texture_tower_free (priv->paint_tower); +- priv->paint_tower = NULL; ++ g_clear_pointer (&priv->paint_tower, meta_texture_tower_free); ++ g_clear_pointer (&priv->paint_tower_right, meta_texture_tower_free); + + g_clear_pointer (&priv->texture, cogl_object_unref); ++ g_clear_pointer (&priv->texture_right, cogl_object_unref); + g_clear_pointer (&priv->opaque_region, cairo_region_destroy); + + meta_shaped_texture_set_mask_texture (self, NULL); +@@ -326,8 +330,9 @@ paint_clipped_rectangle (CoglFramebuffer *fb, + } + + static void +-set_cogl_texture (MetaShapedTexture *stex, +- CoglTexture *cogl_tex) ++set_cogl_textures (MetaShapedTexture *stex, ++ CoglTexture *cogl_tex, ++ CoglTexture *cogl_tex_right) + { + MetaShapedTexturePrivate *priv; + guint width, height; +@@ -338,8 +343,11 @@ set_cogl_texture (MetaShapedTexture *stex, + + if (priv->texture) + cogl_object_unref (priv->texture); ++ if (priv->texture_right) ++ cogl_object_unref (priv->texture_right); + + priv->texture = cogl_tex; ++ priv->texture_right = cogl_tex_right; + + if (cogl_tex != NULL) + { +@@ -353,6 +361,9 @@ set_cogl_texture (MetaShapedTexture *stex, + height = 0; + } + ++ if (cogl_tex_right != NULL) ++ cogl_object_ref (cogl_tex_right); ++ + if (priv->tex_width != width || + priv->tex_height != height) + { +@@ -368,52 +379,41 @@ set_cogl_texture (MetaShapedTexture *stex, + * previous buffer. We only queue a redraw in response to surface + * damage. */ + ++ if (cogl_tex_right != NULL) ++ { ++ if (priv->paint_tower_right == NULL) ++ priv->paint_tower_right = meta_texture_tower_new (); ++ } ++ else ++ { ++ g_clear_pointer (&priv->paint_tower_right, meta_texture_tower_free); ++ } ++ + if (priv->create_mipmaps) +- meta_texture_tower_set_base_texture (priv->paint_tower, cogl_tex); ++ { ++ meta_texture_tower_set_base_texture (priv->paint_tower, cogl_tex); ++ ++ if (priv->paint_tower_right) ++ meta_texture_tower_set_base_texture (priv->paint_tower_right, cogl_tex_right); ++ } + } + + static void +-meta_shaped_texture_paint (ClutterActor *actor) ++paint_texture (MetaShapedTexture *stex, ++ CoglTexture *paint_tex) + { +- MetaShapedTexture *stex = (MetaShapedTexture *) actor; ++ ClutterActor *actor = CLUTTER_ACTOR (stex); + MetaShapedTexturePrivate *priv = stex->priv; + guint tex_width, tex_height; + guchar opacity; + CoglContext *ctx; + CoglFramebuffer *fb; +- CoglTexture *paint_tex; + ClutterActorBox alloc; + CoglPipelineFilter filter; + + if (priv->clip_region && cairo_region_is_empty (priv->clip_region)) + return; + +- if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex))) +- clutter_actor_realize (CLUTTER_ACTOR (stex)); +- +- /* The GL EXT_texture_from_pixmap extension does allow for it to be +- * used together with SGIS_generate_mipmap, however this is very +- * rarely supported. Also, even when it is supported there +- * are distinct performance implications from: +- * +- * - Updating mipmaps that we don't need +- * - Having to reallocate pixmaps on the server into larger buffers +- * +- * So, we just unconditionally use our mipmap emulation code. If we +- * wanted to use SGIS_generate_mipmap, we'd have to query COGL to +- * see if it was supported (no API currently), and then if and only +- * if that was the case, set the clutter texture quality to HIGH. +- * Setting the texture quality to high without SGIS_generate_mipmap +- * support for TFP textures will result in fallbacks to XGetImage. +- */ +- if (priv->create_mipmaps) +- paint_tex = meta_texture_tower_get_paint_texture (priv->paint_tower); +- else +- paint_tex = COGL_TEXTURE (priv->texture); +- +- if (paint_tex == NULL) +- return; +- + tex_width = priv->tex_width; + tex_height = priv->tex_height; + +@@ -574,6 +574,76 @@ meta_shaped_texture_paint (ClutterActor *actor) + } + + static void ++meta_shaped_texture_paint (ClutterActor *actor) ++{ ++ MetaShapedTexture *stex = (MetaShapedTexture *) actor; ++ MetaShapedTexturePrivate *priv = stex->priv; ++ CoglFramebuffer *fb; ++ gboolean stereo; ++ CoglTexture *paint_tex; ++ CoglTexture *paint_tex_right; ++ ++ if (priv->clip_region && cairo_region_is_empty (priv->clip_region)) ++ return; ++ ++ if (!CLUTTER_ACTOR_IS_REALIZED (CLUTTER_ACTOR (stex))) ++ clutter_actor_realize (CLUTTER_ACTOR (stex)); ++ ++ /* The GL EXT_texture_from_pixmap extension does allow for it to be ++ * used together with SGIS_generate_mipmap, however this is very ++ * rarely supported. Also, even when it is supported there ++ * are distinct performance implications from: ++ * ++ * - Updating mipmaps that we don't need ++ * - Having to reallocate pixmaps on the server into larger buffers ++ * ++ * So, we just unconditionally use our mipmap emulation code. If we ++ * wanted to use SGIS_generate_mipmap, we'd have to query COGL to ++ * see if it was supported (no API currently), and then if and only ++ * if that was the case, set the clutter texture quality to HIGH. ++ * Setting the texture quality to high without SGIS_generate_mipmap ++ * support for TFP textures will result in fallbacks to XGetImage. ++ */ ++ if (priv->create_mipmaps) ++ paint_tex = meta_texture_tower_get_paint_texture (priv->paint_tower); ++ else ++ paint_tex = COGL_TEXTURE (priv->texture); ++ ++ if (paint_tex == NULL) ++ return; ++ ++ fb = cogl_get_draw_framebuffer (); ++ ++ stereo = priv->texture_right && cogl_framebuffer_get_is_stereo (fb); ++ ++ if (stereo) ++ { ++ if (priv->create_mipmaps) ++ paint_tex_right = meta_texture_tower_get_paint_texture (priv->paint_tower_right); ++ else ++ paint_tex_right = COGL_TEXTURE (priv->texture_right); ++ } ++ else ++ paint_tex_right = NULL; ++ ++ if (paint_tex != NULL) ++ { ++ if (stereo) ++ cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_LEFT); ++ paint_texture (stex, paint_tex); ++ if (stereo) ++ cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_BOTH); ++ } ++ ++ if (paint_tex_right != NULL) ++ { ++ cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_RIGHT); ++ paint_texture (stex, paint_tex_right); ++ cogl_framebuffer_set_stereo_mode (fb, COGL_STEREO_BOTH); ++ } ++} ++ ++static void + meta_shaped_texture_get_preferred_width (ClutterActor *self, + gfloat for_height, + gfloat *min_width_p, +@@ -692,6 +762,12 @@ meta_shaped_texture_set_create_mipmaps (MetaShapedTexture *stex, + priv->create_mipmaps = create_mipmaps; + base_texture = create_mipmaps ? priv->texture : NULL; + meta_texture_tower_set_base_texture (priv->paint_tower, base_texture); ++ ++ if (priv->paint_tower_right) ++ { ++ base_texture = create_mipmaps ? priv->texture_right : NULL; ++ meta_texture_tower_set_base_texture (priv->paint_tower_right, base_texture); ++ } + } + } + +@@ -757,6 +833,8 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, + return FALSE; + + meta_texture_tower_update_area (priv->paint_tower, x, y, width, height); ++ if (priv->paint_tower_right) ++ meta_texture_tower_update_area (priv->paint_tower_right, x, y, width, height); + + unobscured_region = effective_unobscured_region (stex); + if (unobscured_region) +@@ -789,17 +867,18 @@ meta_shaped_texture_update_area (MetaShapedTexture *stex, + } + + /** +- * meta_shaped_texture_set_texture: ++ * meta_shaped_texture_set_textures: + * @stex: The #MetaShapedTexture + * @pixmap: The #CoglTexture to display + */ + void +-meta_shaped_texture_set_texture (MetaShapedTexture *stex, +- CoglTexture *texture) ++meta_shaped_texture_set_textures (MetaShapedTexture *stex, ++ CoglTexture *texture, ++ CoglTexture *texture_right) + { + g_return_if_fail (META_IS_SHAPED_TEXTURE (stex)); + +- set_cogl_texture (stex, texture); ++ set_cogl_textures (stex, texture, texture_right); + } + + /** +diff --git a/src/compositor/meta-surface-actor-wayland.c b/src/compositor/meta-surface-actor-wayland.c +index 7505b7d..9475c20 100644 +--- a/src/compositor/meta-surface-actor-wayland.c ++++ b/src/compositor/meta-surface-actor-wayland.c +@@ -187,7 +187,7 @@ meta_surface_actor_wayland_dispose (GObject *object) + MetaShapedTexture *stex = + meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); + +- meta_shaped_texture_set_texture (stex, NULL); ++ meta_shaped_texture_set_textures (stex, NULL, NULL); + if (priv->surface) + { + g_object_remove_weak_pointer (G_OBJECT (priv->surface), +@@ -246,6 +246,14 @@ meta_surface_actor_wayland_new (MetaWaylandSurface *surface) + return META_SURFACE_ACTOR (self); + } + ++void ++meta_surface_actor_wayland_set_texture (MetaSurfaceActorWayland *self, ++ CoglTexture *texture) ++{ ++ MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); ++ meta_shaped_texture_set_textures (stex, texture, NULL); ++} ++ + MetaWaylandSurface * + 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 d32aeb6..52db380 100644 +--- a/src/compositor/meta-surface-actor-x11.c ++++ b/src/compositor/meta-surface-actor-x11.c +@@ -31,6 +31,7 @@ + #include + + #include ++#include "compositor-private.h" + #include "window-private.h" + #include "meta-shaped-texture-private.h" + #include "meta-cullable.h" +@@ -43,6 +44,7 @@ struct _MetaSurfaceActorX11Private + MetaDisplay *display; + + CoglTexture *texture; ++ CoglTexture *texture_right; + Pixmap pixmap; + Damage damage; + +@@ -58,6 +60,8 @@ struct _MetaSurfaceActorX11Private + guint size_changed : 1; + + guint unredirected : 1; ++ ++ guint stereo : 1; + }; + typedef struct _MetaSurfaceActorX11Private MetaSurfaceActorX11Private; + +@@ -94,7 +98,7 @@ detach_pixmap (MetaSurfaceActorX11 *self) + * you are supposed to be able to free a GLXPixmap after freeing the underlying + * pixmap, but it certainly doesn't work with current DRI/Mesa + */ +- meta_shaped_texture_set_texture (stex, NULL); ++ meta_shaped_texture_set_textures (stex, NULL, NULL); + cogl_flush (); + + meta_error_trap_push (display); +@@ -103,6 +107,7 @@ detach_pixmap (MetaSurfaceActorX11 *self) + meta_error_trap_pop (display); + + g_clear_pointer (&priv->texture, cogl_object_unref); ++ g_clear_pointer (&priv->texture_right, cogl_object_unref); + } + + static void +@@ -114,23 +119,35 @@ set_pixmap (MetaSurfaceActorX11 *self, + CoglContext *ctx = clutter_backend_get_cogl_context (clutter_get_default_backend ()); + MetaShapedTexture *stex = meta_surface_actor_get_texture (META_SURFACE_ACTOR (self)); + CoglError *error = NULL; +- CoglTexture *texture; ++ CoglTexturePixmapX11 *texture; ++ CoglTexturePixmapX11 *texture_right; + + g_assert (priv->pixmap == None); + priv->pixmap = pixmap; + +- texture = COGL_TEXTURE (cogl_texture_pixmap_x11_new (ctx, priv->pixmap, FALSE, &error)); ++ if (priv->stereo) ++ texture = cogl_texture_pixmap_x11_new_left (ctx, pixmap, FALSE, &error); ++ else ++ texture = cogl_texture_pixmap_x11_new (ctx, pixmap, FALSE, &error); ++ ++ if (priv->stereo) ++ texture_right = cogl_texture_pixmap_x11_new_right (texture); ++ else ++ texture_right = NULL; + + if (error != NULL) + { + g_warning ("Failed to allocate stex texture: %s", error->message); + cogl_error_free (error); + } +- else if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (COGL_TEXTURE_PIXMAP_X11 (texture)))) ++ else if (G_UNLIKELY (!cogl_texture_pixmap_x11_is_using_tfp_extension (texture))) + g_warning ("NOTE: Not using GLX TFP!\n"); + +- priv->texture = texture; +- meta_shaped_texture_set_texture (stex, texture); ++ priv->texture = COGL_TEXTURE (texture); ++ if (priv->stereo) ++ priv->texture_right = COGL_TEXTURE (texture_right); ++ ++ meta_shaped_texture_set_textures (stex, COGL_TEXTURE (texture), COGL_TEXTURE (texture_right)); + } + + static void +@@ -433,8 +450,8 @@ reset_texture (MetaSurfaceActorX11 *self) + /* Setting the texture to NULL will cause all the FBO's cached by the + * shaped texture's MetaTextureTower to be discarded and recreated. + */ +- meta_shaped_texture_set_texture (stex, NULL); +- meta_shaped_texture_set_texture (stex, priv->texture); ++ meta_shaped_texture_set_textures (stex, NULL, NULL); ++ meta_shaped_texture_set_textures (stex, priv->texture, priv->texture_right); + } + + MetaSurfaceActor * +@@ -443,12 +460,17 @@ meta_surface_actor_x11_new (MetaWindow *window) + MetaSurfaceActorX11 *self = g_object_new (META_TYPE_SURFACE_ACTOR_X11, NULL); + MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); + MetaDisplay *display = meta_window_get_display (window); ++ Window xwindow; + + g_assert (!meta_is_wayland_compositor ()); + + priv->window = window; + priv->display = display; + ++ xwindow = meta_window_x11_get_toplevel_xwindow (window); ++ priv->stereo = meta_compositor_window_is_stereo (display->screen, xwindow); ++ meta_compositor_select_stereo_notify (display->screen, xwindow); ++ + g_signal_connect_object (priv->display, "gl-video-memory-purged", + G_CALLBACK (reset_texture), self, G_CONNECT_SWAPPED); + +@@ -479,3 +501,21 @@ meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self, + priv->last_height = height; + meta_shaped_texture_set_fallback_size (stex, width, height); + } ++ ++void ++meta_surface_actor_x11_stereo_notify (MetaSurfaceActorX11 *self, ++ gboolean stereo_tree) ++{ ++ MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); ++ ++ priv->stereo = stereo_tree != FALSE; ++ detach_pixmap (self); ++} ++ ++gboolean ++meta_surface_actor_x11_is_stereo (MetaSurfaceActorX11 *self) ++{ ++ MetaSurfaceActorX11Private *priv = meta_surface_actor_x11_get_instance_private (self); ++ ++ return priv->stereo; ++} +diff --git a/src/compositor/meta-surface-actor-x11.h b/src/compositor/meta-surface-actor-x11.h +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); + void meta_surface_actor_x11_set_size (MetaSurfaceActorX11 *self, + int width, int height); + ++void meta_surface_actor_x11_stereo_notify (MetaSurfaceActorX11 *self, ++ gboolean stereo_tree); ++ ++gboolean meta_surface_actor_x11_is_stereo (MetaSurfaceActorX11 *self); ++ + G_END_DECLS + + #endif /* __META_SURFACE_ACTOR_X11_H__ */ +diff --git a/src/compositor/meta-window-actor-private.h b/src/compositor/meta-window-actor-private.h +index ce5e7ea..5b011ce 100644 +--- a/src/compositor/meta-window-actor-private.h ++++ b/src/compositor/meta-window-actor-private.h +@@ -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); ++ ++gboolean meta_window_actor_is_stereo (MetaWindowActor *actor); ++ + #endif /* META_WINDOW_ACTOR_PRIVATE_H */ +diff --git a/src/compositor/meta-window-actor.c b/src/compositor/meta-window-actor.c +index 120b043..b2c7725 100644 +--- a/src/compositor/meta-window-actor.c ++++ b/src/compositor/meta-window-actor.c +@@ -2189,3 +2189,25 @@ meta_window_actor_from_window (MetaWindow *window) + { + return META_WINDOW_ACTOR (meta_window_get_compositor_private (window)); + } ++ ++void ++meta_window_actor_stereo_notify (MetaWindowActor *self, ++ gboolean stereo_tree) ++{ ++ MetaWindowActorPrivate *priv = self->priv; ++ ++ if (META_IS_SURFACE_ACTOR_X11 (priv->surface)) ++ meta_surface_actor_x11_stereo_notify (META_SURFACE_ACTOR_X11 (priv->surface), ++ stereo_tree); ++} ++ ++gboolean ++meta_window_actor_is_stereo (MetaWindowActor *self) ++{ ++ MetaWindowActorPrivate *priv = self->priv; ++ ++ if (META_IS_SURFACE_ACTOR_X11 (priv->surface)) ++ return meta_surface_actor_x11_is_stereo (META_SURFACE_ACTOR_X11 (priv->surface)); ++ else ++ return FALSE; ++} +diff --git a/src/core/main.c b/src/core/main.c +index 04a42c7..faa2081 100644 +--- a/src/core/main.c ++++ b/src/core/main.c +@@ -47,6 +47,7 @@ + #include + #include "util-private.h" + #include "display-private.h" ++#include "stereo.h" + #include + #include "ui.h" + #include +@@ -580,6 +581,9 @@ meta_init (void) + + meta_init_backend (backend_gtype); + ++ if (!meta_is_wayland_compositor ()) ++ meta_stereo_init (); ++ + meta_clutter_init (); + + #ifdef HAVE_WAYLAND +diff --git a/src/core/stereo.c b/src/core/stereo.c +new file mode 100644 +index 0000000..5a232b6 +--- /dev/null ++++ b/src/core/stereo.c +@@ -0,0 +1,153 @@ ++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ ++ ++/* ++ * Copyright (C) 2014 Red Hat, Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++/* ++ * SECTION:stereo ++ * @short_description: Keep track of whether we are a stereo compositor ++ * ++ * With GLX, we need to use a different GL context for stereo and ++ * non-stereo support. Support for multiple GL contexts is unfinished ++ * in Cogl and entirely lacking in Clutter, so it's by far easier ++ * to just restart Mutter when we detect a stereo window. ++ * ++ * A property _MUTTER_ENABLE_STEREO is maintained on the root window ++ * to know whether we should initialize clutter for stereo or not. ++ * When the presence or absence of stereo windows mismatches the ++ * stereo-enabled state for a sufficiently long period of time, ++ * we restart Mutter. ++ */ ++ ++#include ++ ++#include ++#include ++#include ++ ++#include ++#include "ui.h" ++#include ++#include "display-private.h" ++#include "stereo.h" ++#include "util-private.h" ++ ++static guint stereo_switch_id = 0; ++static gboolean stereo_enabled = FALSE; ++/* -1 so the first time meta_stereo_set_have_stereo_windows() is called ++ * we avoid the short-circuit and set up a timeout to restart ++ * if necessary */ ++static gboolean stereo_have_windows = (gboolean)-1; ++static gboolean stereo_restart = FALSE; ++ ++#define STEREO_ENABLE_WAIT 1000 ++#define STEREO_DISABLE_WAIT 5000 ++ ++void ++meta_stereo_init (void) ++{ ++ Display *xdisplay; ++ Window root; ++ Atom atom_enable_stereo; ++ Atom type; ++ int format; ++ unsigned long n_items, bytes_after; ++ guchar *data; ++ ++ xdisplay = XOpenDisplay (NULL); ++ if (xdisplay == NULL) ++ meta_fatal ("Unable to open X display %s\n", XDisplayName (NULL)); ++ ++ root = DefaultRootWindow (xdisplay); ++ atom_enable_stereo = XInternAtom (xdisplay, "_MUTTER_ENABLE_STEREO", False); ++ ++ XGetWindowProperty (xdisplay, root, atom_enable_stereo, ++ 0, 1, False, XA_INTEGER, ++ &type, &format, &n_items, &bytes_after, &data); ++ if (type == XA_INTEGER) ++ { ++ if (format == 32 && n_items == 1 && bytes_after == 0) ++ { ++ stereo_enabled = *(long *)data; ++ } ++ else ++ { ++ meta_warning ("Bad value for _MUTTER_ENABLE_STEREO property\n"); ++ } ++ ++ XFree (data); ++ } ++ else if (type != None) ++ { ++ meta_warning ("Bad type for _MUTTER_ENABLE_STEREO property\n"); ++ } ++ ++ meta_verbose ("On startup, _MUTTER_ENABLE_STEREO=%s", ++ stereo_enabled ? "yes" : "no"); ++ clutter_x11_set_use_stereo_stage (stereo_enabled); ++ XCloseDisplay (xdisplay); ++} ++ ++static gboolean ++meta_stereo_switch (gpointer data) ++{ ++ stereo_switch_id = 0; ++ stereo_restart = TRUE; ++ ++ meta_restart (stereo_have_windows ? ++ _("Enabling stereo...") : ++ _("Disabling stereo...")); ++ ++ return FALSE; ++} ++ ++void ++meta_stereo_set_have_stereo_windows (gboolean have_windows) ++{ ++ have_windows = have_windows != FALSE; ++ ++ if (!stereo_restart && have_windows != stereo_have_windows) ++ { ++ MetaDisplay *display = meta_get_display (); ++ Display *xdisplay = meta_display_get_xdisplay (display); ++ Window root = DefaultRootWindow (xdisplay); ++ Atom atom_enable_stereo = XInternAtom (xdisplay, "_MUTTER_ENABLE_STEREO", False); ++ long value; ++ ++ stereo_have_windows = have_windows; ++ ++ if (stereo_have_windows) ++ meta_verbose ("Detected stereo windows\n"); ++ else ++ meta_verbose ("No stereo windows detected\n"); ++ ++ value = stereo_have_windows; ++ XChangeProperty (xdisplay, root, ++ atom_enable_stereo, XA_INTEGER, 32, ++ PropModeReplace, (guchar *)&value, 1); ++ ++ if (stereo_switch_id != 0) ++ { ++ g_source_remove (stereo_switch_id); ++ stereo_switch_id = 0; ++ } ++ ++ if (stereo_have_windows != stereo_enabled) ++ stereo_switch_id = g_timeout_add (stereo_have_windows ? STEREO_ENABLE_WAIT : STEREO_DISABLE_WAIT, ++ meta_stereo_switch, NULL); ++ } ++} +diff --git a/src/core/stereo.h b/src/core/stereo.h +new file mode 100644 +index 0000000..ccd1d70 +--- /dev/null ++++ b/src/core/stereo.h +@@ -0,0 +1,28 @@ ++/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ ++ ++/* ++ * Copyright (C) 2014 Red Hat, Inc. ++ * ++ * This program is free software; you can redistribute it and/or ++ * modify it under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of the ++ * License, or (at your option) any later version. ++ * ++ * This program is distributed in the hope that it will be useful, but ++ * WITHOUT ANY WARRANTY; without even the implied warranty of ++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU ++ * General Public License for more details. ++ * ++ * You should have received a copy of the GNU General Public License ++ * along with this program; if not, see . ++ */ ++ ++#ifndef META_STEREO_H ++#define META_STEREO_H ++ ++void meta_stereo_init (void); ++void meta_stereo_set_have_stereo_windows (gboolean have_windows); ++gboolean meta_stereo_is_restart (void); ++void meta_stereo_finish_restart (void); ++ ++#endif +diff --git a/src/wayland/meta-wayland-surface.c b/src/wayland/meta-wayland-surface.c +index 899f777..f8f7fc5 100644 +--- a/src/wayland/meta-wayland-surface.c ++++ b/src/wayland/meta-wayland-surface.c +@@ -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); + +- meta_shaped_texture_set_texture (stex, texture); ++ meta_shaped_texture_set_textures (stex, texture, NULL); + meta_shaped_texture_set_snippet (stex, snippet); + meta_shaped_texture_set_is_y_inverted (stex, is_y_inverted); + g_clear_pointer (&snippet, cogl_object_unref); +-- +1.8.3.1 + diff --git a/SOURCES/add-support-for-plain-old-x-device-configuration.patch b/SOURCES/add-support-for-plain-old-x-device-configuration.patch new file mode 100644 index 0000000..3198a09 --- /dev/null +++ b/SOURCES/add-support-for-plain-old-x-device-configuration.patch @@ -0,0 +1,400 @@ +From 81986e9b3c16efa170b2bb4fe2af05a30b9386b3 Mon Sep 17 00:00:00 2001 +From: Rui Matos +Date: Mon, 9 Oct 2017 18:37:11 +0200 +Subject: [PATCH 1/4] backends/x11: Fix a small memory leak + +Introduced in "backends/x11: Support synaptics configuration". +--- + src/backends/x11/meta-input-settings-x11.c | 1 + + 1 file changed, 1 insertion(+) + +diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c +index 467a9b7..27995c8 100644 +--- a/src/backends/x11/meta-input-settings-x11.c ++++ b/src/backends/x11/meta-input-settings-x11.c +@@ -222,6 +222,7 @@ change_synaptics_tap_left_handed (ClutterInputDevice *device, + buttons[0] = left_handed ? 3 : 1; + buttons[2] = left_handed ? 1 : 3; + XSetDeviceButtonMapping (xdisplay, xdevice, buttons, n_buttons); ++ g_free (buttons); + + if (display && meta_error_trap_pop_with_return (display)) + { +-- +1.8.3.1 + + +From c3f4dc97cdb4f1b63e43e38daf02e676d207ad37 Mon Sep 17 00:00:00 2001 +From: Rui Matos +Date: Mon, 9 Oct 2017 18:39:52 +0200 +Subject: [PATCH 2/4] backends/x11: Add a synaptics check for two finger scroll + availability + +Commit "backends/x11: Support synaptics configuration" added support +for synaptics two finger scrolling but didn't add the code to check +that it is available resulting in the upper layer always assuming it +isn't. +--- + src/backends/x11/meta-input-settings-x11.c | 11 +++++++++++ + 1 file changed, 11 insertions(+) + +diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c +index 27995c8..4c2709c 100644 +--- a/src/backends/x11/meta-input-settings-x11.c ++++ b/src/backends/x11/meta-input-settings-x11.c +@@ -621,6 +621,17 @@ meta_input_settings_x11_has_two_finger_scroll (MetaInputSettings *settings, + guchar *available = NULL; + gboolean has_two_finger = TRUE; + ++ if (is_device_synaptics (device)) ++ { ++ available = get_property (device, "Synaptics Capabilities", ++ XA_INTEGER, 8, 4); ++ if (!available || !available[3]) ++ has_two_finger = FALSE; ++ ++ meta_XFree (available); ++ return has_two_finger; ++ } ++ + available = get_property (device, "libinput Scroll Methods Available", + XA_INTEGER, 8, SCROLL_METHOD_NUM_FIELDS); + if (!available || !available[SCROLL_METHOD_FIELD_2FG]) +-- +1.8.3.1 + + +From fd94f5fd842f0f0f9e4a28e69716a30669e2e848 Mon Sep 17 00:00:00 2001 +From: Rui Matos +Date: Mon, 9 Oct 2017 18:55:56 +0200 +Subject: [PATCH 3/4] backends/x11: Add disable while typing support for + synaptics + +This is basically a copy of the old g-s-d mouse plugin code to manage +syndaemon when the synaptics driver is being used. +--- + src/backends/x11/meta-input-settings-x11.c | 112 +++++++++++++++++++++++++++++ + 1 file changed, 112 insertions(+) + +diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c +index 4c2709c..9a85f94 100644 +--- a/src/backends/x11/meta-input-settings-x11.c ++++ b/src/backends/x11/meta-input-settings-x11.c +@@ -35,6 +35,9 @@ + #ifdef HAVE_LIBGUDEV + #include + #endif ++#ifdef __linux ++#include ++#endif + + #include + #include "backends/meta-logical-monitor.h" +@@ -44,6 +47,8 @@ typedef struct _MetaInputSettingsX11Private + #ifdef HAVE_LIBGUDEV + GUdevClient *udev_client; + #endif ++ gboolean syndaemon_spawned; ++ GPid syndaemon_pid; + } MetaInputSettingsX11Private; + + G_DEFINE_TYPE_WITH_PRIVATE (MetaInputSettingsX11, meta_input_settings_x11, +@@ -328,6 +333,107 @@ change_synaptics_speed (ClutterInputDevice *device, + XFreeFeedbackList (states); + } + ++/* Ensure that syndaemon dies together with us, to avoid running several of ++ * them */ ++static void ++setup_syndaemon (gpointer user_data) ++{ ++#ifdef __linux ++ prctl (PR_SET_PDEATHSIG, SIGHUP); ++#endif ++} ++ ++static gboolean ++have_program_in_path (const char *name) ++{ ++ gchar *path; ++ gboolean result; ++ ++ path = g_find_program_in_path (name); ++ result = (path != NULL); ++ g_free (path); ++ return result; ++} ++ ++static void ++syndaemon_died (GPid pid, ++ gint status, ++ gpointer user_data) ++{ ++ MetaInputSettingsX11 *settings_x11 = META_INPUT_SETTINGS_X11 (user_data); ++ MetaInputSettingsX11Private *priv = ++ meta_input_settings_x11_get_instance_private (settings_x11); ++ GError *error = NULL; ++ ++ if (!g_spawn_check_exit_status (status, &error)) ++ { ++ if ((WIFSIGNALED (status) && WTERMSIG (status) != SIGHUP) || ++ error->domain == G_SPAWN_EXIT_ERROR) ++ g_warning ("Syndaemon exited unexpectedly: %s", error->message); ++ g_error_free (error); ++ } ++ ++ g_spawn_close_pid (pid); ++ priv->syndaemon_spawned = FALSE; ++} ++ ++static void ++set_synaptics_disable_w_typing (MetaInputSettings *settings, ++ gboolean state) ++{ ++ MetaInputSettingsX11 *settings_x11 = META_INPUT_SETTINGS_X11 (settings); ++ MetaInputSettingsX11Private *priv = ++ meta_input_settings_x11_get_instance_private (settings_x11); ++ ++ if (state) ++ { ++ GError *error = NULL; ++ GPtrArray *args; ++ ++ if (priv->syndaemon_spawned) ++ return; ++ ++ if (!have_program_in_path ("syndaemon")) ++ return; ++ ++ args = g_ptr_array_new (); ++ ++ g_ptr_array_add (args, "syndaemon"); ++ g_ptr_array_add (args, "-i"); ++ g_ptr_array_add (args, "1.0"); ++ g_ptr_array_add (args, "-t"); ++ g_ptr_array_add (args, "-K"); ++ g_ptr_array_add (args, "-R"); ++ g_ptr_array_add (args, NULL); ++ ++ /* we must use G_SPAWN_DO_NOT_REAP_CHILD to avoid ++ * double-forking, otherwise syndaemon will immediately get ++ * killed again through (PR_SET_PDEATHSIG when the intermediate ++ * process dies */ ++ g_spawn_async (g_get_home_dir (), (char **) args->pdata, NULL, ++ G_SPAWN_SEARCH_PATH|G_SPAWN_DO_NOT_REAP_CHILD, setup_syndaemon, NULL, ++ &priv->syndaemon_pid, &error); ++ ++ priv->syndaemon_spawned = (error == NULL); ++ g_ptr_array_free (args, TRUE); ++ ++ if (error) ++ { ++ g_warning ("Failed to launch syndaemon: %s", error->message); ++ g_error_free (error); ++ } ++ else ++ { ++ g_child_watch_add (priv->syndaemon_pid, syndaemon_died, settings); ++ } ++ } ++ else if (priv->syndaemon_spawned) ++ { ++ kill (priv->syndaemon_pid, SIGHUP); ++ priv->syndaemon_spawned = FALSE; ++ } ++} ++ + static void + meta_input_settings_x11_set_send_events (MetaInputSettings *settings, + ClutterInputDevice *device, +@@ -452,6 +558,12 @@ meta_input_settings_x11_set_disable_while_typing (MetaInputSettings *settings, + { + guchar value = (enabled) ? 1 : 0; + ++ if (is_device_synaptics (device)) ++ { ++ set_synaptics_disable_w_typing (settings, enabled); ++ return; ++ } ++ + change_property (device, "libinput Disable While Typing Enabled", + XA_INTEGER, 8, &value, 1); + } +-- +1.8.3.1 + + +From f5f9195fe23c0af8a498a13ca6bc5521a0c9e6ce Mon Sep 17 00:00:00 2001 +From: Rui Matos +Date: Tue, 10 Oct 2017 19:07:27 +0200 +Subject: [PATCH 4/4] backends/x11: Support plain old X device configuration + +We re-use part of the code added to support synaptics and add a few +bits specific for xorg-x11-drv-evdev devices. +--- + src/backends/x11/meta-input-settings-x11.c | 96 +++++++++++++++++++++++------- + 1 file changed, 74 insertions(+), 22 deletions(-) + +diff --git a/src/backends/x11/meta-input-settings-x11.c b/src/backends/x11/meta-input-settings-x11.c +index 9a85f94..cb4eb00 100644 +--- a/src/backends/x11/meta-input-settings-x11.c ++++ b/src/backends/x11/meta-input-settings-x11.c +@@ -179,35 +179,35 @@ is_device_synaptics (ClutterInputDevice *device) + return TRUE; + } + ++static gboolean ++is_device_libinput (ClutterInputDevice *device) ++{ ++ guchar *has_setting; ++ ++ /* We just need looking for a synaptics-specific property */ ++ has_setting = get_property (device, "libinput Send Events Modes Available", XA_INTEGER, 8, 2); ++ if (!has_setting) ++ return FALSE; ++ ++ meta_XFree (has_setting); ++ return TRUE; ++} ++ + static void +-change_synaptics_tap_left_handed (ClutterInputDevice *device, +- gboolean tap_enabled, +- gboolean left_handed) ++change_x_device_left_handed (ClutterInputDevice *device, ++ gboolean left_handed) + { + MetaDisplay *display = meta_get_display (); + MetaBackend *backend = meta_get_backend (); + Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); + XDevice *xdevice; +- guchar *tap_action, *buttons; ++ guchar *buttons; + guint buttons_capacity = 16, n_buttons; + + xdevice = device_ensure_xdevice (device); + if (!xdevice) + return; + +- tap_action = get_property (device, "Synaptics Tap Action", +- XA_INTEGER, 8, 7); +- if (!tap_action) +- return; +- +- tap_action[4] = tap_enabled ? (left_handed ? 3 : 1) : 0; +- tap_action[5] = tap_enabled ? (left_handed ? 1 : 3) : 0; +- tap_action[6] = tap_enabled ? 2 : 0; +- +- change_property (device, "Synaptics Tap Action", +- XA_INTEGER, 8, tap_action, 7); +- meta_XFree (tap_action); +- + if (display) + meta_error_trap_push (display); + buttons = g_new (guchar, buttons_capacity); +@@ -231,14 +231,37 @@ change_synaptics_tap_left_handed (ClutterInputDevice *device, + + if (display && meta_error_trap_pop_with_return (display)) + { +- g_warning ("Could not set synaptics touchpad left-handed for %s", ++ g_warning ("Could not set left-handed for %s", + clutter_input_device_get_device_name (device)); + } + } + + static void +-change_synaptics_speed (ClutterInputDevice *device, +- gdouble speed) ++change_synaptics_tap_left_handed (ClutterInputDevice *device, ++ gboolean tap_enabled, ++ gboolean left_handed) ++{ ++ guchar *tap_action; ++ ++ tap_action = get_property (device, "Synaptics Tap Action", ++ XA_INTEGER, 8, 7); ++ if (!tap_action) ++ return; ++ ++ tap_action[4] = tap_enabled ? (left_handed ? 3 : 1) : 0; ++ tap_action[5] = tap_enabled ? (left_handed ? 1 : 3) : 0; ++ tap_action[6] = tap_enabled ? 2 : 0; ++ ++ change_property (device, "Synaptics Tap Action", ++ XA_INTEGER, 8, tap_action, 7); ++ meta_XFree (tap_action); ++ ++ change_x_device_left_handed (device, left_handed); ++} ++ ++static void ++change_x_device_speed (ClutterInputDevice *device, ++ gdouble speed) + { + MetaDisplay *display = meta_get_display (); + MetaBackend *backend = meta_get_backend (); +@@ -333,6 +356,23 @@ change_synaptics_speed (ClutterInputDevice *device, + XFreeFeedbackList (states); + } + ++static void ++change_x_device_scroll_button (ClutterInputDevice *device, ++ guint button) ++{ ++ guchar value; ++ ++ value = button > 0 ? 1 : 0; ++ change_property (device, "Evdev Wheel Emulation", ++ XA_INTEGER, 8, &value, 1); ++ if (button > 0) ++ { ++ value = button; ++ change_property (device, "Evdev Wheel Emulation Button", ++ XA_INTEGER, 8, &value, 1); ++ } ++} ++ + /* Ensure that syndaemon dies together with us, to avoid running several of + * them */ + static void +@@ -501,9 +541,10 @@ meta_input_settings_x11_set_speed (MetaInputSettings *settings, + Display *xdisplay = meta_backend_x11_get_xdisplay (META_BACKEND_X11 (backend)); + gfloat value = speed; + +- if (is_device_synaptics (device)) ++ if (is_device_synaptics (device) || ++ !is_device_libinput (device)) + { +- change_synaptics_speed (device, speed); ++ change_x_device_speed (device, speed); + return; + } + +@@ -545,6 +586,11 @@ meta_input_settings_x11_set_left_handed (MetaInputSettings *settings, + g_object_unref (settings); + return; + } ++ else if (!is_device_libinput (device)) ++ { ++ change_x_device_left_handed (device, enabled); ++ return; ++ } + + change_property (device, "libinput Left Handed Enabled", + XA_INTEGER, 8, &value, 1); +@@ -758,6 +804,12 @@ meta_input_settings_x11_set_scroll_button (MetaInputSettings *settings, + ClutterInputDevice *device, + guint button) + { ++ if (!is_device_libinput (device)) ++ { ++ change_x_device_scroll_button (device, button); ++ return; ++ } ++ + change_property (device, "libinput Button Scrolling Button", + XA_INTEGER, 32, &button, 1); + } +-- +1.8.3.1 + diff --git a/SOURCES/deal-more-gracefully-with-oversized-windows.patch b/SOURCES/deal-more-gracefully-with-oversized-windows.patch new file mode 100644 index 0000000..477aded --- /dev/null +++ b/SOURCES/deal-more-gracefully-with-oversized-windows.patch @@ -0,0 +1,85 @@ +From 547af942e6a0586208dbc3f158a7ec2c14611ff8 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Wed, 12 Mar 2014 02:04:13 +0100 +Subject: [PATCH 1/8] constraints: Enforce X11 size limits + +X11 limits windows to a maximum of 32767x32767, enforce that restriction +to keep insanely huge windows from crashing the WM. +--- + src/core/constraints.c | 42 ++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 42 insertions(+) + +diff --git a/src/core/constraints.c b/src/core/constraints.c +index f5360ef9d..3b6203d6b 100644 +--- a/src/core/constraints.c ++++ b/src/core/constraints.c +@@ -106,6 +106,7 @@ typedef enum + PRIORITY_TITLEBAR_VISIBLE = 4, + PRIORITY_PARTIALLY_VISIBLE_ON_WORKAREA = 4, + PRIORITY_CUSTOM_RULE = 4, ++ PRIORITY_XLIMITS = 4, + PRIORITY_MAXIMUM = 4 /* Dummy value used for loop end = max(all priorities) */ + } ConstraintPriority; + +@@ -196,6 +197,10 @@ static gboolean constrain_partially_onscreen (MetaWindow *window, + ConstraintInfo *info, + ConstraintPriority priority, + gboolean check_only); ++static gboolean constrain_xlimits (MetaWindow *window, ++ ConstraintInfo *info, ++ ConstraintPriority priority, ++ gboolean check_only); + + static void setup_constraint_info (ConstraintInfo *info, + MetaWindow *window, +@@ -231,6 +236,7 @@ static const Constraint all_constraints[] = { + {constrain_fully_onscreen, "constrain_fully_onscreen"}, + {constrain_titlebar_visible, "constrain_titlebar_visible"}, + {constrain_partially_onscreen, "constrain_partially_onscreen"}, ++ {constrain_xlimits, "constrain_xlimits"}, + {NULL, NULL} + }; + +@@ -1674,3 +1680,39 @@ constrain_partially_onscreen (MetaWindow *window, + + return retval; + } ++ ++ ++#define MAX_WINDOW_SIZE 32767 ++ ++static gboolean ++constrain_xlimits (MetaWindow *window, ++ ConstraintInfo *info, ++ ConstraintPriority priority, ++ gboolean check_only) ++{ ++ int max_w, max_h; ++ gboolean constraint_already_satisfied; ++ ++ if (priority > PRIORITY_XLIMITS) ++ return TRUE; ++ ++ max_w = max_h = MAX_WINDOW_SIZE; ++ ++ if (window->frame) ++ { ++ MetaFrameBorders borders; ++ meta_frame_calc_borders (window->frame, &borders); ++ ++ max_w -= (borders.total.left + borders.total.right); ++ max_h -= (borders.total.top + borders.total.bottom); ++ } ++ ++ constraint_already_satisfied = info->current.width < max_w && info->current.height < max_h; ++ if (check_only || constraint_already_satisfied) ++ return constraint_already_satisfied; ++ ++ info->current.width = MIN (info->current.width, max_w); ++ info->current.height = MIN (info->current.height, max_h); ++ ++ return TRUE; ++} +-- +2.14.2 + 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/SOURCES/inherit-xrandr-metamodes.patch b/SOURCES/inherit-xrandr-metamodes.patch new file mode 100644 index 0000000..55db669 --- /dev/null +++ b/SOURCES/inherit-xrandr-metamodes.patch @@ -0,0 +1,365 @@ +From ea252d6e8f0e882ad2868853babcb5de4b9d9a6a Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Mon, 18 Mar 2019 17:08:11 +0100 +Subject: [PATCH 1/2] monitor-config-manager: Use current mode when deriving + current config + +Instead of overriding the existing mode with the preferred mode of the monitor, +use the one already configured. Also use the MetaMonitor API for deriving the +position of the monitor in the screen coordinate space. +--- + src/backends/meta-monitor-config-manager.c | 77 +++++++++++++--------- + 1 file changed, 47 insertions(+), 30 deletions(-) + +diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c +index 1ad342a44..aa8105edf 100644 +--- a/src/backends/meta-monitor-config-manager.c ++++ b/src/backends/meta-monitor-config-manager.c +@@ -508,20 +508,19 @@ create_monitor_config (MetaMonitor *monitor, + } + + static MetaLogicalMonitorConfig * +-create_preferred_logical_monitor_config (MetaMonitorManager *monitor_manager, +- MetaMonitor *monitor, +- int x, +- int y, +- MetaLogicalMonitorConfig *primary_logical_monitor_config, +- MetaLogicalMonitorLayoutMode layout_mode) ++create_logical_monitor_config (MetaMonitorManager *monitor_manager, ++ MetaMonitor *monitor, ++ MetaMonitorMode *mode, ++ int x, ++ int y, ++ MetaLogicalMonitorConfig *primary_logical_monitor_config, ++ MetaLogicalMonitorLayoutMode layout_mode) + { +- MetaMonitorMode *mode; + int width, height; + float scale; + MetaMonitorConfig *monitor_config; + MetaLogicalMonitorConfig *logical_monitor_config; + +- mode = meta_monitor_get_preferred_mode (monitor); + meta_monitor_mode_get_resolution (mode, &width, &height); + + if ((meta_monitor_manager_get_capabilities (monitor_manager) & +@@ -561,22 +560,40 @@ create_preferred_logical_monitor_config (MetaMonitorManager *monitor_ma + } + + static MetaLogicalMonitorConfig * +-create_logical_monitor_config_from_output (MetaMonitorManager *monitor_manager, +- MetaMonitor *monitor, +- MetaLogicalMonitorConfig *primary_logical_monitor_config, +- MetaLogicalMonitorLayoutMode layout_mode) ++create_preferred_logical_monitor_config (MetaMonitorManager *monitor_manager, ++ MetaMonitor *monitor, ++ int x, ++ int y, ++ MetaLogicalMonitorConfig *primary_logical_monitor_config, ++ MetaLogicalMonitorLayoutMode layout_mode) + { +- MetaOutput *output; +- MetaCrtc *crtc; ++ return create_logical_monitor_config (monitor_manager, ++ monitor, ++ meta_monitor_get_preferred_mode (monitor), ++ x, y, ++ primary_logical_monitor_config, ++ layout_mode); ++} + +- output = meta_monitor_get_main_output (monitor); +- crtc = meta_output_get_assigned_crtc (output); +- return create_preferred_logical_monitor_config (monitor_manager, +- monitor, +- crtc->rect.x, +- crtc->rect.y, +- primary_logical_monitor_config, +- layout_mode); ++static MetaLogicalMonitorConfig * ++create_logical_monitor_config_from_monitor (MetaMonitorManager *monitor_manager, ++ MetaMonitor *monitor, ++ MetaLogicalMonitorConfig *primary_logical_monitor_config, ++ MetaLogicalMonitorLayoutMode layout_mode) ++{ ++ MetaRectangle monitor_layout; ++ MetaMonitorMode *mode; ++ ++ meta_monitor_derive_layout (monitor, &monitor_layout); ++ mode = meta_monitor_get_current_mode (monitor); ++ ++ return create_logical_monitor_config (monitor_manager, ++ monitor, ++ mode, ++ monitor_layout.x, ++ monitor_layout.y, ++ primary_logical_monitor_config, ++ layout_mode); + } + + MetaMonitorsConfig * +@@ -604,10 +621,10 @@ meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_man + layout_mode = meta_monitor_manager_get_default_layout_mode (monitor_manager); + + primary_logical_monitor_config = +- create_logical_monitor_config_from_output (monitor_manager, +- primary_monitor, +- NULL, +- layout_mode); ++ create_logical_monitor_config_from_monitor (monitor_manager, ++ primary_monitor, ++ NULL, ++ layout_mode); + + primary_logical_monitor_config->is_primary = TRUE; + logical_monitor_configs = g_list_append (NULL, +@@ -626,10 +643,10 @@ meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_man + continue; + + logical_monitor_config = +- create_logical_monitor_config_from_output (monitor_manager, +- monitor, +- primary_logical_monitor_config, +- layout_mode); ++ create_logical_monitor_config_from_monitor (monitor_manager, ++ monitor, ++ primary_logical_monitor_config, ++ layout_mode); + + logical_monitor_configs = g_list_append (logical_monitor_configs, + logical_monitor_config); +-- +2.20.1 + + +From 77c07e77ad233b763c82928c1db6003114b0a479 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Jonas=20=C3=85dahl?= +Date: Mon, 18 Mar 2019 17:10:37 +0100 +Subject: [PATCH 2/2] monitor-manager: Don't try to derive current config on + non-X11 + +This commit also reworks the initial config state reading some. Appart from +avoiding trying to inherit from backends where it doesn't make sense, it does +the following changes: + + * Replace the name "initial" with "inherited", as the initial config in the + context of monitor management is the one used initialization. E.g. if there is + a applicable configuration in monitors.xml, the initial config is taken from + there. + + * Don't make "_create_()" functions have side effects. Previously + meta_monitor_config_manager_create_initial() also set state on the config + manager object. Instead, add a meta_monitor_config_manager_ensure_inherited() + and meta_monitor_manager_get_inherited_config() function to make things more + explicit. + + * Don't recreate "is-applicable" logic, just use the existing helper. +--- + src/backends/meta-monitor-config-manager.c | 39 +++++++++++-------- + src/backends/meta-monitor-config-manager.h | 5 ++- + src/backends/meta-monitor-manager-private.h | 4 +- + src/backends/meta-monitor-manager.c | 32 ++++++++------- + .../x11/meta-monitor-manager-xrandr.c | 3 +- + 5 files changed, 48 insertions(+), 35 deletions(-) + +diff --git a/src/backends/meta-monitor-config-manager.c b/src/backends/meta-monitor-config-manager.c +index aa8105edf..cb67e11e7 100644 +--- a/src/backends/meta-monitor-config-manager.c ++++ b/src/backends/meta-monitor-config-manager.c +@@ -40,7 +40,7 @@ struct _MetaMonitorConfigManager + MetaMonitorConfigStore *config_store; + + MetaMonitorsConfig *current_config; +- MetaMonitorsConfig *initial_config; ++ MetaMonitorsConfig *inherited_config; + GQueue config_history; + }; + +@@ -596,11 +596,10 @@ create_logical_monitor_config_from_monitor (MetaMonitorManager *monito + layout_mode); + } + +-MetaMonitorsConfig * +-meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_manager) ++static MetaMonitorsConfig * ++meta_monitor_config_manager_derive_current (MetaMonitorConfigManager *config_manager) + { + MetaMonitorManager *monitor_manager = config_manager->monitor_manager; +- MetaMonitorsConfig *initial_config; + GList *logical_monitor_configs; + MetaMonitor *primary_monitor; + MetaLogicalMonitorLayoutMode layout_mode; +@@ -608,12 +607,6 @@ meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_man + GList *monitors; + GList *l; + +- if (config_manager->initial_config != NULL) +- return g_object_ref (config_manager->initial_config); +- +- if (meta_monitor_config_store_get_config_count (config_manager->config_store) > 0) +- return NULL; +- + primary_monitor = find_primary_monitor (monitor_manager); + if (!primary_monitor || !meta_monitor_is_active (primary_monitor)) + return NULL; +@@ -652,14 +645,26 @@ meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_man + logical_monitor_config); + } + +- initial_config = meta_monitors_config_new (monitor_manager, +- logical_monitor_configs, +- layout_mode, +- META_MONITORS_CONFIG_FLAG_NONE); ++ return meta_monitors_config_new (monitor_manager, ++ logical_monitor_configs, ++ layout_mode, ++ META_MONITORS_CONFIG_FLAG_NONE); ++} ++ ++void ++meta_monitor_config_manager_ensure_inherited_config (MetaMonitorConfigManager *config_manager) ++{ ++ if (config_manager->inherited_config) ++ return; + +- config_manager->initial_config = g_object_ref (initial_config); ++ config_manager->inherited_config = ++ meta_monitor_config_manager_derive_current (config_manager); ++} + +- return initial_config; ++MetaMonitorsConfig * ++meta_monitor_config_manager_get_inherited_config (MetaMonitorConfigManager *config_manager) ++{ ++ return config_manager->inherited_config; + } + + MetaMonitorsConfig * +@@ -1188,7 +1193,7 @@ meta_monitor_config_manager_dispose (GObject *object) + META_MONITOR_CONFIG_MANAGER (object); + + g_clear_object (&config_manager->current_config); +- g_clear_object (&config_manager->initial_config); ++ g_clear_object (&config_manager->inherited_config); + meta_monitor_config_manager_clear_history (config_manager); + + G_OBJECT_CLASS (meta_monitor_config_manager_parent_class)->dispose (object); +diff --git a/src/backends/meta-monitor-config-manager.h b/src/backends/meta-monitor-config-manager.h +index 16dff6d6a..25dcabcdc 100644 +--- a/src/backends/meta-monitor-config-manager.h ++++ b/src/backends/meta-monitor-config-manager.h +@@ -88,7 +88,10 @@ gboolean meta_monitor_config_manager_assign (MetaMonitorManager *manager, + + MetaMonitorsConfig * meta_monitor_config_manager_get_stored (MetaMonitorConfigManager *config_manager); + +-MetaMonitorsConfig * meta_monitor_config_manager_create_initial (MetaMonitorConfigManager *config_manager); ++void meta_monitor_config_manager_ensure_inherited_config (MetaMonitorConfigManager *config_manager); ++ ++MetaMonitorsConfig * meta_monitor_config_manager_get_inherited_config (MetaMonitorConfigManager *config_manager); ++ + MetaMonitorsConfig * meta_monitor_config_manager_create_linear (MetaMonitorConfigManager *config_manager); + + MetaMonitorsConfig * meta_monitor_config_manager_create_fallback (MetaMonitorConfigManager *config_manager); +diff --git a/src/backends/meta-monitor-manager-private.h b/src/backends/meta-monitor-manager-private.h +index a7a0671ae..0d3ed6830 100644 +--- a/src/backends/meta-monitor-manager-private.h ++++ b/src/backends/meta-monitor-manager-private.h +@@ -77,7 +77,8 @@ typedef enum _MetaMonitorManagerCapability + META_MONITOR_MANAGER_CAPABILITY_NONE = 0, + META_MONITOR_MANAGER_CAPABILITY_MIRRORING = (1 << 0), + META_MONITOR_MANAGER_CAPABILITY_LAYOUT_MODE = (1 << 1), +- META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED = (1 << 2) ++ META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED = (1 << 2), ++ META_MONITOR_MANAGER_CAPABILITY_CAN_DERIVE_CURRENT = (1 << 3), + } MetaMonitorManagerCapability; + + /* Equivalent to the 'method' enum in org.gnome.Mutter.DisplayConfig */ +@@ -178,6 +179,7 @@ struct _MetaMonitorManager + int persistent_timeout_id; + + MetaMonitorConfigManager *config_manager; ++ MetaMonitorsConfig *initial_config; + + GnomePnpIds *pnp_ids; + UpClient *up_client; +diff --git a/src/backends/meta-monitor-manager.c b/src/backends/meta-monitor-manager.c +index f7ada0136..68af15e76 100644 +--- a/src/backends/meta-monitor-manager.c ++++ b/src/backends/meta-monitor-manager.c +@@ -493,14 +493,21 @@ should_use_stored_config (MetaMonitorManager *manager) + !meta_monitor_manager_has_hotplug_mode_update (manager)); + } + ++static gboolean ++can_derive_current_config (MetaMonitorManager *manager) ++{ ++ MetaMonitorManagerCapability capabilities; ++ ++ capabilities = meta_monitor_manager_get_capabilities (manager); ++ return !!(capabilities & META_MONITOR_MANAGER_CAPABILITY_CAN_DERIVE_CURRENT); ++} ++ + MetaMonitorsConfig * + meta_monitor_manager_ensure_configured (MetaMonitorManager *manager) + { +- g_autoptr (MetaMonitorsConfig) initial_config = NULL; + MetaMonitorsConfig *config = NULL; + GError *error = NULL; + gboolean use_stored_config; +- MetaMonitorsConfigKey *current_state_key; + MetaMonitorsConfigMethod method; + MetaMonitorsConfigMethod fallback_method = + META_MONITORS_CONFIG_METHOD_TEMPORARY; +@@ -511,17 +518,8 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager) + else + method = META_MONITORS_CONFIG_METHOD_TEMPORARY; + +- initial_config = meta_monitor_config_manager_create_initial (manager->config_manager); +- +- if (initial_config) +- { +- current_state_key = meta_create_monitors_config_key_for_current_state (manager); +- +- /* don't ever reuse initial configuration, if the monitor topology changed +- */ +- if (current_state_key && !meta_monitors_config_key_equal (current_state_key, initial_config->key)) +- g_clear_object (&initial_config); +- } ++ if (can_derive_current_config (manager)) ++ meta_monitor_config_manager_ensure_inherited_config (manager->config_manager); + + if (use_stored_config) + { +@@ -590,9 +588,13 @@ meta_monitor_manager_ensure_configured (MetaMonitorManager *manager) + g_clear_object (&config); + } + +- config = g_steal_pointer (&initial_config); +- if (config) ++ config = ++ meta_monitor_config_manager_get_inherited_config (manager->config_manager); ++ if (config && ++ meta_monitor_manager_is_config_complete (manager, config)) + { ++ config = g_object_ref (config); ++ + if (!meta_monitor_manager_apply_monitors_config (manager, + config, + method, +diff --git a/src/backends/x11/meta-monitor-manager-xrandr.c b/src/backends/x11/meta-monitor-manager-xrandr.c +index d0da2c539..2c14983e2 100644 +--- a/src/backends/x11/meta-monitor-manager-xrandr.c ++++ b/src/backends/x11/meta-monitor-manager-xrandr.c +@@ -949,7 +949,8 @@ static MetaMonitorManagerCapability + meta_monitor_manager_xrandr_get_capabilities (MetaMonitorManager *manager) + { + return (META_MONITOR_MANAGER_CAPABILITY_MIRRORING | +- META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED); ++ META_MONITOR_MANAGER_CAPABILITY_GLOBAL_SCALE_REQUIRED | ++ META_MONITOR_MANAGER_CAPABILITY_CAN_DERIVE_CURRENT); + } + + static gboolean +-- +2.20.1 + diff --git a/SOURCES/startup-notification.patch b/SOURCES/startup-notification.patch new file mode 100644 index 0000000..1a4dd0b --- /dev/null +++ b/SOURCES/startup-notification.patch @@ -0,0 +1,45 @@ +From 4ed430b4ef3013c96fa56cdc57b925b42d20ead9 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Florian=20M=C3=BCllner?= +Date: Thu, 20 Oct 2016 18:00:04 +0200 +Subject: [PATCH] gtk-shell: Work around non-working startup notifications + +GNOME Shell relies on the MetaScreen::startup-sequence-changed signal, +which is tied to (lib)startup-notification and therefore X11. As a result, +when we remove the startup sequence of a wayland client, GNOME Shell will +not be notified about this until startup-notification's timeout is hit. +As a temporary stop-gap, go through XWayland even for wayland clients, +so that the signal is emitted when expected. + +https://bugzilla.gnome.org/show_bug.cgi?id=768531 +--- + src/wayland/meta-wayland-gtk-shell.c | 10 ++++++++++ + 1 file changed, 10 insertions(+) + +diff --git a/src/wayland/meta-wayland-gtk-shell.c b/src/wayland/meta-wayland-gtk-shell.c +index d6e249f..9d1a19e 100644 +--- a/src/wayland/meta-wayland-gtk-shell.c ++++ b/src/wayland/meta-wayland-gtk-shell.c +@@ -219,11 +219,21 @@ gtk_shell_set_startup_id (struct wl_client *client, + struct wl_resource *resource, + const char *startup_id) + { ++#if 0 + MetaDisplay *display; + + display = meta_get_display (); + meta_startup_notification_remove_sequence (display->startup_notification, + startup_id); ++#else ++ /* HACK: MetaScreen::startup-sequence-changed is currently tied to ++ (lib)startup-notification, which means it only works on X11; ++ so for now, always go through XWayland, even for wayland clients */ ++ gdk_x11_display_broadcast_startup_message (gdk_display_get_default (), ++ "remove", ++ "ID", startup_id, ++ NULL); ++#endif + } + + static void +-- +2.9.3 diff --git a/SPECS/mutter.spec b/SPECS/mutter.spec new file mode 100644 index 0000000..cea0b73 --- /dev/null +++ b/SPECS/mutter.spec @@ -0,0 +1,971 @@ +%global gtk3_version 3.19.8 +%global glib_version 2.53.2 +%global gsettings_desktop_schemas_version 3.21.4 +%global json_glib_version 0.12.0 +%global libinput_version 1.4 + +%ifarch s390 s390x +%global disable_wayland --disable-wayland-egl-server --disable-wayland --disable-native-backend +%endif + +Name: mutter +Version: 3.28.3 +Release: 16%{?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.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 + +Patch5: 0001-events-Don-t-move-sloppy-focus-while-buttons-are-pre.patch +Patch6: 0001-backends-x11-Support-synaptics-configuration.patch + +Patch7: 0001-window-actor-Special-case-shaped-Java-windows.patch + +Patch9: 0001-clutter-Extend-touchpad-device-property-check-for-Sy.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 + +Patch32: 0001-clutter-Do-not-latch-modifiers-on-modifier-keys.patch + +# Prevent titlebar from going off-screen (rhbz#1664407) +Patch33: 0001-constraints-Fix-titlebars-going-off-the-bottom.patch + +# Classic classic mode support +Patch34: 0001-screen-Expose-workspace-layout-properties.patch + +# el7 patches +Patch100: 0001-Revert-build-Require-libgudev-232.patch +Patch101: 0001-rhel7-Fix-build-for-el7.patch +Patch103: 0001-wayland-enable-scale-monitor-framebuffer-by-default.patch +Patch104: add-support-for-plain-old-x-device-configuration.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 + +# 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 + +# System wide monitor configuration (#1583825) +Patch250: 0001-monitor-config-store-Read-system-wide-config-files.patch + +# Don't ignore 'MetaModes' (#1581806) +Patch260: inherit-xrandr-metamodes.patch + +# Handle lack of RANDR (#1579257) +Patch261: 0001-gpu-xrandr-Move-dpms-state-and-screen-size-updating-.patch +Patch262: 0002-monitor-manager-xrandr-Create-dummy-screen-sized-mon.patch + +# Queue stage redraw on reactivate (#1636460) +Patch270: 0001-idle-monitor-Use-G_SOURCE_CONTINUE-instead-of-TRUE.patch +Patch271: 0002-idle-monitor-Postpone-dispatching-of-idle-timeout-if.patch + +# Fix crash in meta_monitor_mode_get_resolution() (#1638727) +Patch272: 0001-monitor-Use-current-monitor-mode-to-check-whether-ac.patch +Patch273: 0002-window-Return-1-if-meta_window_get_monitor-is-called.patch + +# Fix crash on device removal (#1578186) +Patch274: 0001-clutter-input-device-xi2-Check-for-null-group_modes-.patch + +# Backport two performance improvement patches (#1737515) +Patch275: 0001-compositor-Don-t-emit-size-changed-when-only-positio.patch +Patch276: 0002-clutter-Avoid-relayouts-when-raising-lowering-childr.patch + +# Backport window title encoding bug fixes (#1630686) +Patch277: 0001-x11-window-props-Do-not-convert-WM_NAME.patch +Patch278: 0002-xprops-Make-sure-text_property_to_utf8-returns-UTF8.patch + +# Don't loose pointer button grabs (#1657887) +Patch279: 0001-events-Sync-pending-pointer-events-without-a-window.patch + +BuildRequires: chrpath +BuildRequires: pango-devel +BuildRequires: startup-notification-devel +BuildRequires: gnome-desktop3-devel +BuildRequires: glib2-devel >= %{glib_version} +BuildRequires: gtk3-devel >= %{gtk3_version} +BuildRequires: pkgconfig +BuildRequires: gobject-introspection-devel >= 1.41.0 +BuildRequires: libSM-devel +BuildRequires: libwacom-devel +BuildRequires: libX11-devel +BuildRequires: libXdamage-devel +BuildRequires: libXext-devel +BuildRequires: libXfixes-devel +BuildRequires: libXi-devel +BuildRequires: libXrandr-devel +BuildRequires: libXrender-devel +BuildRequires: libXcursor-devel +BuildRequires: libXcomposite-devel +BuildRequires: libxcb-devel +BuildRequires: libxkbcommon-devel +BuildRequires: libxkbcommon-x11-devel +BuildRequires: libxkbfile-devel +BuildRequires: libXtst-devel +BuildRequires: mesa-libEGL-devel +BuildRequires: mesa-libGLES-devel +BuildRequires: mesa-libGL-devel +BuildRequires: mesa-libgbm-devel +BuildRequires: pam-devel +BuildRequires: systemd-devel +BuildRequires: upower-devel +BuildRequires: xkeyboard-config-devel +BuildRequires: zenity +BuildRequires: desktop-file-utils +# Bootstrap requirements +BuildRequires: gtk-doc gnome-common gettext-devel git +BuildRequires: libcanberra-devel +BuildRequires: gsettings-desktop-schemas-devel >= %{gsettings_desktop_schemas_version} +BuildRequires: automake, autoconf, libtool +BuildRequires: pkgconfig(gudev-1.0) +BuildRequires: pkgconfig(libdrm) +BuildRequires: pkgconfig(gbm) +BuildRequires: pkgconfig(wayland-server) + +BuildRequires: json-glib-devel >= %{json_glib_version} +BuildRequires: libgudev1-devel +%ifnarch s390 s390x +BuildRequires: libwayland-server-devel +BuildRequires: libinput-devel >= %{libinput_version} +%endif + +Obsoletes: mutter-wayland < 3.13.0 +Obsoletes: mutter-wayland-devel < 3.13.0 + +# Make sure yum updates gnome-shell as well; otherwise we might end up with +# broken gnome-shell installations due to mutter ABI changes. +Conflicts: gnome-shell < 3.21.1 + +Requires: control-center-filesystem +Requires: gsettings-desktop-schemas%{?_isa} >= %{gsettings_desktop_schemas_version} +Requires: gtk3%{?_isa} >= %{gtk3_version} +Requires: startup-notification +Requires: dbus-x11 +Requires: zenity + +Requires: json-glib%{?_isa} >= %{json_glib_version} +%ifnarch s390 s390x +Requires: libinput%{?_isa} >= %{libinput_version} +%endif + +%description +Mutter is a window and compositing manager that displays and manages +your desktop via OpenGL. Mutter combines a sophisticated display engine +using the Clutter toolkit with solid window-management logic inherited +from the Metacity window manager. + +While Mutter can be used stand-alone, it is primarily intended to be +used as the display core of a larger system such as GNOME Shell. For +this reason, Mutter is very extensible via plugins, which are used both +to add fancy visual effects and to rework the window management +behaviors to meet the needs of the environment. + +%package devel +Summary: Development package for %{name} +Requires: %{name}%{?_isa} = %{version}-%{release} + +%description devel +Header files and libraries for developing Mutter plugins. Also includes +utilities for testing Metacity/Mutter themes. + +%prep +%autosetup -S git + +%build +autoreconf -f -i +(if ! test -x configure; then NOCONFIGURE=1 ./autogen.sh; fi; + %configure --disable-static %{?disable_wayland} --enable-compile-warnings=maximum --with-libwacom) + +SHOULD_HAVE_DEFINED="HAVE_SM HAVE_RANDR HAVE_STARTUP_NOTIFICATION" + +for I in $SHOULD_HAVE_DEFINED; do + if ! grep -q "define $I" config.h; then + echo "$I was not defined in config.h" + grep "$I" config.h + exit 1 + else + echo "$I was defined as it should have been" + grep "$I" config.h + fi +done + +make %{?_smp_mflags} V=1 + +%install +%make_install + +#Remove libtool archives. +rm -rf %{buildroot}/%{_libdir}/*.la + +%find_lang %{name} + +# Mutter contains a .desktop file so we just need to validate it +desktop-file-validate %{buildroot}/%{_datadir}/applications/%{name}.desktop + +%post -p /sbin/ldconfig + +%postun +/sbin/ldconfig +if [ $1 -eq 0 ]; then + glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : +fi + +%posttrans +glib-compile-schemas %{_datadir}/glib-2.0/schemas &> /dev/null || : + +%files -f %{name}.lang +%license COPYING +%doc NEWS +%{_bindir}/mutter +%{_datadir}/applications/*.desktop +%{_libdir}/lib*.so.* +%{_libdir}/mutter/ +%{_libexecdir}/mutter-restart-helper +%{_datadir}/GConf/gsettings/mutter-schemas.convert +%{_datadir}/glib-2.0/schemas/org.gnome.mutter.gschema.xml +%{_datadir}/glib-2.0/schemas/org.gnome.mutter.wayland.gschema.xml +%{_datadir}/gnome-control-center/keybindings/50-mutter-*.xml +%{_mandir}/man1/mutter.1* + +%files devel +%{_includedir}/* +%{_libdir}/lib*.so +%{_libdir}/pkgconfig/* + +%changelog +* Wed Oct 02 2019 Jonas Ådahl ) - 3.28.3-16 +- Don't loose pointer button grabs + Resolves: #1657887 + +* Sun Aug 25 2019 Florian MÜllner - 3.28.3-15 +- Expose workspace layout as properties + Related: #1720286 + +* Thu Aug 15 2019 Jonas Ådahl - 3.28.3-14 +- Backport window title encoding bug fixes + Resolves: #1630686 + +* Mon Aug 12 2019 Jonas Ådahl - 3.28.3-13 +- Backport two performance improvement patches. + Resolves #1737515 + +* Wed Aug 07 2019 Carlos garnacho - 3.28.3-12 +- Fix crash on input device removal + Resolves: #1578186 + +* Mon Aug 05 2019 Jonas Ådahl - 3.28.3-11 +- Fix crash in meta_monitor_mode_get_resolution() + Resolves #1638727 + +* Wed Apr 17 2019 Jonas Ådahl - 3.28.3-10 +- Fix idle monitor race condition + Resolves: #1636460 + +* Thu Mar 28 2019 Jonas Ådahl - 3.28.3-9 +- Handle lack of RANDR + Resolves: #1579257 + +* Mon Mar 18 2019 Jonas Ådahl - 3.28.3-8 +- Don't ignore current mode when deriving current config (#1581806) + +* Tue Mar 12 2019 Jonas Ådahl - 3.28.3-7 +- Backport read system wide monitor configuration patch (#1583825) + +* Wed Jan 16 2019 Florian Müllner - 3.28.3-6 +- Prevent titlebars going off-screen (rhbz#1664407) + +* Wed Oct 10 2018 Carlos Garnacho - 3.28.3-5 +- Do not latch modifiers on modifier keys + Resolves: #1637822 + +* 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 + +* Mon Feb 19 2018 Carlos Garnacho - 3.26.2-12 +- Apply settings on current stylus tools instantly + Resolves: #1543693 + +* Wed Feb 14 2018 Jonas Ådahl - 3.26.2-11 +- Fix GPU memory purge error handling + Resolves: #1542375 + +* Tue Feb 13 2018 Carlos Garnacho - 3.26.2-10 +- Detect CLUTTER_TOUCHPAD_DEVICE on all Synaptics devices + Resolves: #1499788 +- Fix tablet pressure curve configuration not being applied + Resolves: #1543693 + +* Tue Feb 13 2018 Ray Strode - 3.26.2-9 +- Fix VNC sessions + Resolves: #1543073 + +* Wed Feb 07 2018 Carlos Garnacho - 3.26.2-8 +- Avoid XCloseDevice on active XI2 devices + Resolves: #1540790 + +* Wed Feb 07 2018 Florian Müllner - 3.26.2-7 +- Fix crash during session saving + Resolves: #1535080 +- Fix XWayland prevented from starting + Resolves: #1540986 + +* Wed Nov 29 2017 Rui Matos - 3.26.2-6 +- Fix a crash resizing windows while headless + Resolves: #1516408 + +* Wed Nov 29 2017 Rui Matos - 3.26.2-5 +- Fix for certain multi-monitor configurations not being remembered + Resolves: #1516404 + +* Wed Nov 08 2017 Ray Strode - 3.26.2-4 +- Fix crash with screen recorder + Resolves: #1508903 + +* Tue Nov 7 2017 Rui Matos - 3.26.2-3 +- Fix external monitor layout patch to avoid a crash +- Resolves: #1481386 + +* Mon Nov 6 2017 Rui Matos - 3.26.2-2 +- Fix stereo patch to fail gracefully on Xwayland +- Resolves: #1481386 + +* Fri Nov 03 2017 Kalev Lember - 3.26.2-1 +- Update to 3.26.2 +- Resolves: #1481386 + +* Thu Oct 26 2017 Rui Matos - 3.26.1-2 +- Add support for plain old X device configuration + Resolves: #1478397 + +* Fri Oct 06 2017 Florian Müllner - 3.26.1-1 +- Update to 3.26.1 + Resolves: #1481386 + +* Mon Jun 26 2017 Florian Müllner - 3.24.3-11 +- Prevent crash when removing workspace with on-all-workspaces windows + present (like desktop icons) +- Resolves: #1453065 + +* Wed Jun 14 2017 Florian Müllner - 3.24.3-10 +- Keep OR windows stacked on top +- Resolves: #1437203 + +* Thu Jun 08 2017 Florian Müllner - 3.24.3-9 +- Fix crash when a window closes during Alt+Tab +- Resolves: #1438722 + +* Tue May 16 2017 Florian Müllner - 3.24.3-8 +- Special-case shaped java windows to fix OpenJDK's compliance test +- Resolves: #1363784 + +* Fri Apr 28 2017 Florian Müllner - 3.24.3-7 +- Fix cally translation of screen coordinates +- Resolves: #1439194 + +* Fri Mar 17 2017 Florian Müllner - 3.22.3-6 +- Recreate build files after modifying templates with the last patch +- Resolves: #1387025 + +* Thu Mar 16 2017 Owen Taylor - 3.22.3-6 +- Add back quad-buffer stereo patches, rebased to 3.22 +- Resolves: #1387025 + +* Wed Mar 15 2017 Carlos Garnacho - 3.22.3-5 +- Swizzle BGRA buffers to avoid pixel conversions +- Resolves: #1387025 + +* Tue Mar 14 2017 Florian Müllner - 3.22.3-4 +- Don't segfault on early exit +- Resolves: #1369073 + +* Mon Mar 13 2017 Carlos Garnacho - 3.22.3-3 +- Handle synaptics settings +- Resolves: #1387025 + +* Mon Mar 13 2017 Florian Müllner - 3.22.3-2 +- Re-add downstream patches +- Resolves: #1387025 + +* Thu Feb 16 2017 Kalev Lember - 3.22.3-1 +- Update to 3.22.3 +- Resolves: #1387025 + +* Fri Feb 03 2017 Kalev Lember - 3.22.2-1 +- Update to 3.22.2 +- Resolves: #1387025 + +* Fri Sep 16 2016 Florian Müllner - 3.14.4-31 +- Make meta_window_actor_update_visibility() public + Related: #1306670 + +* Mon Aug 29 2016 Owen Taylor - 3.14.4-29 +- Allow clutter to fallback to the classic gl driver since mesa's + software driver doesn't support gl3 + Related: #1361251 + +* Thu Aug 11 2016 Rui Matos - 3.14.4-28 +- Add patch to require clutter to use the gl3 driver + Resolves: #1361251 + +* Mon Jul 18 2016 Rui Matos - 3.14.4-27 +- Require a clutter version that provides all the new APIs + Related: rhbz#1330488 + +* Thu Jun 30 2016 Owen Taylor - 3.14.4-26 +- Turn on newly added "threaded swap wait" functionality in Cogl + so that on NVIDIA cards, frame completion is handled in a proper + non-blocking fashion, fixing bugs with idles not running when + they should. + Resolves: #1305076 + +* Wed Jun 29 2016 Rui Matos - 3.14.4-25 +- Handle video memory purge errors + Resolves: #1330488 + +* Tue Jun 28 2016 Florian Müllner - 3.14.4-24 +- Update translations + Resolves: #1304233 + +* Fri Jun 17 2016 Florian Müllner - 3.14.4-23 +- Track ignored damage + Resolves: #1165840 + +* Thu May 19 2016 Florian Müllner - 3.14.4-22 +- Support external monitor layout configuration + Related: #1290448 + +* Thu May 12 2016 Florian Müllner - 3.14.4-21 +- Ignore window groups for stacking + Resolves: #1167889 + +* Tue May 10 2016 Owen Taylor - 3.14.4-20 +- Rebase and add back stereo support patch that was dropped in + update to 3.14. +- Retain the last active window for seamless restarts. + Resolves: #1305076 + +* Thu Apr 21 2016 Florian Müllner - 3.14.4-19 +- Make Cogl errors non-fatal + Related: #1326372 + +* Wed Apr 20 2016 Carlos Garnacho - 3.14.4-18 +- Fix unredirected windows being transparent to input in sloppy focus + Resolves: #1299616 + +* Mon Oct 26 2015 Rui Matos - 3.14.4-17 +- Fix a crash when plugging monitors + Resolves: #1275215 +- Avoid a critical message when unplugging monitors + Resolves: #1275220 +- Fix monitors remaining undetected on resume from suspend + Resolves: #1219476 + +* Fri Oct 16 2015 Florian Müllner - 3.14.4-16 +- Fix crash during session saving when saving sticky windows + Related: #1272106 + +* Tue Oct 6 2015 Rui Matos - 3.14.4-15 +- Fix integer sign oversight in the previous patch + Related: #1265511 + +* Tue Oct 6 2015 Rui Matos - 3.14.4-14 +- Add a couple of fixes for Xvnc resolution changes + Resolves: #1265511 + +* Thu Oct 01 2015 Florian Müllner - 3.14.4-13 +- Fix a couple more errors in headless mode + Related: #1212702 + +* Fri Sep 04 2015 Florian Müllner - 3.14.4-12 +- Fix maximum potential number of monitors + Resolves: #1260082 + +* Thu Sep 03 2015 Florian Müllner - 3.14.4-11 +- Fix screen flicking issue with propriertary NVidia drivers + Resolves: #1258842 + +* Thu Jul 30 2015 Florian Müllner - 3.14.4-10 +- Fix placement of fullscreen windows + Resolves: #1247718 + +* Fri Jul 24 2015 Florian Müllner - 3.14.4-9 +- Fix some more headless-mode warnings + Related: #1212702 + +* Fri Jul 24 2015 Florian Müllner - 3.14.4-8 +- Fix focus_serial overflow + Resolves: #1236113 + +* Tue Jul 21 2015 Matthias Clasen - 3.14.4-7 +- Fix coverity spotted bugs + Related #1174722 + +* Fri Jul 17 2015 Florian Müllner - 3.14.4-6 +- Fix oversight in headless-mode backport + Resolves: #1212702 + +* Thu Jul 16 2015 Florian Müllner - 3.14.4-5 +- Support headless mode + Resolves: #1212702 + +* Fri Jul 10 2015 Florian Müllner - 3.14.4-4 +- Don't try to focus hidden windows + Related: #1174722 + +* Thu May 21 2015 Florian Müllner - 3.14.4-3 +- support suggested output position + Resolves: rhbz#1166319 + +* Wed May 06 2015 Ray Strode 3.14.4-2 +- rebuild against new gnome-desktop3 + Related: #1174722 + +* Tue Mar 24 2015 Florian Müllner - 3.14.4-1 +- Drop obsolete patches, rebase still relevant one + +* Mon Mar 23 2015 Richard Hughes - 3.14.3-1 +- Update to 3.14.3 +- Resolves: #1174722 + +* Wed Jan 14 2015 Florian Müllner - 3.8.4.16 +- Fix window placement regression + Resolves: rhbz#1153641 + +* Thu Nov 13 2014 Florian Müllner - 3.8.4-15 +- Fix delayed mouse mode + Resolves: rhbz#1149585 + +* Thu Oct 09 2014 Florian Müllner - 3.8.4-14 +- Preserve window placement on monitor changes + Resolves: rhbz#1126754 + +* Thu Oct 09 2014 Florian Müllner - 3.8.4-13 +- Improve handling of vertical monitor layouts + Resolves: rhbz#1108322 + +* Thu Jul 17 2014 Owen Taylor 3.8.4-13 +- Add patches for quadbuffer stereo suppport + Fix a bad performance problem drawing window thumbnails + Resolves: rhbz#861507 + +* Tue Mar 11 2014 Florian Müllner - 3.8.4-10 +- Fix crash when encountering over-sized windows + Resolves: #1027832 + +* Tue Mar 11 2014 Florian Müllner - 3.8.4-10 +- Backport another minor memory leak fix + Resolves: #1067456 + +* Tue Mar 11 2014 Debarshi Ray - 3.8.4-9 +- Do not save pixbuf in user data + Resolves: #1067456 + +* Wed Feb 12 2014 Carlos Garnacho - 3.8.4-8 +- Fix window dragging on touchscreens + Resolves: #1051006 + +* Tue Feb 11 2014 Owen Taylor - 3.8.4-7 +- Add an upstream patch that fixes a bug with left-over window + shadows that show up when we add patches to Clutter to stop + redrawing the entire screen on every window move. + Resolves: rhbz#1063984 + +* Fri Jan 24 2014 Daniel Mach - 3.8.4-6 +- Mass rebuild 2014-01-24 + +* Fri Dec 27 2013 Daniel Mach - 3.8.4-5 +- Mass rebuild 2013-12-27 + +* Thu Nov 28 2013 Florian Müllner - 3.8.4-4 +- Include translation updates + Resolves: rhbz#1030369 + +* Mon Nov 11 2013 Florian Müllner - 3.8.4-3 +- Backport allowing sliced textures for large backgrounds + Resolves: rhbz#1028586 + +* Thu Oct 31 2013 Florian Müllner - 3.8.4-2 +- Backport performance improvements for software rendering from 3.10 + +* Tue Jul 30 2013 Ray Strode 3.8.4-1 +- Update to 3.8.4 + +* Tue Jul 02 2013 Florian Müllner - 3.8.3-2 +- Rebuild with (re-)fixed download URL + +* Fri Jun 07 2013 Florian Müllner - 3.8.3-1 +- Update to 3.8.3 + +* Tue May 14 2013 Florian Müllner - 3.8.2-1 +- Update to 3.8.2 + +* Tue Apr 16 2013 Florian Müllner - 3.8.1-1 +- Update to 3.8.1 + +* Tue Mar 26 2013 Florian Müllner - 3.8.0-1 +- Update to 3.8.0 + +* Tue Mar 19 2013 Florian Müllner - 3.7.92-1 +- Update to 3.7.92 + +* Mon Mar 04 2013 Florian Müllner - 3.7.91-1 +- Update to 3.7.91 + +* Wed Feb 20 2013 Florian Müllner - 3.7.90-1 +- Update to 3.7.90 + +* Tue Feb 05 2013 Florian Müllner - 3.7.5-1 +- Update to 3.7.5 + +* Fri Jan 25 2013 Peter Robinson 3.7.4-2 +- Rebuild for new cogl + +* Tue Jan 15 2013 Florian Müllner - 3.7.4-1 +- Update to 3.7.4 + +* Tue Dec 18 2012 Florian Müllner - 3.7.3-1 +- Update to 3.7.3 + +* Mon Nov 19 2012 Florian Müllner - 3.7.2-1 +- Update to 3.7.2 + +* Fri Nov 09 2012 Kalev Lember - 3.7.1-1 +- Update to 3.7.1 + +* Mon Oct 15 2012 Florian Müllner - 3.6.1-1 +- Update to 3.6.1 + +* Tue Sep 25 2012 Florian Müllner - 3.6.0-1 +- Update to 3.6.0 + +* Wed Sep 19 2012 Florian Müllner - 3.5.92-1 +- Update to 3.5.92 + +* Tue Sep 04 2012 Debarshi Ray - 3.5.91-2 +- Rebuild against new cogl + +* Tue Sep 04 2012 Debarshi Ray - 3.5.91-1 +- Update to 3.5.91 + +* Tue Aug 28 2012 Matthias Clasen - 3.5.90-2 +- Rebuild against new cogl/clutter + +* Tue Aug 21 2012 Richard Hughes - 3.5.90-1 +- Update to 3.5.90 + +* Tue Aug 07 2012 Richard Hughes - 3.5.5-1 +- Update to 3.5.5 + +* Fri Jul 27 2012 Fedora Release Engineering - 3.5.4-2 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_18_Mass_Rebuild + +* Tue Jul 17 2012 Richard Hughes - 3.5.4-1 +- Update to 3.5.4 + +* Tue Jun 26 2012 Matthias Clasen - 3.5.3-1 +- Update to 3.5.3 + +* Fri Jun 8 2012 Matthias Clasen - 3.5.2-3 +- Make resize grip area larger + +* Thu Jun 07 2012 Matthias Clasen - 3.5.2-2 +- Don't check for Xinerama anymore - it is now mandatory + +* Thu Jun 07 2012 Richard Hughes - 3.5.2-1 +- Update to 3.5.2 +- Remove upstreamed patches + +* Wed May 09 2012 Adam Jackson 3.4.1-3 +- mutter-never-slice-shape-mask.patch, mutter-use-cogl-texrect-api.patch: + Fix window texturing on hardware without ARB_texture_non_power_of_two + (#813648) + +* Wed Apr 18 2012 Kalev Lember - 3.4.1-2 +- Silence glib-compile-schemas scriplets + +* Wed Apr 18 2012 Kalev Lember - 3.4.1-1 +- Update to 3.4.1 +- Conflict with gnome-shell versions older than 3.4.1 + +* Tue Mar 27 2012 Richard Hughes - 3.4.0-1 +- Update to 3.4.0 + +* Wed Mar 21 2012 Kalev Lember - 3.3.92-1 +- Update to 3.3.92 + +* Sat Mar 10 2012 Matthias Clasen - 3.3.90-2 +- Rebuild against new cogl + +* Sat Feb 25 2012 Matthias Clasen - 3.3.90-1 +- Update to 3.3.90 + +* Tue Feb 7 2012 Matthias Clasen - 3.3.5-1 +- Update to 3.3.5 + +* Fri Jan 20 2012 Matthias Clasen - 3.3.4-1 +- Update to 3.3.4 + +* Thu Jan 19 2012 Matthias Clasen - 3.3.3-2 +- Rebuild against new cogl + +* Thu Jan 5 2012 Matthias Clasen - 3.3.3-1 +- Update to 3.3.3 + +* Wed Nov 23 2011 Matthias Clasen - 3.3.2-2 +- Rebuild against new clutter + +* Tue Nov 22 2011 Matthias Clasen - 3.3.2-1 +- Update to 3.3.2 + +* Wed Oct 26 2011 Fedora Release Engineering - 3.2.1-2 +- Rebuilt for glibc bug#747377 + +* Wed Oct 19 2011 Matthias Clasen - 3.2.1-1 +- Update to 3.2.1 + +* Mon Sep 26 2011 Owen Taylor - 3.2.0-1 +- Update to 3.2.0 + +* Tue Sep 20 2011 Matthias Clasen - 3.1.92-1 +- Update to 3.1.92 + +* Wed Sep 14 2011 Owen Taylor - 3.1.91.1-1 +- Update to 3.1.91.1 + +* Wed Aug 31 2011 Matthias Clasen - 3.1.90.1-1 +- Update to 3.1.90.1 + +* Wed Jul 27 2011 Matthias Clasen - 3.1.4-1 +- Update to 3.1.4 + +* Wed Jul 27 2011 Matthias Clasen - 3.1.3.1-3 +- Rebuild + +* Mon Jul 4 2011 Peter Robinson - 3.1.3.1-2 +- rebuild against new clutter/cogl + +* Mon Jul 04 2011 Adam Williamson - 3.1.3.1-1 +- Update to 3.1.3.1 + +* Thu Jun 30 2011 Owen Taylor - 3.1.3-1 +- Update to 3.1.3 + +* Wed May 25 2011 Owen Taylor - 3.0.2.1-1 +- Update to 3.0.2.1 + +* Fri Apr 29 2011 Matthias Clasen - 3.0.1-3 +- Actually apply the patch for #700276 + +* Thu Apr 28 2011 Matthias Clasen - 3.0.1-2 +- Make session saving of gnome-shell work + +* Mon Apr 25 2011 Owen Taylor - 3.0.1-1 +- Update to 3.0.1 + +* Mon Apr 4 2011 Owen Taylor - 3.0.0-1 +- Update to 3.0.0 + +* Mon Mar 28 2011 Matthias Clasen - 2.91.93-1 +- Update to 2.91.93 + +* Wed Mar 23 2011 Matthias Clasen - 2.91.92-1 +- Update to 2.91.92 + +* Mon Mar 7 2011 Owen Taylor - 2.91.91-1 +- Update to 2.91.91 + +* Tue Mar 1 2011 Matthias Clasen - 2.91.90-2 +- Build against libcanberra, to enable AccessX feedback features + +* Tue Feb 22 2011 Matthias Clasen - 2.91.90-1 +- Update to 2.91.90 + +* Thu Feb 10 2011 Matthias Clasen - 2.91.6-4 +- Rebuild against newer gtk + +* Tue Feb 08 2011 Fedora Release Engineering - 2.91.6-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_15_Mass_Rebuild + +* Wed Feb 2 2011 Matthias Clasen - 2.91.6-2 +- Rebuild against newer gtk + +* Tue Feb 1 2011 Owen Taylor - 2.91.6-1 +- Update to 2.91.6 + +* Tue Jan 11 2011 Matthias Clasen - 2.91.5-1 +- Update to 2.91.5 + +* Fri Jan 7 2011 Matthias Clasen - 2.91.4-1 +- Update to 2.91.4 + +* Fri Dec 3 2010 Matthias Clasen - 2.91.3-2 +- Rebuild against new gtk +- Drop no longer needed %%clean etc + +* Mon Nov 29 2010 Owen Taylor - 2.91.3-1 +- Update to 2.91.3 + +* Tue Nov 9 2010 Owen Taylor - 2.91.2-1 +- Update to 2.91.2 + +* Tue Nov 2 2010 Matthias Clasen - 2.91.1-2 +- Rebuild against newer gtk3 + +* Fri Oct 29 2010 Owen Taylor - 2.91.1-1 +- Update to 2.91.1 + +* Mon Oct 4 2010 Owen Taylor - 2.91.0-1 +- Update to 2.91.0 + +* Wed Sep 22 2010 Matthias Clasen - 2.31.5-4 +- Rebuild against newer gobject-introspection + +* Wed Jul 14 2010 Colin Walters - 2.31.5-3 +- Rebuild for new gobject-introspection + +* Tue Jul 13 2010 Adel Gadllah - 2.31.5-2 +- Build against gtk3 + +* Mon Jul 12 2010 Colin Walters - 2.31.5-1 +- New upstream version + +* Mon Jul 12 2010 Colin Walters - 2.31.2-5 +- Rebuild against new gobject-introspection + +* Tue Jul 6 2010 Colin Walters - 2.31.2-4 +- Changes to support snapshot builds + +* Fri Jun 25 2010 Colin Walters - 2.31.2-3 +- drop gir-repository-devel dep + +* Wed May 26 2010 Adam Miller - 2.31.2-2 +- removed "--with-clutter" as configure is claiming it to be an unknown option + +* Wed May 26 2010 Adam Miller - 2.31.2-1 +- New upstream 2.31.2 release + +* Thu Mar 25 2010 Peter Robinson 2.29.1-1 +- New upstream 2.29.1 release + +* Wed Mar 17 2010 Peter Robinson 2.29.0-1 +- New upstream 2.29.0 release + +* Tue Feb 16 2010 Adam Jackson 2.28.1-0.2 +- mutter-2.28.1-add-needed.patch: Fix FTBFS from --no-add-needed + +* Thu Feb 4 2010 Peter Robinson 2.28.1-0.1 +- Move to git snapshot + +* Wed Oct 7 2009 Owen Taylor - 2.28.0-1 +- Update to 2.28.0 + +* Tue Sep 15 2009 Owen Taylor - 2.27.5-1 +- Update to 2.27.5 + +* Fri Sep 4 2009 Owen Taylor - 2.27.4-1 +- Remove workaround for #520209 +- Update to 2.27.4 + +* Sat Aug 29 2009 Owen Taylor - 2.27.3-3 +- Fix %%preun GConf script to properly be for package removal + +* Fri Aug 28 2009 Owen Taylor - 2.27.3-2 +- Add a workaround for Red Hat bug #520209 + +* Fri Aug 28 2009 Owen Taylor - 2.27.3-1 +- Update to 2.27.3, remove mutter-metawindow.patch + +* Fri Aug 21 2009 Peter Robinson 2.27.2-2 +- Add upstream patch needed by latest mutter-moblin + +* Tue Aug 11 2009 Peter Robinson 2.27.2-1 +- New upstream 2.27.2 release. Drop upstreamed patches. + +* Wed Jul 29 2009 Peter Robinson 2.27.1-5 +- Add upstream patches for clutter 1.0 + +* Wed Jul 29 2009 Peter Robinson 2.27.1-4 +- Add patch to fix mutter --replace + +* Sat Jul 25 2009 Fedora Release Engineering - 2.27.1-3 +- Rebuilt for https://fedoraproject.org/wiki/Fedora_12_Mass_Rebuild + +* Sat Jul 18 2009 Peter Robinson 2.27.1-2 +- Updates from review request + +* Fri Jul 17 2009 Peter Robinson 2.27.1-1 +- Update to official 2.27.1 and review updates + +* Thu Jun 18 2009 Peter Robinson 2.27.0-0.2 +- Updates from initial reviews + +* Thu Jun 18 2009 Peter Robinson 2.27.0-0.1 +- Initial packaging