Fix immediate exit when displaying an invalid UTF8 title on Wayland

A non UTF8 title on Wayland causes disconnection from the server.
Resolve by using the path as-is unless invalid UTF8 byte sequences
are found, in that case they're replaced by `?`.

This is skipped on WIN32 & macOS since the issue only exists on Wayland.
This commit is contained in:
Campbell Barton
2025-06-26 17:48:09 +10:00
parent c5bae85893
commit 6d06fc3979
3 changed files with 64 additions and 3 deletions

View File

@@ -49,6 +49,18 @@ int BLI_str_utf8_invalid_strip(char *str, size_t str_len) ATTR_NONNULL(1);
int BLI_str_utf8_invalid_substitute(char *str, size_t str_len, const char substitute)
ATTR_NONNULL(1);
/**
* A utility for #BLI_str_utf8_invalid_substitute that returns `str` when it contains a
* valid UTF8 string. Otherwise it is copied into `buf` with invalid byte sequences
* substituted for `substitute`.
*
* \note This is intended for situations when the string is expected to be valid,
* where copying and substituting values is typically not needed.
*/
[[nodiscard]] const char *BLI_str_utf8_invalid_substitute_as_needed(
const char *str, size_t str_len, const char substitute, char *buf, const size_t buf_maxncpy)
ATTR_NONNULL(1, 4);
/**
* \return The size (in bytes) of a single UTF8 char.
* \warning Can return -1 on bad chars.

View File

@@ -326,6 +326,40 @@ int BLI_str_utf8_invalid_substitute(char *str, size_t str_len, const char substi
return tot;
}
const char *BLI_str_utf8_invalid_substitute_as_needed(const char *str,
const size_t str_len,
const char substitute,
char *buf,
const size_t buf_maxncpy)
{
BLI_assert(str[str_len] == '\0');
const ptrdiff_t bad_char = BLI_str_utf8_invalid_byte(str, str_len);
if (LIKELY(bad_char == -1)) {
return str;
}
BLI_assert(bad_char >= 0);
/* In the case a bad character is outside the buffer limit,
* simply perform a truncating UTF8 copy into the buffer and return that. */
if (UNLIKELY(size_t(bad_char) >= buf_maxncpy)) {
BLI_strncpy_utf8(buf, str, buf_maxncpy);
return buf;
}
size_t buf_len;
if (str_len < buf_maxncpy) {
memcpy(buf, str, str_len + 1);
buf_len = str_len;
}
else {
buf_len = BLI_strncpy_rlen(buf, str, buf_maxncpy);
}
/* Skip the good characters. */
BLI_str_utf8_invalid_substitute(buf + bad_char, buf_len - size_t(bad_char), substitute);
return buf;
}
/**
* Internal utility for implementing #BLI_strncpy_utf8 / #BLI_strncpy_utf8_rlen.
*

View File

@@ -512,11 +512,26 @@ void WM_window_title(wmWindowManager *wm, wmWindow *win, const char *title)
return;
}
const char *filepath = BKE_main_blendfile_path_from_global();
const char *filename = BLI_path_basename(filepath);
/* This path may contain invalid UTF8 byte sequences on UNIX systems,
* use `filepath` for display which is sanitized as needed. */
const char *filepath_as_bytes = BKE_main_blendfile_path_from_global();
char _filepath_utf8_buf[FILE_MAX];
/* Allow non-UTF8 characters on systems that support it.
*
* On Wayland, invalid UTF8 characters will disconnect
* from the server - exiting immediately. */
const char *filepath = (OS_MAC || OS_WINDOWS) ?
filepath_as_bytes :
BLI_str_utf8_invalid_substitute_as_needed(filepath_as_bytes,
strlen(filepath_as_bytes),
'?',
_filepath_utf8_buf,
sizeof(_filepath_utf8_buf));
const char *filename = BLI_path_basename(filepath);
const bool has_filepath = filepath[0] != '\0';
const bool native_filepath_display = GHOST_SetPath(handle, filepath) == GHOST_kSuccess;
const bool native_filepath_display = GHOST_SetPath(handle, filepath_as_bytes) == GHOST_kSuccess;
const bool include_filepath = has_filepath && (filepath != filename) && !native_filepath_display;
/* File saved state. */