diff options
| author | Jefferson González <jgmdev@gmail.com> | 2025-07-31 12:02:53 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2025-07-31 15:02:53 -0400 |
| commit | 2863e6d45043672d4afcbc38d953987edd548cd3 (patch) | |
| tree | fbd18b9ec5125a893e3d131580d58e3d223552cd | |
| parent | e2127ae4643c7a37fa03ff2dd8e26c71c4c6762b (diff) | |
| download | pragtical-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>
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(¤t_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 */ @@ -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, ¤t_immersive_mode, 4) != FACILITY_NULL) - DwmGetWindowAttribute(handle, WINDOWS_DARK_MODE, ¤t_immersive_mode, 4); - - if (current_mode != current_immersive_mode) - if (DwmSetWindowAttribute(handle, WINDOWS_DARK_MODE_BEFORE_20H1, ¤t_mode, 4) != 0) - DwmSetWindowAttribute(handle, WINDOWS_DARK_MODE, ¤t_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 |
