Wayland: Fix crash if mouse connected after init

The cursor theme was only loaded if the chosen seat had a mouse
(wl_pointer) during initialization.  If a mouse was connected only after
glfwInit, there would be no cursor theme but the rest of the cursor
related code assumed one had already been loaded.

This also moves the details of cursor theme loading out into a separate
function to declutter platform init.

Because the original cursor theme loading code checked whether we got
a wl_shm, and because the rest of the code just assumes we have
a wl_shm, initialization will now fail if there isn't one.

Fixes #1450

(cherry picked from commit 71be34a6c3)
This commit is contained in:
Camilla Löwy 2022-07-15 13:12:58 +02:00
parent b08271d315
commit ad206bdaee
3 changed files with 44 additions and 31 deletions

View File

@ -183,6 +183,7 @@ video tutorials.
- Philip Rideout
- Eddie Ringle
- Max Risuhin
- Joe Roback
- Jorge Rodriguez
- Luca Rood
- Ed Ropple

View File

@ -123,6 +123,7 @@ information on what to include when reporting a bug.
## Changelog
- [Wayland] Bugfix: Connecting a mouse after `glfwInit` would segfault (#1450)
- [Linux] Bugfix: Joysticks without buttons were ignored (#2042,#2043)

View File

@ -300,12 +300,7 @@ static void createKeyTables(void)
}
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
int _glfwPlatformInit(void)
static GLFWbool loadCursorTheme(void)
{
const char* cursorTheme;
const char* cursorSizeStr;
@ -313,6 +308,40 @@ int _glfwPlatformInit(void)
long cursorSizeLong;
int cursorSize;
cursorTheme = getenv("XCURSOR_THEME");
cursorSizeStr = getenv("XCURSOR_SIZE");
cursorSize = 32;
if (cursorSizeStr)
{
errno = 0;
cursorSizeLong = strtol(cursorSizeStr, &cursorSizeEnd, 10);
if (!*cursorSizeEnd && !errno && cursorSizeLong > 0 && cursorSizeLong <= INT_MAX)
cursorSize = (int)cursorSizeLong;
}
_glfw.wl.cursorTheme =
wl_cursor_theme_load(cursorTheme, cursorSize, _glfw.wl.shm);
if (!_glfw.wl.cursorTheme)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to load default cursor theme");
return GLFW_FALSE;
}
// If this happens to be NULL, we just fallback to the scale=1 version.
_glfw.wl.cursorThemeHiDPI =
wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm);
_glfw.wl.cursorSurface =
wl_compositor_create_surface(_glfw.wl.compositor);
_glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
return GLFW_TRUE;
}
//////////////////////////////////////////////////////////////////////////
////// GLFW platform API //////
//////////////////////////////////////////////////////////////////////////
int _glfwPlatformInit(void)
{
// These must be set before any failure checks
_glfw.wl.keyRepeatTimerfd = -1;
_glfw.wl.cursorTimerfd = -1;
@ -448,33 +477,15 @@ int _glfwPlatformInit(void)
return GLFW_FALSE;
}
if (_glfw.wl.pointer && _glfw.wl.shm)
{
cursorTheme = getenv("XCURSOR_THEME");
cursorSizeStr = getenv("XCURSOR_SIZE");
cursorSize = 32;
if (cursorSizeStr)
{
errno = 0;
cursorSizeLong = strtol(cursorSizeStr, &cursorSizeEnd, 10);
if (!*cursorSizeEnd && !errno && cursorSizeLong > 0 && cursorSizeLong <= INT_MAX)
cursorSize = (int)cursorSizeLong;
}
_glfw.wl.cursorTheme =
wl_cursor_theme_load(cursorTheme, cursorSize, _glfw.wl.shm);
if (!_glfw.wl.cursorTheme)
if (!_glfw.wl.shm)
{
_glfwInputError(GLFW_PLATFORM_ERROR,
"Wayland: Failed to load default cursor theme");
"Wayland: Failed to find wl_shm in your compositor");
return GLFW_FALSE;
}
// If this happens to be NULL, we just fallback to the scale=1 version.
_glfw.wl.cursorThemeHiDPI =
wl_cursor_theme_load(cursorTheme, 2 * cursorSize, _glfw.wl.shm);
_glfw.wl.cursorSurface =
wl_compositor_create_surface(_glfw.wl.compositor);
_glfw.wl.cursorTimerfd = timerfd_create(CLOCK_MONOTONIC, TFD_CLOEXEC | TFD_NONBLOCK);
}
if (!loadCursorTheme())
return GLFW_FALSE;
if (_glfw.wl.seat && _glfw.wl.dataDeviceManager)
{