Skip to content

Commit c0034b1

Browse files
author
Semphris
committed
Add basic Ubuntu Touch functions
This adds support for: - System theme - Sandbox detection - Platform detection - Device form factor detection
1 parent 90fd2a3 commit c0034b1

11 files changed

+163
-1
lines changed

CMakeLists.txt

+1
Original file line numberDiff line numberDiff line change
@@ -1791,6 +1791,7 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
17911791
sdl_sources(
17921792
"${SDL3_SOURCE_DIR}/src/core/linux/SDL_evdev_capabilities.c"
17931793
"${SDL3_SOURCE_DIR}/src/core/linux/SDL_threadprio.c"
1794+
"${SDL3_SOURCE_DIR}/src/core/linux/SDL_ubuntu_touch.c"
17941795
)
17951796

17961797
# src/core/unix/*.c is included in a generic if(UNIX) section, elsewhere.

docs/README-ubuntu-touch.md

+38
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
# Ubuntu Touch / Lomiri
2+
3+
Ubuntu Touch being similar to Ubuntu desktop, most features should be supported
4+
out-of-the-box with SDL.
5+
6+
## Developing apps
7+
8+
Ubuntu Touch apps are developed using [Clickable](https://clickable-ut.dev/).
9+
10+
Clickable provides an SDL template. It is highly recommended to use the template
11+
as a starting point for both new and existing apps.
12+
13+
## Considerations
14+
15+
Ubuntu Touch is similar to the desktop version of Ubuntu, but presents some
16+
differences in behavior. Developers should be wary of the following:
17+
18+
### SDL_GetPrefPath
19+
20+
The only allowed writable folder is `~/.local/share/<appname>/`, where
21+
`<appname>` is the identifier string for the app. It can be found in the
22+
`manifest.json` file under the key `"name"`, and usually looks like
23+
`appname.yourname`.
24+
25+
A future version of SDL may change how `SDL_GetPrefPath` operates on Ubuntu
26+
Touch to make it ignore its arguments and always choose the correct writable
27+
folder. For future-proof-ness, using `SDL_GetPrefPath("", "<appname>")` as a
28+
writable directory is a safe choice.
29+
30+
### Video driver
31+
32+
Currently, [a bug](https://github.com/libsdl-org/SDL/issues/12247) forces SDL to
33+
use the Wayland driver on Ubuntu Touch. No changes are needed in apps.
34+
35+
### Extra functions
36+
37+
SDL provides `SDL_IsUbuntuTouch()` to differentiate between Ubuntu Touch and
38+
regular Unix, which can help if certain platform-specific tweaks are needed.

include/SDL3/SDL_system.h

+18-1
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,8 @@ typedef enum SDL_Sandbox
631631
SDL_SANDBOX_UNKNOWN_CONTAINER,
632632
SDL_SANDBOX_FLATPAK,
633633
SDL_SANDBOX_SNAP,
634-
SDL_SANDBOX_MACOS
634+
SDL_SANDBOX_MACOS,
635+
SDL_SANDBOX_LOMIRI
635636
} SDL_Sandbox;
636637

637638
/**
@@ -809,6 +810,22 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetGDKDefaultUser(XUserHandle *outUserHandl
809810

810811
#endif
811812

813+
/*
814+
* Functions used only with Ubuntu Touch
815+
*/
816+
#ifdef SDL_PLATFORM_LINUX
817+
818+
/**
819+
* Detect whether the current platform is Ubuntu Touch.
820+
*
821+
* \returns true if the platform is Ubuntu Touch; false otherwise.
822+
*
823+
* \since This function is available since SDL 3.4.0.
824+
*/
825+
extern SDL_DECLSPEC bool SDLCALL SDL_IsUbuntuTouch(void);
826+
827+
#endif
828+
812829
/* Ends C function definitions when using C++ */
813830
#ifdef __cplusplus
814831
}

src/SDL.c

+6
Original file line numberDiff line numberDiff line change
@@ -804,6 +804,12 @@ static SDL_Sandbox SDL_DetectSandbox(void)
804804
return SDL_SANDBOX_SNAP;
805805
}
806806

