aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJefferson González <jgmdev@gmail.com>2025-07-31 12:02:53 -0700
committerGitHub <noreply@github.com>2025-07-31 15:02:53 -0400
commit2863e6d45043672d4afcbc38d953987edd548cd3 (patch)
treefbd18b9ec5125a893e3d131580d58e3d223552cd
parente2127ae4643c7a37fa03ff2dd8e26c71c4c6762b (diff)
downloadpragtical-2863e6d45043672d4afcbc38d953987edd548cd3.tar.gz
pragtical-2863e6d45043672d4afcbc38d953987edd548cd3.zip
SDL3 port (#254)
* Updates for SDL3 support Port of Pragtical to SDL3 using a cherry-picked commit from upstream with additional changes and adjustments from pragtical/pragtical#8 --------- Co-authored-by: Jan <sentrycraft123@gmail.com> Co-authored-by: takase1121 <20792268+takase1121@users.noreply.github.com> * replace memory functions with SDL equivalent --------- Co-authored-by: Jan <sentrycraft123@gmail.com> Co-authored-by: takase1121 <20792268+takase1121@users.noreply.github.com>
-rw-r--r--.github/workflows/pr_ci.yml6
-rw-r--r--.github/workflows/release.yml4
-rw-r--r--.github/workflows/rolling.yml4
-rw-r--r--data/core/commands/command.lua1
-rw-r--r--data/core/commands/findreplace.lua1
-rw-r--r--data/core/commands/statusbar.lua1
-rw-r--r--data/core/contextmenu.lua1
-rw-r--r--data/core/dirwatch.lua2
-rw-r--r--data/core/doc/highlighter.lua1
-rw-r--r--data/core/emptyview.lua1
-rw-r--r--data/core/ime.lua4
-rw-r--r--data/core/init.lua63
-rw-r--r--data/core/keymap.lua2
-rw-r--r--data/core/process.lua1
-rw-r--r--data/core/start.lua3
-rw-r--r--data/core/titleview.lua4
-rw-r--r--data/core/tokenizer.lua1
-rw-r--r--data/plugins/contextmenu.lua1
-rw-r--r--data/plugins/lineguide.lua1
-rw-r--r--data/plugins/quote.lua1
-rw-r--r--data/plugins/reflow.lua1
-rw-r--r--docs/api/system.lua20
-rw-r--r--meson.build109
-rw-r--r--resources/README.md4
-rw-r--r--resources/linux/dev.pragtical.Pragtical.appdata.xml (renamed from resources/linux/org.pragtical.pragtical.appdata.xml)4
-rw-r--r--resources/linux/dev.pragtical.Pragtical.desktop (renamed from resources/linux/org.pragtical.pragtical.desktop)2
-rw-r--r--scripts/appimage.sh2
-rw-r--r--src/api/channel.c60
-rw-r--r--src/api/channel.h4
-rw-r--r--src/api/diff.c26
-rw-r--r--src/api/dirmonitor.c6
-rw-r--r--src/api/dirmonitor/fsevents.c20
-rw-r--r--src/api/dirmonitor/inodewatcher.cpp5
-rw-r--r--src/api/dirmonitor/inotify.c3
-rw-r--r--src/api/dirmonitor/kqueue.c3
-rw-r--r--src/api/dirmonitor/win32.c3
-rw-r--r--src/api/encoding.c6
-rw-r--r--src/api/process.c32
-rw-r--r--src/api/regex.c13
-rw-r--r--src/api/renderer.c2
-rw-r--r--src/api/renwindow.c35
-rw-r--r--src/api/shmem.c27
-rw-r--r--src/api/system.c572
-rw-r--r--src/api/thread.c27
-rw-r--r--src/main.c62
-rw-r--r--src/meson.build22
-rw-r--r--src/rencache.c5
-rw-r--r--src/renderer.c150
-rw-r--r--src/renderer.h7
-rw-r--r--src/renwindow.c47
-rw-r--r--src/renwindow.h2
-rw-r--r--src/utfconv.h8
-rw-r--r--src/windows/darkmode.c50
-rw-r--r--src/windows/darkmode.h13
-rw-r--r--subprojects/packagefiles/sdl3/meson.build1
-rw-r--r--subprojects/sdl2.wrap15
-rw-r--r--subprojects/sdl3.wrap8
57 files changed, 575 insertions, 904 deletions
diff --git a/.github/workflows/pr_ci.yml b/.github/workflows/pr_ci.yml
index b35a1f42..315c482a 100644
--- a/.github/workflows/pr_ci.yml
+++ b/.github/workflows/pr_ci.yml
@@ -33,6 +33,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: 3.9
+ - name: Setup cmake
+ uses: jwlawson/actions-setup-cmake@v2
- name: Update Packages
run: sudo apt-get update
- name: Install Dependencies
@@ -80,6 +82,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: 3.9
+ - name: Setup cmake
+ uses: jwlawson/actions-setup-cmake@v2
- name: Install Dependencies
run: bash scripts/install-dependencies.sh --debug
- name: Build
@@ -213,6 +217,8 @@ jobs:
python-version: '3.x'
- name: Install meson and ninja
run: pip install meson ninja
+ - name: Setup cmake
+ uses: jwlawson/actions-setup-cmake@v2
- name: Set up environment variables
run: |
"INSTALL_NAME=pragtical-$($env:GITHUB_REF -replace ".*/")-windows-msvc-${{ matrix.arch.name }}" >> $env:GITHUB_ENV
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index 85a572a2..c6484569 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -85,6 +85,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: 3.9
+ - name: Setup cmake
+ uses: jwlawson/actions-setup-cmake@v2
- name: Update Packages
run: sudo apt-get update
- name: Install Dependencies
@@ -136,6 +138,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: 3.9
+ - name: Setup cmake
+ uses: jwlawson/actions-setup-cmake@v2
- name: Install Dependencies
run: bash scripts/install-dependencies.sh --debug
- name: Build
diff --git a/.github/workflows/rolling.yml b/.github/workflows/rolling.yml
index e3ca3edd..7ee9d110 100644
--- a/.github/workflows/rolling.yml
+++ b/.github/workflows/rolling.yml
@@ -83,6 +83,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: 3.9
+ - name: Setup cmake
+ uses: jwlawson/actions-setup-cmake@v2
- name: Update Packages
run: sudo apt-get update
- name: Install Dependencies
@@ -135,6 +137,8 @@ jobs:
uses: actions/setup-python@v5
with:
python-version: 3.9
+ - name: Setup cmake
+ uses: jwlawson/actions-setup-cmake@v2
- name: Install Dependencies
run: bash scripts/install-dependencies.sh --debug
- name: Build
diff --git a/data/core/commands/command.lua b/data/core/commands/command.lua
index 44e894f5..ac8eff79 100644
--- a/data/core/commands/command.lua
+++ b/data/core/commands/command.lua
@@ -1,4 +1,3 @@
-local core = require "core"
local command = require "core.command"
command.add("core.commandview", {
diff --git a/data/core/commands/findreplace.lua b/data/core/commands/findreplace.lua
index 98da33e9..5e43a8a7 100644
--- a/data/core/commands/findreplace.lua
+++ b/data/core/commands/findreplace.lua
@@ -5,7 +5,6 @@ local search = require "core.doc.search"
local keymap = require "core.keymap"
local DocView = require "core.docview"
local CommandView = require "core.commandview"
-local StatusView = require "core.statusview"
local last_view, last_fn, last_text, last_sel
diff --git a/data/core/commands/statusbar.lua b/data/core/commands/statusbar.lua
index 5676ef52..83605c34 100644
--- a/data/core/commands/statusbar.lua
+++ b/data/core/commands/statusbar.lua
@@ -1,7 +1,6 @@
local core = require "core"
local command = require "core.command"
local common = require "core.common"
-local style = require "core.style"
local StatusView = require "core.statusview"
local function status_view_item_names()
diff --git a/data/core/contextmenu.lua b/data/core/contextmenu.lua
index 6be294ee..965f2137 100644
--- a/data/core/contextmenu.lua
+++ b/data/core/contextmenu.lua
@@ -1,7 +1,6 @@
local core = require "core"
local common = require "core.common"
local command = require "core.command"
-local config = require "core.config"
local keymap = require "core.keymap"
local style = require "core.style"
local Object = require "core.object"
diff --git a/data/core/dirwatch.lua b/data/core/dirwatch.lua
index 820e9ecb..3dc46b3d 100644
--- a/data/core/dirwatch.lua
+++ b/data/core/dirwatch.lua
@@ -1,6 +1,6 @@
local core = require "core"
-local common = require "core.common"
local config = require "core.config"
+local common = require "core.common"
local Object = require "core.object"
diff --git a/data/core/doc/highlighter.lua b/data/core/doc/highlighter.lua
index 43977f3d..753434df 100644
--- a/data/core/doc/highlighter.lua
+++ b/data/core/doc/highlighter.lua
@@ -1,6 +1,5 @@
local core = require "core"
local common = require "core.common"
-local config = require "core.config"
local tokenizer = require "core.tokenizer"
local Object = require "core.object"
diff --git a/data/core/emptyview.lua b/data/core/emptyview.lua
index 542bf326..48f73518 100644
--- a/data/core/emptyview.lua
+++ b/data/core/emptyview.lua
@@ -2,7 +2,6 @@ local core = require "core"
local command = require "core.command"
local common = require "core.common"
local style = require "core.style"
-local keymap = require "core.keymap"
local Widget = require "widget"
local Button = require "widget.button"
local ListBox = require "widget.listbox"
diff --git a/data/core/ime.lua b/data/core/ime.lua
index 85803f17..e1893e85 100644
--- a/data/core/ime.lua
+++ b/data/core/ime.lua
@@ -65,7 +65,7 @@ end
function ime.stop()
if ime.editing then
-- SDL_ClearComposition for now doesn't work everywhere
- system.clear_ime()
+ system.clear_ime(core.window)
ime.on_text_editing("", 0, 0)
end
end
@@ -84,7 +84,7 @@ function ime.set_location(x, y, w, h)
ime.last_location.h ~= h
then
ime.last_location.x, ime.last_location.y, ime.last_location.w, ime.last_location.h = x, y, w, h
- system.set_text_input_rect(x, y, w, h)
+ system.set_text_input_rect(core.window, x, y, w, h)
end
end
diff --git a/data/core/init.lua b/data/core/init.lua
index 0b935d8b..c6ad7195 100644
--- a/data/core/init.lua
+++ b/data/core/init.lua
@@ -336,7 +336,7 @@ end
function core.configure_borderless_window()
- system.set_window_bordered(not config.borderless)
+ system.set_window_bordered(core.window, not config.borderless)
core.title_view:configure_hit_test(config.borderless)
core.title_view.visible = config.borderless
end
@@ -413,26 +413,28 @@ function core.init()
local project_dir = core.recent_projects[1] or "."
local project_dir_explicit = false
local files = {}
- for i = 2, #ARGS do
- local arg_filename = strip_trailing_slash(ARGS[i])
- local info = system.get_file_info(arg_filename) or {}
- if info.type == "dir" then
- project_dir = arg_filename
- project_dir_explicit = true
- else
- -- on macOS we can get an argument like "-psn_0_52353" that we just ignore.
- if not ARGS[i]:match("^-psn") then
- local filename = common.normalize_path(arg_filename)
- local abs_filename = system.absolute_path(filename or "")
- local file_abs
- if filename == abs_filename then
- file_abs = abs_filename
- else
- file_abs = system.absolute_path(".") .. PATHSEP .. filename
- end
- if file_abs then
- table.insert(files, file_abs)
- project_dir = file_abs:match("^(.+)[/\\].+$")
+ if not RESTARTED then
+ for i = 2, #ARGS do
+ local arg_filename = strip_trailing_slash(ARGS[i])
+ local info = system.get_file_info(arg_filename) or {}
+ if info.type == "dir" then
+ project_dir = arg_filename
+ project_dir_explicit = true
+ else
+ -- on macOS we can get an argument like "-psn_0_52353" that we just ignore.
+ if not ARGS[i]:match("^-psn") then
+ local filename = common.normalize_path(arg_filename)
+ local abs_filename = system.absolute_path(filename or "")
+ local file_abs
+ if filename == abs_filename then
+ file_abs = abs_filename
+ else
+ file_abs = system.absolute_path(".") .. PATHSEP .. filename
+ end
+ if file_abs then
+ table.insert(files, file_abs)
+ project_dir = file_abs:match("^(.+)[/\\].+$")
+ end
end
end
end
@@ -1047,7 +1049,7 @@ function core.set_active_view(view)
-- Reset the IME even if the focus didn't change
ime.stop()
if view ~= core.active_view then
- system.text_input(view:supports_text_input())
+ system.text_input(core.window, view:supports_text_input())
if core.active_view and core.active_view.force_focus then
core.next_active_view = view
return
@@ -1258,8 +1260,9 @@ end
---This function rescales the interface to the system default scale
---by incrementing or decrementing current user scale.
-local function update_scale()
- local new_scale, prev_default = system.get_scale(core.window), DEFAULT_SCALE
+---@param new_scale number
+local function update_scale(new_scale)
+ local prev_default = DEFAULT_SCALE
DEFAULT_SCALE = new_scale
if SCALE == prev_default or config.plugins.scale.autodetect then
if new_scale == SCALE then return end
@@ -1311,14 +1314,6 @@ function core.on_event(type, ...)
elseif type == "touchmoved" then
core.root_view:on_touch_moved(...)
elseif type == "resized" then
- if not core.updating_scale then
- core.updating_scale = true
- core.add_thread(function()
- coroutine.yield(1) -- don't call system.get_scale too frequently
- update_scale()
- core.updating_scale = nil
- end)
- end
local window_mode = system.get_window_mode(core.window)
if window_mode ~= "fullscreen" and window_mode ~= "maximized" then
core.window_size = table.pack(system.get_window_size(core.window))
@@ -1425,8 +1420,8 @@ function core.step(next_frame_time)
-- required to avoid flashing and refresh issues on mobile
event_received = type
break
- elseif type == "displaychanged" then
- update_scale()
+ elseif type == "scalechanged" then
+ update_scale(a)
else
local _, res = core.try(core.on_event, type, a, b, c, d)
did_keymap = res or did_keymap
diff --git a/data/core/keymap.lua b/data/core/keymap.lua
index 1f67d86a..2424ba77 100644
--- a/data/core/keymap.lua
+++ b/data/core/keymap.lua
@@ -1,7 +1,7 @@
local core = require "core"
local command = require "core.command"
local config = require "core.config"
-local ime = require "core.ime"
+
local keymap = {}
---@alias keymap.shortcut string
diff --git a/data/core/process.lua b/data/core/process.lua
index 6c2efd8c..b9270f12 100644
--- a/data/core/process.lua
+++ b/data/core/process.lua
@@ -1,5 +1,4 @@
local config = require "core.config"
-local common = require "core.common"
---An abstraction over the standard input and outputs of a process
diff --git a/data/core/start.lua b/data/core/start.lua
index db18e23f..8d034920 100644
--- a/data/core/start.lua
+++ b/data/core/start.lua
@@ -139,6 +139,9 @@ if os.getenv("APPIMAGE") and appimage_owd then
system.chdir(appimage_owd)
end
+-- Temporary SDL3 compatibility PLATFORM correction on macOS
+if PLATFORM == "macOS" then PLATFORM = "Mac OS X" end
+
-- Manually add /usr/local/bin to the PATH environment variable if needed.
-- On Mac OS X package managers like brew install binaries into /usr/local/bin
-- but this location is not globally added to the PATH environment variable.
diff --git a/data/core/titleview.lua b/data/core/titleview.lua
index 9f8ea9c9..f2660554 100644
--- a/data/core/titleview.lua
+++ b/data/core/titleview.lua
@@ -46,10 +46,10 @@ function TitleView:configure_hit_test(borderless)
local icon_w = style.icon_font:get_width("_")
local icon_spacing = icon_w
local controls_width = (icon_w + icon_spacing) * #title_commands + icon_spacing
- system.set_window_hit_test(title_height, controls_width, icon_spacing)
+ system.set_window_hit_test(core.window, title_height, controls_width, icon_spacing)
-- core.hit_test_title_height = title_height
else
- system.set_window_hit_test()
+ system.set_window_hit_test(core.window)
end
end
diff --git a/data/core/tokenizer.lua b/data/core/tokenizer.lua
index a0bdc095..713aa095 100644
--- a/data/core/tokenizer.lua
+++ b/data/core/tokenizer.lua
@@ -1,6 +1,5 @@
local core = require "core"
local syntax = require "core.syntax"
-local config = require "core.config"
---Functionality to tokenize source code using syntax definitions.
---@class core.tokenizer
diff --git a/data/plugins/contextmenu.lua b/data/plugins/contextmenu.lua
index 26afbb57..225072ac 100644
--- a/data/plugins/contextmenu.lua
+++ b/data/plugins/contextmenu.lua
@@ -1,5 +1,4 @@
-- mod-version:3
-local core = require "core"
local command = require "core.command"
local keymap = require "core.keymap"
local ContextMenu = require "core.contextmenu"
diff --git a/data/plugins/lineguide.lua b/data/plugins/lineguide.lua
index 31716519..71a5780b 100644
--- a/data/plugins/lineguide.lua
+++ b/data/plugins/lineguide.lua
@@ -4,7 +4,6 @@ local command = require "core.command"
local config = require "core.config"
local style = require "core.style"
local DocView = require "core.docview"
-local CommandView = require "core.commandview"
---Configuration options for `lineguide` plugin.
---@class config.plugins.lineguide
diff --git a/data/plugins/quote.lua b/data/plugins/quote.lua
index 60f0cf1e..a5f95d9e 100644
--- a/data/plugins/quote.lua
+++ b/data/plugins/quote.lua
@@ -1,5 +1,4 @@
-- mod-version:3
-local core = require "core"
local command = require "core.command"
local keymap = require "core.keymap"
diff --git a/data/plugins/reflow.lua b/data/plugins/reflow.lua
index e70b06f6..98913c6c 100644
--- a/data/plugins/reflow.lua
+++ b/data/plugins/reflow.lua
@@ -1,5 +1,4 @@
-- mod-version:3
-local core = require "core"
local config = require "core.config"
local command = require "core.command"
local keymap = require "core.keymap"
diff --git a/docs/api/system.lua b/docs/api/system.lua
index 36d93293..56e4e9b2 100644
--- a/docs/api/system.lua
+++ b/docs/api/system.lua
@@ -116,8 +116,9 @@ function system.get_window_mode(window) end
---
---Toggle between bordered and borderless.
---
+---@param window renwindow
---@param bordered boolean
-function system.set_window_bordered(bordered) end
+function system.set_window_bordered(window, bordered) end
---
---When then window is run borderless (without system decorations), this
@@ -126,10 +127,11 @@ function system.set_window_bordered(bordered) end
---To disable custom window management, call this function without any
---arguments
---
+---@param window renwindow Target window
---@param title_height? number Height of the window decoration
---@param controls_width? number Width of window controls (maximize,minimize and close buttons, etc).
---@param resize_border? number The amount of pixels reserved for resizing
-function system.set_window_hit_test(title_height, controls_width, resize_border) end
+function system.set_window_hit_test(window, title_height, controls_width, resize_border) end
---
---Get the size and coordinates of the window.
@@ -161,17 +163,27 @@ function system.set_window_size(window, width, height, x, y) end
function system.window_has_focus(window) end
---
+---Enables or disables text input.
+---
+---@param window renwindow
+---@param enabled boolean
+function system.text_input(window, enabled) end
+
+---
---Sets the position of the IME composition window.
---
+---@param window renwindow
---@param x number
---@param y number
---@param width number
---@param height number
-function system.set_text_input_rect(x, y, width, height) end
+function system.set_text_input_rect(window, x, y, width, height) end
---
---Clears any ongoing composition on the IME
-function system.clear_ime() end
+---
+---@param window renwindow
+function system.clear_ime(window) end
---
---Raise the main window and give it input focus.
diff --git a/meson.build b/meson.build
index 95f1f5c3..744592ff 100644
--- a/meson.build
+++ b/meson.build
@@ -79,7 +79,10 @@ endif
cc = meson.get_compiler('c')
pragtical_includes = []
-pragtical_cargs = ['-DSDL_MAIN_HANDLED', '-DPCRE2_STATIC']
+pragtical_cargs = [
+ '-DPCRE2_STATIC',
+ '-DPRAGTICAL_PROJECT_VERSION_STR="@0@"'.format(version)
+]
if get_option('renderer')
pragtical_cargs += '-DPRAGTICAL_USE_SDL_RENDERER'
endif
@@ -163,65 +166,61 @@ if not get_option('source-only')
default_options: default_fallback_options + ['default_library=static']
)
- sdl_options = ['default_library=static']
-
- # 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'
+ if get_option('wrap_mode') != 'forcefallback'
+ sdl_dep = dependency('sdl3')
+ sdl_uclibc_dep = dependency('', required: false)
else
- sdl_options += 'use_render=enabled'
- sdl_options += 'use_video_x11=auto'
- sdl_options += 'use_video_wayland=auto'
- endif
+ cmake = import('cmake')
- # 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
+ sdl_build_type = 'Release'
+ if get_option('buildtype') == 'debug'
+ sdl_build_type = 'Debug'
+ 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_dep = dependency('sdl2', fallback: ['sdl2', 'sdl2_dep'],
- default_options: default_fallback_options + sdl_options
- )
+ sdl_x11 = 'ON'
+ sdl_wayland = 'ON'
+ if host_machine.system() == 'windows' or host_machine.system() == 'darwin'
+ sdl_x11 = 'OFF'
+ sdl_wayland = 'OFF'
+ endif
- 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')
+ sdl_opengl = 'ON'
+ sdl_opengles = 'ON'
+ if host_machine.system() == 'windows'
+ sdl_opengl = 'OFF'
+ sdl_opengles = 'OFF'
endif
- else
- sdlmain_dep = dependency('', required: false)
+
+ sdl_osx_deploy_target = '10.11'
+ if host_machine.system() == 'darwin' and target_machine.cpu_family() == 'aarch64'
+ sdl_osx_deploy_target = '11.0'
+ endif
+
+ sdl_options = cmake.subproject_options()
+
+ sdl_options.add_cmake_defines({
+ 'CMAKE_BUILD_TYPE': sdl_build_type,
+ 'CMAKE_POSITION_INDEPENDENT_CODE': 'ON',
+ 'CMAKE_OSX_DEPLOYMENT_TARGET': sdl_osx_deploy_target,
+ 'SDL_DEPS_SHARED': 'ON', 'SDL_SHARED': 'OFF', 'SDL_STATIC': 'ON',
+ 'SDL_DBUS': 'ON', 'SDL_IBUS': 'ON', 'SDL_AUDIO': 'OFF',
+ 'SDL_GPU': 'OFF', 'SDL_RPATH': 'OFF', 'SDL_PIPEWIRE': 'OFF',
+ 'SDL_CAMERA': 'OFF', 'SDL_JOYSTICK': 'OFF', 'SDL_HAPTIC': 'OFF',
+ 'SDL_HIDAPI': 'OFF', 'SDL_DIALOG': 'OFF', 'SDL_POWER': 'OFF',
+ 'SDL_SENSOR': 'OFF', 'SDL_VULKAN': 'OFF', 'SDL_LIBUDEV': 'ON',
+ 'SDL_X11': sdl_x11, 'SDL_WAYLAND': sdl_wayland, 'SDL_TESTS': 'OFF',
+ 'SDL_OPENGL': sdl_opengl, 'SDL_OPENGLES': sdl_opengles,
+ 'SDL_DIRECTX': 'ON', 'SDL_EXAMPLES': 'OFF',
+ 'SDL_VENDOR_INFO': 'pragtical'
+ })
+
+ sdl = cmake.subproject('sdl3', options: sdl_options)
+
+ sdl_dep = sdl.dependency('SDL3-static')
+ sdl_uclibc_dep = sdl.dependency('SDL_uclibc')
endif
- pragtical_deps = [lua_dep, sdl_dep, sdlmain_dep, freetype_dep, pcre2_dep, uchardet_dep, libm, libdl, librt]
+ pragtical_deps = [lua_dep, sdl_dep, sdl_uclibc_dep, freetype_dep, pcre2_dep, uchardet_dep, libm, libdl, librt]
endif
lua_compat_needed = lua_dep.version() < '5.3.0'
@@ -276,10 +275,10 @@ else
install_dir : 'share/icons/hicolor/scalable/apps',
rename : 'pragtical.svg'
)
- install_data('resources/linux/org.pragtical.pragtical.desktop',
+ install_data('resources/linux/dev.pragtical.Pragtical.desktop',
install_dir : 'share/applications'
)
- install_data('resources/linux/org.pragtical.pragtical.appdata.xml',
+ install_data('resources/linux/dev.pragtical.Pragtical.appdata.xml',
install_dir : 'share/metainfo'
)
endif
diff --git a/resources/README.md b/resources/README.md
index fa8f1d85..cc823734 100644
--- a/resources/README.md
+++ b/resources/README.md
@@ -9,8 +9,8 @@ This folder contains resources that is used for building or packaging the projec
### Packaging
- `icons/icon.{icns,ico,inl,rc,svg}`: pragtical icon in various formats.
-- `linux/org.pragtical.pragtical.appdata.xml`: AppStream metadata.
-- `linux/org.pragtical.pragtical.desktop`: Desktop file for Linux desktops.
+- `linux/dev.pragtical.Pragtical.appdata.xml`: AppStream metadata.
+- `linux/dev.pragtical.Pragtical.desktop`: Desktop file for Linux desktops.
- `macos/appdmg.png`: Background image for packaging MacOS DMGs.
- `macos/Info.plist.in`: Template for generating `info.plist` on MacOS. See `macos/macos-retina-display.md` for details.
- `windows/001-lua-unicode.diff`: Patch for allowing Lua to load files with UTF-8 filenames on Windows.
diff --git a/resources/linux/org.pragtical.pragtical.appdata.xml b/resources/linux/dev.pragtical.Pragtical.appdata.xml
index 810650bd..bbba2b4f 100644
--- a/resources/linux/org.pragtical.pragtical.appdata.xml
+++ b/resources/linux/dev.pragtical.Pragtical.appdata.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop">
- <id>org.pragtical.pragtical</id>
+ <id>dev.pragtical.Pragtical</id>
<metadata_license>MIT</metadata_license>
<project_license>MIT</project_license>
<name>Pragtical</name>
<summary>The practical and pragmatic code editor</summary>
<content_rating type="oars-1.0" />
- <launchable type="desktop-id">org.pragtical.pragtical.desktop</launchable>
+ <launchable type="desktop-id">dev.pragtical.Pragtical.desktop</launchable>
<description>
<p>
diff --git a/resources/linux/org.pragtical.pragtical.desktop b/resources/linux/dev.pragtical.Pragtical.desktop
index f86f94a7..820e581a 100644
--- a/resources/linux/org.pragtical.pragtical.desktop
+++ b/resources/linux/dev.pragtical.Pragtical.desktop
@@ -5,6 +5,6 @@ Comment=The practical and pragmatic code editor.
Exec=pragtical %F
Icon=pragtical
Terminal=false
-StartupWMClass=pragtical
+StartupWMClass=dev.pragtical.Pragtical
Categories=Development;IDE;TextEditor;
MimeType=text/plain;inode/directory;
diff --git a/scripts/appimage.sh b/scripts/appimage.sh
index fa515d28..f702c801 100644
--- a/scripts/appimage.sh
+++ b/scripts/appimage.sh
@@ -234,7 +234,7 @@ main() {
# These could be symlinks but it seems they doesn't work with AppimageLauncher
cp resources/icons/logo.svg Pragtical.AppDir/pragtical.svg
- cp resources/linux/org.pragtical.pragtical.desktop Pragtical.AppDir/
+ cp resources/linux/dev.pragtical.Pragtical.desktop Pragtical.AppDir/
if [[ $addons == true ]]; then
addons_download "${build_dir}"
diff --git a/src/api/channel.c b/src/api/channel.c
index ea16ab1f..bcab5fe8 100644
--- a/src/api/channel.c
+++ b/src/api/channel.c
@@ -55,9 +55,9 @@ typedef struct channel {
ChannelValue** last;
} queue;
- SDL_atomic_t ref;
- SDL_mutex* mutex;
- SDL_cond* cond;
+ SDL_AtomicInt ref;
+ SDL_Mutex* mutex;
+ SDL_Condition* cond;
unsigned int sent;
unsigned int received;
@@ -77,7 +77,7 @@ typedef struct channel_list {
static ChannelList g_channels = { NULL, &(g_channels).first };
/* Mutex initialized when plugin is loaded */
-SDL_mutex* ChannelsListMutex = NULL;
+SDL_Mutex* ChannelsListMutex = NULL;
/* --------------------------------------------------------
* Channel private functions
@@ -92,7 +92,7 @@ static void channelValueFree(ChannelValue *v)
switch (v->type) {
case LUA_TSTRING:
- free(v->data.string.data);
+ SDL_free(v->data.string.data);
break;
case LUA_TTABLE:
for (
@@ -102,12 +102,12 @@ static void channelValueFree(ChannelValue *v)
){
channelValueFree(t->key);
channelValueFree(t->value);
- free(t);
+ SDL_free(t);
}
break;
}
- free(v);
+ SDL_free(v);
}
static ChannelValue* channelValueGet(lua_State *L, int index)
@@ -118,7 +118,7 @@ static ChannelValue* channelValueGet(lua_State *L, int index)
if ((type = lua_type(L, index)) == LUA_TNIL)
return NULL;
- if ((v = calloc(1, sizeof (ChannelValue))) == NULL)
+ if ((v = SDL_calloc(1, sizeof (ChannelValue))) == NULL)
return NULL;
v->type = type;
@@ -132,8 +132,8 @@ static ChannelValue* channelValueGet(lua_State *L, int index)
size_t length;
str = lua_tolstring(L, index, &length);
- if ((v->data.string.data = malloc(length)) == NULL) {
- free(v);
+ if ((v->data.string.data = SDL_malloc(length)) == NULL) {
+ SDL_free(v);
return NULL;
}
@@ -155,7 +155,7 @@ static ChannelValue* channelValueGet(lua_State *L, int index)
lua_pushnil(L);
while (lua_next(L, index)) {
- ChannelValuePair* pair = malloc(sizeof (ChannelValuePair));
+ ChannelValuePair* pair = SDL_malloc(sizeof (ChannelValuePair));
if (pair == NULL) {
lua_pop(L, 1);
@@ -171,7 +171,7 @@ static ChannelValue* channelValueGet(lua_State *L, int index)
channelValueFree(pair->key);
channelValueFree(pair->value);
channelValueFree(v);
- free(pair);
+ SDL_free(pair);
break;
}
@@ -289,7 +289,7 @@ static int channelPush(Channel* c, ChannelValue* v)
c->queue.last = &v->next;
SDL_UnlockMutex(c->mutex);
- SDL_CondBroadcast(c->cond);
+ SDL_BroadcastCondition(c->cond);
return ++c->sent;
}
@@ -298,12 +298,12 @@ static const ChannelValue* channelWait(Channel *c)
{
SDL_LockMutex(c->mutex);
while (c->queue.first == NULL)
- SDL_CondWait(c->cond, c->mutex);
+ SDL_WaitCondition(c->cond, c->mutex);
++ c->received;
SDL_UnlockMutex(c->mutex);
- SDL_CondBroadcast(c->cond);
+ SDL_BroadcastCondition(c->cond);
return c->queue.first;
}
@@ -316,7 +316,7 @@ static void channelSupply(Channel* c, ChannelValue* v)
id = channelPush(c, v);
while (!channelGiven(id, c->received))
- SDL_CondWait(c->cond, c->mutex);
+ SDL_WaitCondition(c->cond, c->mutex);
}
static void channelClear(Channel* c)
@@ -335,7 +335,7 @@ static void channelClear(Channel* c)
c->queue.last = &c->queue.first;
SDL_UnlockMutex(c->mutex);
- SDL_CondBroadcast(c->cond);
+ SDL_BroadcastCondition(c->cond);
}
static void channelPop(Channel* c)
@@ -344,7 +344,7 @@ static void channelPop(Channel* c)
if (c->queue.first == NULL) {
SDL_UnlockMutex(c->mutex);
- SDL_CondBroadcast(c->cond);
+ SDL_BroadcastCondition(c->cond);
return;
}
@@ -360,7 +360,7 @@ static void channelPop(Channel* c)
channelValueFree(previous_first);
SDL_UnlockMutex(c->mutex);
- SDL_CondBroadcast(c->cond);
+ SDL_BroadcastCondition(c->cond);
}
static void removeChannelFromList(Channel* c)
@@ -401,10 +401,10 @@ static void channelFree(Channel* c)
channelClear(c);
SDL_DestroyMutex(c->mutex);
- SDL_DestroyCond(c->cond);
+ SDL_DestroyCondition(c->cond);
- free(c->name);
- free(c);
+ SDL_free(c->name);
+ SDL_free(c);
}
/* --------------------------------------------------------
@@ -440,11 +440,11 @@ int f_channel_get(lua_State *L)
const char* error_message = NULL;
if (!found) {
- if ((c = calloc(1, sizeof (Channel))) == NULL) {
+ if ((c = SDL_calloc(1, sizeof (Channel))) == NULL) {
error_message = strerror(errno);
goto fail;
}
- if ((c->name = malloc(name_len+1)) == NULL) {
+ if ((c->name = SDL_malloc(name_len+1)) == NULL) {
error_message = strerror(errno);
goto fail;
}
@@ -452,7 +452,7 @@ int f_channel_get(lua_State *L)
error_message = SDL_GetError();
goto fail;
}
- if ((c->cond = SDL_CreateCond()) == NULL) {
+ if ((c->cond = SDL_CreateCondition()) == NULL) {
error_message = SDL_GetError();
goto fail;
}
@@ -481,10 +481,10 @@ fail:
if (c->mutex)
SDL_DestroyMutex(c->mutex);
if (c->cond)
- SDL_DestroyCond(c->cond);
+ SDL_DestroyCondition(c->cond);
- free(c->name);
- free(c);
+ SDL_free(c->name);
+ SDL_free(c);
SDL_UnlockMutex(ChannelsListMutex);
@@ -642,7 +642,7 @@ int m_channel_wait(lua_State *L)
else
channelValuePush(L, v);
- SDL_CondBroadcast(self->cond);
+ SDL_BroadcastCondition(self->cond);
return 1;
}
@@ -661,7 +661,7 @@ int mm_channel_gc(lua_State *L)
))->channel;
(void)SDL_AtomicDecRef(&self->ref);
- if (SDL_AtomicGet(&self->ref) == 0)
+ if (SDL_GetAtomicInt(&self->ref) == 0)
channelFree(self);
return 0;
diff --git a/src/api/channel.h b/src/api/channel.h
index 2da857d6..62c0acaa 100644
--- a/src/api/channel.h
+++ b/src/api/channel.h
@@ -1,8 +1,8 @@
-#include <SDL.h>
+#include <SDL3/SDL.h>
#include "api.h"
-extern SDL_mutex* ChannelsListMutex;
+extern SDL_Mutex* ChannelsListMutex;
// channel table functions
int f_channel_get(lua_State*);
diff --git a/src/api/diff.c b/src/api/diff.c
index a9599bec..ef79f4d9 100644
--- a/src/api/diff.c
+++ b/src/api/diff.c
@@ -1,7 +1,9 @@
+#include <SDL3/SDL.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#include <stdbool.h>
+
#include "api.h"
#define MAX_TOKENS 64
@@ -99,8 +101,8 @@ static Pair *build_lcs(lua_State *L, int Aidx, int Bidx, int *npairs, double thr
int n = (int)lua_rawlen(L, Aidx);
int m = (int)lua_rawlen(L, Bidx);
- int **dp = malloc((n+1) * sizeof(int*));
- for (int i = 0; i <= n; i++) dp[i] = calloc(m+1, sizeof(int));
+ int **dp = SDL_malloc((n+1) * sizeof(int*));
+ for (int i = 0; i <= n; i++) dp[i] = SDL_calloc(m+1, sizeof(int));
for (int i = 1; i <= n; i++) {
lua_rawgeti(L, Aidx, i);
@@ -117,7 +119,7 @@ static Pair *build_lcs(lua_State *L, int Aidx, int Bidx, int *npairs, double thr
lua_pop(L, 1);
}
- Pair *pairs = malloc((n + m) * sizeof(Pair));
+ Pair *pairs = SDL_malloc((n + m) * sizeof(Pair));
int count = 0;
int i = n, j = m;
while (i > 0 && j > 0) {
@@ -143,8 +145,8 @@ static Pair *build_lcs(lua_State *L, int Aidx, int Bidx, int *npairs, double thr
pairs[count - k - 1] = tmp;
}
- for (int i = 0; i <= n; i++) free(dp[i]);
- free(dp);
+ for (int i = 0; i <= n; i++) SDL_free(dp[i]);
+ SDL_free(dp);
*npairs = count;
return pairs;
@@ -237,9 +239,9 @@ static int f_inline_diff(lua_State *L) {
}
int m = strlen(a), n = strlen(b);
- int **dp = malloc((m+1) * sizeof(int*));
+ int **dp = SDL_malloc((m+1) * sizeof(int*));
for (int i = 0; i <= m; i++) {
- dp[i] = calloc(n+1, sizeof(int));
+ dp[i] = SDL_calloc(n+1, sizeof(int));
}
for (int i = 1; i <= m; i++) {
@@ -313,8 +315,8 @@ static int f_inline_diff(lua_State *L) {
lua_remove(L, -2); // remove un-reversed table
- for (int k = 0; k <= m; k++) free(dp[k]);
- free(dp);
+ for (int k = 0; k <= m; k++) SDL_free(dp[k]);
+ SDL_free(dp);
return 1;
}
@@ -402,7 +404,7 @@ static int f_diff(lua_State *L) {
}
}
- free(pairs);
+ SDL_free(pairs);
return 1;
}
@@ -481,7 +483,7 @@ static int diff_iterator(lua_State *L) {
}
if (state->pairs) {
- free(state->pairs);
+ SDL_free(state->pairs);
state->pairs = NULL;
}
@@ -503,7 +505,7 @@ static int f_diff_iter(lua_State *L) {
luaL_checktype(L, 2, LUA_TTABLE);
double threshold = luaL_optnumber(L, 3, 0.75);
- DiffState *state = malloc(sizeof(DiffState));
+ DiffState *state = SDL_malloc(sizeof(DiffState));
state->lenA = (int)lua_rawlen(L, 1);
state->lenB = (int)lua_rawlen(L, 2);
state->ai = 1;
diff --git a/src/api/dirmonitor.c b/src/api/dirmonitor.c
index 64a5f172..5d882a26 100644
--- a/src/api/dirmonitor.c
+++ b/src/api/dirmonitor.c
@@ -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>
@@ -11,7 +11,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_backend* backend;
@@ -124,7 +124,7 @@ static int f_dirmonitor_gc(lua_State* L) {
monitor->backend->deinit(monitor->internal);
SDL_UnlockMutex(monitor->mutex);
SDL_WaitThread(monitor->thread, NULL);
- free(monitor->internal);
+ SDL_free(monitor->internal);
SDL_DestroyMutex(monitor->mutex);
return 0;
}
diff --git a/src/api/dirmonitor/fsevents.c b/src/api/dirmonitor/fsevents.c
index 5f16d5dc..f07e29b4 100644
--- a/src/api/dirmonitor/fsevents.c
+++ b/src/api/dirmonitor/fsevents.c
@@ -1,10 +1,10 @@
-#include <SDL.h>
+#include <SDL3/SDL.h>
#include <CoreServices/CoreServices.h>
#include "dirmonitor.h"
struct dirmonitor_internal {
- SDL_mutex* lock;
+ SDL_Mutex* lock;
char** changes;
size_t count;
FSEventStreamRef stream;
@@ -21,7 +21,7 @@ static struct dirmonitor_internal* init_dirmonitor() {
mainloop_registered = true;
}
- struct dirmonitor_internal* monitor = malloc(sizeof(struct dirmonitor_internal));
+ struct dirmonitor_internal* monitor = SDL_calloc(1, sizeof(struct dirmonitor_internal));
monitor->stream = NULL;
monitor->changes = NULL;
monitor->count = 0;
@@ -47,9 +47,9 @@ static void stop_monitor_stream(struct dirmonitor_internal* monitor) {
close(monitor->fds[1]);
if (monitor->count > 0) {
for (size_t i = 0; i<monitor->count; i++) {
- free(monitor->changes[i]);
+ SDL_free(monitor->changes[i]);
}
- free(monitor->changes);
+ SDL_free(monitor->changes);
monitor->changes = NULL;
monitor->count = 0;
}
@@ -84,17 +84,17 @@ static void stream_callback(
size_t total = 0;
if (monitor->count == 0) {
total = numEvents;
- monitor->changes = calloc(numEvents, sizeof(char*));
+ monitor->changes = SDL_calloc(numEvents, sizeof(char*));
} else {
total = monitor->count + numEvents;
- monitor->changes = realloc(
+ monitor->changes = SDL_realloc(
monitor->changes,
sizeof(char*) * total
);
}
for (size_t idx = monitor->count; idx < total; idx++) {
size_t pidx = idx - monitor->count;
- monitor->changes[idx] = malloc(strlen(path_list[pidx])+1);
+ monitor->changes[idx] = SDL_malloc(strlen(path_list[pidx])+1);
strcpy(monitor->changes[idx], path_list[pidx]);
}
monitor->count = total;
@@ -133,9 +133,9 @@ static int translate_changes_dirmonitor(
if (monitor->count > 0) {
for (size_t i = 0; i<monitor->count; i++) {
change_callback(strlen(monitor->changes[i]), monitor->changes[i], L);
- free(monitor->changes[i]);
+ SDL_free(monitor->changes[i]);
}
- free(monitor->changes);
+ SDL_free(monitor->changes);
monitor->changes = NULL;
monitor->count = 0;
}
diff --git a/src/api/dirmonitor/inodewatcher.cpp b/src/api/dirmonitor/inodewatcher.cpp
index c42383bd..e2f55dab 100644
--- a/src/api/dirmonitor/inodewatcher.cpp
+++ b/src/api/dirmonitor/inodewatcher.cpp
@@ -1,3 +1,4 @@
+#include <SDL3/SDL.h>
#include <AK/NumericLimits.h>
#include <Kernel/API/InodeWatcherEvent.h>
#include <Kernel/API/InodeWatcherFlags.h>
@@ -26,8 +27,8 @@ struct dirmonitor_internal {
};
-static struct dirmonitor_internal* init_dirmonitor() {
- struct dirmonitor_internal* monitor = (struct dirmonitor_internal*)calloc(sizeof(struct dirmonitor_internal), 1);
+struct dirmonitor_internal* init_dirmonitor() {
+ struct dirmonitor_internal* monitor = (struct dirmonitor_internal*)SDL_calloc(sizeof(struct dirmonitor_internal), 1);
monitor->fd = create_inode_watcher(0);
pipe(monitor->sig);
fcntl(monitor->sig[0], F_SETFD, FD_CLOEXEC);
diff --git a/src/api/dirmonitor/inotify.c b/src/api/dirmonitor/inotify.c
index 2bb1e6ad..74f96f70 100644
--- a/src/api/dirmonitor/inotify.c
+++ b/src/api/dirmonitor/inotify.c
@@ -1,3 +1,4 @@
+#include <SDL3/SDL.h>
#include <sys/inotify.h>
#include <stdlib.h>
#include <unistd.h>
@@ -14,7 +15,7 @@ struct dirmonitor_internal {
static struct dirmonitor_internal* init_dirmonitor() {
- struct dirmonitor_internal* monitor = calloc(1, sizeof(struct dirmonitor_internal));
+ struct dirmonitor_internal* monitor = SDL_calloc(1, sizeof(struct dirmonitor_internal));
monitor->fd = inotify_init();
pipe(monitor->sig);
fcntl(monitor->sig[0], F_SETFD, FD_CLOEXEC);
diff --git a/src/api/dirmonitor/kqueue.c b/src/api/dirmonitor/kqueue.c
index 35811287..50cb5614 100644
--- a/src/api/dirmonitor/kqueue.c
+++ b/src/api/dirmonitor/kqueue.c
@@ -1,3 +1,4 @@
+#include <SDL3/SDL.h>
#include <sys/event.h>
#include <sys/stat.h>
#include <stdlib.h>
@@ -14,7 +15,7 @@ struct dirmonitor_internal {
static struct dirmonitor_internal* init_dirmonitor() {
- struct dirmonitor_internal* monitor = calloc(1, sizeof(struct dirmonitor_internal));
+ struct dirmonitor_internal* monitor = SDL_calloc(1, sizeof(struct dirmonitor_internal));
monitor->fd = kqueue();
return monitor;
}
diff --git a/src/api/dirmonitor/win32.c b/src/api/dirmonitor/win32.c
index 9f19750c..3b065736 100644
--- a/src/api/dirmonitor/win32.c
+++ b/src/api/dirmonitor/win32.c
@@ -1,3 +1,4 @@
+#include <SDL3/SDL.h>
#include <windows.h>
#include "dirmonitor.h"
@@ -20,7 +21,7 @@ static int get_changes_dirmonitor(struct dirmonitor_internal* monitor, char* buf
static struct dirmonitor* init_dirmonitor() {
- return calloc(1, sizeof(struct dirmonitor_internal));
+ return SDL_calloc(1, sizeof(struct dirmonitor_internal));
}
diff --git a/src/api/encoding.c b/src/api/encoding.c
index c08f2cbd..335f926f 100644
--- a/src/api/encoding.c
+++ b/src/api/encoding.c
@@ -1,4 +1,4 @@
-#include <SDL.h>
+#include <SDL3/SDL.h>
#include <lua.h>
#include <lauxlib.h>
#include <lualib.h>
@@ -325,7 +325,7 @@ int f_detect(lua_State *L) {
/* TODO: on max_read_size if the ending byte is incomplete codepoint expand it */
size_t file_size = ftell(file);
size_t read_size = file_size > MAX_READ_SIZE ? MAX_READ_SIZE : file_size;
- char* string = malloc(read_size);
+ char* string = SDL_malloc(read_size);
if (!string) {
lua_pushnil(L);
@@ -357,7 +357,7 @@ int f_detect(lua_State *L) {
rcount = 3;
}
- free(string);
+ SDL_free(string);
return rcount;
}
diff --git a/src/api/process.c b/src/api/process.c
index 1290bee5..5c87396f 100644
--- a/src/api/process.c
+++ b/src/api/process.c
@@ -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,13 +133,13 @@ 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;
node = node->next;
- free(temp);
+ SDL_free(temp);
}
memset(list, 0, sizeof(process_kill_list_t));
}
@@ -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,9 +279,9 @@ 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);
+ SDL_free(current_task);
}
}
delay = list->head ? (list->head->start_time + PROCESS_TERM_DELAY) - SDL_GetTicks() : 0;
@@ -746,7 +746,7 @@ static int f_gc(lua_State* L) {
if (poll_process(self, 0) && !self->detached) {
// attempt to kill the process if still running and not detached
signal_process(self, SIGNAL_TERM);
- if (!list || !list->worker_thread || !(p = malloc(sizeof(process_kill_t)))) {
+ if (!list || !list->worker_thread || !(p = SDL_malloc(sizeof(process_kill_t)))) {
// use synchronous waiting
if (poll_process(self, PROCESS_TERM_DELAY)) {
signal_process(self, SIGNAL_KILL);
@@ -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);
}
}
diff --git a/src/api/regex.c b/src/api/regex.c
index 635eab7a..7ddbc945 100644
--- a/src/api/regex.c
+++ b/src/api/regex.c
@@ -2,6 +2,7 @@
#define PCRE2_CODE_UNIT_WIDTH 8
+#include <SDL3/SDL.h>
#include <string.h>
#include <pcre2.h>
#include <stdbool.h>
@@ -379,7 +380,7 @@ static int f_pcre_gsub(lua_State *L) {
pcre2_match_data* match_data = pcre2_match_data_create_from_pattern(re, NULL);
size_t buffer_size = 1024;
- char *output = (char *)malloc(buffer_size);
+ char *output = (char *)SDL_malloc(buffer_size);
uint32_t options = PCRE2_SUBSTITUTE_OVERFLOW_LENGTH | PCRE2_SUBSTITUTE_EXTENDED;
if (limit == 0) options |= PCRE2_SUBSTITUTE_GLOBAL;
@@ -414,19 +415,19 @@ static int f_pcre_gsub(lua_State *L) {
} else {
offset = ovector[1] - (subject_len - outlen);
}
- if (limit_count > 1) free(subject);
+ if (limit_count > 1) SDL_free(subject);
if (limit_count == limit || offset-1 == outlen) {
done = true;
results_count = limit_count;
} else {
subject = output;
subject_len = outlen;
- output = (char *)malloc(buffer_size);
+ output = (char *)SDL_malloc(buffer_size);
outlen = buffer_size;
}
} else {
if (limit_count > 1) {
- free(subject);
+ SDL_free(subject);
}
done = true;
results_count = limit_count;
@@ -434,7 +435,7 @@ static int f_pcre_gsub(lua_State *L) {
}
} else {
buffer_size = outlen;
- output = (char *)realloc(output, buffer_size);
+ output = (char *)SDL_realloc(output, buffer_size);
}
}
@@ -450,7 +451,7 @@ static int f_pcre_gsub(lua_State *L) {
return_count = 2;
}
- free(output);
+ SDL_free(output);
pcre2_match_data_free(match_data);
if (regex_compiled)
pcre2_code_free(re);
diff --git a/src/api/renderer.c b/src/api/renderer.c
index 6ee3221b..84e092bd 100644
--- a/src/api/renderer.c
+++ b/src/api/renderer.c
@@ -242,7 +242,7 @@ static int f_font_get_size(lua_State *L) {
static int f_font_set_size(lua_State *L) {
RenFont* fonts[FONT_FALLBACK_MAX]; font_retrieve(L, fonts, 1);
float size = luaL_checknumber(L, 2);
- double scale = 1.0;
+ float scale = 1.0;
#ifdef PRAGTICAL_USE_SDL_RENDERER
RenWindow *window = ren_get_target_window();
if (window != NULL) {
diff --git a/src/api/renwindow.c b/src/api/renwindow.c
index 01e7cade..9e71c43a 100644
--- a/src/api/renwindow.c
+++ b/src/api/renwindow.c
@@ -1,62 +1,45 @@
#include "api.h"
#include "../renwindow.h"
#include "lua.h"
-#include <SDL.h>
+#include <SDL3/SDL.h>
#include <stdlib.h>
-#ifdef _WIN32
- #include "windows/darkmode.h"
-#endif
-
static RenWindow *persistant_window = NULL;
static void init_window_icon(SDL_Window *window) {
#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
}
static int f_renwin_create(lua_State *L) {
const char *title = luaL_checkstring(L, 1);
- const int x = luaL_optinteger(L, 2, SDL_WINDOWPOS_UNDEFINED);
- const int y = luaL_optinteger(L, 3, SDL_WINDOWPOS_UNDEFINED);
float width = luaL_optnumber(L, 4, 0);
float height = luaL_optnumber(L, 5, 0);
if (width < 1 || height < 1) {
- SDL_DisplayMode dm;
- SDL_GetCurrentDisplayMode(0, &dm);
+ const SDL_DisplayMode* dm = SDL_GetCurrentDisplayMode(SDL_GetPrimaryDisplay());
if (width < 1) {
- width = dm.w * 0.8;
+ width = dm->w * 0.8;
}
if (height < 1) {
- height = dm.h * 0.8;
+ height = dm->h * 0.8;
}
}
SDL_Window *window = SDL_CreateWindow(
- title, x, y, width, height,
- SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN
+ title, width, height,
+ SDL_WINDOW_RESIZABLE | SDL_WINDOW_HIGH_PIXEL_DENSITY | SDL_WINDOW_HIDDEN
);
if (!window) {
return luaL_error(L, "Error creating pragtical window: %s", SDL_GetError());
}
-
-#ifdef _WIN32
- windows_darkmode_set_theme(window, NULL, false);
-#endif
-
init_window_icon(window);
RenWindow **window_renderer = (RenWindow**)lua_newuserdata(L, sizeof(RenWindow*));
diff --git a/src/api/shmem.c b/src/api/shmem.c
index 30091378..1fc8cf4f 100644
--- a/src/api/shmem.c
+++ b/src/api/shmem.c
@@ -15,6 +15,7 @@
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
+#include <SDL3/SDL.h>
#ifdef _WIN32
#include <windows.h>
@@ -102,7 +103,7 @@ static inline bool shmem_name_valid(const char* name) {
}
shmem_object* shmem_open(const char* name, size_t size) {
- shmem_object* object = malloc(sizeof(shmem_object));
+ shmem_object* object = SDL_malloc(sizeof(shmem_object));
strcpy(object->name, name);
object->size = size;
@@ -144,7 +145,7 @@ shmem_object* shmem_open(const char* name, size_t size) {
return object;
shmem_open_error:
- free(object);
+ SDL_free(object);
return NULL;
}
@@ -160,7 +161,7 @@ void shmem_close(shmem_object* object, bool unregister) {
shm_unlink(object->name);
#endif
- free(object);
+ SDL_free(object);
}
shmem_object* shmem_resize(shmem_object** object, size_t new_size) {
@@ -175,7 +176,7 @@ shmem_object* shmem_resize(shmem_object** object, size_t new_size) {
}
shmem_mutex* shmem_mutex_open(const char* name) {
- shmem_mutex* mutex = malloc(sizeof(shmem_mutex));
+ shmem_mutex* mutex = SDL_malloc(sizeof(shmem_mutex));
#ifdef _WIN32
mutex->handle = CreateMutexA(NULL, FALSE, name);
@@ -190,7 +191,7 @@ shmem_mutex* shmem_mutex_open(const char* name) {
return mutex;
shmem_mutex_open_error:
- free(mutex);
+ SDL_free(mutex);
return NULL;
}
@@ -217,7 +218,7 @@ void shmem_mutex_close(shmem_mutex* mutex, bool unregister) {
sem_close(mutex->handle);
if (unregister) sem_unlink(mutex->name);
#endif
- free(mutex);
+ SDL_free(mutex);
}
void shmem_container_entry_clear(shmem_container* container, bool unregister) {
@@ -441,7 +442,7 @@ char* shmem_container_ns_entries_get(
);
if (object && container->namespace->entries[i].size > 0) {
- data = malloc(container->namespace->entries[i].size);
+ data = SDL_malloc(container->namespace->entries[i].size);
memcpy(data, object->map, container->namespace->entries[i].size);
*data_len = container->namespace->entries[i].size;
}
@@ -479,7 +480,7 @@ char* shmem_container_ns_entries_get_by_position(
);
if (object) {
- data = malloc(size);
+ data = SDL_malloc(size);
memcpy(data, object->map, size);
*data_len = size;
}
@@ -548,7 +549,7 @@ size_t shmem_container_ns_get_capacity(shmem_container* container) {
}
shmem_container* shmem_container_open(const char* namespace, size_t capacity) {
- shmem_container* container = malloc(
+ shmem_container* container = SDL_malloc(
sizeof(shmem_container)
+
(capacity * sizeof(shmem_object*))
@@ -595,7 +596,7 @@ shmem_container* shmem_container_open(const char* namespace, size_t capacity) {
return container;
shmem_container_open_error:
- free(container);
+ SDL_free(container);
return NULL;
}
@@ -611,7 +612,7 @@ void shmem_container_close(shmem_container* container) {
shmem_close(container->handle, unregister);
- free(container);
+ SDL_free(container);
}
@@ -651,7 +652,7 @@ static int l_shmem_pairs_iterator(lua_State *L) {
lua_pushstring(L, name);
lua_pushlstring(L, data, data_len);
- free(data);
+ SDL_free(data);
return 2;
}
@@ -730,7 +731,7 @@ static int m_shmem_get(lua_State* L) {
if (data) {
lua_pushlstring(L, data, data_len);
- free(data);
+ SDL_free(data);
}
else
lua_pushnil(L);
diff --git a/src/api/system.c b/src/api/system.c
index 99c1625a..811e81d7 100644
--- a/src/api/system.c
+++ b/src/api/system.c
@@ -1,22 +1,20 @@
-#include <SDL.h>
+#include <SDL3/SDL.h>
+#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#include <stdlib.h>
#include <ctype.h>
#include <errno.h>
-#include <math.h>
#include <sys/types.h>
#include <sys/stat.h>
#include "api.h"
#include "../rencache.h"
#include "../renwindow.h"
-#include "../renderer.h"
#ifdef _WIN32
#include <direct.h>
#include <windows.h>
#include <fileapi.h>
#include "../utfconv.h"
- #include "../windows/darkmode.h"
#define fileno _fileno
#define ftruncate _chsize
#else
@@ -99,12 +97,12 @@ static SDL_HitTestResult SDLCALL hit_test(SDL_Window *window, const SDL_Point *p
static const char *numpad[] = { "end", "down", "pagedown", "left", "clear", "right", "home", "up", "pageup", "insert", "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.
@@ -117,8 +115,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);
@@ -153,7 +151,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;
@@ -163,22 +162,12 @@ top:
}
switch (e.type) {
- case SDL_QUIT:
+ case SDL_EVENT_QUIT:
lua_pushstring(L, "quit");
return 1;
-#ifdef _WIN32
- case SDL_SYSWMEVENT:
- if (e.syswm.msg->msg.win.msg == WM_SETTINGCHANGE) {
- if (e.syswm.msg->msg.win.lParam) {
- windows_darkmode_set_theme(NULL, e.syswm.msg->msg.win.hwnd, true);
- }
- }
- return 0;
- #endif
-
- case SDL_WINDOWEVENT:
- if (e.window.event == SDL_WINDOWEVENT_RESIZED) {
+ case SDL_EVENT_WINDOW_RESIZED:
+ {
RenWindow* window_renderer = ren_find_window_from_id(e.window.windowID);
if(!window_renderer) return 0;
ren_resize_window(window_renderer);
@@ -187,103 +176,102 @@ top:
lua_pushinteger(L, e.window.data1);
lua_pushinteger(L, e.window.data2);
return 3;
- } else if (e.window.event == SDL_WINDOWEVENT_DISPLAY_CHANGED ) {
- lua_pushstring(L, "displaychanged");
- /* The display index. */
- lua_pushinteger(L, e.window.data1);
- return 2;
- } 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_DISPLAY_SCALE_CHANGED:
+ {
+ RenWindow* window_renderer = ren_find_window_from_id(e.window.windowID);
+ lua_pushstring(L, "scalechanged");
+ float new_scale = SDL_GetWindowDisplayScale(window_renderer->window);
+ lua_pushnumber(L, new_scale);
+ return 2;
}
+
+ 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:
+
+ case SDL_EVENT_DROP_FILE:
{
RenWindow* window_renderer = ren_find_window_from_id(e.drop.windowID);
SDL_GetMouseState(&mx, &my);
lua_pushstring(L, "filedropped");
- lua_pushstring(L, e.drop.file);
+ lua_pushstring(L, e.drop.data);
// a DND into dock event fired before a window is created
lua_pushinteger(L, mx * (window_renderer ? window_renderer->scale_x : 0));
lua_pushinteger(L, my * (window_renderer ? window_renderer->scale_y : 0));
- SDL_free(e.drop.file);
return 4;
}
- case SDL_KEYDOWN:
+ 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:
+ case SDL_EVENT_MOUSE_BUTTON_DOWN:
{
if (e.button.button == 1) { SDL_CaptureMouse(1); }
RenWindow* window_renderer = ren_find_window_from_id(e.button.windowID);
@@ -295,7 +283,7 @@ top:
return 5;
}
- case SDL_MOUSEBUTTONUP:
+ case SDL_EVENT_MOUSE_BUTTON_UP:
{
if (e.button.button == 1) { SDL_CaptureMouse(0); }
RenWindow* window_renderer = ren_find_window_from_id(e.button.windowID);
@@ -306,10 +294,10 @@ top:
return 4;
}
- case SDL_MOUSEMOTION:
+ case SDL_EVENT_MOUSE_MOTION:
{
SDL_PumpEvents();
- while (SDL_PeepEvents(&event_plus, 1, SDL_GETEVENT, SDL_MOUSEMOTION, SDL_MOUSEMOTION) > 0) {
+ 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;
@@ -324,46 +312,41 @@ top:
return 5;
}
- case SDL_MOUSEWHEEL:
+ 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:
+ case SDL_EVENT_FINGER_DOWN:
{
RenWindow* window_renderer = ren_find_window_from_id(e.tfinger.windowID);
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);
+ lua_pushnumber(L, e.tfinger.x * w);
+ lua_pushnumber(L, e.tfinger.y * h);
+ lua_pushinteger(L, e.tfinger.fingerID);
return 4;
}
- case SDL_FINGERUP:
+ case SDL_EVENT_FINGER_UP:
{
RenWindow* window_renderer = ren_find_window_from_id(e.tfinger.windowID);
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);
+ lua_pushnumber(L, e.tfinger.x * w);
+ lua_pushnumber(L, e.tfinger.y * h);
+ lua_pushinteger(L, e.tfinger.fingerID);
return 4;
}
- case SDL_FINGERMOTION:
+ case SDL_EVENT_FINGER_MOTION:
{
SDL_PumpEvents();
- while (SDL_PeepEvents(&event_plus, 1, SDL_GETEVENT, SDL_FINGERMOTION, SDL_FINGERMOTION) > 0) {
+ 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;
@@ -373,15 +356,15 @@ top:
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);
+ lua_pushnumber(L, e.tfinger.x * w);
+ lua_pushnumber(L, e.tfinger.y * h);
+ lua_pushnumber(L, e.tfinger.dx * w);
+ lua_pushnumber(L, e.tfinger.dy * h);
+ lua_pushinteger(L, e.tfinger.fingerID);
return 6;
}
- case SDL_APP_WILLENTERFOREGROUND:
- case SDL_APP_DIDENTERFOREGROUND:
+ case SDL_EVENT_WILL_ENTER_FOREGROUND:
+ case SDL_EVENT_DID_ENTER_FOREGROUND:
{
#ifdef PRAGTICAL_USE_SDL_RENDERER
rencache_invalidate();
@@ -392,13 +375,13 @@ top:
SDL_UpdateWindowSurface(window_list[--window_count]->window);
}
#endif
- lua_pushstring(L, e.type == SDL_APP_WILLENTERFOREGROUND ? "enteringforeground" : "enteredforeground");
+ lua_pushstring(L, e.type == SDL_EVENT_WILL_ENTER_FOREGROUND ? "enteringforeground" : "enteredforeground");
return 1;
}
- case SDL_APP_WILLENTERBACKGROUND:
+ case SDL_EVENT_WILL_ENTER_BACKGROUND:
lua_pushstring(L, "enteringbackground");
return 1;
- case SDL_APP_DIDENTERBACKGROUND:
+ case SDL_EVENT_DID_ENTER_BACKGROUND:
lua_pushstring(L, "enteredbackground");
return 1;
@@ -423,7 +406,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",
@@ -435,11 +418,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) {
@@ -454,92 +437,6 @@ static int f_set_cursor(lua_State *L) {
return 0;
}
-#ifdef X11_FOUND
-/* For reference, headers where the utilized functions and structs are found.
- #include <X11/Xlib.h>
- #include <X11/Xatom.h>
- #include <X11/Xresource.h>
-*/
-
-typedef struct _XrmHashBucketRec* XrmDatabase;
-typedef char* XPointer;
-typedef struct { unsigned int size; XPointer addr; } XrmValue;
-typedef struct _XDisplay Display;
-
-static float x11_scale_factor() {
- static bool initialized = false;
- static bool libs_found = false;
-
- static void (*XrmInitialize)(void);
- static char* (*XResourceManagerString)(Display*);
- static Display* (*XOpenDisplay)(const char*);
- static XrmDatabase (*XrmGetStringDatabase)(const char*);
- static int (*XrmGetResource)(XrmDatabase, const char*, const char*, char**, XrmValue*);
- static void (*XrmDestroyDatabase)(XrmDatabase);
-
- if (!initialized) {
- const char x11_path[2][32] = {
- "/usr/lib/libX11.so",
- "/usr/local/lib/libX11.so"
- };
- const char xres_path[2][32] = {
- "/usr/lib/libXRes.so",
- "/usr/local/lib/libXRes.so"
- };
-
- void* libX11 = NULL;
- void* libXRes = NULL;
-
- for (int i=0; i<2; i++)
- if((libX11 = SDL_LoadObject(x11_path[i])) != NULL)
- break;
-
- for (int i=0; i<2; i++)
- if((libXRes = SDL_LoadObject(xres_path[i])) != NULL)
- break;
-
- if (libX11 && libXRes) {
- XrmInitialize = SDL_LoadFunction(libX11, "XrmInitialize");
- XResourceManagerString = SDL_LoadFunction(libX11, "XResourceManagerString");
- XOpenDisplay = SDL_LoadFunction(libX11, "XOpenDisplay");
- XrmGetStringDatabase = SDL_LoadFunction(libXRes, "XrmGetStringDatabase");
- XrmGetResource = SDL_LoadFunction(libXRes, "XrmGetResource");
- XrmDestroyDatabase = SDL_LoadFunction(libXRes, "XrmDestroyDatabase");
-
- XrmInitialize();
-
- libs_found = true;
- }
- initialized = true;
- }
-
- if (!libs_found) {
- return 0.0;
- }
-
- float scale = 0.0;
- char *resourceString = XResourceManagerString(XOpenDisplay(NULL));
-
- if (resourceString) {
- XrmDatabase db = XrmGetStringDatabase(resourceString);
- XrmValue value;
- char *type = NULL;
- float dpi = 0.0;
-
- if (XrmGetResource(db, "Xft.dpi", "String", &type, &value)) {
- if (value.addr) {
- dpi = atof(value.addr);
- if (dpi > 0)
- scale = roundf((dpi / 96) * 100) / 100;
- }
- }
- XrmDestroyDatabase(db);
- free(resourceString);
- }
-
- return scale;
-}
-#endif
static int f_get_scale(lua_State *L) {
#ifdef PRAGTICAL_USE_SDL_RENDERER
@@ -548,62 +445,12 @@ static int f_get_scale(lua_State *L) {
return 1;
#else
RenWindow *window_renderer = *(RenWindow**)luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
- SDL_Window* window = window_renderer->window;
- static bool got_initial_scale = false;
-
- /* returns the startup scale factor on first call if not 100% */
- if (!got_initial_scale) {
- float initial_scale = ren_get_scale_factor(window);
- if (initial_scale != 1.0) {
- got_initial_scale = true;
- lua_pushnumber(L, initial_scale);
- return 1;
- }
- }
-
- float scale = 1.0;
- char* env_scale = NULL;
- float system_scale = 0;
-#if _WIN32
- float dpi = 0;
- int display_index = SDL_GetWindowDisplayIndex(window_renderer->window);
-#endif
-
- if (
- (env_scale = getenv("GDK_SCALE")) != NULL
- &&
- (system_scale = strtod(env_scale, NULL)) > 0
- ) {
- scale = system_scale;
- } else if (
- (env_scale = getenv("QT_SCALE_FACTOR")) != NULL
- &&
- (system_scale = strtod(env_scale, NULL)) > 0
- ) {
- scale = system_scale;
-#ifdef X11_FOUND
- } else if (
- strstr(SDL_GetCurrentVideoDriver(), "x11")
- &&
- (system_scale = x11_scale_factor()) > 0
- ) {
- scale = system_scale;
-#endif
-#if _WIN32
- } else if (SDL_GetDisplayDPI(display_index, NULL, &dpi, NULL) == 0) {
- scale = dpi / 96.0;
-#endif
- } else if (
- got_initial_scale && (system_scale = ren_get_scale_factor(window)) > 0
- ) {
- scale = system_scale;
- }
- got_initial_scale = true;
- lua_pushnumber(L, scale);
+ lua_pushnumber(L, SDL_GetWindowDisplayScale(window_renderer->window));
return 1;
#endif /* PRAGTICAL_USE_SDL_RENDERER */
}
+
static int f_set_window_title(lua_State *L) {
RenWindow *window_renderer = *(RenWindow**)luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
const char *title = luaL_checkstring(L, 2);
@@ -618,8 +465,7 @@ enum { WIN_NORMAL, WIN_MINIMIZED, WIN_MAXIMIZED, WIN_FULLSCREEN };
static int f_set_window_mode(lua_State *L) {
RenWindow *window_renderer = *(RenWindow**)luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
int n = luaL_checkoption(L, 2, "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); }
@@ -628,34 +474,23 @@ static int f_set_window_mode(lua_State *L) {
static int f_set_window_bordered(lua_State *L) {
- RenWindow** window_list;
- size_t window_count = ren_get_window_list(&window_list);
- int bordered = lua_toboolean(L, 1);
- while (window_count) {
- SDL_SetWindowBordered(window_list[--window_count]->window, bordered);
- }
-
+ RenWindow *window_renderer = *(RenWindow**) luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
+ SDL_SetWindowBordered(window_renderer->window, lua_toboolean(L, 2));
return 0;
}
static int f_set_window_hit_test(lua_State *L) {
- RenWindow** window_list;
- size_t window_count = ren_get_window_list(&window_list);
- if (lua_gettop(L) == 0) {
- while (window_count) {
- SDL_SetWindowHitTest(window_list[--window_count]->window, NULL, NULL);
- }
+ RenWindow *window_renderer = *(RenWindow**) luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
+ if (lua_gettop(L) == 1) {
+ SDL_SetWindowHitTest(window_renderer->window, NULL, NULL);
return 0;
}
- while (window_count) {
- int i = --window_count;
- float scale = window_list[i]->scale_x;
- window_list[i]->hit_test_info.title_height = luaL_checkinteger(L, 1) / scale;
- window_list[i]->hit_test_info.controls_width = luaL_checkinteger(L, 2) / scale;
- window_list[i]->hit_test_info.resize_border = luaL_checkinteger(L, 3) / scale;
- SDL_SetWindowHitTest(window_list[i]->window, hit_test, window_list[i]);
- }
+ float scale = window_renderer->scale_x;
+ window_renderer->hit_test_info.title_height = luaL_checkinteger(L, 2) / scale;
+ window_renderer->hit_test_info.controls_width = luaL_checkinteger(L, 3) / scale;
+ window_renderer->hit_test_info.resize_border = luaL_checkinteger(L, 4) / scale;
+ SDL_SetWindowHitTest(window_renderer->window, &hit_test, window_renderer);
return 0;
}
@@ -697,7 +532,7 @@ static int f_window_has_focus(lua_State *L) {
static int f_get_window_mode(lua_State *L) {
RenWindow *window_renderer = *(RenWindow**)luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
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");
@@ -710,32 +545,25 @@ static int f_get_window_mode(lua_State *L) {
}
static int f_set_text_input_rect(lua_State *L) {
+ RenWindow *window_renderer = *(RenWindow**)luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
SDL_Rect rect;
- rect.x = luaL_checknumber(L, 1);
- rect.y = luaL_checknumber(L, 2);
- rect.w = luaL_checknumber(L, 3);
- rect.h = luaL_checknumber(L, 4);
- SDL_SetTextInputRect(&rect);
+ rect.x = luaL_checknumber(L, 2);
+ rect.y = luaL_checknumber(L, 3);
+ rect.w = luaL_checknumber(L, 4);
+ rect.h = luaL_checknumber(L, 5);
+ 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
+ RenWindow *window_renderer = *(RenWindow**)luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
+ SDL_ClearComposition(window_renderer->window);
return 0;
}
static int f_raise_window(lua_State *L) {
RenWindow *window_renderer = *(RenWindow**)luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
- /*
- 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;
}
@@ -756,31 +584,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());
- return 2;
- }
-#else
- int deleted = remove(path);
- if(deleted < 0) {
- lua_pushboolean(L, 0);
- lua_pushstring(L, strerror(errno));
-
+ lua_pushboolean(L, SDL_RemovePath(luaL_checkstring(L, 1)));
+ if (!lua_toboolean(L, -1)) {
+ lua_pushstring(L, SDL_GetError());
return 2;
- } else {
- lua_pushboolean(L, 1);
}
-#endif
-
return 1;
}
@@ -791,7 +599,7 @@ static int f_chdir(lua_State *L) {
LPWSTR wpath = utfconv_utf8towc(path);
if (wpath == NULL) { return luaL_error(L, UTFCONV_ERROR_INVALID_CONVERSION ); }
int err = _wchdir(wpath);
- free(wpath);
+ SDL_free(wpath);
#else
int err = chdir(path);
#endif
@@ -801,99 +609,32 @@ static int f_chdir(lua_State *L) {
static int f_getcwd(lua_State* L) {
- #ifdef _WIN32
- wchar_t buffer[MAX_PATH];
- if (!_wgetcwd(buffer, MAX_PATH))
- return luaL_error(L, "error getcwd: %s", strerror(errno));
- char *utf8_buffer = utfconv_wctoutf8(buffer);
- if (utf8_buffer == NULL) { return luaL_error(L, UTFCONV_ERROR_INVALID_CONVERSION ); }
- lua_pushstring(L, utf8_buffer);
- free(utf8_buffer);
- #else
- char buffer[PATH_MAX];
- if (!getcwd(buffer, sizeof(buffer)))
- return luaL_error(L, "error getcwd: %s", strerror(errno));
- lua_pushstring(L, buffer);
- #endif
+ char *cwd = SDL_GetCurrentDirectory();
+ lua_pushstring(L, cwd);
+ SDL_free(cwd);
return 1;
}
+static SDL_EnumerationResult list_dir_enumeration_callback(void *userdata, const char *dirname, const char *fname) {
+ (void) dirname;
+ lua_State *L = userdata;
+ int len = lua_rawlen(L, -1);
+ lua_pushstring(L, fname);
+ lua_rawseti(L, -2, len + 1);
+ return SDL_ENUM_CONTINUE;
+}
+
static int f_list_dir(lua_State *L) {
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) {
+ bool res = SDL_EnumerateDirectory(path, list_dir_enumeration_callback, L);
+ if (!res) {
lua_pushnil(L);
- push_win32_error(L, GetLastError());
- FindClose(find_handle);
+ lua_pushstring(L, SDL_GetError());
return 2;
}
-
- FindClose(find_handle);
return 1;
-#else
- DIR *dir = opendir(path);
- if (!dir) {
- lua_pushnil(L);
- lua_pushstring(L, strerror(errno));
- 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++;
- }
-
- closedir(dir);
- return 1;
-#endif
}
@@ -908,17 +649,17 @@ static int f_absolute_path(lua_State *L) {
if (!wpath) { return 0; }
LPWSTR wfullpath = realpath(wpath, NULL);
- free(wpath);
+ SDL_free(wpath);
if (!wfullpath) { return 0; }
char *res = utfconv_wctoutf8(wfullpath);
- free(wfullpath);
+ SDL_free(wfullpath);
#else
char *res = realpath(path, NULL);
#endif
if (!res) { return 0; }
lua_pushstring(L, res);
- free(res);
+ SDL_free(res);
return 1;
}
@@ -935,11 +676,11 @@ static int f_get_file_info(lua_State *L) {
}
WIN32_FILE_ATTRIBUTE_DATA data;
if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &data)) {
- free(wpath);
+ SDL_free(wpath);
lua_pushnil(L); push_win32_error(L, GetLastError());
return 2;
}
- free(wpath);
+ SDL_free(wpath);
ULARGE_INTEGER large_int = {0};
#define TICKS_PER_MILISECOND 10000
#define EPOCH_DIFFERENCE 11644473600000LL
@@ -1072,7 +813,7 @@ static int f_mkdir(lua_State *L) {
}
int err = _wmkdir(wpath);
- free(wpath);
+ SDL_free(wpath);
#else
int err = mkdir(path, S_IRUSR|S_IWUSR|S_IXUSR|S_IRGRP|S_IXGRP|S_IROTH|S_IXOTH);
#endif
@@ -1111,23 +852,17 @@ static int f_set_clipboard(lua_State *L) {
static int f_get_primary_selection(lua_State *L) {
-#if SDL_VERSION_ATLEAST(2, 26, 0)
char *text = SDL_GetPrimarySelectionText();
if (!text) { return 0; }
lua_pushstring(L, text);
SDL_free(text);
return 1;
-#else
- return 0;
-#endif
}
static int f_set_primary_selection(lua_State *L) {
-#if SDL_VERSION_ATLEAST(2, 26, 0)
const char *text = luaL_checkstring(L, 1);
SDL_SetPrimarySelectionText(text);
-#endif
return 0;
}
@@ -1160,7 +895,7 @@ static int f_sleep(lua_State *L) {
static int f_exec(lua_State *L) {
size_t len;
const char *cmd = luaL_checklstring(L, 1, &len);
- char *buf = malloc(len + 32);
+ char *buf = SDL_malloc(len + 32);
if (!buf) { luaL_error(L, "buffer allocation failed"); }
#if _WIN32
sprintf(buf, "cmd /c \"%s\"", cmd);
@@ -1170,7 +905,7 @@ static int f_exec(lua_State *L) {
int res = system(buf);
(void) res;
#endif
- free(buf);
+ SDL_free(buf);
return 0;
}
@@ -1451,30 +1186,21 @@ static int f_path_compare(lua_State *L) {
static int f_text_input(lua_State* L) {
- if (lua_toboolean(L, 1))
- SDL_StartTextInput();
- else
- SDL_StopTextInput();
+ RenWindow *window_renderer = *(RenWindow**)luaL_checkudata(L, 1, API_TYPE_RENWINDOW);
+ if (!window_renderer) return 0;
+ if (lua_toboolean(L, 2)) {
+ SDL_StartTextInput(window_renderer->window);
+ } else {
+ SDL_StopTextInput(window_renderer->window);
+ }
return 0;
}
static int f_setenv(lua_State* L) {
const char *key = luaL_checkstring(L, 1);
const char *val = luaL_checkstring(L, 2);
-
- int ok;
-#ifdef _WIN32
- LPWSTR wkey = utfconv_utf8towc(key);
- LPWSTR wval = utfconv_utf8towc(val);
- ok = (wkey && wval) ? SetEnvironmentVariableW(wkey, wval)
- /* utfconv error */ : 0;
- free(wkey); free(wval);
-#else
// right now we overwrite unconditionally
- // this could be expanded later as an optional 3rd boolean argument
- ok = !setenv(key, val, 1);
-#endif
- lua_pushboolean(L, ok);
+ lua_pushboolean(L, SDL_setenv_unsafe(key, val, 1) == 0);
return 1;
}
@@ -1499,7 +1225,6 @@ static const luaL_Reg lib[] = {
{ "rmdir", f_rmdir },
{ "chdir", f_chdir },
{ "getcwd", f_getcwd },
- { "ftruncate", f_ftruncate },
{ "mkdir", f_mkdir },
{ "list_dir", f_list_dir },
{ "absolute_path", f_absolute_path },
@@ -1519,6 +1244,7 @@ static const luaL_Reg lib[] = {
{ "get_fs_type", f_get_fs_type },
{ "text_input", f_text_input },
{ "setenv", f_setenv },
+ { "ftruncate", f_ftruncate },
{ NULL, NULL }
};
diff --git a/src/api/thread.c b/src/api/thread.c
index 559e276c..6acab517 100644
--- a/src/api/thread.c
+++ b/src/api/thread.c
@@ -26,8 +26,8 @@
typedef struct thread {
lua_State *L;
SDL_Thread *ptr;
- SDL_atomic_t ref;
- int joined;
+ SDL_AtomicInt ref;
+ int clean;
} LuaThread;
typedef struct thread_container {
@@ -53,7 +53,7 @@ static int writer(lua_State *L, const char *data, size_t sz, LoadState *state)
for (i = 0; i < sz; ++i) {
if (state->buffer.last_written + 1 >= state->buffer.size) {
- if (!(state->buffer.data = realloc(state->buffer.data, state->buffer.size + 32))) {
+ if (!(state->buffer.data = SDL_realloc(state->buffer.data, state->buffer.size + 32))) {
lua_pushstring(L, strerror(errno));
return -1;
} else {
@@ -86,9 +86,9 @@ static void destroy(LuaThread *t)
{
(void)SDL_AtomicDecRef(&t->ref);
- if (SDL_AtomicGet(&t->ref) == 0) {
+ if (SDL_GetAtomicInt(&t->ref) <= 0) {
lua_close(t->L);
- free(t);
+ SDL_free(t);
}
}
@@ -115,7 +115,7 @@ static int loadfunction(lua_State *owner, lua_State *thread, int index)
memset(&state, 0, sizeof (LoadState));
- if (!(state.buffer.data = malloc(32))) {
+ if (!(state.buffer.data = SDL_malloc(32))) {
lua_pushnil(owner);
lua_pushstring(owner, strerror(errno));
ret = 2;
@@ -148,7 +148,7 @@ static int loadfunction(lua_State *owner, lua_State *thread, int index)
cleanup:
if (state.buffer.data) {
- free(state.buffer.data);
+ SDL_free(state.buffer.data);
}
return ret;
@@ -348,7 +348,7 @@ static int f_thread_create(lua_State *L)
int ret, iv;
LuaThread *thread;
- if ((thread = calloc(1, sizeof (LuaThread))) == NULL){
+ if ((thread = SDL_calloc(1, sizeof (LuaThread))) == NULL){
luaL_error(L, "could not allocate a new thread");
return 2;
}
@@ -404,7 +404,7 @@ static int f_thread_create(lua_State *L)
failure:
lua_close(thread->L);
- free(thread);
+ SDL_free(thread);
return 2;
}
@@ -419,7 +419,7 @@ failure:
*/
static int f_thread_get_cpu_count(lua_State *L)
{
- lua_pushinteger(L, SDL_GetCPUCount());
+ lua_pushinteger(L, SDL_GetNumLogicalCPUCores());
return 1;
}
@@ -475,7 +475,7 @@ static int m_thread_wait(lua_State *L)
int status;
SDL_WaitThread(self->ptr, &status);
- self->joined = 1;
+ self->clean = 1;
lua_pushinteger(L, status);
@@ -513,10 +513,9 @@ static int mm_thread_gc(lua_State *L)
L, 1, API_TYPE_THREAD
))->thread;
-#if SDL_VERSION_ATLEAST(2, 0, 2)
- if (!self->joined)
+ /* allow self clean */
+ if (!self->clean)
SDL_DetachThread(self->ptr);
-#endif
/* this can take place before or after the thread callback ends
* which is why ref counting is needed */
diff --git a/src/main.c b/src/main.c
index 29c1958f..7d991bfe 100644
--- a/src/main.c
+++ b/src/main.c
@@ -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__) || defined(__serenity__)
#include <unistd.h>
-#elif defined(__APPLE__)
+#elif defined(SDL_PLATFORM_APPLE)
#include <mach-o/dyld.h>
#elif defined(__FreeBSD__)
#include <sys/sysctl.h>
@@ -20,14 +21,14 @@
static void get_exe_filename(char *buf, int sz) {
#if _WIN32
int len;
- wchar_t *buf_w = malloc(sizeof(wchar_t) * sz);
+ wchar_t *buf_w = SDL_malloc(sizeof(wchar_t) * sz);
if (buf_w) {
len = GetModuleFileNameW(NULL, buf_w, sz - 1);
buf_w[len] = L'\0';
// if the conversion failed we'll empty the string
if (!WideCharToMultiByte(CP_UTF8, 0, buf_w, -1, buf, sz, NULL, NULL))
buf[0] = '\0';
- free(buf_w);
+ SDL_free(buf_w);
} else {
buf[0] = '\0';
}
@@ -36,7 +37,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. */
@@ -63,7 +64,7 @@ static void get_exe_filename(char *buf, int sz) {
#define PRAGTICAL_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);
@@ -88,7 +89,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"
#elif __serenity__
#define ARCH_PLATFORM "serenity"
@@ -128,54 +129,41 @@ int main(int argc, char **argv) {
if (getenv("SDL_VIDEODRIVER") == NULL) {
const char *session_type = getenv("XDG_SESSION_TYPE");
if (session_type && strcmp(session_type, "wayland") == 0) {
- SDL_SetHint(SDL_HINT_VIDEODRIVER, "wayland");
+ SDL_SetHint(SDL_HINT_VIDEO_DRIVER, "wayland");
}
}
#endif
- if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_EVENTS) != 0) {
- fprintf(stderr, "Error initializing SDL: %s\n", SDL_GetError());
+ SDL_SetAppMetadata("Pragtical", PRAGTICAL_PROJECT_VERSION_STR, "dev.pragtical.Pragtical");
+
+ 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_SetHint(SDL_HINT_RENDER_DRIVER, "software");
+ SDL_SetHint(SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS, "4");
if (ren_init() != 0) {
fprintf(stderr, "Error initializing renderer: %s\n", SDL_GetError());
exit(1);
}
+ int has_restarted = 0;
lua_State *L;
init_lua:
L = luaL_newstate();
@@ -196,6 +184,9 @@ init_lua:
lua_pushstring(L, PRAGTICAL_ARCH_TUPLE);
lua_setglobal(L, "ARCH");
+ lua_pushboolean(L, has_restarted);
+ lua_setglobal(L, "RESTARTED");
+
char exename[2048];
get_exe_filename(exename, sizeof(exename));
if (*exename) {
@@ -206,18 +197,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_EventState(SDL_TEXTINPUT, SDL_ENABLE);
- SDL_EventState(SDL_TEXTEDITING, SDL_ENABLE);
-
-#ifdef _WIN32
- SDL_EventState(SDL_SYSWMEVENT, SDL_ENABLE);
-#endif
+ SDL_SetEventEnabled(SDL_EVENT_TEXT_INPUT, true);
+ SDL_SetEventEnabled(SDL_EVENT_TEXT_EDITING, true);
const char *init_code = \
"local core\n"
@@ -265,6 +252,7 @@ init_lua:
if (lua_toboolean(L, -1)) {
lua_close(L);
rencache_invalidate();
+ has_restarted = 1;
goto init_lua;
}
diff --git a/src/meson.build b/src/meson.build
index 5aeaf5da..f1157aad 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -111,10 +111,28 @@ if host_machine.system() == 'windows'
pragtical_rc += windows.compile_resources('../resources/icons/icon.rc')
pragtical_rc += windows.compile_resources('../resources/windows/manifest.rc')
- pragtical_sources += 'windows/darkmode.c'
- pragtical_deps += cc.find_library('dwmapi', required : true)
+ # solve missing symbols when building from sdl3 cmake subproject
+ if sdl_dep.type_name() == 'internal'
+ pragtical_deps += cc.find_library('winmm', required : true)
+ pragtical_deps += cc.find_library('imm32', required: true)
+ pragtical_deps += cc.find_library('setupapi', required: true)
+ pragtical_deps += cc.find_library('version', required: true)
+ endif
elif host_machine.system() == 'darwin'
pragtical_sources += 'bundle_open.m'
+
+ # solve missing symbols when building from sdl3 cmake subproject
+ if sdl_dep.type_name() == 'internal'
+ pragtical_link_args += [
+ '-framework', 'Carbon',
+ '-framework', 'CoreFoundation',
+ '-framework', 'Metal',
+ '-framework', 'AppKit',
+ '-framework', 'CoreVideo',
+ '-framework', 'IOKit',
+ '-framework', 'UniformTypeIdentifiers'
+ ]
+ endif
endif
pragtical_includes += include_directories('.')
diff --git a/src/rencache.c b/src/rencache.c
index 3fa0ae8a..0d2ac5fa 100644
--- a/src/rencache.c
+++ b/src/rencache.c
@@ -1,3 +1,4 @@
+#include <stdlib.h>
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
@@ -50,7 +51,7 @@ typedef struct {
RenRect rect;
RenColor color;
RenFont *fonts[FONT_FALLBACK_MAX];
- double text_x;
+ float text_x;
size_t len;
int8_t tab_size;
RenTab tab;
@@ -120,7 +121,7 @@ static bool expand_command_buffer(RenWindow *window_renderer) {
if (new_size == 0) {
new_size = CMD_BUF_INIT_SIZE;
}
- uint8_t *new_command_buf = realloc(window_renderer->command_buf, new_size);
+ uint8_t *new_command_buf = SDL_realloc(window_renderer->command_buf, new_size);
if (!new_command_buf) {
return false;
}
diff --git a/src/renderer.c b/src/renderer.c
index 13d771b0..d057a5c4 100644
--- a/src/renderer.c
+++ b/src/renderer.c
@@ -117,7 +117,9 @@ typedef struct RenFont {
FT_Face face;
CharMap charmap;
GlyphMap glyphs;
- double scale;
+#if PRAGTICAL_USE_SDL_RENDERER
+ float scale;
+#endif
float size, space_advance;
unsigned short baseline, height, tab_size;
unsigned short underline_thickness;
@@ -130,7 +132,7 @@ typedef struct RenFont {
#ifdef PRAGTICAL_USE_SDL_RENDERER
void update_font_scale(RenWindow *window_renderer, RenFont **fonts) {
if (window_renderer == NULL) return;
- const double surface_scale = renwin_get_surface(window_renderer).scale_x;
+ const float surface_scale = renwin_get_surface(window_renderer).scale_x;
for (int i = 0; i < FONT_FALLBACK_MAX && fonts[i]; ++i) {
if (fonts[i]->scale != surface_scale) {
ren_font_group_set_size(fonts, fonts[0]->size, surface_scale);
@@ -202,7 +204,7 @@ static unsigned int font_get_glyph_id(RenFont *font, unsigned int codepoint) {
if (codepoint > MAX_UNICODE) return 0;
size_t row = codepoint / CHARMAP_COL;
size_t col = codepoint - (row * CHARMAP_COL);
- if (!font->charmap.rows[row]) font->charmap.rows[row] = check_alloc(calloc(sizeof(unsigned int), CHARMAP_COL));
+ if (!font->charmap.rows[row]) font->charmap.rows[row] = check_alloc(SDL_calloc(sizeof(unsigned int), CHARMAP_COL));
if (font->charmap.rows[row][col] == 0) {
unsigned int glyph_id = FT_Get_Char_Index(font->face, codepoint);
// use -1 as a sentinel value for "glyph not available", a bit risky, but OpenType
@@ -216,7 +218,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;
@@ -236,7 +238,7 @@ static SDL_Surface *font_allocate_glyph_surface(RenFont *font, FT_GlyphSlot slot
}
if (atlas_idx < 0) {
font->glyphs.atlas[glyph_format] = check_alloc(
- realloc(font->glyphs.atlas[glyph_format], sizeof(GlyphAtlas) * (font->glyphs.natlas[glyph_format] + 1))
+ SDL_realloc(font->glyphs.atlas[glyph_format], sizeof(GlyphAtlas) * (font->glyphs.natlas[glyph_format] + 1))
);
font->glyphs.atlas[glyph_format][font->glyphs.natlas[glyph_format]] = (GlyphAtlas) {
.width = metric->x1 + FONT_WIDTH_OVERFLOW_PX, .nsurface = 0,
@@ -247,12 +249,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;
@@ -264,19 +268,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);
- 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;
+ int depth = 0;
+ SDL_PixelFormat format = glyphformat_to_pixelformat(glyph_format, &depth);
+ atlas->surfaces = check_alloc(SDL_realloc(atlas->surfaces, sizeof(SDL_Surface *) * (atlas->nsurface + 1)));
+ 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];
}
@@ -295,7 +302,7 @@ static GlyphMetric *font_load_glyph_metric(RenFont *font, unsigned int glyph_id,
for (int i = 0; i < bitmaps; i++) {
// save the metrics for all subpixel indexes
if (!font->glyphs.metrics[i][row]) {
- font->glyphs.metrics[i][row] = check_alloc(calloc(sizeof(GlyphMetric), GLYPHMAP_COL));
+ font->glyphs.metrics[i][row] = check_alloc(SDL_calloc(sizeof(GlyphMetric), GLYPHMAP_COL));
font->glyphs.bytesize += sizeof(GlyphMetric) * GLYPHMAP_COL;
}
GlyphMetric *metric = &font->glyphs.metrics[i][row][col];
@@ -389,18 +396,18 @@ 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);
+ SDL_free(atlas->surfaces);
}
- free(font->glyphs.atlas[glyph_format_idx]);
+ SDL_free(font->glyphs.atlas[glyph_format_idx]);
font->glyphs.atlas[glyph_format_idx] = NULL;
font->glyphs.natlas[glyph_format_idx] = 0;
}
// clear glyph metric
for (int subpixel_idx = 0; subpixel_idx < FONT_BITMAP_COUNT(font); subpixel_idx++) {
for (int glyphmap_row = 0; glyphmap_row < GLYPHMAP_ROW; glyphmap_row++) {
- free(font->glyphs.metrics[subpixel_idx][glyphmap_row]);
+ SDL_free(font->glyphs.metrics[subpixel_idx][glyphmap_row]);
font->glyphs.metrics[subpixel_idx][glyphmap_row] = NULL;
}
}
@@ -410,11 +417,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;
@@ -422,8 +429,8 @@ 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);
- free(stream);
+ SDL_CloseIO((SDL_IOStream *) stream->descriptor.pointer);
+ SDL_free(stream);
}
static int font_set_face_metrics(RenFont *font, FT_Face face) {
@@ -455,31 +462,31 @@ static int font_set_face_metrics(RenFont *font, FT_Face face) {
RenFont* ren_font_load(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));
+ font = check_alloc(SDL_calloc(1, sizeof(RenFont) + len + 1));
strcpy(font->path, path);
font->size = size;
font->antialiasing = antialiasing;
font->hinting = hinting;
font->style = style;
font->tab_size = 2;
+#ifdef PRAGTICAL_USE_SDL_RENDERER
font->scale = 1.0;
+#endif
- stream = check_alloc(calloc(1, sizeof(FT_StreamRec)));
+ stream = check_alloc(SDL_calloc(1, sizeof(FT_StreamRec)));
if (!stream) goto stream_failure;
stream->read = &font_file_read;
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,11 +495,11 @@ RenFont* ren_font_load(const char* path, float size, ERenFontAntialiasing antial
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);
- if (font) free(font);
+ if (font) SDL_free(font);
return NULL;
}
@@ -512,10 +519,10 @@ void ren_font_free(RenFont* font) {
font_clear_glyph_cache(font);
// free codepoint cache as well
for (int i = 0; i < CHARMAP_ROW; i++) {
- free(font->charmap.rows[i]);
+ SDL_free(font->charmap.rows[i]);
}
FT_Done_Face(font->face);
- free(font);
+ SDL_free(font);
}
/**
@@ -626,7 +633,7 @@ int ren_font_get_metadata(
FT_SfntName metaprop;
FT_Get_Sfnt_Name(face, i, &metaprop);
- unsigned char *name = malloc(metaprop.string_len * 2);
+ unsigned char *name = SDL_malloc(metaprop.string_len * 2);
int outlen, inlen;
outlen = metaprop.string_len * 2;
inlen = metaprop.string_len;
@@ -695,15 +702,15 @@ int ren_font_get_metadata(
}
}
if (meta.tag == -1) {
- free(name);
+ SDL_free(name);
} else {
meta.value = (char*) name;
meta.len = outlen;
if (meta_count == 0) {
- *data = malloc(sizeof(FontMetaData));
+ *data = SDL_malloc(sizeof(FontMetaData));
} else {
- *data = realloc(*data, sizeof(FontMetaData) * (meta_count+1));
+ *data = SDL_realloc(*data, sizeof(FontMetaData) * (meta_count+1));
}
memcpy((*data)+meta_count, &meta, sizeof(FontMetaData));
meta_count++;
@@ -737,7 +744,7 @@ float ren_font_group_get_size(RenFont **fonts) {
return fonts[0]->size;
}
-void ren_font_group_set_size(RenFont **fonts, float size, double surface_scale) {
+void ren_font_group_set_size(RenFont **fonts, float size, float surface_scale) {
for (int i = 0; i < FONT_FALLBACK_MAX && fonts[i]; ++i) {
font_clear_glyph_cache(fonts[i]);
fonts[i]->size = size;
@@ -819,9 +826,9 @@ void ren_font_dump(RenFont *font) {
double ren_draw_text(RenSurface *rs, RenFont **fonts, const char *text, size_t len, float x, float y, RenColor color, RenTab tab) {
SDL_Surface *surface = rs->surface;
SDL_Rect clip;
- SDL_GetClipRect(surface, &clip);
+ SDL_GetSurfaceClipRect(surface, &clip);
- const double surface_scale_x = rs->scale_x, surface_scale_y = rs->scale_y;
+ const float surface_scale_x = rs->scale_x, surface_scale_y = rs->scale_y;
double pen_x = x * surface_scale_x;
double original_pen_x = pen_x;
y *= surface_scale_y;
@@ -861,12 +868,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) {
@@ -884,7 +899,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;
}
}
}
@@ -920,8 +935,8 @@ void ren_draw_rect(RenSurface *rs, RenRect rect, RenColor color) {
if (color.a == 0) { return; }
SDL_Surface *surface = rs->surface;
- const double surface_scale_x = rs->scale_x;
- const double surface_scale_y = rs->scale_y;
+ const float surface_scale_x = rs->scale_x;
+ const float surface_scale_y = rs->scale_y;
SDL_Rect dest_rect = { rect.x * surface_scale_x,
rect.y * surface_scale_y,
@@ -929,25 +944,25 @@ void ren_draw_rect(RenSurface *rs, RenRect rect, RenColor color) {
rect.height * surface_scale_y };
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 ****************/
static void ren_add_window(RenWindow *window_renderer) {
window_count += 1;
- window_list = realloc(window_list, window_count * sizeof(RenWindow*));
+ window_list = SDL_realloc(window_list, window_count * sizeof(RenWindow*));
window_list[window_count-1] = window_renderer;
}
@@ -963,10 +978,9 @@ static void ren_remove_window(RenWindow *window_renderer) {
int ren_init(void) {
FT_Error err;
- SDL_ClearError();
- 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
@@ -977,13 +991,13 @@ int ren_init(void) {
}
void ren_free(void) {
- SDL_FreeSurface(draw_rect_surface);
+ SDL_DestroySurface(draw_rect_surface);
FT_Done_FreeType(library);
}
RenWindow* ren_create(SDL_Window *win) {
assert(win);
- RenWindow* window_renderer = calloc(1, sizeof(RenWindow));
+ RenWindow* window_renderer = SDL_calloc(1, sizeof(RenWindow));
window_renderer->window = win;
renwin_init_surface(window_renderer);
@@ -998,10 +1012,10 @@ void ren_destroy(RenWindow* window_renderer) {
assert(window_renderer);
ren_remove_window(window_renderer);
renwin_free(window_renderer);
- free(window_renderer->command_buf);
+ SDL_free(window_renderer->command_buf);
window_renderer->command_buf = NULL;
window_renderer->command_buf_size = 0;
- free(window_renderer);
+ SDL_free(window_renderer);
}
void ren_resize_window(RenWindow *window_renderer) {
@@ -1035,16 +1049,6 @@ void ren_get_size(RenWindow *window_renderer, int *x, int *y) {
#endif
}
-
-float ren_get_scale_factor(SDL_Window *win) {
- int w_pixels, h_pixels;
- int w_points, h_points;
- SDL_GL_GetDrawableSize(win, &w_pixels, &h_pixels);
- SDL_GetWindowSize(win, &w_points, &h_points);
- float scale = (float) w_pixels / (float) w_points;
- return roundf(scale * 100) / 100;
-}
-
size_t ren_get_window_list(RenWindow ***window_list_dest) {
*window_list_dest = window_list;
return window_count;
diff --git a/src/renderer.h b/src/renderer.h
index 024af1b1..8130ba2b 100644
--- a/src/renderer.h
+++ b/src/renderer.h
@@ -1,7 +1,7 @@
#ifndef RENDERER_H
#define RENDERER_H
-#include <SDL.h>
+#include <SDL3/SDL.h>
#include <stdint.h>
#include <stdbool.h>
@@ -26,7 +26,7 @@ typedef enum { FONT_FAMILY, FONT_SUBFAMILY, FONT_ID, FONT_FULLNAME, FONT_VERSION
typedef struct { uint8_t b, g, r, a; } RenColor;
typedef struct { RECT_TYPE x, y, width, height; } RenRect;
typedef struct { double offset; } RenTab;
-typedef struct { SDL_Surface *surface; double scale_x, scale_y; } RenSurface;
+typedef struct { SDL_Surface *surface; float scale_x, scale_y; } RenSurface;
typedef struct { EFontMetaTag tag; char *value; size_t len; } FontMetaData;
struct RenWindow;
@@ -40,7 +40,7 @@ int ren_font_get_metadata(const char *path, FontMetaData **data, int *count, boo
int ren_font_group_get_tab_size(RenFont **font);
int ren_font_group_get_height(RenFont **font);
float ren_font_group_get_size(RenFont **font);
-void ren_font_group_set_size(RenFont **font, float size, double surface_scale);
+void ren_font_group_set_size(RenFont **font, float size, float surface_scale);
#ifdef PRAGTICAL_USE_SDL_RENDERER
void update_font_scale(RenWindow *window_renderer, RenFont **fonts);
#endif
@@ -58,7 +58,6 @@ void ren_resize_window(RenWindow *window_renderer);
void ren_update_rects(RenWindow *window_renderer, RenRect *rects, int count);
void ren_set_clip_rect(RenWindow *window_renderer, RenRect rect);
void ren_get_size(RenWindow *window_renderer, int *x, int *y); /* Reports the size in points. */
-float ren_get_scale_factor(SDL_Window *win);
size_t ren_get_window_list(RenWindow ***window_list_dest);
RenWindow* ren_find_window(SDL_Window *window);
RenWindow* ren_find_window_from_id(uint32_t id);
diff --git a/src/renwindow.c b/src/renwindow.c
index 36362b56..ba72d771 100644
--- a/src/renwindow.c
+++ b/src/renwindow.c
@@ -1,15 +1,17 @@
+#include <math.h>
+#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include "renwindow.h"
#ifdef PRAGTICAL_USE_SDL_RENDERER
-static void query_surface_scale(RenWindow *ren, double* scale_x, double* scale_y) {
+static void query_surface_scale(RenWindow *ren, float* scale_x, float* scale_y) {
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);
- double scaleX = (double) w_pixels / (double) w_points;
- double scaleY = (double) h_pixels / (double) h_points;
+ float scaleX = (float) w_pixels / (float) w_points;
+ float scaleY = (float) h_pixels / (float) h_points;
if(scale_x)
*scale_x = round(scaleX * 100) / 100;
if(scale_y)
@@ -18,14 +20,14 @@ static void query_surface_scale(RenWindow *ren, double* scale_x, double* scale_y
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);
query_surface_scale(ren, &ren->rensurface.scale_x, &ren->rensurface.scale_y);
}
#endif
@@ -35,11 +37,12 @@ void renwin_init_surface(RenWindow *ren) {
ren->scale_x = ren->scale_y = 1;
#ifdef PRAGTICAL_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);
@@ -57,8 +60,8 @@ void renwin_init_command_buf(RenWindow *ren) {
static RenRect scaled_rect(const RenRect rect, const RenSurface *rs) {
#ifdef PRAGTICAL_USE_SDL_RENDERER
- double scale_x = rs->scale_x;
- double scale_y = rs->scale_y;
+ float scale_x = rs->scale_x;
+ float scale_y = rs->scale_y;
#else
int scale_x = 1;
int scale_y = 1;
@@ -73,14 +76,14 @@ static RenRect scaled_rect(const RenRect rect, const RenSurface *rs) {
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);
- 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});
}
@@ -100,8 +103,8 @@ RenSurface renwin_get_surface(RenWindow *ren) {
void renwin_resize_surface(UNUSED RenWindow *ren) {
#ifdef PRAGTICAL_USE_SDL_RENDERER
int new_w, new_h;
- double new_scale;
- SDL_GL_GetDrawableSize(ren->window, &new_w, &new_h);
+ float new_scale;
+ SDL_GetWindowSizeInPixels(ren->window, &new_w, &new_h);
query_surface_scale(ren, &new_scale, NULL);
/* Note that (w, h) may differ from (new_w, new_h) on retina displays. */
if (new_scale != ren->rensurface.scale_x ||
@@ -130,17 +133,17 @@ void renwin_show_window(RenWindow *ren) {
void renwin_update_rects(RenWindow *ren, RenRect *rects, int count) {
#ifdef PRAGTICAL_USE_SDL_RENDERER
- const double scale_x = ren->rensurface.scale_x;
- const double scale_y = ren->rensurface.scale_y;
+ const float scale_x = ren->rensurface.scale_x;
+ const float scale_y = ren->rensurface.scale_y;
for (int i = 0; i < count; i++) {
const RenRect *r = &rects[i];
const int x = scale_x * r->x, y = scale_y * r->y;
const int w = scale_x * r->width, h = scale_y * 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);
@@ -151,7 +154,7 @@ void renwin_free(RenWindow *ren) {
#ifdef PRAGTICAL_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;
diff --git a/src/renwindow.h b/src/renwindow.h
index 21fa3f4d..a696e5b4 100644
--- a/src/renwindow.h
+++ b/src/renwindow.h
@@ -1,4 +1,4 @@
-#include <SDL.h>
+#include <SDL3/SDL.h>
#include "renderer.h"
struct HitTestInfo {
diff --git a/src/utfconv.h b/src/utfconv.h
index d5d9092e..f8af9aa8 100644
--- a/src/utfconv.h
+++ b/src/utfconv.h
@@ -49,13 +49,13 @@ static UNUSED LPWSTR utfconv_utf8towc(const char *str) {
if (len == 0)
return NULL;
- output = (LPWSTR) malloc(sizeof(WCHAR) * len);
+ output = (LPWSTR) SDL_malloc(sizeof(WCHAR) * len);
if (output == NULL)
return NULL;
len = MultiByteToWideChar(CP_UTF8, 0, str, -1, output, len);
if (len == 0) {
- free(output);
+ SDL_free(output);
return NULL;
}
@@ -71,13 +71,13 @@ static UNUSED char *utfconv_wctoutf8(LPCWSTR str) {
if (len == 0)
return NULL;
- output = (char *) malloc(sizeof(char) * len);
+ output = (char *) SDL_malloc(sizeof(char) * len);
if (output == NULL)
return NULL;
len = WideCharToMultiByte(CP_UTF8, 0, str, -1, output, len, NULL, NULL);
if (len == 0) {
- free(output);
+ SDL_free(output);
return NULL;
}
diff --git a/src/windows/darkmode.c b/src/windows/darkmode.c
deleted file mode 100644
index 83816d9d..00000000
--- a/src/windows/darkmode.c
+++ /dev/null
@@ -1,50 +0,0 @@
-#ifdef _WIN32
-
-#include "windows/darkmode.h"
-#include <dwmapi.h>
-
-#define WINDOWS_DARK_MODE_BEFORE_20H1 19
-#define WINDOWS_DARK_MODE 20
-
-static HWND get_window_handle(SDL_Window* window) {
- SDL_SysWMinfo sysInfo;
-
- SDL_VERSION(&sysInfo.version);
- SDL_GetWindowWMInfo(window, &sysInfo);
- return sysInfo.info.win.window;
-}
-
-static int dark_theme_activated() {
- DWORD type, value, count = 4;
-
- LSTATUS st = RegGetValue(
- HKEY_CURRENT_USER,
- TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Themes\\Personalize"),
- TEXT("AppsUseLightTheme"),
- RRF_RT_REG_DWORD,
- &type,
- &value,
- &count
- );
-
- if (st == ERROR_SUCCESS && type == REG_DWORD)
- return value == 0 ? 1 : 0;
-
- return 0;
-}
-
-void windows_darkmode_set_theme(SDL_Window* win, HWND hwnd, bool check_immersive) {
- HWND handle = win ? get_window_handle(win) : hwnd;
- int current_immersive_mode = 0;
- int current_mode = dark_theme_activated();
-
- if (check_immersive)
- if(DwmGetWindowAttribute(handle, WINDOWS_DARK_MODE_BEFORE_20H1, &current_immersive_mode, 4) != FACILITY_NULL)
- DwmGetWindowAttribute(handle, WINDOWS_DARK_MODE, &current_immersive_mode, 4);
-
- if (current_mode != current_immersive_mode)
- if (DwmSetWindowAttribute(handle, WINDOWS_DARK_MODE_BEFORE_20H1, &current_mode, 4) != 0)
- DwmSetWindowAttribute(handle, WINDOWS_DARK_MODE, &current_mode, 4);
-}
-
-#endif
diff --git a/src/windows/darkmode.h b/src/windows/darkmode.h
deleted file mode 100644
index 768d3480..00000000
--- a/src/windows/darkmode.h
+++ /dev/null
@@ -1,13 +0,0 @@
-#ifndef WINDOWS_DARKMODE_H
-#define WINDOWS_DARKMODE_H
-
-#ifdef _WIN32
- #include <SDL.h>
- #include <SDL_syswm.h>
- #include <stdbool.h>
- #include <windows.h>
-
- void windows_darkmode_set_theme(SDL_Window* win, HWND hwnd, bool check_immersive);
-#endif
-
-#endif
diff --git a/subprojects/packagefiles/sdl3/meson.build b/subprojects/packagefiles/sdl3/meson.build
new file mode 100644
index 00000000..05cf4b96
--- /dev/null
+++ b/subprojects/packagefiles/sdl3/meson.build
@@ -0,0 +1 @@
+project('sdl3', version : '3.2.16', license : 'zlib')
diff --git a/subprojects/sdl2.wrap b/subprojects/sdl2.wrap
deleted file mode 100644
index 39031b2d..00000000
--- a/subprojects/sdl2.wrap
+++ /dev/null
@@ -1,15 +0,0 @@
-[wrap-file]
-directory = SDL2-2.32.8
-source_url = https://github.com/libsdl-org/SDL/releases/download/release-2.32.8/SDL2-2.32.8.tar.gz
-source_filename = SDL2-2.32.8.tar.gz
-source_hash = 0ca83e9c9b31e18288c7ec811108e58bac1f1bb5ec6577ad386830eac51c787e
-patch_filename = sdl2_2.32.8-1_patch.zip
-patch_url = https://wrapdb.mesonbuild.com/v2/sdl2_2.32.8-1/get_patch
-patch_hash = 5df17ea39ca418826db20e96bd821fa52b5718dac64b6225119fb6588c2744f0
-source_fallback_url = https://github.com/mesonbuild/wrapdb/releases/download/sdl2_2.32.8-1/SDL2-2.32.8.tar.gz
-wrapdb_version = 2.32.8-1
-
-[provide]
-sdl2 = sdl2_dep
-sdl2main = sdl2main_dep
-sdl2_test = sdl2_test_dep
diff --git a/subprojects/sdl3.wrap b/subprojects/sdl3.wrap
new file mode 100644
index 00000000..e8d97b3b
--- /dev/null
+++ b/subprojects/sdl3.wrap
@@ -0,0 +1,8 @@
+[wrap-git]
+url = https://github.com/libsdl-org/SDL.git
+revision = release-3.2.16
+depth = 1
+patch_directory = sdl3
+
+[provide]
+sdl3 = sdl3_dep