* update to SDL 3.2.0

* remove SDL wrap

* fix darwin and windows CI

* update build box, correct msys sdl3 dependency

* port leftovers from renderer backend to SDL3

* remove SDL main dep
the main implementation is now included in a header

* main.c: use SDL_main.h

This needs to be included to work.

* ci: use vcpkg and pkgconf to support SDL3 on MSVC

* ci: use 7z to create zip

* renwindow: create texture and surface suitable for the display

* system: remove trailing whitespace

* renderer: fix trailing whitespace

* system: fix checking the wrong argument

* system: port rmdir and stat to SDL3 API

* system: remove unneeded API level check

* system: fix wrong parameter index

* system: make set_window_hit_test and set_window_bordered accept a window

* docs/system: update docs

* system: restore some comments

* docs/system: add missing documentation for system.text_input

* system: use SDL_setenv_unsafe

* system: add back comment for setenv

* system,renderer: remove unnecessary SDL_ClearError calls

---------

Co-authored-by: takase1121 <20792268+takase1121@users.noreply.github.com>
(cherry picked from commit 2716f14b6903f055f6bdf010a7e4a3d040cf059d)
This commit is contained in:
takase1121
2025-05-18 22:55:30 +08:00
parent 16d81d0b9c
commit bb05cf3e4d
15 changed files with 338 additions and 446 deletions
+41 -12
View File
@@ -19,7 +19,8 @@ jobs:
matrix:
config:
- { name: "GCC", cc: gcc, cxx: g++ }
- { name: "clang", cc: clang, cxx: clang++ }
# disable this until we have clang in the build box
# - { name: "clang", cc: clang, cxx: clang++ }
env:
CC: ${{ matrix.config.cc }}
CXX: ${{ matrix.config.cxx }}
@@ -35,21 +36,30 @@ jobs:
- name: Checkout code
uses: actions/checkout@v4
# disabled because this will break our own Python install
- name: Python Setup
if: false
uses: actions/setup-python@v5
with:
python-version: "3.11"
# disabled because the container has up-to-date packages
- name: Update Packages
if: false
run: sudo apt-get update
# disabled as the dependencies are already installed
- name: Install Dependencies
if: false
run: bash scripts/install-dependencies.sh --debug
- name: Build
run: |
bash --version
bash scripts/build.sh --debug --forcefallback --portable
uses: docker://ghcr.io/lite-xl/lite-xl-build-box-manylinux:v4
with:
entrypoint: /entrypoint.sh
args: |
bash --version
bash scripts/build.sh --debug --forcefallback --portable
- name: Package
if: ${{ matrix.config.cc == 'gcc' }}
@@ -101,7 +111,7 @@ jobs:
# installing md5sha1sum will eliminate a warning with arm64 and libusb
- name: Install Dependencies
run: |
brew install bash md5sha1sum
brew install bash md5sha1sum sdl3
pip install meson ninja dmgbuild
- name: Build
@@ -192,11 +202,14 @@ jobs:
base-devel
git
zip
mingw-w64-${{ matrix.config.arch }}-gcc
mingw-w64-${{ matrix.config.arch }}-meson
mingw-w64-${{ matrix.config.arch }}-ninja
mingw-w64-${{ matrix.config.arch }}-ca-certificates
mingw-w64-${{ matrix.config.arch }}-ntldd
patch
pacboy: >-
gcc:p
meson:p
ca-certificates:p
ninja:p
pkg-config:p
sdl3:p
- name: Set Environment Variables
run: |
@@ -251,7 +264,23 @@ jobs:
python-version: "3.11"
- name: Install meson and ninja
run: pip install meson ninja
run: pip install --no-cache-dir meson ninja
- name: Export GitHub Actions cache environment variables
uses: actions/github-script@v7
with:
script: |
core.exportVariable('ACTIONS_CACHE_URL', process.env.ACTIONS_CACHE_URL || '');
core.exportVariable('ACTIONS_RUNTIME_TOKEN', process.env.ACTIONS_RUNTIME_TOKEN || '');
- name: Install SDL
env: { VCPKG_BINARY_SOURCES: "clear;x-gha,readwrite" }
run: vcpkg install sdl3:x64-windows-static pkgconf:x64-windows-release
- name: Add environment variables
run: |
echo "PKG_CONFIG_PATH=C:\vcpkg\installed\x64-windows-static\lib\pkgconfig" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
echo "PKG_CONFIG=C:\vcpkg\installed\x64-windows-release\tools\pkgconf\pkgconf.exe" | Out-File -FilePath $env:GITHUB_ENV -Encoding utf8 -Append
- name: Set up environment variables
run: |
@@ -276,7 +305,7 @@ jobs:
- name: Package
run: |
Remove-Item -Recurse -Force -Path "lite-xl/lib","lite-xl/include"
Compress-Archive -Path lite-xl -DestinationPath "$env:INSTALL_NAME.zip"
7z a -mx=9 "$env:INSTALL_NAME.zip" lite-xl
- name: Upload Artifacts
uses: actions/upload-artifact@v4
+12 -9
View File
@@ -92,7 +92,7 @@ jobs:
sudo apt-get install -y ccache
- name: Build Portable
uses: docker://ghcr.io/lite-xl/lite-xl-build-box-manylinux:v3
uses: docker://ghcr.io/lite-xl/lite-xl-build-box-manylinux:v4
with:
entrypoint: /entrypoint.sh
args: |
@@ -100,7 +100,7 @@ jobs:
bash scripts/build.sh --debug --forcefallback --portable --release --lto
- name: Package Portables
uses: docker://ghcr.io/lite-xl/lite-xl-build-box-manylinux:v3
uses: docker://ghcr.io/lite-xl/lite-xl-build-box-manylinux:v4
with:
entrypoint: /entrypoint.sh
args: |
@@ -108,7 +108,7 @@ jobs:
bash scripts/package.sh --version ${INSTALL_REF} --debug --addons --binary --release
- name: Build AppImages
uses: docker://ghcr.io/lite-xl/lite-xl-build-box-manylinux:v3
uses: docker://ghcr.io/lite-xl/lite-xl-build-box-manylinux:v4
with:
entrypoint: /entrypoint.sh
args: |
@@ -164,7 +164,7 @@ jobs:
- name: Install Dependencies
run: |
brew install bash md5sha1sum
brew install bash md5sha1sum sdl3
pip install meson ninja dmgbuild
- name: Build
@@ -269,11 +269,14 @@ jobs:
git
zip
unzip
mingw-w64-${{ matrix.config.arch }}-gcc
mingw-w64-${{ matrix.config.arch }}-meson
mingw-w64-${{ matrix.config.arch }}-ninja
mingw-w64-${{ matrix.config.arch }}-ca-certificates
mingw-w64-${{ matrix.config.arch }}-ntldd
patch
pacboy: >-
gcc:p
meson:p
ca-certificates:p
ninja:p
pkg-config:p
sdl3:p
- name: Set Environment Variables
run: |
+1 -1
View File
@@ -43,7 +43,7 @@ conf_data.set('PROJECT_ASSEMBLY_VERSION', meson.project_version() + '.0')
cc = meson.get_compiler('c')
lite_includes = []
lite_cargs = ['-DSDL_MAIN_HANDLED', '-DPCRE2_STATIC']
lite_cargs = ['-DPCRE2_STATIC']
# On macos we need to use the SDL renderer to support retina displays
if get_option('renderer') or host_machine.system() == 'darwin'
lite_cargs += '-DLITE_USE_SDL_RENDERER'
+2 -2
View File
@@ -1,6 +1,6 @@
#include "api.h"
#include "lua.h"
#include <SDL.h>
#include <SDL3/SDL.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
@@ -9,7 +9,7 @@ static unsigned int DIR_EVENT_TYPE = 0;
struct dirmonitor {
SDL_Thread* thread;
SDL_mutex* mutex;
SDL_Mutex* mutex;
char buffer[64512];
volatile int length;
struct dirmonitor_internal* internal;
+2 -2
View File
@@ -1,8 +1,8 @@
#include <SDL.h>
#include <SDL3/SDL.h>
#include <CoreServices/CoreServices.h>
struct dirmonitor_internal {
SDL_mutex* lock;
SDL_Mutex* lock;
char** changes;
size_t count;
FSEventStreamRef stream;
+13 -13
View File
@@ -4,8 +4,8 @@
#include <stdbool.h>
#include <stdint.h>
#include <stdlib.h>
#include <SDL.h>
#include <SDL_thread.h>
#include <SDL3/SDL.h>
#include <SDL3/SDL_thread.h>
#include <assert.h>
#if _WIN32
@@ -85,8 +85,8 @@ typedef struct process_kill_s {
typedef struct {
bool stop;
SDL_mutex *mutex;
SDL_cond *has_work, *work_done;
SDL_Mutex *mutex;
SDL_Condition *has_work, *work_done;
SDL_Thread *worker_thread;
process_kill_t *head;
process_kill_t *tail;
@@ -133,8 +133,8 @@ static void kill_list_free(process_kill_list_t *list) {
process_kill_t *node, *temp;
SDL_WaitThread(list->worker_thread, NULL);
SDL_DestroyMutex(list->mutex);
SDL_DestroyCond(list->has_work);
SDL_DestroyCond(list->work_done);
SDL_DestroyCondition(list->has_work);
SDL_DestroyCondition(list->work_done);
node = list->head;
while (node) {
temp = node;
@@ -148,8 +148,8 @@ static void kill_list_free(process_kill_list_t *list) {
static bool kill_list_init(process_kill_list_t *list) {
memset(list, 0, sizeof(process_kill_list_t));
list->mutex = SDL_CreateMutex();
list->has_work = SDL_CreateCond();
list->work_done = SDL_CreateCond();
list->has_work = SDL_CreateCondition();
list->work_done = SDL_CreateCondition();
list->head = list->tail = NULL;
list->stop = false;
if (!list->mutex || !list->has_work || !list->work_done) {
@@ -190,10 +190,10 @@ static void kill_list_wait_all(process_kill_list_t *list) {
SDL_LockMutex(list->mutex);
// wait until list is empty
while (list->head)
SDL_CondWait(list->work_done, list->mutex);
SDL_WaitCondition(list->work_done, list->mutex);
// tell the worker to stop
list->stop = true;
SDL_CondSignal(list->has_work);
SDL_SignalCondition(list->has_work);
SDL_UnlockMutex(list->mutex);
}
@@ -257,7 +257,7 @@ static int kill_list_worker(void *ud) {
// wait until we have work to do
while (!list->head && !list->stop)
SDL_CondWait(list->has_work, list->mutex); // LOCK MUTEX
SDL_WaitCondition(list->has_work, list->mutex); // LOCK MUTEX
if (list->stop) break;
@@ -279,7 +279,7 @@ static int kill_list_worker(void *ud) {
kill_list_push(list, current_task);
} else {
free_task:
SDL_CondSignal(list->work_done);
SDL_SignalCondition(list->work_done);
process_handle_close(&current_task->handle);
free(current_task);
}
@@ -759,7 +759,7 @@ static int f_gc(lua_State* L) {
p->tries = 1;
SDL_LockMutex(list->mutex);
kill_list_push(list, p);
SDL_CondSignal(list->has_work);
SDL_SignalCondition(list->has_work);
SDL_UnlockMutex(list->mutex);
}
}
+177 -241
View File
@@ -1,4 +1,5 @@
#include <SDL.h>
#include <SDL3/SDL.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
@@ -117,12 +118,12 @@ static SDL_HitTestResult SDLCALL hit_test(SDL_Window *window, const SDL_Point *p
static const char *numpad[] = { "end", "down", "pagedown", "left", "", "right", "home", "up", "pageup", "ins", "delete" };
static const char *get_key_name(const SDL_Event *e, char *buf) {
SDL_Scancode scancode = e->key.keysym.scancode;
SDL_Scancode scancode = e->key.scancode;
/* Is the scancode from the keypad and the number-lock off?
** We assume that SDL_SCANCODE_KP_1 up to SDL_SCANCODE_KP_9 and SDL_SCANCODE_KP_0
** and SDL_SCANCODE_KP_PERIOD are declared in SDL2 in that order. */
if (scancode >= SDL_SCANCODE_KP_1 && scancode <= SDL_SCANCODE_KP_1 + 10 &&
!(e->key.keysym.mod & KMOD_NUM)) {
!(e->key.mod & SDL_KMOD_NUM)) {
return numpad[scancode - SDL_SCANCODE_KP_1];
} else {
/* We need to correctly handle non-standard layouts such as dvorak.
@@ -135,8 +136,8 @@ static const char *get_key_name(const SDL_Event *e, char *buf) {
and others, are masked with SDLK_SCANCODE_MASK, which moves them outside
the unicode range (>0x10FFFF). Users can remap these buttons, so we need
to return the correct name, not scancode based. */
if ((e->key.keysym.sym < 128) || (e->key.keysym.sym & SDLK_SCANCODE_MASK))
strcpy(buf, SDL_GetKeyName(e->key.keysym.sym));
if ((e->key.key < 128) || (e->key.key & SDLK_SCANCODE_MASK))
strcpy(buf, SDL_GetKeyName(e->key.key));
else
strcpy(buf, SDL_GetScancodeName(scancode));
str_tolower(buf);
@@ -171,7 +172,8 @@ static void push_win32_error(lua_State *L, DWORD rc) {
static int f_poll_event(lua_State *L) {
char buf[16];
int mx, my, w, h;
float mx, my;
int w, h;
SDL_Event e;
SDL_Event event_plus;
@@ -181,184 +183,205 @@ top:
}
switch (e.type) {
case SDL_QUIT:
case SDL_EVENT_QUIT:
lua_pushstring(L, "quit");
return 1;
case SDL_WINDOWEVENT:
if (e.window.event == SDL_WINDOWEVENT_RESIZED) {
case SDL_EVENT_WINDOW_RESIZED:
{
ren_resize_window(&window_renderer);
lua_pushstring(L, "resized");
/* The size below will be in points. */
lua_pushinteger(L, e.window.data1);
lua_pushinteger(L, e.window.data2);
return 3;
} else if (e.window.event == SDL_WINDOWEVENT_EXPOSED) {
rencache_invalidate();
lua_pushstring(L, "exposed");
return 1;
} else if (e.window.event == SDL_WINDOWEVENT_MINIMIZED) {
lua_pushstring(L, "minimized");
return 1;
} else if (e.window.event == SDL_WINDOWEVENT_MAXIMIZED) {
lua_pushstring(L, "maximized");
return 1;
} else if (e.window.event == SDL_WINDOWEVENT_RESTORED) {
lua_pushstring(L, "restored");
return 1;
} else if (e.window.event == SDL_WINDOWEVENT_LEAVE) {
lua_pushstring(L, "mouseleft");
return 1;
}
if (e.window.event == SDL_WINDOWEVENT_FOCUS_LOST) {
lua_pushstring(L, "focuslost");
return 1;
}
case SDL_EVENT_WINDOW_EXPOSED:
rencache_invalidate();
lua_pushstring(L, "exposed");
return 1;
case SDL_EVENT_WINDOW_MINIMIZED:
lua_pushstring(L, "minimized");
return 1;
case SDL_EVENT_WINDOW_MAXIMIZED:
lua_pushstring(L, "maximized");
return 1;
case SDL_EVENT_WINDOW_RESTORED:
lua_pushstring(L, "restored");
return 1;
case SDL_EVENT_WINDOW_MOUSE_LEAVE:
lua_pushstring(L, "mouseleft");
return 1;
case SDL_EVENT_WINDOW_FOCUS_LOST:
lua_pushstring(L, "focuslost");
return 1;
case SDL_EVENT_WINDOW_FOCUS_GAINED:
/* on some systems, when alt-tabbing to the window SDL will queue up
** several KEYDOWN events for the `tab` key; we flush all keydown
** events on focus so these are discarded */
if (e.window.event == SDL_WINDOWEVENT_FOCUS_GAINED) {
SDL_FlushEvent(SDL_KEYDOWN);
}
SDL_FlushEvent(SDL_EVENT_KEY_DOWN);
goto top;
case SDL_DROPFILE:
SDL_GetMouseState(&mx, &my);
lua_pushstring(L, "filedropped");
lua_pushstring(L, e.drop.file);
lua_pushinteger(L, mx * window_renderer.scale_x);
lua_pushinteger(L, my * window_renderer.scale_y);
SDL_free(e.drop.file);
return 4;
case SDL_KEYDOWN:
case SDL_EVENT_DROP_FILE:
{
SDL_GetMouseState(&mx, &my);
lua_pushstring(L, "filedropped");
lua_pushstring(L, e.drop.data);
lua_pushinteger(L, mx * window_renderer.scale_x);
lua_pushinteger(L, my * window_renderer.scale_y);
return 4;
}
case SDL_EVENT_KEY_DOWN:
#ifdef __APPLE__
/* on macos 11.2.3 with sdl 2.0.14 the keyup handler for cmd+w below
** was not enough. Maybe the quit event started to be triggered from the
** keydown handler? In any case, flushing the quit event here too helped. */
if ((e.key.keysym.sym == SDLK_w) && (e.key.keysym.mod & KMOD_GUI)) {
SDL_FlushEvent(SDL_QUIT);
if ((e.key.key == SDLK_W) && (e.key.mod & SDL_KMOD_GUI)) {
SDL_FlushEvent(SDL_EVENT_QUIT);
}
#endif
lua_pushstring(L, "keypressed");
lua_pushstring(L, get_key_name(&e, buf));
return 2;
case SDL_KEYUP:
case SDL_EVENT_KEY_UP:
#ifdef __APPLE__
/* on macos command+w will close the current window
** we want to flush this event and let the keymapper
** handle this key combination.
** Thanks to mathewmariani, taken from his lite-macos github repository. */
if ((e.key.keysym.sym == SDLK_w) && (e.key.keysym.mod & KMOD_GUI)) {
SDL_FlushEvent(SDL_QUIT);
if ((e.key.key == SDLK_W) && (e.key.mod & SDL_KMOD_GUI)) {
SDL_FlushEvent(SDL_EVENT_QUIT);
}
#endif
lua_pushstring(L, "keyreleased");
lua_pushstring(L, get_key_name(&e, buf));
return 2;
case SDL_TEXTINPUT:
case SDL_EVENT_TEXT_INPUT:
lua_pushstring(L, "textinput");
lua_pushstring(L, e.text.text);
return 2;
case SDL_TEXTEDITING:
case SDL_EVENT_TEXT_EDITING:
lua_pushstring(L, "textediting");
lua_pushstring(L, e.edit.text);
lua_pushinteger(L, e.edit.start);
lua_pushinteger(L, e.edit.length);
return 4;
#if SDL_VERSION_ATLEAST(2, 0, 22)
case SDL_TEXTEDITING_EXT:
lua_pushstring(L, "textediting");
lua_pushstring(L, e.editExt.text);
lua_pushinteger(L, e.editExt.start);
lua_pushinteger(L, e.editExt.length);
SDL_free(e.editExt.text);
return 4;
#endif
case SDL_MOUSEBUTTONDOWN:
if (e.button.button == 1) { SDL_CaptureMouse(1); }
lua_pushstring(L, "mousepressed");
lua_pushstring(L, button_name(e.button.button));
lua_pushinteger(L, e.button.x * window_renderer.scale_x);
lua_pushinteger(L, e.button.y * window_renderer.scale_y);
lua_pushinteger(L, e.button.clicks);
return 5;
case SDL_MOUSEBUTTONUP:
if (e.button.button == 1) { SDL_CaptureMouse(0); }
lua_pushstring(L, "mousereleased");
lua_pushstring(L, button_name(e.button.button));
lua_pushinteger(L, e.button.x * window_renderer.scale_x);
lua_pushinteger(L, e.button.y * window_renderer.scale_y);
return 4;
case SDL_MOUSEMOTION:
SDL_PumpEvents();
while (SDL_PeepEvents(&event_plus, 1, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEMOTION) > 0) {
e.motion.x = event_plus.motion.x;
e.motion.y = event_plus.motion.y;
e.motion.xrel += event_plus.motion.xrel;
e.motion.yrel += event_plus.motion.yrel;
case SDL_EVENT_MOUSE_BUTTON_DOWN:
{
if (e.button.button == 1) { SDL_CaptureMouse(1); }
lua_pushstring(L, "mousepressed");
lua_pushstring(L, button_name(e.button.button));
lua_pushinteger(L, e.button.x * window_renderer.scale_x);
lua_pushinteger(L, e.button.y * window_renderer.scale_y);
lua_pushinteger(L, e.button.clicks);
return 5;
}
lua_pushstring(L, "mousemoved");
lua_pushinteger(L, e.motion.x * window_renderer.scale_x);
lua_pushinteger(L, e.motion.y * window_renderer.scale_y);
lua_pushinteger(L, e.motion.xrel * window_renderer.scale_x);
lua_pushinteger(L, e.motion.yrel * window_renderer.scale_y);
return 5;
case SDL_MOUSEWHEEL:
case SDL_EVENT_MOUSE_BUTTON_UP:
{
if (e.button.button == 1) { SDL_CaptureMouse(0); }
lua_pushstring(L, "mousereleased");
lua_pushstring(L, button_name(e.button.button));
lua_pushinteger(L, e.button.x * window_renderer.scale_x);
lua_pushinteger(L, e.button.y * window_renderer.scale_y);
return 4;
}
case SDL_EVENT_MOUSE_MOTION:
{
SDL_PumpEvents();
while (SDL_PeepEvents(&event_plus, 1, SDL_GETEVENT, SDL_EVENT_MOUSE_MOTION, SDL_EVENT_MOUSE_MOTION) > 0) {
e.motion.x = event_plus.motion.x;
e.motion.y = event_plus.motion.y;
e.motion.xrel += event_plus.motion.xrel;
e.motion.yrel += event_plus.motion.yrel;
}
lua_pushstring(L, "mousemoved");
lua_pushinteger(L, e.motion.x * window_renderer.scale_x);
lua_pushinteger(L, e.motion.y * window_renderer.scale_y);
lua_pushinteger(L, e.motion.xrel * window_renderer.scale_x);
lua_pushinteger(L, e.motion.yrel * window_renderer.scale_y);
return 5;
}
case SDL_EVENT_MOUSE_WHEEL:
lua_pushstring(L, "mousewheel");
#if SDL_VERSION_ATLEAST(2, 0, 18)
lua_pushnumber(L, e.wheel.preciseY);
lua_pushnumber(L, e.wheel.y);
// Use -x to keep consistency with vertical scrolling values (e.g. shift+scroll)
lua_pushnumber(L, -e.wheel.preciseX);
#else
lua_pushinteger(L, e.wheel.y);
lua_pushinteger(L, -e.wheel.x);
#endif
lua_pushnumber(L, -e.wheel.x);
return 3;
case SDL_FINGERDOWN:
SDL_GetWindowSize(window_renderer.window, &w, &h);
case SDL_EVENT_FINGER_DOWN:
{
SDL_GetWindowSize(window_renderer.window, &w, &h);
lua_pushstring(L, "touchpressed");
lua_pushinteger(L, (lua_Integer)(e.tfinger.x * w));
lua_pushinteger(L, (lua_Integer)(e.tfinger.y * h));
lua_pushinteger(L, e.tfinger.fingerId);
return 4;
case SDL_FINGERUP:
SDL_GetWindowSize(window_renderer.window, &w, &h);
lua_pushstring(L, "touchreleased");
lua_pushinteger(L, (lua_Integer)(e.tfinger.x * w));
lua_pushinteger(L, (lua_Integer)(e.tfinger.y * h));
lua_pushinteger(L, e.tfinger.fingerId);
return 4;
case SDL_FINGERMOTION:
SDL_PumpEvents();
while (SDL_PeepEvents(&event_plus, 1, SDL_GETEVENT, SDL_FINGERMOTION, SDL_FINGERMOTION) > 0) {
e.tfinger.x = event_plus.tfinger.x;
e.tfinger.y = event_plus.tfinger.y;
e.tfinger.dx += event_plus.tfinger.dx;
e.tfinger.dy += event_plus.tfinger.dy;
lua_pushstring(L, "touchpressed");
lua_pushinteger(L, (lua_Integer)(e.tfinger.x * w));
lua_pushinteger(L, (lua_Integer)(e.tfinger.y * h));
lua_pushinteger(L, e.tfinger.fingerID);
return 4;
}
SDL_GetWindowSize(window_renderer.window, &w, &h);
lua_pushstring(L, "touchmoved");
lua_pushinteger(L, (lua_Integer)(e.tfinger.x * w));
lua_pushinteger(L, (lua_Integer)(e.tfinger.y * h));
lua_pushinteger(L, (lua_Integer)(e.tfinger.dx * w));
lua_pushinteger(L, (lua_Integer)(e.tfinger.dy * h));
lua_pushinteger(L, e.tfinger.fingerId);
return 6;
case SDL_EVENT_FINGER_UP:
{
SDL_GetWindowSize(window_renderer.window, &w, &h);
lua_pushstring(L, "touchreleased");
lua_pushinteger(L, (lua_Integer)(e.tfinger.x * w));
lua_pushinteger(L, (lua_Integer)(e.tfinger.y * h));
lua_pushinteger(L, e.tfinger.fingerID);
return 4;
}
case SDL_EVENT_FINGER_MOTION:
{
SDL_PumpEvents();
while (SDL_PeepEvents(&event_plus, 1, SDL_GETEVENT, SDL_EVENT_FINGER_MOTION, SDL_EVENT_FINGER_MOTION) > 0) {
e.tfinger.x = event_plus.tfinger.x;
e.tfinger.y = event_plus.tfinger.y;
e.tfinger.dx += event_plus.tfinger.dx;
e.tfinger.dy += event_plus.tfinger.dy;
}
SDL_GetWindowSize(window_renderer.window, &w, &h);
lua_pushstring(L, "touchmoved");
lua_pushinteger(L, (lua_Integer)(e.tfinger.x * w));
lua_pushinteger(L, (lua_Integer)(e.tfinger.y * h));
lua_pushinteger(L, (lua_Integer)(e.tfinger.dx * w));
lua_pushinteger(L, (lua_Integer)(e.tfinger.dy * h));
lua_pushinteger(L, e.tfinger.fingerID);
return 6;
}
case SDL_EVENT_WILL_ENTER_FOREGROUND:
case SDL_EVENT_DID_ENTER_FOREGROUND:
{
#ifdef LITE_USE_SDL_RENDERER
rencache_invalidate();
#else
SDL_UpdateWindowSurface(window_renderer.window);
#endif
lua_pushstring(L, e.type == SDL_EVENT_WILL_ENTER_FOREGROUND ? "enteringforeground" : "enteredforeground");
return 1;
}
case SDL_EVENT_WILL_ENTER_BACKGROUND:
lua_pushstring(L, "enteringbackground");
return 1;
case SDL_EVENT_DID_ENTER_BACKGROUND:
lua_pushstring(L, "enteredbackground");
return 1;
default:
goto top;
@@ -381,7 +404,7 @@ static int f_wait_event(lua_State *L) {
}
static SDL_Cursor* cursor_cache[SDL_SYSTEM_CURSOR_HAND + 1];
static SDL_Cursor* cursor_cache[SDL_SYSTEM_CURSOR_POINTER + 1];
static const char *cursor_opts[] = {
"arrow",
@@ -393,11 +416,11 @@ static const char *cursor_opts[] = {
};
static const int cursor_enums[] = {
SDL_SYSTEM_CURSOR_ARROW,
SDL_SYSTEM_CURSOR_IBEAM,
SDL_SYSTEM_CURSOR_SIZEWE,
SDL_SYSTEM_CURSOR_SIZENS,
SDL_SYSTEM_CURSOR_HAND
SDL_SYSTEM_CURSOR_DEFAULT,
SDL_SYSTEM_CURSOR_TEXT,
SDL_SYSTEM_CURSOR_EW_RESIZE,
SDL_SYSTEM_CURSOR_NS_RESIZE,
SDL_SYSTEM_CURSOR_POINTER
};
static int f_set_cursor(lua_State *L) {
@@ -425,8 +448,7 @@ enum { WIN_NORMAL, WIN_MINIMIZED, WIN_MAXIMIZED, WIN_FULLSCREEN };
static int f_set_window_mode(lua_State *L) {
int n = luaL_checkoption(L, 1, "normal", window_opts);
SDL_SetWindowFullscreen(window_renderer.window,
n == WIN_FULLSCREEN ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
SDL_SetWindowFullscreen(window_renderer.window, n == WIN_FULLSCREEN);
if (n == WIN_NORMAL) { SDL_RestoreWindow(window_renderer.window); }
if (n == WIN_MAXIMIZED) { SDL_MaximizeWindow(window_renderer.window); }
if (n == WIN_MINIMIZED) { SDL_MinimizeWindow(window_renderer.window); }
@@ -435,21 +457,20 @@ static int f_set_window_mode(lua_State *L) {
static int f_set_window_bordered(lua_State *L) {
int bordered = lua_toboolean(L, 1);
SDL_SetWindowBordered(window_renderer.window, bordered);
SDL_SetWindowBordered(window_renderer.window, lua_toboolean(L, 1));
return 0;
}
static int f_set_window_hit_test(lua_State *L) {
if (lua_gettop(L) == 0) {
if (lua_isnoneornil(L, 1)) {
SDL_SetWindowHitTest(window_renderer.window, NULL, NULL);
return 0;
}
window_hit_info->title_height = luaL_checknumber(L, 1);
window_hit_info->controls_width = luaL_checknumber(L, 2);
window_hit_info->resize_border = luaL_checknumber(L, 3);
SDL_SetWindowHitTest(window_renderer.window, hit_test, window_hit_info);
SDL_SetWindowHitTest(window_renderer.window, &hit_test, window_hit_info);
return 0;
}
@@ -487,7 +508,7 @@ static int f_window_has_focus(lua_State *L) {
static int f_get_window_mode(lua_State *L) {
unsigned flags = SDL_GetWindowFlags(window_renderer.window);
if (flags & SDL_WINDOW_FULLSCREEN_DESKTOP) {
if (flags & SDL_WINDOW_FULLSCREEN) {
lua_pushstring(L, "fullscreen");
} else if (flags & SDL_WINDOW_MINIMIZED) {
lua_pushstring(L, "minimized");
@@ -505,26 +526,17 @@ static int f_set_text_input_rect(lua_State *L) {
rect.y = luaL_checknumber(L, 2);
rect.w = luaL_checknumber(L, 3);
rect.h = luaL_checknumber(L, 4);
SDL_SetTextInputRect(&rect);
SDL_SetTextInputArea(window_renderer.window, &rect, 0);
return 0;
}
static int f_clear_ime(lua_State *L) {
#if SDL_VERSION_ATLEAST(2, 0, 22)
SDL_ClearComposition();
#endif
SDL_ClearComposition(window_renderer.window);
return 0;
}
static int f_raise_window(lua_State *L) {
/*
SDL_RaiseWindow should be enough but on some window managers like the
one used on Gnome the window needs to first have input focus in order
to allow the window to be focused. Also on wayland the raise window event
may not always be obeyed.
*/
SDL_SetWindowInputFocus(window_renderer.window);
SDL_RaiseWindow(window_renderer.window);
return 0;
}
@@ -545,31 +557,11 @@ static int f_show_fatal_error(lua_State *L) {
// removes an empty directory
static int f_rmdir(lua_State *L) {
const char *path = luaL_checkstring(L, 1);
#ifdef _WIN32
LPWSTR wpath = utfconv_utf8towc(path);
int deleted = RemoveDirectoryW(wpath);
free(wpath);
if (deleted > 0) {
lua_pushboolean(L, 1);
} else {
lua_pushboolean(L, 0);
push_win32_error(L, GetLastError());
lua_pushboolean(L, SDL_RemovePath(luaL_checkstring(L, 1)));
if (!lua_toboolean(L, -1)) {
lua_pushstring(L, SDL_GetError());
return 2;
}
#else
int deleted = remove(path);
if(deleted < 0) {
lua_pushboolean(L, 0);
lua_pushstring(L, strerror(errno));
return 2;
} else {
lua_pushboolean(L, 1);
}
#endif
return 1;
}
@@ -590,80 +582,24 @@ static int f_chdir(lua_State *L) {
static int f_list_dir(lua_State *L) {
int count = 0;
const char *path = luaL_checkstring(L, 1);
#ifdef _WIN32
lua_settop(L, 1);
if (path[0] == 0 || strchr("\\/", path[strlen(path) - 1]) != NULL)
lua_pushstring(L, "*");
else
lua_pushstring(L, "/*");
lua_concat(L, 2);
path = lua_tostring(L, -1);
LPWSTR wpath = utfconv_utf8towc(path);
if (wpath == NULL) {
lua_pushnil(L);
lua_pushstring(L, UTFCONV_ERROR_INVALID_CONVERSION);
return 2;
}
WIN32_FIND_DATAW fd;
HANDLE find_handle = FindFirstFileExW(wpath, FindExInfoBasic, &fd, FindExSearchNameMatch, NULL, 0);
free(wpath);
if (find_handle == INVALID_HANDLE_VALUE) {
lua_pushnil(L);
push_win32_error(L, GetLastError());
return 2;
}
char mbpath[MAX_PATH * 4]; // utf-8 spans 4 bytes at most
int len, i = 1;
lua_newtable(L);
do
{
if (wcscmp(fd.cFileName, L".") == 0) { continue; }
if (wcscmp(fd.cFileName, L"..") == 0) { continue; }
len = WideCharToMultiByte(CP_UTF8, 0, fd.cFileName, -1, mbpath, MAX_PATH * 4, NULL, NULL);
if (len == 0) { break; }
lua_pushlstring(L, mbpath, len - 1); // len includes \0
lua_rawseti(L, -2, i++);
} while (FindNextFileW(find_handle, &fd));
if (GetLastError() != ERROR_NO_MORE_FILES) {
lua_pushnil(L);
push_win32_error(L, GetLastError());
FindClose(find_handle);
return 2;
}
FindClose(find_handle);
return 1;
#else
DIR *dir = opendir(path);
char **dir = SDL_GlobDirectory(path, NULL, 0, &count);
if (!dir) {
lua_pushnil(L);
lua_pushstring(L, strerror(errno));
lua_pushstring(L, SDL_GetError());
return 2;
}
lua_newtable(L);
int i = 1;
struct dirent *entry;
while ( (entry = readdir(dir)) ) {
if (strcmp(entry->d_name, "." ) == 0) { continue; }
if (strcmp(entry->d_name, "..") == 0) { continue; }
lua_pushstring(L, entry->d_name);
lua_rawseti(L, -2, i);
i++;
lua_createtable(L, count, 0);
for (int ti = 1, i = 0; i < count; i++) {
if (strcmp(dir[i], ".") == 0) continue;
if (strcmp(dir[i], "..") == 0) continue;
lua_pushstring(L, dir[i]);
lua_rawseti(L, -2, ti++);
}
closedir(dir);
SDL_free(dir);
return 1;
#endif
}
+23 -40
View File
@@ -1,6 +1,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <SDL.h>
#include <SDL3/SDL.h>
#include <SDL3/SDL_main.h>
#include "api/api.h"
#include "rencache.h"
#include "renderer.h"
@@ -11,7 +12,7 @@
#include <windows.h>
#elif defined(__linux__)
#include <unistd.h>
#elif defined(__APPLE__)
#elif defined(SDL_PLATFORM_APPLE)
#include <mach-o/dyld.h>
#elif defined(__FreeBSD__)
#include <sys/sysctl.h>
@@ -39,7 +40,7 @@ static void get_exe_filename(char *buf, int sz) {
ssize_t len = readlink(path, buf, sz - 1);
if (len > 0)
buf[len] = '\0';
#elif __APPLE__
#elif SDL_PLATFORM_APPLE
/* use realpath to resolve a symlink if the process was launched from one.
** This happens when Homebrew installs a cack and creates a symlink in
** /usr/loca/bin for launching the executable from the command line. */
@@ -61,15 +62,10 @@ static void init_window_icon(void) {
#if !defined(_WIN32) && !defined(__APPLE__)
#include "../resources/icons/icon.inl"
(void) icon_rgba_len; /* unused */
SDL_Surface *surf = SDL_CreateRGBSurfaceFrom(
icon_rgba, 64, 64,
32, 64 * 4,
0x000000ff,
0x0000ff00,
0x00ff0000,
0xff000000);
SDL_PixelFormat format = SDL_GetPixelFormatForMasks(32, 0x000000ff, 0x0000ff00, 0x00ff0000, 0xff000000);
SDL_Surface *surf = SDL_CreateSurfaceFrom(64, 64, format, icon_rgba, 64 * 4);
SDL_SetWindowIcon(window, surf);
SDL_FreeSurface(surf);
SDL_DestroySurface(surf);
#endif
}
@@ -83,7 +79,7 @@ static void init_window_icon(void) {
#define LITE_NONPATHSEP_PATTERN "[^/]+"
#endif
#ifdef __APPLE__
#ifdef SDL_PLATFORM_APPLE
void enable_momentum_scroll();
#ifdef MACOS_USE_BUNDLE
void set_macos_bundle_resources(lua_State *L);
@@ -108,7 +104,7 @@ void set_macos_bundle_resources(lua_State *L);
#define ARCH_PLATFORM "linux"
#elif __FreeBSD__
#define ARCH_PLATFORM "freebsd"
#elif __APPLE__
#elif SDL_PLATFORM_APPLE
#define ARCH_PLATFORM "darwin"
#endif
@@ -124,53 +120,38 @@ int main(int argc, char **argv) {
signal(SIGPIPE, SIG_IGN);
#endif
if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
fprintf(stderr, "Error initializing SDL: %s\n", SDL_GetError());
if (!SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS)) {
fprintf(stderr, "Error initializing SDL: %s", SDL_GetError());
exit(1);
}
SDL_EnableScreenSaver();
SDL_EventState(SDL_DROPFILE, SDL_ENABLE);
SDL_SetEventEnabled(SDL_EVENT_DROP_FILE, true);
atexit(SDL_Quit);
#ifdef SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR /* Available since 2.0.8 */
SDL_SetHint(SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR, "0");
#endif
#if SDL_VERSION_ATLEAST(2, 0, 5)
SDL_SetHint(SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH, "1");
#endif
#if SDL_VERSION_ATLEAST(2, 0, 18)
SDL_SetHint(SDL_HINT_IME_SHOW_UI, "1");
#endif
#if SDL_VERSION_ATLEAST(2, 0, 22)
SDL_SetHint(SDL_HINT_IME_SUPPORT_EXTENDED_TEXT, "1");
#endif
SDL_SetHint(SDL_HINT_IME_IMPLEMENTED_UI, "1");
SDL_SetHint(SDL_HINT_RENDER_DRIVER, "software");
#if SDL_VERSION_ATLEAST(2, 0, 8)
/* This hint tells SDL to respect borderless window as a normal window.
** For example, the window will sit right on top of the taskbar instead
** of obscuring it. */
SDL_SetHint("SDL_BORDERLESS_WINDOWED_STYLE", "1");
#endif
#if SDL_VERSION_ATLEAST(2, 0, 12)
/* This hint tells SDL to allow the user to resize a borderless windoow.
** It also enables aero-snap on Windows apparently. */
SDL_SetHint("SDL_BORDERLESS_RESIZABLE_STYLE", "1");
#endif
#if SDL_VERSION_ATLEAST(2, 0, 9)
SDL_SetHint("SDL_MOUSE_DOUBLE_CLICK_RADIUS", "4");
#endif
SDL_DisplayMode dm;
SDL_GetCurrentDisplayMode(0, &dm);
SDL_SetHint(SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS, "4");
const SDL_DisplayMode* dm = SDL_GetCurrentDisplayMode(SDL_GetPrimaryDisplay());
window = SDL_CreateWindow(
"", SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, dm.w * 0.8, dm.h * 0.8,
SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN);
init_window_icon();
"", (dm ? dm->w : 2) * 0.8, (dm ? dm->h : 2) * 0.8,
SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_HIDDEN);
if (!window) {
fprintf(stderr, "Error creating lite-xl window: %s", SDL_GetError());
exit(1);
}
init_window_icon();
if (ren_init(window) != 0) {
fprintf(stderr, "Error initializing renderer: %s\n", SDL_GetError());
exit(1);
@@ -206,12 +187,14 @@ init_lua:
}
lua_setglobal(L, "EXEFILE");
#ifdef __APPLE__
#ifdef SDL_PLATFORM_APPLE
enable_momentum_scroll();
#ifdef MACOS_USE_BUNDLE
set_macos_bundle_resources(L);
#endif
#endif
SDL_SetEventEnabled(SDL_EVENT_TEXT_INPUT, true);
SDL_SetEventEnabled(SDL_EVENT_TEXT_EDITING, true);
const char *init_lite_code = \
"local core\n"
+2 -60
View File
@@ -59,67 +59,9 @@ freetype_dep = dependency('freetype2', fallback: ['freetype2', 'freetype_dep'],
)
sdl_options = ['default_library=static']
sdl_dep = dependency('sdl3', static: true)
# we explicitly need these
sdl_options += 'use_loadso=enabled'
sdl_options += 'prefer_dlopen=true'
sdl_options += 'use_video=enabled'
sdl_options += 'use_atomic=enabled'
sdl_options += 'use_threads=enabled'
sdl_options += 'use_timers=enabled'
# investigate if this is truly needed
# Do not remove before https://github.com/libsdl-org/SDL/issues/5413 is released
sdl_options += 'use_events=enabled'
if host_machine.system() == 'darwin' or host_machine.system() == 'windows'
sdl_options += 'use_video_x11=disabled'
sdl_options += 'use_video_wayland=disabled'
else
sdl_options += 'use_render=enabled'
sdl_options += 'use_video_x11=auto'
sdl_options += 'use_video_wayland=auto'
endif
# we leave this up to what the host system has except on windows
if host_machine.system() != 'windows'
sdl_options += 'use_video_opengl=auto'
sdl_options += 'use_video_openglesv2=auto'
else
sdl_options += 'use_video_opengl=disabled'
sdl_options += 'use_video_openglesv2=disabled'
endif
# we don't need these
sdl_options += 'test=false'
sdl_options += 'use_sensor=disabled'
sdl_options += 'use_haptic=disabled'
sdl_options += 'use_hidapi=disabled'
sdl_options += 'use_audio=disabled'
sdl_options += 'use_cpuinfo=disabled'
sdl_options += 'use_joystick=disabled'
sdl_options += 'use_joystick_xinput=disabled'
sdl_options += 'use_video_vulkan=disabled'
sdl_options += 'use_video_offscreen=disabled'
sdl_options += 'use_power=disabled'
sdl_options += 'system_iconv=disabled'
sdl_dep = dependency('sdl2', fallback: ['sdl2', 'sdl2_dep'],
default_options: default_fallback_options + sdl_options
)
if host_machine.system() == 'windows'
if sdl_dep.type_name() == 'internal'
sdlmain_dep = dependency('sdl2main', fallback: ['sdl2main_dep'])
else
sdlmain_dep = cc.find_library('SDL2main')
endif
else
sdlmain_dep = dependency('', required: false)
assert(not sdlmain_dep.found(), 'checking if fake dependency has been found')
endif
lite_deps = [lua_dep, sdl_dep, sdlmain_dep, freetype_dep, pcre2_dep, libm, libdl]
lite_deps = [lua_dep, sdl_dep, freetype_dep, pcre2_dep, libm, libdl]
lite_sources += 'api/dirmonitor.c'
# dirmonitor backend
+1
View File
@@ -1,3 +1,4 @@
#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
+46 -35
View File
@@ -214,7 +214,7 @@ static unsigned int font_get_glyph_id(RenFont *font, unsigned int codepoint) {
#define FONT_BITMAP_COUNT(F) ((F)->antialiasing == FONT_ANTIALIASING_SUBPIXEL ? SUBPIXEL_BITMAPS_CACHED : 1)
#define SLOT_BITMAP_TYPE(B) ((B).pixel_mode == FT_PIXEL_MODE_LCD ? EGlyphFormatSubpixel : EGlyphFormatGrayscale)
static inline SDL_PixelFormatEnum glyphformat_to_pixelformat(ERenGlyphFormat format, int *depth) {
static inline SDL_PixelFormat glyphformat_to_pixelformat(ERenGlyphFormat format, int *depth) {
switch (format) {
case EGlyphFormatSubpixel: *depth = 24; return SDL_PIXELFORMAT_RGB24;
case EGlyphFormatGrayscale: *depth = 8; return SDL_PIXELFORMAT_INDEX8;
@@ -245,12 +245,14 @@ static SDL_Surface *font_allocate_glyph_surface(RenFont *font, FT_GlyphSlot slot
}
metric->atlas_idx = atlas_idx;
GlyphAtlas *atlas = &font->glyphs.atlas[glyph_format][atlas_idx];
SDL_PropertiesID userdata;
// find the surface with the minimum height that can fit the glyph (limited to last 100 surfaces)
int surface_idx = -1, max_surface_idx = (int) atlas->nsurface - 100, min_waste = INT_MAX;
for (int i = atlas->nsurface - 1; i >= 0 && i > max_surface_idx; i--) {
assert(atlas->surfaces[i]->userdata);
GlyphMetric *m = (GlyphMetric *) atlas->surfaces[i]->userdata;
userdata = SDL_GetSurfaceProperties(atlas->surfaces[i]);
assert(SDL_HasProperty(userdata, "metric"));
GlyphMetric *m = (GlyphMetric *) SDL_GetPointerProperty(userdata, "metric", NULL);
int new_min_waste = (int) atlas->surfaces[i]->h - (int) m->y1;
if (new_min_waste >= metric->y1 && new_min_waste < min_waste) {
surface_idx = i;
@@ -262,19 +264,22 @@ static SDL_Surface *font_allocate_glyph_surface(RenFont *font, FT_GlyphSlot slot
int h = FONT_HEIGHT_OVERFLOW_PX + (double) font->face->size->metrics.height / 64.0f;
if (h <= FONT_HEIGHT_OVERFLOW_PX) h += slot->bitmap.rows;
if (h <= FONT_HEIGHT_OVERFLOW_PX) h += font->size;
int depth = 0; SDL_PixelFormatEnum format = glyphformat_to_pixelformat(glyph_format, &depth);
int depth = 0;
SDL_PixelFormat format = glyphformat_to_pixelformat(glyph_format, &depth);
atlas->surfaces = check_alloc(realloc(atlas->surfaces, sizeof(SDL_Surface *) * (atlas->nsurface + 1)));
atlas->surfaces[atlas->nsurface] = check_alloc(SDL_CreateRGBSurfaceWithFormat(0, atlas->width, GLYPHS_PER_ATLAS * h, depth, format));
atlas->surfaces[atlas->nsurface]->userdata = NULL;
atlas->surfaces[atlas->nsurface] = check_alloc(SDL_CreateSurface(atlas->width, GLYPHS_PER_ATLAS * h, format));
userdata = SDL_GetSurfaceProperties(atlas->surfaces[atlas->nsurface]);
SDL_SetPointerProperty(userdata, "metric", NULL);
surface_idx = atlas->nsurface++;
font->glyphs.bytesize += (sizeof(SDL_Surface *) + sizeof(SDL_Surface) + atlas->width * GLYPHS_PER_ATLAS * h * glyph_format);
}
metric->surface_idx = surface_idx;
if (atlas->surfaces[surface_idx]->userdata) {
GlyphMetric *last_metric = (GlyphMetric *) atlas->surfaces[surface_idx]->userdata;
userdata = SDL_GetSurfaceProperties(atlas->surfaces[surface_idx]);
if (SDL_HasProperty(userdata, "metric")) {
GlyphMetric *last_metric = (GlyphMetric *) SDL_GetPointerProperty(userdata, "metric", NULL);
metric->y0 = last_metric->y1; metric->y1 += last_metric->y1;
}
atlas->surfaces[surface_idx]->userdata = (void *) metric;
SDL_SetPointerProperty(userdata, "metric", (void *) metric);
return atlas->surfaces[surface_idx];
}
@@ -387,7 +392,7 @@ static void font_clear_glyph_cache(RenFont* font) {
for (int atlas_idx = 0; atlas_idx < font->glyphs.natlas[glyph_format_idx]; atlas_idx++) {
GlyphAtlas *atlas = &font->glyphs.atlas[glyph_format_idx][atlas_idx];
for (int surface_idx = 0; surface_idx < atlas->nsurface; surface_idx++) {
SDL_FreeSurface(atlas->surfaces[surface_idx]);
SDL_DestroySurface(atlas->surfaces[surface_idx]);
}
free(atlas->surfaces);
}
@@ -408,11 +413,11 @@ static void font_clear_glyph_cache(RenFont* font) {
// based on https://github.com/libsdl-org/SDL_ttf/blob/2a094959055fba09f7deed6e1ffeb986188982ae/SDL_ttf.c#L1735
static unsigned long font_file_read(FT_Stream stream, unsigned long offset, unsigned char *buffer, unsigned long count) {
uint64_t amount;
SDL_RWops *file = (SDL_RWops *) stream->descriptor.pointer;
SDL_RWseek(file, (int) offset, RW_SEEK_SET);
SDL_IOStream *file = (SDL_IOStream *) stream->descriptor.pointer;
SDL_SeekIO(file, (int) offset, SDL_IO_SEEK_SET);
if (count == 0)
return 0;
amount = SDL_RWread(file, buffer, sizeof(char), count);
amount = SDL_ReadIO(file, buffer, sizeof(char) * count);
if (amount <= 0)
return 0;
return (unsigned long) amount;
@@ -420,7 +425,7 @@ static unsigned long font_file_read(FT_Stream stream, unsigned long offset, unsi
static void font_file_close(FT_Stream stream) {
if (stream && stream->descriptor.pointer)
SDL_RWclose((SDL_RWops *) stream->descriptor.pointer);
SDL_CloseIO((SDL_IOStream *) stream->descriptor.pointer);
free(stream);
}
@@ -453,13 +458,11 @@ static int font_set_face_metrics(RenFont *font, FT_Face face) {
RenFont* ren_font_load(RenWindow *window_renderer, const char* path, float size, ERenFontAntialiasing antialiasing, ERenFontHinting hinting, unsigned char style) {
FT_Error err = FT_Err_Ok;
SDL_RWops *file = NULL; RenFont *font = NULL;
SDL_IOStream *file = NULL; RenFont *font = NULL;
FT_Face face = NULL; FT_Stream stream = NULL;
SDL_ClearError();
file = SDL_RWFromFile(path, "rb");
if (!file) return NULL; // error set by SDL_RWFromFile
file = SDL_IOFromFile(path, "rb");
if (!file) return NULL; // error set by SDL_IOFromFile
int len = strlen(path);
font = check_alloc(calloc(1, sizeof(RenFont) + len + 1));
@@ -479,7 +482,7 @@ RenFont* ren_font_load(RenWindow *window_renderer, const char* path, float size,
stream->close = &font_file_close;
stream->descriptor.pointer = file;
stream->pos = 0;
stream->size = (unsigned long) SDL_RWsize(file);
stream->size = (unsigned long) SDL_GetIOSize(file);
if ((err = FT_Open_Face(library, &(FT_Open_Args) { .flags = FT_OPEN_STREAM, .stream = stream }, 0, &face)) != 0)
goto failure;
@@ -488,7 +491,7 @@ RenFont* ren_font_load(RenWindow *window_renderer, const char* path, float size,
return font;
stream_failure:
if (file) SDL_RWclose(file);
if (file) SDL_CloseIO(file);
failure:
if (err != FT_Err_Ok) SDL_SetError("%s", get_ft_error(err));
if (face) FT_Done_Face(face);
@@ -596,7 +599,7 @@ void ren_font_dump(RenFont *font) {
double ren_draw_text(RenSurface *rs, RenFont **fonts, const char *text, size_t len, float x, int y, RenColor color) {
SDL_Surface *surface = rs->surface;
SDL_Rect clip;
SDL_GetClipRect(surface, &clip);
SDL_GetSurfaceClipRect(surface, &clip);
const int surface_scale = rs->scale;
double pen_x = x * surface_scale;
@@ -637,12 +640,20 @@ double ren_draw_text(RenSurface *rs, RenFont **fonts, const char *text, size_t l
start_x += offset;
glyph_start += offset;
}
uint32_t* destination_pixel = (uint32_t*)&(destination_pixels[surface->pitch * target_y + start_x * surface->format->BytesPerPixel ]);
uint8_t* source_pixel = &source_pixels[line * font_surface->pitch + glyph_start * font_surface->format->BytesPerPixel];
const SDL_PixelFormatDetails* surface_format = SDL_GetPixelFormatDetails(surface->format);
const SDL_PixelFormatDetails* font_surface_format = SDL_GetPixelFormatDetails(font_surface->format);
uint32_t* destination_pixel = (uint32_t*)&(destination_pixels[surface->pitch * target_y + start_x * surface_format->bytes_per_pixel]);
uint8_t* source_pixel = &source_pixels[line * font_surface->pitch + glyph_start * font_surface_format->bytes_per_pixel];
for (int x = glyph_start; x < glyph_end; ++x) {
uint32_t destination_color = *destination_pixel;
// the standard way of doing this would be SDL_GetRGBA, but that introduces a performance regression. needs to be investigated
SDL_Color dst = { (destination_color & surface->format->Rmask) >> surface->format->Rshift, (destination_color & surface->format->Gmask) >> surface->format->Gshift, (destination_color & surface->format->Bmask) >> surface->format->Bshift, (destination_color & surface->format->Amask) >> surface->format->Ashift };
SDL_Color dst = {
(destination_color & surface_format->Rmask) >> surface_format->Rshift,
(destination_color & surface_format->Gmask) >> surface_format->Gshift,
(destination_color & surface_format->Bmask) >> surface_format->Bshift,
(destination_color & surface_format->Amask) >> surface_format->Ashift};
SDL_Color src;
if (metric->format == EGlyphFormatSubpixel) {
@@ -660,7 +671,7 @@ double ren_draw_text(RenSurface *rs, RenFont **fonts, const char *text, size_t l
g = (color.g * src.g * color.a + dst.g * (65025 - src.g * color.a) + 32767) / 65025;
b = (color.b * src.b * color.a + dst.b * (65025 - src.b * color.a) + 32767) / 65025;
// the standard way of doing this would be SDL_GetRGBA, but that introduces a performance regression. needs to be investigated
*destination_pixel++ = (unsigned int) dst.a << surface->format->Ashift | r << surface->format->Rshift | g << surface->format->Gshift | b << surface->format->Bshift;
*destination_pixel++ = (unsigned int) dst.a << surface_format->Ashift | r << surface_format->Rshift | g << surface_format->Gshift | b << surface_format->Bshift;
}
}
}
@@ -704,25 +715,25 @@ void ren_draw_rect(RenSurface *rs, RenRect rect, RenColor color) {
rect.height * surface_scale };
if (color.a == 0xff) {
uint32_t translated = SDL_MapRGB(surface->format, color.r, color.g, color.b);
SDL_FillRect(surface, &dest_rect, translated);
uint32_t translated = SDL_MapSurfaceRGB(surface, color.r, color.g, color.b);
SDL_FillSurfaceRect(surface, &dest_rect, translated);
} else {
// Seems like SDL doesn't handle clipping as we expect when using
// scaled blitting, so we "clip" manually.
SDL_Rect clip;
SDL_GetClipRect(surface, &clip);
if (!SDL_IntersectRect(&clip, &dest_rect, &dest_rect)) return;
SDL_GetSurfaceClipRect(surface, &clip);
if (!SDL_GetRectIntersection(&clip, &dest_rect, &dest_rect)) return;
uint32_t *pixel = (uint32_t *)draw_rect_surface->pixels;
*pixel = SDL_MapRGBA(draw_rect_surface->format, color.r, color.g, color.b, color.a);
SDL_BlitScaled(draw_rect_surface, NULL, surface, &dest_rect);
*pixel = SDL_MapSurfaceRGBA(draw_rect_surface, color.r, color.g, color.b, color.a);
SDL_BlitSurfaceScaled(draw_rect_surface, NULL, surface, &dest_rect, SDL_SCALEMODE_LINEAR);
}
}
/*************** Window Management ****************/
void ren_free_window_resources(RenWindow *window_renderer) {
renwin_free(window_renderer);
SDL_FreeSurface(draw_rect_surface);
SDL_DestroySurface(draw_rect_surface);
free(window_renderer->command_buf);
window_renderer->command_buf = NULL;
window_renderer->command_buf_size = 0;
@@ -734,8 +745,8 @@ int ren_init(SDL_Window *win) {
SDL_ClearError();
assert(win);
draw_rect_surface = SDL_CreateRGBSurface(0, 1, 1, 32,
0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
draw_rect_surface = SDL_CreateSurface(1, 1, SDL_PIXELFORMAT_RGBA32);
if (!draw_rect_surface)
return -1; // error set by SDL_CreateRGBSurface
+1 -1
View File
@@ -1,7 +1,7 @@
#ifndef RENDERER_H
#define RENDERER_H
#include <SDL.h>
#include <SDL3/SDL.h>
#include <stdint.h>
#include <stdbool.h>
+16 -14
View File
@@ -1,3 +1,4 @@
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include "renwindow.h"
@@ -6,7 +7,7 @@
static int query_surface_scale(RenWindow *ren) {
int w_pixels, h_pixels;
int w_points, h_points;
SDL_GL_GetDrawableSize(ren->window, &w_pixels, &h_pixels);
SDL_GetWindowSizeInPixels(ren->window, &w_pixels, &h_pixels);
SDL_GetWindowSize(ren->window, &w_points, &h_points);
/* We consider that the ratio pixel/point will always be an integer and
it is the same along the x and the y axis. */
@@ -16,14 +17,14 @@ static int query_surface_scale(RenWindow *ren) {
static void setup_renderer(RenWindow *ren, int w, int h) {
/* Note that w and h here should always be in pixels and obtained from
a call to SDL_GL_GetDrawableSize(). */
a call to SDL_GetWindowSizeInPixels(). */
if (!ren->renderer) {
ren->renderer = SDL_CreateRenderer(ren->window, -1, 0);
ren->renderer = SDL_CreateRenderer(ren->window, NULL);
}
if (ren->texture) {
SDL_DestroyTexture(ren->texture);
}
ren->texture = SDL_CreateTexture(ren->renderer, SDL_PIXELFORMAT_BGRA32, SDL_TEXTUREACCESS_STREAMING, w, h);
ren->texture = SDL_CreateTexture(ren->renderer, ren->rensurface.surface->format, SDL_TEXTUREACCESS_STREAMING, w, h);
ren->rensurface.scale = query_surface_scale(ren);
}
#endif
@@ -33,11 +34,12 @@ void renwin_init_surface(RenWindow *ren) {
ren->scale_x = ren->scale_y = 1;
#ifdef LITE_USE_SDL_RENDERER
if (ren->rensurface.surface) {
SDL_FreeSurface(ren->rensurface.surface);
SDL_DestroySurface(ren->rensurface.surface);
}
int w, h;
SDL_GL_GetDrawableSize(ren->window, &w, &h);
ren->rensurface.surface = SDL_CreateRGBSurfaceWithFormat(0, w, h, 32, SDL_PIXELFORMAT_BGRA32);
SDL_GetWindowSizeInPixels(ren->window, &w, &h);
SDL_PixelFormat format = SDL_GetWindowPixelFormat(ren->window);
ren->rensurface.surface = SDL_CreateSurface(w, h, format == SDL_PIXELFORMAT_UNKNOWN ? SDL_PIXELFORMAT_BGRA32 : format);
if (!ren->rensurface.surface) {
fprintf(stderr, "Error creating surface: %s", SDL_GetError());
exit(1);
@@ -59,14 +61,14 @@ static RenRect scaled_rect(const RenRect rect, const int scale) {
void renwin_clip_to_surface(RenWindow *ren) {
SDL_SetClipRect(renwin_get_surface(ren).surface, NULL);
SDL_SetSurfaceClipRect(renwin_get_surface(ren).surface, NULL);
}
void renwin_set_clip_rect(RenWindow *ren, RenRect rect) {
RenSurface rs = renwin_get_surface(ren);
RenRect sr = scaled_rect(rect, rs.scale);
SDL_SetClipRect(rs.surface, &(SDL_Rect){.x = sr.x, .y = sr.y, .w = sr.width, .h = sr.height});
SDL_SetSurfaceClipRect(rs.surface, &(SDL_Rect){.x = sr.x, .y = sr.y, .w = sr.width, .h = sr.height});
}
@@ -86,7 +88,7 @@ RenSurface renwin_get_surface(RenWindow *ren) {
void renwin_resize_surface(RenWindow *ren) {
#ifdef LITE_USE_SDL_RENDERER
int new_w, new_h, new_scale;
SDL_GL_GetDrawableSize(ren->window, &new_w, &new_h);
SDL_GetWindowSizeInPixels(ren->window, &new_w, &new_h);
new_scale = query_surface_scale(ren);
/* Note that (w, h) may differ from (new_w, new_h) on retina displays. */
if (new_scale != ren->rensurface.scale ||
@@ -121,10 +123,10 @@ void renwin_update_rects(RenWindow *ren, RenRect *rects, int count) {
const int x = scale * r->x, y = scale * r->y;
const int w = scale * r->width, h = scale * r->height;
const SDL_Rect sr = {.x = x, .y = y, .w = w, .h = h};
int32_t *pixels = ((int32_t *) ren->rensurface.surface->pixels) + x + ren->rensurface.surface->w * y;
SDL_UpdateTexture(ren->texture, &sr, pixels, ren->rensurface.surface->w * 4);
uint8_t *pixels = ((uint8_t *) ren->rensurface.surface->pixels) + y * ren->rensurface.surface->pitch + x * SDL_BYTESPERPIXEL(ren->rensurface.surface->format);
SDL_UpdateTexture(ren->texture, &sr, pixels, ren->rensurface.surface->pitch);
}
SDL_RenderCopy(ren->renderer, ren->texture, NULL, NULL);
SDL_RenderTexture(ren->renderer, ren->texture, NULL, NULL);
SDL_RenderPresent(ren->renderer);
#else
SDL_UpdateWindowSurfaceRects(ren->window, (SDL_Rect*) rects, count);
@@ -135,7 +137,7 @@ void renwin_free(RenWindow *ren) {
#ifdef LITE_USE_SDL_RENDERER
SDL_DestroyTexture(ren->texture);
SDL_DestroyRenderer(ren->renderer);
SDL_FreeSurface(ren->rensurface.surface);
SDL_DestroySurface(ren->rensurface.surface);
#endif
SDL_DestroyWindow(ren->window);
ren->window = NULL;
+1 -1
View File
@@ -1,4 +1,4 @@
#include <SDL.h>
#include <SDL3/SDL.h>
#include "renderer.h"
struct RenWindow {
-15
View File
@@ -1,15 +0,0 @@
[wrap-file]
directory = SDL2-2.30.3
source_url = https://github.com/libsdl-org/SDL/releases/download/release-2.30.3/SDL2-2.30.3.tar.gz
source_filename = SDL2-2.30.3.tar.gz
source_hash = 820440072f8f5b50188c1dae104f2ad25984de268785be40c41a099a510f0aec
patch_filename = sdl2_2.30.3-2_patch.zip
patch_url = https://wrapdb.mesonbuild.com/v2/sdl2_2.30.3-2/get_patch
patch_hash = 2c08bde67b3896db88e01481c379322625ea6c928cdb68ead91d0e3749863bc2
source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/sdl2_2.30.3-2/SDL2-2.30.3.tar.gz
wrapdb_version = 2.30.3-2
[provide]
sdl2 = sdl2_dep
sdl2main = sdl2main_dep
sdl2_test = sdl2_test_dep