GHOST/Wayland: use XDG_CURRENT_DESKTOP to detect GNOME

This change was made previously [0] but reverted as it caused the
title-bar to disappear on Ubuntu (see #121241).
Check if the value is set to GNOME delimited by `:`.

Previously checking the interfaces was used which has the down-side
that any compositor that adds `gtk_shell*` support may hang on startup
because of bugs in Blender/LIBDECOR as happened with WAYFIRE,
see reply to #76428.

[0]: 3a5389d5ab
This commit is contained in:
Campbell Barton
2024-05-02 10:20:59 +10:00
parent 523d84db85
commit 2d152db090

View File

@@ -191,15 +191,6 @@ static bool use_gnome_confine_hack = false;
*/
#define USE_KDE_TABLET_HIDDEN_CURSOR_HACK
/**
* When GNOME is found, require `libdecor`.
* This is a hack because it seems there is no way to check if the compositor supports
* server side decorations when initializing WAYLAND.
*/
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
# define USE_GNOME_NEEDS_LIBDECOR_HACK
#endif
/** \} */
/* -------------------------------------------------------------------- */
@@ -1362,12 +1353,6 @@ struct GWL_Display {
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
GWL_LibDecor_System *libdecor = nullptr;
bool libdecor_required = false;
/**
* When true, behave as if `libdecor_required` is false.
* `libdecor_required` can't simply be set to false because the order of assignment is undefined.
*/
bool libdecor_required_ignore = false;
#endif
GWL_XDG_Decor_System *xdg_decor = nullptr;
@@ -1778,6 +1763,35 @@ static void gwl_registry_entry_update_all(GWL_Display *display, const int interf
/** \name Private Utility Functions
* \{ */
static const char *strchr_or_end(const char *str, const char ch)
{
const char *p = str;
while (!ELEM(*p, ch, '\0')) {
p++;
}
return p;
}
static bool string_elem_split_by_delim(const char *haystack, const char delim, const char *needle)
{
/* Local copy of #BLI_string_elem_split_by_delim (would be a bad level call). */
/* May be zero, returns true when an empty span exists. */
const size_t needle_len = strlen(needle);
const char *p = haystack, *p_next;
while (true) {
p_next = strchr_or_end(p, delim);
if ((size_t(p_next - p) == needle_len) && (memcmp(p, needle, needle_len) == 0)) {
return true;
}
if (*p_next == '\0') {
break;
}
p = p_next + 1;
}
return false;
}
static uint64_t sub_abs_u64(const uint64_t a, const uint64_t b)
{
return a > b ? a - b : b - a;
@@ -6985,35 +6999,6 @@ static void global_handle_add(void *data,
added = display->registry_entry != registry_entry_prev;
}
else {
/* Not found. */
#ifdef USE_GNOME_NEEDS_LIBDECOR_HACK
/* NOTE(@ideasman42): I'm not happy with the logic here because it's fairly fragile
* and will cause problems whenever any non-GNOME compositor adds support for `gtk_shell*`
* Ideally there would be a way to:
* - Detect when server-side-decorations aren't supported.
* `zxdg_decoration_manager_v1` looks like it *could* be used
* but it's not supported by GNOME.
* - Detect the underlying compositor.
* `XDG_CURRENT_DESKTOP` could be used but isn't always set, see: #121241.
*
* All things considered, inspecting interface names seems least terrible (sigh).
*/
/* `gtk_shell1` at time of writing. */
if (STRPREFIX(interface, "gtk_shell")) {
/* Only require `libdecor` when built with X11 support,
* otherwise there is nothing to fall back on. */
display->libdecor_required = true;
}
/* `zwf_shell_manager_v2` at time of writing. */
else if (STRPREFIX(interface, "zwf_shell_manager_v")) {
/* Needed when non GNOME compositors provide the `gtk_shell*` interface.
* WAYFIRE in this case. */
display->libdecor_required_ignore = true;
}
#endif
}
CLOG_INFO(LOG,
2,
@@ -7171,28 +7156,33 @@ GHOST_SystemWayland::GHOST_SystemWayland(bool background)
}
#ifdef WITH_GHOST_WAYLAND_LIBDECOR
if (display_->libdecor_required_ignore) {
display_->libdecor_required = false;
bool libdecor_required = false;
if (const char *xdg_current_desktop = getenv("XDG_CURRENT_DESKTOP")) {
/* See the free-desktop specifications for details on `XDG_CURRENT_DESKTOP`.
* https://specifications.freedesktop.org/desktop-entry-spec/desktop-entry-spec-latest.html */
if (string_elem_split_by_delim(xdg_current_desktop, ':', "GNOME")) {
libdecor_required = true;
}
}
if (display_->libdecor_required) {
if (libdecor_required) {
/* Ignore windowing requirements when running in background mode,
* as it doesn't make sense to fall back to X11 because of windowing functionality
* in background mode, also LIBDECOR is crashing in background mode `blender -b -f 1`
* for e.g. while it could be fixed, requiring the library at all makes no sense. */
if (background) {
display_->libdecor_required = false;
libdecor_required = false;
}
# ifdef WITH_GHOST_X11
else if (!has_libdecor && !ghost_wayland_is_x11_available()) {
/* Only require LIBDECOR when X11 is available, otherwise there is nothing to fall back to.
* It's better to open without window decorations than failing entirely. */
display_->libdecor_required = false;
libdecor_required = false;
}
# endif /* WITH_GHOST_X11 */
}
if (display_->libdecor_required) {
if (libdecor_required) {
gwl_xdg_decor_system_destroy(display_, display_->xdg_decor);
display_->xdg_decor = nullptr;