Skip to content

[WIP] feat(ptk): add preliminary Wayland backend implementation - #322

Draft
wineee wants to merge 66 commits into
lc-soft:developfrom
wineee:wayland
Draft

[WIP] feat(ptk): add preliminary Wayland backend implementation#322
wineee wants to merge 66 commits into
lc-soft:developfrom
wineee:wayland

Conversation

@wineee

@wineee wineee commented May 19, 2026

Copy link
Copy Markdown
Contributor

仍然是草稿

@wineee wineee changed the title feat(ptk): add preliminary Wayland backend implementation [WIP] feat(ptk): add preliminary Wayland backend implementation May 19, 2026
lc-soft added 3 commits May 20, 2026 23:44
BREAKING CHANGE: lcui_app_get_fps -> lcui_get_fps,
lcui_app_set_frame_rate_cap -> lcui_set_fps_cap,
settings.frame_rate_cap -> settings.fps_cap.
lcui_app_init, lcui_app_destroy, lcui_app_process_events
removed from public header — use lcui_init, lcui_destroy,
lcui_run instead.
OrbisAI Security and others added 3 commits May 23, 2026 18:53
Multiple unbounded strcpy() calls in lib/css/src/selector
Introduce ctest_suite_t, ctest_parse_args, ctest_run_suites and CTEST_MAIN macro to standardize test binary entry points. Support --grep / --grep= / --list / --interactive / --help. Add lib/ctest/tests/ for self-tests covering str converters and grep filter logic.
lc-soft added 6 commits May 24, 2026 17:56
Restructure the test infrastructure with these changes:

* Extend libctest with ctest_suite_t, ctest_parse_args, ctest_run_suites and CTEST_MAIN macro to standardize test entry points; support --grep / --grep= / --list / --interactive flags; add ctest-tests for self-tests.

* Regroup tests by lib boundary: sink unit tests into lib/<name>/tests/ with <lib>_<topic> entry function names, move fixtures into lib/<name>/tests/fixtures/, rename top-level tests/cases/ to tests/integration/ for cross-lib integration tests.

* Add tests/scenes/ for reusable widget tree builders shared by integration cases and visual preview binaries; add tests/previews/ with 4 diagnostic binaries (flex_layout, block_layout, widget_opacity, scrollbar).

* Rewrite all describe/equal description strings using 'should ...' style or noun topic names; drop redundant lcui_quit/lcui_main calls from integration cases.

* Integrate xmake test via add_tests(\default\) and a shared tests.runnable rule defined in the root xmake.lua; the rule wraps the test binary with drmemory (Windows) or valgrind (Linux) when option memcheck=y.

* Drop the lcui-tests aggregation: lcui-tests now contains only integration cases and scenes, not the union of lib tests. Use xmake test to run everything across libs.

* Fix .clang-format: InsertNewlineAtEndOfFile -> InsertNewlineAtEOF (correct key for clang-format 16+).

* Update AGENTS.md with the new test layout, naming rules, description style and run commands.

* Update CI to use xmake test and xmake f --memcheck=y instead of per-lib runs.
Create lib/ui-router/ as a thin UI binding layer between libui and librouter, exposing the router-link and router-view widgets under <ui_router/...>.

* Move src/widgets/router_{link,view}.c and the matching public headers into lib/ui-router/src and lib/ui-router/include.

* Drop include/LCUI/widgets/router_{link,view}.h and the corresponding entries in include/LCUI/widgets.h; src/lcui_widgets.c now pulls registrations from <ui_router.h>.

* Wire libui-router into the root xmake.lua add_includedirs and lcui add_deps chain; libui-router depends on yutil + libui + librouter only.

* tests/integration/test_router.c stays at the integration layer (router widgets exercise text inheritance and other libui internals); only its #include set is updated to use <ui_router.h>.

* Bump CHANGELOG and add bilingual lib/ui-router/README.
Pulls in yutil c91be801 which sets the yutil-tests rundir to scriptdir, fixing the Windows execv error 267 reported by xmake run yutil-tests.
Add actions/cache step covering xmake package and repository directories on both Linux and Windows runners. Cache key is keyed by runner OS, build mode (coverage on Linux, release on Windows) and the hashes of root and examples xmake-requires.lock so coverage and release artifacts do not pollute each other and examples deps share the same cache.

