Skip to content

Add basic Ubuntu Touch functions #12543

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
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
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1791,6 +1791,7 @@ elseif(UNIX AND NOT APPLE AND NOT RISCOS AND NOT HAIKU)
sdl_sources(
"${SDL3_SOURCE_DIR}/src/core/linux/SDL_evdev_capabilities.c"
"${SDL3_SOURCE_DIR}/src/core/linux/SDL_threadprio.c"
"${SDL3_SOURCE_DIR}/src/core/linux/SDL_ubuntu_touch.c"
)

# src/core/unix/*.c is included in a generic if(UNIX) section, elsewhere.
Expand Down
38 changes: 38 additions & 0 deletions docs/README-ubuntu-touch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# Ubuntu Touch / Lomiri

Ubuntu Touch being similar to Ubuntu desktop, most features should be supported
out-of-the-box with SDL.

## Developing apps

Ubuntu Touch apps are developed using [Clickable](https://clickable-ut.dev/).

Clickable provides an SDL template. It is highly recommended to use the template
as a starting point for both new and existing apps.

## Considerations

Ubuntu Touch is similar to the desktop version of Ubuntu, but presents some
differences in behavior. Developers should be wary of the following:

### SDL_GetPrefPath

The only allowed writable folder is `~/.local/share/<appname>/`, where
`<appname>` is the identifier string for the app. It can be found in the
`manifest.json` file under the key `"name"`, and usually looks like
`appname.yourname`.

A future version of SDL may change how `SDL_GetPrefPath` operates on Ubuntu
Touch to make it ignore its arguments and always choose the correct writable
folder. For future-proof-ness, using `SDL_GetPrefPath("", "<appname>")` as a
writable directory is a safe choice.

### Video driver

Currently, [a bug](https://github.com/libsdl-org/SDL/issues/12247) forces SDL to
use the Wayland driver on Ubuntu Touch. No changes are needed in apps.

### Extra functions

SDL provides `SDL_IsUbuntuTouch()` to differentiate between Ubuntu Touch and
regular Unix, which can help if certain platform-specific tweaks are needed.
19 changes: 18 additions & 1 deletion include/SDL3/SDL_system.h
Original file line number Diff line number Diff line change
Expand Up @@ -631,7 +631,8 @@ typedef enum SDL_Sandbox
SDL_SANDBOX_UNKNOWN_CONTAINER,
SDL_SANDBOX_FLATPAK,
SDL_SANDBOX_SNAP,
SDL_SANDBOX_MACOS
SDL_SANDBOX_MACOS,
SDL_SANDBOX_LOMIRI
} SDL_Sandbox;

/**
Expand Down Expand Up @@ -809,6 +810,22 @@ extern SDL_DECLSPEC bool SDLCALL SDL_GetGDKDefaultUser(XUserHandle *outUserHandl

#endif

/*
* Functions used only with Ubuntu Touch
*/
#ifdef SDL_PLATFORM_LINUX

/**
* Detect whether the current platform is Ubuntu Touch.
*
* \returns true if the platform is Ubuntu Touch; false otherwise.
*
* \since This function is available since SDL 3.4.0.
*/
extern SDL_DECLSPEC bool SDLCALL SDL_IsUbuntuTouch(void);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Under what conditions does the application need to know this is Ubuntu Touch?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's used internally by SDL to detect when to use certain tweaks for Ubuntu Touch, like the Wayland driver bug. Since Ubuntu Touch is just Linux, it doesn't expose any compiler macro like __UBUNTU_TOUCH__ that could help determine when to use these tweaks.

Since app developers may also want to tweak their apps on Ubuntu Touch, I considered it might help to expose that function in the API.


#endif

/* Ends C function definitions when using C++ */
#ifdef __cplusplus
}
Expand Down
6 changes: 6 additions & 0 deletions src/SDL.c
Original file line number Diff line number Diff line change
Expand Up @@ -804,6 +804,12 @@ static SDL_Sandbox SDL_DetectSandbox(void)
return SDL_SANDBOX_SNAP;
}

/* Ubuntu Touch also supports Snap; check for classic sandboxing only if
* Snap hasn't been detected. */
if (SDL_getenv("LOMIRI_APPLICATION_ISOLATION") || SDL_getenv("CLICKABLE_DESKTOP_MODE")) {
return SDL_SANDBOX_LOMIRI;
}

if (access("/run/host/container-manager", F_OK) == 0) {
return SDL_SANDBOX_UNKNOWN_CONTAINER;
}
Expand Down
10 changes: 10 additions & 0 deletions src/core/SDL_core_unsupported.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,3 +211,13 @@ Sint32 JNI_OnLoad(void *vm, void *reserved)
return -1; // JNI_ERR
}
#endif

#ifndef SDL_PLATFORM_LINUX

SDL_DECLSPEC bool SDLCALL SDL_IsUbuntuTouch(void);
bool SDL_IsUbuntuTouch(void)
{
return false;
}

#endif
49 changes: 49 additions & 0 deletions src/core/linux/SDL_system_theme.c
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
#include "SDL_system_theme.h"
#include "../../video/SDL_sysvideo.h"

#include <stdio.h>
#include <unistd.h>

#define PORTAL_DESTINATION "org.freedesktop.portal.Desktop"
Expand Down Expand Up @@ -150,7 +151,55 @@ bool SDL_SystemTheme_Init(void)
return true;
}

SDL_SystemTheme UbuntuTouch_GetSystemTheme(void)
{
SDL_SystemTheme theme = SDL_SYSTEM_THEME_UNKNOWN;
FILE *config_file = NULL;
char *line = NULL;
size_t line_alloc = 0;
ssize_t line_size = 0;
bool is_in_general_category = false;

// "Lomiri": Ubuntu Touch 20.04+
// "Ubuntu": Ubuntu Touch 16.04
config_file = fopen("/home/phablet/.config/lomiri-ui-toolkit/theme.ini", "r");
if (!config_file) {
config_file = fopen("/home/phablet/.config/ubuntu-ui-toolkit/theme.ini", "r");
if (!config_file) {
return SDL_SYSTEM_THEME_UNKNOWN;
}
}

while ((line_size = getline(&line, &line_alloc, config_file)) != -1) {
if (line_size >= 1 && line[0] == '[') {
is_in_general_category = SDL_strcmp(line, "[General]\n") == 0;
} else if (is_in_general_category && SDL_strncmp(line, "theme=", 6) == 0) {
if (SDL_strcmp(line, "theme=Lomiri.Components.Themes.SuruDark\n") == 0 ||
SDL_strcmp(line, "theme=Ubuntu.Components.Themes.SuruDark\n") == 0) {
theme = SDL_SYSTEM_THEME_DARK;
} else if (SDL_strcmp(line, "theme=Lomiri.Components.Themes.Ambiance\n") == 0 ||
SDL_strcmp(line, "theme=Ubuntu.Components.Themes.Ambiance\n") == 0) {
theme = SDL_SYSTEM_THEME_LIGHT;
} else {
theme = SDL_SYSTEM_THEME_UNKNOWN;
}
}

free(line); // This should NOT be SDL_free()
}

fclose(config_file);

return theme;
}

SDL_SystemTheme SDL_SystemTheme_Get(void)
{
if (system_theme_data.theme == SDL_SYSTEM_THEME_UNKNOWN) {
// TODO: Use inotify to watch for changes, so that the config file
// doesn't need to be checked each time.
return UbuntuTouch_GetSystemTheme();
}

return system_theme_data.theme;
}
32 changes: 32 additions & 0 deletions src/core/linux/SDL_ubuntu_touch.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
Simple DirectMedia Layer
Copyright (C) 1997-2025 Sam Lantinga <[email protected]>

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.
*/
#include "SDL_internal.h"

#ifdef SDL_PLATFORM_LINUX
#include <stdio.h>
#include <unistd.h>

bool SDL_IsUbuntuTouch(void)
{
return access("/etc/ubuntu-touch-session.d/", F_OK) == 0;
}

#endif
1 change: 1 addition & 0 deletions src/dynapi/SDL_dynapi.sym
Original file line number Diff line number Diff line change
Expand Up @@ -1250,6 +1250,7 @@ SDL3_0.0.0 {
SDL_GetRenderTextureAddressMode;
SDL_GetGPUDeviceProperties;
SDL_CreateGPURenderer;
SDL_IsUbuntuTouch;
# extra symbols go here (don't modify this line)
local: *;
};
1 change: 1 addition & 0 deletions src/dynapi/SDL_dynapi_overrides.h
Original file line number Diff line number Diff line change
Expand Up @@ -1275,3 +1275,4 @@
#define SDL_GetRenderTextureAddressMode SDL_GetRenderTextureAddressMode_REAL
#define SDL_GetGPUDeviceProperties SDL_GetGPUDeviceProperties_REAL
#define SDL_CreateGPURenderer SDL_CreateGPURenderer_REAL
#define SDL_IsUbuntuTouch SDL_IsUbuntuTouch_REAL
1 change: 1 addition & 0 deletions src/dynapi/SDL_dynapi_procs.h
Original file line number Diff line number Diff line change
Expand Up @@ -1283,3 +1283,4 @@ SDL_DYNAPI_PROC(bool,SDL_SetRenderTextureAddressMode,(SDL_Renderer *a,SDL_Textur
SDL_DYNAPI_PROC(bool,SDL_GetRenderTextureAddressMode,(SDL_Renderer *a,SDL_TextureAddressMode *b,SDL_TextureAddressMode *c),(a,b,c),return)
SDL_DYNAPI_PROC(SDL_PropertiesID,SDL_GetGPUDeviceProperties,(SDL_GPUDevice *a),(a),return)
SDL_DYNAPI_PROC(SDL_Renderer*,SDL_CreateGPURenderer,(SDL_Window *a,SDL_GPUShaderFormat b,SDL_GPUDevice **c),(a,b,c),return)
SDL_DYNAPI_PROC(bool,SDL_IsUbuntuTouch,(void),(),return)
6 changes: 6 additions & 0 deletions src/video/SDL_video.c
Original file line number Diff line number Diff line change
Expand Up @@ -644,6 +644,12 @@ bool SDL_VideoInit(const char *driver_name)

// Select the proper video driver
video = NULL;
#ifdef SDL_PLATFORM_LINUX
// https://github.com/libsdl-org/SDL/issues/12247
if (SDL_IsUbuntuTouch()) {
driver_name = "wayland";
}
#endif
if (!driver_name) {
driver_name = SDL_GetHint(SDL_HINT_VIDEO_DRIVER);
}
Expand Down
Loading