commit 257c346322e6ba248d25a69bd5473560e7760de1
Author: Mamoru TASAKA <mtasaka(a)fedoraproject.org>
Date: Mon Sep 20 16:41:33 2021 +0900
wayland-manager: allocate new wl_output information by checking id
(Fix segfault on KDE Plasma wayland session: redhat bug 2000812)
Explicitly disable EGL support for now
...ayland-manager-allocate-new-wl_output-inf.patch | 327 +++++++++++++++++++++
cairo-dock-freeworld.spec | 68 ++++-
2 files changed, 385 insertions(+), 10 deletions(-)
---
diff --git a/0001-LP1943052-wayland-manager-allocate-new-wl_output-inf.patch
b/0001-LP1943052-wayland-manager-allocate-new-wl_output-inf.patch
new file mode 100644
index 0000000..36dfff3
--- /dev/null
+++ b/0001-LP1943052-wayland-manager-allocate-new-wl_output-inf.patch
@@ -0,0 +1,327 @@
+From 275fa02a15ebdb75b07c100de9395392f9543300 Mon Sep 17 00:00:00 2001
+From: Mamoru TASAKA <mtasaka(a)fedoraproject.org>
+Date: Mon, 20 Sep 2021 16:22:40 +0900
+Subject: [PATCH] [LP1943052] wayland-manager: allocate new wl_output
+ information by checking id
+
+With KDE Plasma Wayland session, after calling wl_output_add_listener()
+and waiting for wl_output information with wl_display_roundtrip(),
+wl_output::mode info is returned before wl_output::geometry info.
+
+Current cairo-dock-wayland-manager logic expects the opposite order, and
+on KDE session this causes cairo-dock segfault.
+
+To avoid this, when collecting wl_output information, we should also check
+"id" member of global registry object associated with that wl_output info,
+check if the "id" is already the duplicates of the old infos.
+
+Then if the "id" is new one, then allocate the new buffer to register new
+wl_output information beforehand, then call wl_display_roundtrip() to gain
+wl_output::geometry or wl_output::output information.
+---
+ src/gldit/cairo-dock-desktop-manager.h | 13 +-
+ src/implementations/cairo-dock-X-utilities.c | 20 +--
+ .../cairo-dock-wayland-manager.c | 134 +++++++++++++++---
+ 3 files changed, 139 insertions(+), 28 deletions(-)
+
+diff --git a/src/gldit/cairo-dock-desktop-manager.h
b/src/gldit/cairo-dock-desktop-manager.h
+index b8ecb0d0..2774913b 100644
+--- a/src/gldit/cairo-dock-desktop-manager.h
++++ b/src/gldit/cairo-dock-desktop-manager.h
+@@ -59,10 +59,21 @@ typedef enum {
+ NB_NOTIFICATIONS_DESKTOP
+ } CairoDesktopNotifications;
+
++typedef struct GldiWlOutput {
++ struct wl_output *output;
++ uint32_t id, ver;
++} GldiWlOutput;
++
++typedef struct GldiScreenInfo {
++ int x, y;
++ int width, height;
++ GldiWlOutput wloutput; // wl_registry object identifier (in wayland session)
++} GldiScreenInfo;
++
+ // data
+ struct _GldiDesktopGeometry {
+ int iNbScreens;
+- GtkAllocation *pScreens; // liste of all screen devices.
++ GldiScreenInfo *pScreens; // liste of all screen devices.
+ GtkAllocation Xscreen; // logical screen, possibly made of several screen devices.
+ int iNbDesktops;
+ int iNbViewportX, iNbViewportY;
+diff --git a/src/implementations/cairo-dock-X-utilities.c
b/src/implementations/cairo-dock-X-utilities.c
+index 26217dab..9d39e017 100644
+--- a/src/implementations/cairo-dock-X-utilities.c
++++ b/src/implementations/cairo-dock-X-utilities.c
+@@ -89,7 +89,7 @@ static Atom s_aUtf8String;
+ static Atom s_aString;
+ static unsigned char error_code = Success;
+
+-static GtkAllocation *_get_screens_geometry (int *pNbScreens);
++static GldiScreenInfo *_get_screens_geometry (int *pNbScreens);
+
+ static gboolean cairo_dock_support_X_extension (void);
+
+@@ -185,14 +185,14 @@ unsigned char cairo_dock_get_X_error_code (void)
+ return error_code;
+ }
+
+-static GtkAllocation *_get_screens_geometry (int *pNbScreens)
++static GldiScreenInfo *_get_screens_geometry (int *pNbScreens)
+ {
+- GtkAllocation *pScreens = NULL;
+- GtkAllocation *pScreen;
++ GldiScreenInfo *pScreens = NULL;
++ GldiScreenInfo *pScreen;
+ int iNbScreens = 0;
+ /*Unit Tests
+ iNbScreens = 2;
+- pScreens = g_new0 (GtkAllocation, iNbScreens);
++ pScreens = g_new0 (GldiScreenInfo, iNbScreens);
+ pScreens[0].x = 0;
+ pScreens[0].y = 0;
+ pScreens[0].width = 1000;
+@@ -213,7 +213,7 @@ static GtkAllocation *_get_screens_geometry (int *pNbScreens)
+ {
+ int n = res->ncrtc;
+ cd_debug (" number of screen(s): %d", n);
+- pScreens = g_new0 (GtkAllocation, n);
++ pScreens = g_new0 (GldiScreenInfo, n);
+ int i;
+ for (i = 0; i < n; i++)
+ {
+@@ -256,7 +256,7 @@ static GtkAllocation *_get_screens_geometry (int *pNbScreens)
+ if (scr != NULL)
+ {
+ cd_debug (" number of screen(s): %d", n);
+- pScreens = g_new0 (GtkAllocation, n);
++ pScreens = g_new0 (GldiScreenInfo, n);
+ int i;
+ for (i = 0; i < n; i++)
+ {
+@@ -286,7 +286,7 @@ static GtkAllocation *_get_screens_geometry (int *pNbScreens)
+ #endif
+
+ iNbScreens = 1;
+- pScreens = g_new0 (GtkAllocation, iNbScreens);
++ pScreens = g_new0 (GldiScreenInfo, iNbScreens);
+ pScreen = &pScreens[0];
+ pScreen->x = 0;
+ pScreen->y = 0;
+@@ -335,7 +335,7 @@ gboolean cairo_dock_update_screen_geometry (void)
+ }
+
+ // get the size and position of each screen (they could have changed even though the X
screen has not changed, for instance if you swap 2 screens).
+- GtkAllocation *pScreens = g_desktopGeometry.pScreens;
++ GldiScreenInfo *pScreens = g_desktopGeometry.pScreens;
+ int iNbScreens = g_desktopGeometry.iNbScreens;
+ g_desktopGeometry.pScreens = _get_screens_geometry
(&g_desktopGeometry.iNbScreens);
+
+@@ -347,7 +347,7 @@ gboolean cairo_dock_update_screen_geometry (void)
+ int i;
+ for (i = 0; i < MIN (iNbScreens, g_desktopGeometry.iNbScreens); i ++)
+ {
+- if (memcmp (&pScreens[i], &g_desktopGeometry.pScreens[i], sizeof
(GtkAllocation)) != 0)
++ if (memcmp (&pScreens[i], &g_desktopGeometry.pScreens[i], sizeof
(GldiScreenInfo)) != 0)
+ {
+ bNewSize = TRUE;
+ break;
+diff --git a/src/implementations/cairo-dock-wayland-manager.c
b/src/implementations/cairo-dock-wayland-manager.c
+index 9ce8d505..f9732133 100644
+--- a/src/implementations/cairo-dock-wayland-manager.c
++++ b/src/implementations/cairo-dock-wayland-manager.c
+@@ -73,31 +73,97 @@ struct desktop
+ };
+ static gboolean s_bInitializing = TRUE; // each time a callback is called on startup,
it will set this to TRUE, and we'll make a roundtrip to the server until no callback
is called.
+
+-static void _output_geometry_cb (G_GNUC_UNUSED void *data, G_GNUC_UNUSED struct
wl_output *wl_output,
++static int get_position_gldi_screeninfo_by_id (GldiScreenInfo *array_screens, int
iNbScreens, uint32_t obj_id)
++{
++ int i_screen;
++ GldiScreenInfo *p_screen = array_screens;
++ for (i_screen = 0; i_screen < iNbScreens; i_screen++)
++ {
++ if (p_screen->wloutput.id == obj_id)
++ {
++ return i_screen;
++ }
++ p_screen++;
++ }
++
++ return -1;
++}
++
++static GldiScreenInfo *append_gldi_screeninfo(GldiScreenInfo **ref_array_screens, int
*ref_iNbScreens)
++{
++ int iNbScreens_old = *ref_iNbScreens;
++ int iNbScreens_new = iNbScreens_old + 1;
++ GldiScreenInfo *p_new_screeninfo;
++
++ if (!*ref_array_screens)
++ *ref_array_screens = g_new(GldiScreenInfo, 1);
++ else
++ *ref_array_screens = g_realloc(*ref_array_screens, iNbScreens_new * sizeof
(**ref_array_screens));
++ if (!*ref_array_screens) abort();
++
++ p_new_screeninfo = *ref_array_screens + (iNbScreens_new - 1);
++ *ref_iNbScreens = iNbScreens_new;
++
++ return p_new_screeninfo;
++}
++
++static void remove_gldi_screeninfo_by_id(GldiScreenInfo **ref_array_screens, int
*ref_iNbScreens, uint32_t obj_id)
++{
++ int iNbScreens_old = *ref_iNbScreens;
++ int pos_screen;
++ GldiScreenInfo *p_screen;
++
++ if (iNbScreens_old <= 1) return; // Keep at least one information for now
++
++ pos_screen = get_position_gldi_screeninfo_by_id(*ref_array_screens, *ref_iNbScreens,
obj_id);
++ if (pos_screen < 0) return;
++
++ p_screen = *ref_array_screens + pos_screen;
++#ifdef WL_OUTPUT_RELEASE_SINCE_VERSION
++ if (p_screen->wloutput.id >= WL_OUTPUT_RELEASE_SINCE_VERSION)
++ {
++ wl_output_release(p_screen->wloutput.output);
++ } else
++#endif
++ {
++ wl_output_destroy(p_screen->wloutput.output);
++ }
++
++ if (iNbScreens_old > pos_screen + 1)
++ {
++ memmove(
++ p_screen, p_screen + 1,
++ (iNbScreens_old - pos_screen - 1) * sizeof (**ref_array_screens)
++ );
++ }
++
++ (*ref_iNbScreens)--;
++}
++
++static void _output_geometry_cb (void *data, G_GNUC_UNUSED struct wl_output *wl_output,
+ int32_t x, int32_t y,
+ G_GNUC_UNUSED int32_t physical_width, G_GNUC_UNUSED int32_t physical_height,
+ G_GNUC_UNUSED int32_t subpixel, G_GNUC_UNUSED const char *make, G_GNUC_UNUSED const
char *model, G_GNUC_UNUSED int32_t output_transform)
+ {
++ GldiScreenInfo *p_screeninfo = (GldiScreenInfo *)data;
+ cd_debug ("Geometry: %d;%d", x, y);
+- g_desktopGeometry.iNbScreens ++;
+- if (!g_desktopGeometry.pScreens)
+- g_desktopGeometry.pScreens = g_new0 (GtkAllocation, 1);
+- else
+- g_desktopGeometry.pScreens = g_realloc (g_desktopGeometry.pScreens,
g_desktopGeometry.iNbScreens * sizeof(GtkAllocation));
++ cd_debug ("id: %u", (unsigned int)p_screeninfo->wloutput.id);
+
+- g_desktopGeometry.pScreens[g_desktopGeometry.iNbScreens-1].x = x;
+- g_desktopGeometry.pScreens[g_desktopGeometry.iNbScreens-1].y = y;
++ p_screeninfo->x = x;
++ p_screeninfo->y = y;
+ s_bInitializing = TRUE;
+ }
+
+-static void _output_mode_cb (G_GNUC_UNUSED void *data, G_GNUC_UNUSED struct wl_output
*wl_output,
++static void _output_mode_cb (void *data, G_GNUC_UNUSED struct wl_output *wl_output,
+ uint32_t flags, int32_t width, int32_t height, G_GNUC_UNUSED int32_t refresh)
+ {
++ GldiScreenInfo *p_screeninfo = (GldiScreenInfo *)data;
+ cd_debug ("Output mode: %dx%d, %d", width, height, flags);
++ cd_debug ("id: %u", (unsigned int)p_screeninfo->wloutput.id);
+ if (flags & WL_OUTPUT_MODE_CURRENT) // not the current one -> don't bother
+ {
+- g_desktopGeometry.pScreens[g_desktopGeometry.iNbScreens-1].width = width;
+- g_desktopGeometry.pScreens[g_desktopGeometry.iNbScreens-1].height = height;
++ p_screeninfo->width = width;
++ p_screeninfo->height = height;
+ g_desktopGeometry.Xscreen.width = width;
+ g_desktopGeometry.Xscreen.height = height;
+ }
+@@ -124,14 +190,29 @@ static void _output_scale_cb (G_GNUC_UNUSED void *data,
G_GNUC_UNUSED struct wl_
+
+ static const struct wl_output_listener output_listener = {
+ _output_geometry_cb,
+- _output_mode_cb,
++ _output_mode_cb
++#ifdef WL_OUTPUT_SCALE_SINCE_VERSION
++ ,
+ _output_done_cb,
+ _output_scale_cb
++#endif
+ };
+
+-static void _registry_global_cb (G_GNUC_UNUSED void *data, struct wl_registry *registry,
uint32_t id, const char *interface, G_GNUC_UNUSED uint32_t version)
++static void _registry_global_cb (G_GNUC_UNUSED void *data, struct wl_registry *registry,
uint32_t id, const char *interface, uint32_t version)
+ {
+- cd_debug ("got a new global object, instance of %s, id=%d", interface, id);
++ cd_debug ("got a new global object, instance of %s, id=%d, version=%u",
interface, id, version);
++ uint32_t wl_output_version =
++#if defined(WL_OUTPUT_RELEASE_SINCE_VERSION)
++ WL_OUTPUT_RELEASE_SINCE_VERSION;
++#elif defined(WL_OUTPUT_SCALE_SINCE_VERSION)
++ WL_OUTPUT_SCALE_SINCE_VERSION;
++#else
++ 1;
++#endif
++ // server side may not support newer version, in such case suppress the version to use
++ if (wl_output_version > version)
++ wl_output_version = version;
++
+ if (!strcmp (interface, "wl_shell"))
+ {
+ // this is the global that should give us info and signals about the desktop, but
currently it's pretty useless ...
+@@ -142,10 +223,26 @@ static void _registry_global_cb (G_GNUC_UNUSED void *data, struct
wl_registry *r
+ struct wl_output *output = wl_registry_bind (registry,
+ id,
+ &wl_output_interface,
+- 1);
++ wl_output_version);
++
++ GldiScreenInfo *p_screeninfo = NULL;
++ int screen_num = get_position_gldi_screeninfo_by_id(g_desktopGeometry.pScreens,
g_desktopGeometry.iNbScreens, id);
++ if (screen_num >= 0)
++ p_screeninfo = g_desktopGeometry.pScreens + screen_num;
++ else
++ p_screeninfo = append_gldi_screeninfo(&g_desktopGeometry.pScreens,
&g_desktopGeometry.iNbScreens);
++
++ {
++ // register new wl_output
++ GldiWlOutput *p_wloutput = &p_screeninfo->wloutput;
++ p_wloutput->output = output;
++ p_wloutput->id = id;
++ p_wloutput->ver = wl_output_version;
++ }
++
+ wl_output_add_listener (output,
+ &output_listener,
+- NULL);
++ p_screeninfo);
+ }
+ s_bInitializing = TRUE;
+ }
+@@ -153,7 +250,7 @@ static void _registry_global_cb (G_GNUC_UNUSED void *data, struct
wl_registry *r
+ static void _registry_global_remove_cb (G_GNUC_UNUSED void *data, G_GNUC_UNUSED struct
wl_registry *registry, uint32_t id)
+ {
+ cd_debug ("got a global object has disappeared: id=%d", id);
+- /// TODO: find it and destroy it...
++ remove_gldi_screeninfo_by_id(&g_desktopGeometry.pScreens,
&g_desktopGeometry.iNbScreens, id);
+
+ /// TODO: and if it was a wl_output for instance, update the desktop geometry...
+
+@@ -171,6 +268,9 @@ static void init (void)
+ s_pDisplay = wl_display_connect (NULL);
+
+ g_desktopGeometry.iNbDesktops = g_desktopGeometry.iNbViewportX =
g_desktopGeometry.iNbViewportY = 1;
++ // Explicitly initialize below for readability
++ g_desktopGeometry.pScreens = NULL;
++ g_desktopGeometry.iNbScreens = 0;
+
+
+ struct wl_registry *registry = wl_display_get_registry (s_pDisplay);
+--
+2.31.1
+
diff --git a/cairo-dock-freeworld.spec b/cairo-dock-freeworld.spec
index 2bbdf43..b5e5693 100644
--- a/cairo-dock-freeworld.spec
+++ b/cairo-dock-freeworld.spec
@@ -1,7 +1,7 @@
-%global urlver 3.4
-%global mainver 3.4.0
+%global urlver 3.4
+%global mainver 3.4.1
-%global plugin_least_ver 3.4.0
+%global plugin_least_ver 3.4.1
%global use_git 1
%global gitdate 20210327
@@ -9,11 +9,24 @@
%global shorthash %(c=%{githash} ; echo ${c:0:7})
%global tarballver %{mainver}%{?use_git:-%{gitdate}git%{shorthash}}
-%global mainrel 12
+
+%global mainrel 13
+
+%undefine _ld_strict_symbol_defs
+%undefine __brp_mangle_shebangs
+
+##########################################
+%global flagrel %{nil}
+%global use_gcc_strict_sanitize 0
+
+%if 0%{?use_gcc_strict_sanitize} >= 1
+%global flagrel %{flagrel}.san
+%endif
+##########################################
Name: cairo-dock-freeworld
Version: 3.4.1
-Release: %{mainrel}%{?use_git:.D%{gitdate}git%{shorthash}}%{?dist}.1
+Release: %{mainrel}%{?use_git:.D%{gitdate}git%{shorthash}}%{?dist}%{flagrel}
Summary: Light eye-candy fully themable animated dock
License: GPLv3+
@@ -24,9 +37,19 @@
Source0:
https://github.com/Cairo-Dock/cairo-dock-core/archive/%{githash}/cairo
Source0:
https://github.com/Cairo-Dock/cairo-dock-core/archive/%{version}/cairo-do...
%endif
Source1: cairo-dock-freeworld-oldchangelog
+# wayland-manager: allocate new wl_output information by checking id
+#
https://bugzilla.redhat.com/show_bug.cgi?id=2000812
+#
https://github.com/Cairo-Dock/cairo-dock-core/pull/12
+Patch1: 0001-LP1943052-wayland-manager-allocate-new-wl_output-inf.patch
+
+BuildRequires: gcc
+BuildRequires: gcc-c++
+BuildRequires: cmake
+%if 0%{?use_gcc_strict_sanitize}
+BuildRequires: libasan
+BuildRequires: libubsan
+%endif
-BuildRequires: cmake
-BuildRequires: gcc-c++
#BuildRequires: desktop-file-utils
BuildRequires: gettext
BuildRequires: intltool
@@ -34,6 +57,7 @@ BuildRequires: intltool
BuildRequires: pkgconfig(cairo)
BuildRequires: pkgconfig(dbus-1)
BuildRequires: pkgconfig(dbus-glib-1)
+#BuildRequires: pkgconfig(egl)
BuildRequires: pkgconfig(gl)
BuildRequires: pkgconfig(glib-2.0)
BuildRequires: pkgconfig(glu)
@@ -66,9 +90,9 @@ This package contains library files for %{name}.
%prep
%if 0%{?use_git} >= 1
-%setup -q -n cairo-dock-core-%{githash}
+%autosetup -n cairo-dock-core-%{githash} -p1
%else
-%setup -q -n cairo-dock-core-%{version}
+%autosetup -n cairo-dock-core-%{version} -p1
%endif
## permission
@@ -92,8 +116,27 @@ sed -i.stat \
sed -i CMakeLists.txt -e '\@set (VERSION @s|VERSION.*|VERSION
"%{version}")|'
%build
+%set_build_flags
+
+%if 0%{?use_gcc_strict_sanitize}
+export CC="${CC} -fsanitize=address -fsanitize=undefined"
+export CXX="${CXX} -fsanitize=address -fsanitize=undefined"
+export LDFLAGS="${LDFLAGS} -pthread"
+
+# Currently -fPIE binary cannot work with ASAN on kernel 4.12
+#
https://github.com/google/sanitizers/issues/837
+export CFLAGS="$(echo $CFLAGS | sed -e 's|-specs=[^ \t][^ \t]*hardened[^
\t][^ \t]*||g')"
+export CXXFLAGS="$(echo $CXXFLAGS | sed -e 's|-specs=[^ \t][^ \t]*hardened[^
\t][^ \t]*||g')"
+export LDFLAGS="$(echo $LDFLAGS | sed -e 's|-specs=[^ \t][^ \t]*hardened[^
\t][^ \t]*||g')"
+%endif
+
rm -f CMakeCache.txt
-%cmake -B . -DCMAKE_SKIP_RPATH:BOOL=ON .
+%cmake \
+ -B . \
+ -DCMAKE_SKIP_RPATH:BOOL=ON \
+ -Denable-egl-support:BOOL=OFF \
+ . \
+ %{nil}
make -C src/gldit %{?_smp_mflags}
%install
@@ -143,6 +186,11 @@ install -cpm 644 \
%{_libdir}/%{name}/libgldi.so.3*
%changelog
+* Mon Sep 20 2021 Mamoru TASAKA <mtasaka(a)fedoraproject.org> -
3.4.1-13.D20210327git6c569e6
+- wayland-manager: allocate new wl_output information by checking id
+ (Fix segfault on KDE Plasma wayland session: redhat bug 2000812)
+- Explicitly disable EGL support for now
+
* Mon Aug 02 2021 RPM Fusion Release Engineering <leigh123linux(a)gmail.com> -
3.4.1-12.D20210327git6c569e6.1
- Rebuilt for
https://fedoraproject.org/wiki/Fedora_35_Mass_Rebuild