Bump actions/checkout to v4 with submodules: recursive (replacing the manual submodule update step), upload-artifact to v4 and download-artifact to v4.
lc-soft and others added 13 commits May 24, 2026 18:04
pd_text_delete_ex
- Use-after-free: in same-line branch, pd_text_delete_line(end_y) was
  followed by pd_text_line_set_length / pd_text_update_line_size on the
  freed line. Now returns immediately after delete_line in that path.
- Off-by-one: cross-line merge used j = end_x + 1, dropping one char
  when end_x is mid-line. Now j = end_x, and the line-tail special
  case resets end_x to 0 explicitly.
- OOB read: prev_line = text->lines[char_y - 1] without bounds check.
  Now guarded with char_y > 0 ? ... : NULL.
- Memory leak: chars in the deleted range were never freed and
  ownership transfer between lines could double-free on delete_line.

pd_text_line_set_length
- realloc-grown slots were not zeroed, leaving uninitialized pointer
  values that could be misread as live pd_char_t *.

pd_text_dump
- col was not reset when advancing to the next line, so output was
  truncated at the first line's length.
- Did not emit the line-ending characters recorded in line->eol, so
  multi-line text was concatenated without separators.

Helpers
- Extract pd_text_line_erase / pd_text_line_move to centralize char
  ownership transfer; reused in pd_text_merge_line.

Tests
- Add lib/pandagl/tests/test_text_edit.c with 11 cases covering the
  original crash scenarios (backspace at last empty line, delete at
  line end), boundary cases, and dump behavior.

Closes lc-soft#270
The previous naming conflated multiple levels of the font model:
pd_font_t actually owned a single typeface resource (FT_Face), while
pd_font_bitmap_t represented a per-glyph bitmap. The pd_font_library_*
prefix was redundant under the pd_font_ namespace and resulted in
verbose call sites (up to 34 chars).

Type renames
- pd_font_t          -> pd_font_face_t
- pd_font_bitmap_t   -> pd_glyph_bitmap_t
- font_engine_t      -> pd_font_engine_t
- struct tags updated to match the typedef names.

API renames (grouped by sub-object)
- Face lifecycle:    pd_font_create/destroy -> pd_font_face_create/destroy
- Face registry:     pd_font_library_add_font     -> pd_font_register
                     pd_font_library_get_font     -> pd_font_get
                     pd_font_library_get_font_id  -> pd_font_get_id
                     pd_font_library_query        -> pd_font_query
                     pd_font_library_load_file    -> pd_font_load_file
                     pd_font_library_get_font_path-> pd_font_find_path
                     pd_font_library_get_default_font -> pd_font_get_default
                     pd_font_library_set_default_font -> pd_font_set_default
                     pd_font_library_set_font_family_alias
                                                  -> pd_font_family_set_alias
                     pd_font_library_update_font_weight
                                                  -> pd_font_replace_weight
                     pd_font_library_update_font_style
                                                  -> pd_font_replace_style
- Parsing helpers:   pd_font_library_detect_weight -> pd_font_parse_weight
                     pd_font_library_detect_style  -> pd_font_parse_style
- Glyph rendering:   pd_font_library_render_bitmap -> pd_font_render_glyph
                     pd_canvas_mix_font_bitmap     -> pd_canvas_mix_glyph_bitmap
                     pd_font_bitmap_init/destroy   -> pd_glyph_bitmap_init/destroy
- Glyph cache:       pd_font_library_add_bitmap    -> pd_font_cache_add_bitmap
                     pd_font_library_get_bitmap    -> pd_font_cache_get_bitmap

pd_font_library_init/destroy are kept as the module lifecycle entry
points, matching the FT_Init_FreeType / FT_Done_FreeType convention.

All call sites in lib/pandagl, lib/ui, lib/ui-xml, src/, tests/ and
examples/ are updated accordingly.
The previous bitmap cache was a three-level rbtree keyed by
(wchar_t, font_id, size), which had two problems:

1. The wchar_t key collapses Unicode codepoints that map to the
   same glyph in a given face into separate cache slots, missing
   real reuse opportunities and bloating memory under text-heavy
   workloads.
2. There was no upper bound; long-running apps would grow the
   cache without limit until pd_font_library_destroy.

Replace it with a flat hash table keyed by a packed 64-bit
(face_id, glyph_index, size) tuple, plus a doubly-linked LRU list
for O(1) eviction.

- pd_font_engine gets a new get_glyph_index hook; FreeType maps
  via FT_Get_Char_Index, the in-core engine treats codepoints as
  identity (no cmap).