807+
/* Ubuntu Touch also supports Snap; check for classic sandboxing only if
808+
* Snap hasn't been detected. */
809+
if (SDL_getenv("LOMIRI_APPLICATION_ISOLATION") || SDL_getenv("CLICKABLE_DESKTOP_MODE")) {
810+
return SDL_SANDBOX_LOMIRI;
811+
}
812+
807813
if (access("/run/host/container-manager", F_OK) == 0) {
808814
return SDL_SANDBOX_UNKNOWN_CONTAINER;
809815
}

src/core/SDL_core_unsupported.c

+10
Original file line numberDiff line numberDiff line change
@@ -211,3 +211,13 @@ Sint32 JNI_OnLoad(void *vm, void *reserved)
211211
return -1; // JNI_ERR
212212
}
213213
#endif
214+
215+
#ifndef SDL_PLATFORM_LINUX
216+
217+
SDL_DECLSPEC bool SDLCALL SDL_IsUbuntuTouch(void);
218+
bool SDL_IsUbuntuTouch(void)
219+
{
220+
return false;
221+
}
222+
223+
#endif

src/core/linux/SDL_system_theme.c

+49
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
#include "SDL_system_theme.h"
2525
#include "../../video/SDL_sysvideo.h"
2626

27+
#include <stdio.h>
2728
#include <unistd.h>
2829

2930
#define PORTAL_DESTINATION "org.freedesktop.portal.Desktop"
@@ -150,7 +151,55 @@ bool SDL_SystemTheme_Init(void)
150151
return true;
151152
}
152153

154+
SDL_SystemTheme UbuntuTouch_GetSystemTheme(void)
155+
{
156+
SDL_SystemTheme theme = SDL_SYSTEM_THEME_UNKNOWN;
157+
FILE *config_file = NULL;
158+
char *line = NULL;
159+
size_t line_alloc = 0;
160+
ssize_t line_size = 0;
161+
bool is_in_general_category = false;
162+
163+
// "Lomiri": Ubuntu Touch 20.04+
164+
// "Ubuntu": Ubuntu Touch 16.04
165+
config_file = fopen("/home/phablet/.config/lomiri-ui-toolkit/theme.ini", "r");
166+
if (!config_file) {
167+
config_file = fopen("/home/phablet/.config/ubuntu-ui-toolkit/theme.ini", "r");
168+
if (!config_file) {
169+
return SDL_SYSTEM_THEME_UNKNOWN;
170+
}
171+
}
172+
173+
while ((line_size = getline(&line, &line_alloc, config_file)) != -1) {
174+
if (line_size >= 1 && line[0] == '[') {
175+
is_in_general_category = SDL_strcmp(line, "[General]\n") == 0;
176+
} else if (is_in_general_category && SDL_strncmp(line, "theme=", 6) == 0) {
177+
if (SDL_strcmp(line, "theme=Lomiri.Components.Themes.SuruDark\n") == 0 ||
178+
SDL_strcmp(line, "theme=Ubuntu.Components.Themes.SuruDark\n") == 0) {
179+
theme = SDL_SYSTEM_THEME_DARK;
180+
} else if (SDL_strcmp(line, "theme=Lomiri.Components.Themes.Ambiance\n") == 0 ||
181+
SDL_strcmp(line, "theme=Ubuntu.Components.Themes.Ambiance\n") == 0) {
182+
theme = SDL_SYSTEM_THEME_LIGHT;
183+
} else {
184+
theme = SDL_SYSTEM_THEME_UNKNOWN;
185+
}
186+
}
187+
188+
free(line); // This should NOT be SDL_free()
189+
}
190+
191+
fclose(config_file);
192+
193+
return theme;
194+
}
195+
153196
SDL_SystemTheme SDL_SystemTheme_Get(void)
154197
{
198+
if (system_theme_data.theme == SDL_SYSTEM_THEME_UNKNOWN) {
199+
// TODO: Use inotify to watch for changes, so that the config file
200+
// doesn't need to be checked each time.
201+
return UbuntuTouch_GetSystemTheme();
202+
}
203+
155204
return system_theme_data.theme;
156205
}

src/core/linux/SDL_ubuntu_touch.c

+32
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
/*
2+
Simple DirectMedia Layer
3+
Copyright (C) 1997-2025 Sam Lantinga <[email protected]>
4+
5+
This software is provided 'as-is', without any express or implied
6+
warranty. In no event will the authors be held liable for any damages
7+
arising from the use of this software.
8+
9+
Permission is granted to anyone to use this software for any purpose,
10+
including commercial applications, and to alter it and redistribute it
11+
freely, subject to the following restrictions:
12+
13+
1. The origin of this software must not be misrepresented; you must not
14+
claim that you wrote the original software. If you use this software
15+
in a product, an acknowledgment in the product documentation would be
16+
appreciated but is not required.
17+
2. Altered source versions must be plainly marked as such, and must not be
18+
misrepresented as being the original software.
19+
3. This notice may not be removed or altered from any source distribution.
20+
*/
21+
#include "SDL_internal.h"
22+
23+
#ifdef SDL_PLATFORM_LINUX
24+
#include <stdio.h>
25+
#include <unistd.h>
26+
27+
bool SDL_IsUbuntuTouch(void)
28+
{
29+
return access("/etc/ubuntu-touch-session.d/", F_OK) == 0;
30+
}
31+
32+
#endif

src/dynapi/SDL_dynapi.sym

+1
Original file line numberDiff line numberDiff line change
@@ -1250,6 +1250,7 @@ SDL3_0.0.0 {
12501250
SDL_GetRenderTextureAddressMode;
12511251
SDL_GetGPUDeviceProperties;
12521252
SDL_CreateGPURenderer;
1253+
SDL_IsUbuntuTouch;
12531254
# extra symbols go here (don't modify this line)
12541255
local: *;
12551256
};

src/dynapi/SDL_dynapi_overrides.h

+1
Original file line numberDiff line numberDiff line change
@@ -1275,3 +1275,4 @@
12751275
#define SDL_GetRenderTextureAddressMode SDL_GetRenderTextureAddressMode_REAL
12761276
#define SDL_GetGPUDeviceProperties SDL_GetGPUDeviceProperties_REAL
12771277
#define SDL_CreateGPURenderer SDL_CreateGPURenderer_REAL
1278+
#define SDL_IsUbuntuTouch SDL_IsUbuntuTouch_REAL

src/dynapi/SDL_dynapi_procs.h

+1
Original file line numberDiff line numberDiff line change
@@ -1283,3 +1283,4 @@ SDL_DYNAPI_PROC(bool,SDL_SetRenderTextureAddressMode,(SDL_Renderer *a,SDL_Textur
12831283
SDL_DYNAPI_PROC(bool,SDL_GetRenderTextureAddressMode,(SDL_Renderer *a,SDL_TextureAddressMode *b,SDL_TextureAddressMode *c),(a,b,c),return)
12841284
SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetGPUDeviceProperties,(SDL_GPUDevice *a),(a),return)
12851285
SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateGPURenderer,(SDL_Window *a,SDL_GPUShaderFormat b,SDL_GPUDevice **c),(a,b,c),return)
1286+
SDL_DYNAPI_PROC(bool,SDL_IsUbuntuTouch,(void),(),return)

src/video/SDL_video.c

+6
Original file line numberDiff line numberDiff line change
@@ -644,6 +644,12 @@ bool SDL_VideoInit(const char *driver_name)
644644

645645
// Select the proper video driver
646646
video = NULL;
647+
#ifdef SDL_PLATFORM_LINUX
648+
// https://github.com/libsdl-org/SDL/issues/12247
649+
if (SDL_IsUbuntuTouch()) {
650+
driver_name = "wayland";
651+
}
652+
#endif
647653
if (!driver_name) {
648654
driver_name = SDL_GetHint(SDL_HINT_VIDEO_DRIVER);
649655
}

0 commit comments

Comments
 (0)