Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,8 @@ dep_option(SDL_WAYLAND "Use Wayland video driver" ${UNIX_SYS} "SDL_V
dep_option(SDL_WAYLAND_SHARED "Dynamically load Wayland support" ON "SDL_WAYLAND;SDL_DEPS_SHARED" OFF)
dep_option(SDL_WAYLAND_LIBDECOR "Use client-side window decorations on Wayland" ON "SDL_WAYLAND" OFF)
dep_option(SDL_WAYLAND_LIBDECOR_SHARED "Dynamically load libdecor support" ON "SDL_WAYLAND_LIBDECOR;SDL_WAYLAND_SHARED;SDL_DEPS_SHARED" OFF)
dep_option(SDL_WAYLAND_FCFT "International text rendering for Wayland toolkit functionality" ON "SDL_WAYLAND" OFF)
dep_option(SDL_WAYLAND_FCFT_SHARED "Dynamically load fcft support" ON "SDL_WAYLAND_FCFT;SDL_WAYLAND_SHARED;SDL_DEPS_SHARED" OFF)
dep_option(SDL_RPI "Use Raspberry Pi video driver" ON "SDL_VIDEO;UNIX_SYS;SDL_CPU_ARM32 OR SDL_CPU_ARM64" OFF)
dep_option(SDL_ROCKCHIP "Use ROCKCHIP Hardware Acceleration video driver" ON "SDL_VIDEO;UNIX_SYS;SDL_CPU_ARM32 OR SDL_CPU_ARM64" OFF)
dep_option(SDL_COCOA "Use Cocoa video driver" ON "APPLE" OFF)
Expand Down
25 changes: 24 additions & 1 deletion cmake/sdlchecks.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -649,10 +649,33 @@ macro(CheckWayland)
sdl_link_dependency(libdecor INCLUDES $<TARGET_PROPERTY:PkgConfig::PC_LIBDECOR,INTERFACE_INCLUDE_DIRECTORIES>)
else()
sdl_link_dependency(libdecor LIBS PkgConfig::PC_LIBDECOR PKG_CONFIG_PREFIX PC_LIBDECOR PKG_CONFIG_SPECS ${LibDecor_PKG_CONFIG_SPEC})
endif()
endif()
endif()
endif()

if(SDL_WAYLAND_FCFT)
set(LibFcft_PKG_CONFIG_SPEC fcft)
pkg_check_modules(PC_LIBFCFT IMPORTED_TARGET ${LibFcft_PKG_CONFIG_SPEC})
if(PC_LIBFCFT_FOUND)
if(PC_LIBFCFT_VERSION VERSION_GREATER_EQUAL "3.0.0")
set(LibFcft_PKG_CONFIG_SPEC "fcft>=3.0.0")
endif()
set(HAVE_WAYLAND_FCFT TRUE)
set(HAVE_FCFT_H 1)
if(SDL_WAYLAND_FCFT_SHARED AND NOT HAVE_SDL_LOADSO)
message(WARNING "You must have SDL_LoadObject() support for dynamic fcft loading")
endif()
FindLibraryAndSONAME(fcft LIBDIRS ${PC_LIBFCFT_LIBRARY_DIRS})
if(SDL_WAYLAND_FCFT_SHARED AND FCFT_LIB AND HAVE_SDL_LOADSO)
set(HAVE_WAYLAND_FCFT_SHARED TRUE)
set(SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_FCFT "\"${FCFT_LIB_SONAME}\"")
sdl_link_dependency(libfcft INCLUDES $<TARGET_PROPERTY:PkgConfig::PC_LIBFCFT,INTERFACE_INCLUDE_DIRECTORIES>)
else()
sdl_link_dependency(libfcft LIBS PkgConfig::PC_LIBFCFT PKG_CONFIG_PREFIX PC_LIBFCFT PKG_CONFIG_SPECS ${LibFcft_PKG_CONFIG_SPEC})
endif()
endif()
endif()

set(SDL_VIDEO_DRIVER_WAYLAND 1)
endif()
endif()
Expand Down
37 changes: 37 additions & 0 deletions include/SDL3/SDL_hints.h
Original file line number Diff line number Diff line change
Expand Up @@ -3792,6 +3792,43 @@ extern "C" {
*/
#define SDL_HINT_VIDEO_WAYLAND_SCALE_TO_DISPLAY "SDL_VIDEO_WAYLAND_SCALE_TO_DISPLAY"

/**
* A variable controlling whether the built in SDL toolkit is prefered over Zenity
* under the Wayland driver.
*
* When this hint is set, the Wayland driver will use the built in toolkit even
* in cases where Zenity is avalible.
*
* The variable can be set to the following values:
*
* - "0": The built in toolkit is only used in cases where Zenity fails or is unavalible.
* (default)
* - "1": The built in toolkit is always used if available.
*
* This hint should be set before SDL is initialized.
*
* \since This hint is available since SDL 3.?.?.
*/
#define SDL_HINT_VIDEO_WAYLAND_PREFER_TOOLKIT "SDL_VIDEO_WAYLAND_PREFER_TOOLKIT"

/**
* A variable controlling whether the built in SDL toolkit uses fcft or
* built in bitmap fonts.
*
* The fcft library is used over the built in bitmap fonts in cases
* where it is avalible.
*
* The variable can be set to the following values:
*
* - "0": Usage of the fcft library is disabled.
* - "1": Usage of the fcft library is enabled. (default)
*
* This hint should be set before SDL is initialized.
*
* \since This hint is available since SDL 3.?.?.
*/
#define SDL_HINT_VIDEO_WAYLAND_ALLOW_FCFT "SDL_VIDEO_WAYLAND_ALLOW_FCFT"

/**
* A variable specifying which shader compiler to preload when using the
* Chrome ANGLE binaries.
Expand Down
2 changes: 2 additions & 0 deletions include/build_config/SDL_build_config.h.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -215,6 +215,7 @@
#cmakedefine HAVE_LINUX_INPUT_H 1
#cmakedefine HAVE_LIBUDEV_H 1
#cmakedefine HAVE_LIBDECOR_H 1
#cmakedefine HAVE_FCFT_H 1
#cmakedefine HAVE_LIBURING_H 1

#cmakedefine HAVE_DDRAW_H 1
Expand Down Expand Up @@ -416,6 +417,7 @@
#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_EGL@
#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_LIBDECOR@
#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_XKBCOMMON@
#cmakedefine SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_FCFT @SDL_VIDEO_DRIVER_WAYLAND_DYNAMIC_FCFT@
#cmakedefine SDL_VIDEO_DRIVER_WINDOWS 1
#cmakedefine SDL_VIDEO_DRIVER_X11 1
#cmakedefine SDL_VIDEO_DRIVER_X11_DYNAMIC @SDL_VIDEO_DRIVER_X11_DYNAMIC@
Expand Down
40 changes: 38 additions & 2 deletions src/video/wayland/SDL_waylandmessagebox.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,33 @@
#ifdef SDL_VIDEO_DRIVER_WAYLAND

#include "SDL_waylandmessagebox.h"
#include "SDL_waylandtoolkit.h"
#include "../../dialog/unix/SDL_zenitymessagebox.h"

typedef struct SDL_MessageBoxDataToolkit
{
SDL_WaylandTextRenderer *text_renderer;

const SDL_MessageBoxData *messageboxdata;
} SDL_MessageBoxDataToolkit;

bool Wayland_ShowToolkitMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonID) {
SDL_MessageBoxDataToolkit data;
SDL_Color color;

data.messageboxdata = messageboxdata;
color.r = 255;
color.g = 0;
color.b = 255;
color.a = 255;

data.text_renderer = WaylandToolkit_CreateTextRenderer();
WaylandToolkit_RenderText(data.text_renderer, (char *)messageboxdata->message, &color);
WaylandToolkit_FreeTextRenderer(data.text_renderer);

return true;
}

bool Wayland_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *buttonID)
{
// Are we trying to connect to or are currently in a Wayland session?
Expand All @@ -35,8 +60,19 @@ bool Wayland_ShowMessageBox(const SDL_MessageBoxData *messageboxdata, int *butto
return SDL_SetError("Not on a wayland display");
}
}

return SDL_Zenity_ShowMessageBox(messageboxdata, buttonID);

if (SDL_GetHintBoolean(SDL_HINT_VIDEO_WAYLAND_PREFER_TOOLKIT, false)) {
return Wayland_ShowToolkitMessageBox(messageboxdata, buttonID);
} else {
bool ret;

ret = SDL_Zenity_ShowMessageBox(messageboxdata, buttonID);
if (!ret) {
return Wayland_ShowToolkitMessageBox(messageboxdata, buttonID);
} else {
return ret;
}
}
}

#endif // SDL_VIDEO_DRIVER_WAYLAND
175 changes: 175 additions & 0 deletions src/video/wayland/SDL_waylandtoolkit.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>

This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/

#ifdef SDL_VIDEO_DRIVER_WAYLAND

#include "SDL_internal.h"
#include "SDL_waylandtoolkit.h"
#include "SDL_waylandtoolkitbitmap.h"
#ifdef HAVE_FCFT_H
#include "SDL_waylandtoolkitfcft.h"
#endif

/* Nasty struct definition needed because of macro hell :( */
struct SDL_Surface
{
SDL_SurfaceFlags flags;
SDL_PixelFormat format;
int w;
int h;
int pitch;
void *pixels;
int refcount;
void *reserved;
};

extern SDL_WaylandTextRenderer *WaylandToolkit_CreateTextRenderer() {
SDL_WaylandTextRenderer *ret;

#ifdef HAVE_FCFT_H
if (SDL_GetHintBoolean(SDL_HINT_VIDEO_WAYLAND_ALLOW_FCFT, true)) {
ret = WaylandToolkit_CreateTextRendererFcft();
} else {
ret = NULL;
}
#else
ret = NULL;
#endif

if (!ret) {
return WaylandToolkit_CreateTextRendererBitmap();
} else {
return ret;
}
}

/* For debugging */
void rand_str(char *dest, size_t length) {
char charset[] = "0123456789"
"abcdefghijklmnopqrstuvwxyz"
"ABCDEFGHIJKLMNOPQRSTUVWXYZ";

while (length-- > 0) {
size_t index = (size_t)((double) rand() / RAND_MAX * (sizeof charset - 1));
*dest++ = charset[index];
}
*dest = '\0';
}

SDL_Surface *WaylandToolkit_RenderText(SDL_WaylandTextRenderer *renderer, char *utf8, SDL_Color *bg_fill) {
if (renderer) {
SDL_Surface **surfaces;
SDL_Surface *ret;
char *utf8t;
char *start;
char *end;
size_t utf8t_sz;
int surfaces_count;
int max_surface_width;
int total_surface_height;
int i;
SDL_Rect rct;

surfaces = NULL;
max_surface_width = 0;
surfaces_count = 0;
total_surface_height = 0;
rct.x = 0;
rct.y = 0;
ret = NULL;
utf8t_sz = SDL_strlen(utf8) + 2;
utf8t = SDL_malloc(utf8t_sz);
if (!utf8t) {
return NULL;
}
SDL_strlcpy(utf8t, utf8, utf8t_sz);
SDL_strlcat(utf8t, "\n", utf8t_sz);
start = end = utf8t;

while ((end = SDL_strpbrk(start, "\n\r\f\v"))) {
Uint32 *utf32;
char *utf8ta;
size_t sz;
size_t ci;

i = surfaces_count;
surfaces_count++;
if (surfaces_count == 1) {
surfaces = SDL_calloc(surfaces_count, sizeof(SDL_Surface *));
} else {
surfaces = SDL_realloc(surfaces, surfaces_count * sizeof(SDL_Surface *));
}
utf8ta = SDL_strndup(start, (size_t)(end - start));
sz = SDL_utf8strlen(utf8ta);
utf32 = SDL_iconv_utf8_ucs4(utf8ta);
for (ci = 0; ci < sz; ci++) {
utf32[ci] = SDL_Swap32BE(utf32[ci]);
}
surfaces[i] = renderer->render(renderer, utf32, sz, bg_fill);
max_surface_width = SDL_max(max_surface_width, surfaces[i]->w);
total_surface_height += surfaces[i]->h;
SDL_free(utf32);
SDL_free(utf8ta);
start = end + 1;
}

ret = SDL_CreateSurface(max_surface_width, total_surface_height, SDL_PIXELFORMAT_ARGB8888);
puts(SDL_GetError()); /* debug */
for (i = 0; i < surfaces_count; i++) {
SDL_BlitSurface(surfaces[i], NULL, ret, &rct);
rct.y += surfaces[i]->h;
SDL_DestroySurface(surfaces[i]);
}

/* debug */
char a[256];
strcpy(a, "tkdbg_");
rand_str(a+6, 6);
strcpy(a+11, ".bmp");
a[15] = '\0';
SDL_SaveBMP(ret, a);
SDL_free(utf8t);
return ret;
} else {
return NULL;
}
}

void WaylandToolkit_FreeTextRenderer(SDL_WaylandTextRenderer *renderer) {
if (renderer) {
renderer->free(renderer);
}
}

void WaylandToolkit_SetTextRendererSize(SDL_WaylandTextRenderer *renderer, int pt_sz) {
if (renderer) {
renderer->set_pt_sz(renderer, pt_sz);
}
}

void WaylandToolkit_SetTextRendererColor(SDL_WaylandTextRenderer *renderer, SDL_Color *color) {
if (renderer) {
renderer->set_color(renderer, color);
}
}

#endif // SDL_VIDEO_DRIVER_WAYLAND

43 changes: 43 additions & 0 deletions src/video/wayland/SDL_waylandtoolkit.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>

This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.

Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:

1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*/

#ifndef SDL_waylandtoolkit_h_
#define SDL_waylandtoolkit_h_

#ifdef SDL_VIDEO_DRIVER_WAYLAND

/* TEXT RENDERING */
typedef struct SDL_WaylandTextRenderer {
SDL_Surface *(*render)(struct SDL_WaylandTextRenderer *renderer, Uint32 *utf32, int sz, SDL_Color *bg_fill);
void (*set_color)(struct SDL_WaylandTextRenderer *renderer, SDL_Color *color);
void (*set_pt_sz)(struct SDL_WaylandTextRenderer *renderer, int pt_sz);
void (*free)(struct SDL_WaylandTextRenderer *renderer);
} SDL_WaylandTextRenderer;

extern SDL_WaylandTextRenderer *WaylandToolkit_CreateTextRenderer();
extern void WaylandToolkit_SetTextRendererSize(SDL_WaylandTextRenderer *renderer, int pt_sz);
extern void WaylandToolkit_SetTextRendererColor(SDL_WaylandTextRenderer *renderer, SDL_Color *color);
extern SDL_Surface *WaylandToolkit_RenderText(SDL_WaylandTextRenderer *renderer, char *utf8, SDL_Color *bg_fill);
extern void WaylandToolkit_FreeTextRenderer(SDL_WaylandTextRenderer *renderer);

#endif // SDL_VIDEO_DRIVER_WAYLAND

#endif // SDL_waylandtoolkit_h_
Loading
Loading