- pd_font_cache_add_bitmap / pd_font_cache_get_bitmap now resolve
  the glyph index via the engine before keying the cache, so the
  same glyph reused across composed sequences hits the same entry.
- pd_font_cache_set_capacity / pd_font_cache_count expose the LRU
  bound (default 8192 entries, 0 = unlimited) for runtime tuning
  and tests. Shrinking the capacity evicts immediately.
- list_t is used with append at tail / evict from head so the
  yutil tail.prev pointer stays consistent (list_link does not
  update it).

Adds lib/pandagl/tests/test_font_cache.c covering hit identity,
size differentiation, unknown-codepoint fallback, and LRU eviction.
Split lib/pandagl/src/text/text.c into four cohesive units backed
by a library-private header:

- text.c           : type lifecycle, line storage, geometry,
                     dirty-rect bookkeeping, top-level update
- text_typeset.c   : line breaking, merging, autowrap, alignment
- text_render.c    : per-char bitmap refresh and drawing
- text_edit.c      : caret, insert/delete/backspace, text I/O
- text_internal.h  : library-private cross-file helpers
                     (not installed)

Drop the 'insert' overload that conflated 'cursor' with 'insertion
point' and align the field/API names with the cursor concept used
in mainstream GUI toolkits:

  insert_x, insert_y                -> caret.x, caret.y
                                       (new pd_text_caret_t sub-struct)
  pd_text_set_insert_position       -> pd_text_set_caret
  pd_text_set_insert_pixel_position -> pd_text_set_caret_pixel
  pd_text_get_insert_pixel_position -> pd_text_get_caret_pixel
  pd_text_get_char_pixel_position   -> pd_text_get_char_pixel

Make text I/O symmetric and intent-revealing:

  pd_text_dump                       -> pd_text_read
                                        (mirrors pd_text_write)
  pd_text_empty                      -> pd_text_clear
                                        (the previous static helper
                                        is renamed to pd_text_reset_lines)
  pd_text_set_typeset_task           -> pd_text_request_typeset

Add pd_text_to_wcs(text), which allocates and returns the full
buffer contents including line endings. It complements the
range-based pd_text_read for callers that just want the whole
text as a wide string.

Fix the mulitiline_enabled -> multiline_enabled typo while at it.

All call sites in lib/pandagl, src/widgets and the tests are
updated. test_text_edit.c gains two cases for pd_text_to_wcs
covering full-text round-trip and the empty-text edge case.
- Remove per-lib set_project() calls that overrode the global lcui
  project name; xmake show now correctly reports the project as lcui.
- Move per-lib set_version() into the corresponding target() block so
  each sub-library keeps an independent version usable for standalone
  packaging.
- Add set_default(false) and set_group(examples) to all pandagl
  examples so they are no longer picked up by xmake package.
- Rename targets to use dashes for consistency:
    pandagl_cairo_example  -> pandagl-cairo-example
    preview_block_layout   -> preview-block-layout
    preview_flex_layout    -> preview-flex-layout
    preview_scrollbar      -> preview-scrollbar
    preview_widget_opacity -> preview-widget-opacity
- Bump yutil submodule to drop its set_project() call as well.
The %ls format in logger_error went through UCRT's wide-to-multibyte path, which triggered a debug assertion in mbstowcs.cpp under non-UTF-8 locales and also produced unreadable output when the console code page was GBK.

Switch the tree drawing to UTF-8 byte literals so the log path stays purely narrow, and temporarily set the console output code page to CP_UTF8 around the dump so the box-drawing characters render correctly.
The visible property check was missing '== 0', so any non-visible property change incorrectly set update_visible to true, while actual visible mutations were ignored. This caused the window to never receive ptk_window_show on Windows.
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Liu <lc-soft@live.cn>
…-soft#327)

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: Liu <lc-soft@live.cn>
lc-soft added 6 commits June 29, 2026 23:06
- charset module renamed to encoding (decode/encode kept)
- time: get_time_ms → y_gettime, sleep_ms → y_sleep
- time: delete get_time_us, get_time_delta, sleep_s
- string: strdup2 → y_strdup, wcsdup2 → y_wcsdup
- string: strtolower → y_strlower, strtrim → y_strtrim
- string: wcstrim → y_wcstrim, strhash → y_strhash
- string: strreplace → y_strreplace, strsplit → y_strsplit
- string: delete wcsreplace, cmdsplit
- math: delete y_iround, y_pow2
- timer module migrated from yutil to ptk as internal timer_scheduler
- WinMain simplified to use __argc/__argv instead of cmdsplit

BREAKING CHANGE: all renamed yutil public APIs require downstream
  to update function names. Deleted APIs require code changes:
  - get_time_us: use y_gettime() for ms timestamps
  - get_time_delta: use y_gettime() - start instead
  - sleep_s: use y_sleep(ms) with millisecond argument
  - wcsreplace: no replacement, had zero callers
  - cmdsplit: WinMain now uses __argc/__argv from CRT
  - timer_list_*: migrated to ptk timer_scheduler_*;
    ptk_reset_timer still available for external use
@wineee
wineee force-pushed the wayland branch 2 times, most recently from b6e3366 to ac5e535 Compare July 29, 2026 03:04
@codecov

codecov Bot commented Jul 29, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 1.35747% with 654 lines in your changes missing coverage. Please review.
✅ Project coverage is 62.31%. Comparing base (4a3a65e) to head (49f1d59).

Files with missing lines Patch % Lines
lib/ptk/src/linux/waylandapp_window.c 0.00% 236 Missing ⚠️
lib/ptk/src/linux/waylandapp_input.c 0.00% 211 Missing ⚠️
lib/ptk/src/linux/waylandapp_core.c 0.00% 174 Missing ⚠️
lib/ptk/src/linux/app.c 36.00% 12 Missing and 4 partials ⚠️
lib/ptk/src/linux/waylandapp_output.c 0.00% 12 Missing ⚠️
lib/ptk/src/linux/ime.c 0.00% 5 Missing ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##           develop     #322      +/-   ##
===========================================
- Coverage    64.22%   62.31%   -1.91%     
===========================================
  Files          221      225       +4     
  Lines        21137    21787     +650     
  Branches      2938     3051     +113     
===========================================
+ Hits         13575    13577       +2     
- Misses        6467     7113     +646     
- Partials      1095     1097       +2     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

wineee added 6 commits July 29, 2026 18:39
Check WAYLAND_DISPLAY for wayland, DISPLAY for x11, and fallback to
framebuffer. Log warnings when preferred backend is not compiled in.
Add missing PTK_HAS_WAYLAND template in config.h.in so the macro is
actually defined in generated config.h. Include ptk.h before the
#if guard in wayland source files so the macro is visible at the
preprocessor check. Move ptk_waylandapp_destroy() before
ptk_waylandapp_init() to resolve forward declaration warning.

Fix cursor scaling on HiDPI: load cursor theme at logical size (32)
instead of physical size (32*output_scale) and remove redundant
hotspot division by output_scale, avoiding double scaling via
wl_surface_set_buffer_scale.

Only compile wayland source files when the wayland package is available.
…e space

Store wnd->width/height as logical pixels (matching xdg_toplevel
configure), allocate buffer at logical size, and let buffer_scale
handle the upscaling to physical pixels. This eliminates the
physical/logical coordinate mismatch that caused content to render
in only a quarter of the window on HiDPI displays.

Size events send physical dimensions (logical * scale) so the upper
layer correctly divides by DPI scale. Size hints pass logical values
directly to the Wayland protocol as it expects.
- Allocate SHM buffer at physical pixel dimensions (logical * scale)
- Scale pointer coordinates to physical pixels in mouse events
- Return physical pixel dimensions from screen and window size getters
- Convert physical pixels to logical in set_size and size hints
- Post size event on output_scale change to trigger layout refresh
Add wp_viewporter and wp_fractional_scale_v1 protocol support to
handle non-integer HiDPI scaling on Wayland.

- Bind viewporter and fractional-scale manager from registry
- Create wp_viewport per window with source following buffer size
- Use wp_fractional_scale_v1 to receive per-window scale from compositor
- Fall back to wl_surface_set_buffer_scale when viewporter unavailable
- Change output_scale from int to double, use lround for int conversions
- Fix initial window size by setting xdg_surface window geometry
- Use per-window scale for input coordinate conversion
- Reuse ptk_waylandwindow_destroy in app destroy to avoid resource leak
Call xdg_surface_set_window_geometry before each surface commit so
that SSD decorations track resize correctly.
@lc-soft
lc-soft force-pushed the develop branch 3 times, most recently from 70a8c84 to 873971f Compare August 5, 2026 15:36
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants