Commit graph

1,792 commits

Author SHA1 Message Date
Kevin Boos
1cda404284
Fix behavior of PortalList::at_end() to be fully correct (#1007)
* Fix behavior of `PortalList::at_end()` to be fully correct

This has been buggy for a long time, now it is flawless.

* cleanup, add some clarifying comments
2026-04-02 08:31:33 +02:00
Kevin Boos
10c33aca95
Fix text wrapping breaking before trailing punctuation marks (#1006)
This was causing punctuation marks to wrap to the next line
by themselves instead of sticking with the previous word,
but that looks really strange/wrong.

---------------

Unicode word boundary segmentation (UAX#29) treats punctuation as
separate segments from words, causing the text layouter to wrap
punctuation like `.` `,` `;` `)` to a new line by itself.

Added `merge_segments_for_line_breaking()` that post-processes word
boundary segments before width measurement, following standard
line-breaking conventions (UAX#14 / CSS Text Module Level 3):
- Trailing/closing punctuation (`. , : ; ! ? ) ] }` etc.) merges into
  the preceding segment (no break before).
- Opening punctuation (`( [ {` etc.) merges into the following segment
  (no break after).
- Consecutive punctuation chains correctly (e.g., `):` stays with the
  preceding word).
2026-04-02 08:31:20 +02:00
Kevin Boos
7bcacc33f8
Properly animate caption bar when entering/exiting macOS fullscreen (#1005)
add handlers for "will enter/exit fullscreen" instead of just handling
"did" enter/exit, in order to properly animate. Otherwise it looks
janky for a split second where the traffic light buttons are on top of
the old app content before it refreshes.
2026-04-02 08:31:10 +02:00
Kevin Boos
0f2939945c
Expose window chrome button bounding box in WindowGeom (#1001)
* Expose window chrome button bounding box in `WindowGeom`

This allows apps that wanna draw something in the title/caption bar
to do so in a proper way without potentially drawing over the native
window chrome buttons (on macOS, the traffic light buttons).
Without this it'd be pretty tough to figure that out.

This also auto-sets the caption bar height to be tall enough such that
the window chrome / traffic light buttons are perfectly vertically-centered
in the middle of the caption bar. This was needed on macOS to prevent
things from looking janky as hell on newer macOS versions, which changed
the default size of the traffic chrome buttons.
It'll also be useful for drawing things in the caption bar on linux
or windows too.

Full change set:

- `widgets/src/window.rs`: Hide the caption bar on `LinuxWindow` when
  `!custom_window_chrome` (X11 — WM provides native decorations) directly in
  `sync_caption_bar_state`, removing the need for apps to do this manually.
- `event/window.rs`: Add `window_chrome_buttons: Rect` to `WindowGeom` —
  the bounding box of the OS/app-drawn window chrome buttons in logical window
  coordinates (top-left origin). Non-zero on macOS (traffic lights), Windows
  (min/max/close), and Wayland with `custom_window_chrome`. Zero on all other
  platforms (X11, LinuxDirect, mobile, web). Documented with per-platform
  details and guidance on how to use it for caption-bar layout margins.
- `macos_window.rs`: Add `traffic_lights_geom()` — queries all three
  traffic-light buttons via `standardWindowButton:`, converts their frames
  to Makepad's coordinate system via `convertRect:fromView:`, and returns
  the bounding box as a `Rect`.
- `win32_window.rs`: Populate `window_chrome_buttons` with the right-aligned
  138×29 px bounding box of the three Makepad-drawn caption buttons.
- `linux_wayland.rs`: Populate `window_chrome_buttons` in the
  `WindowGeomChange` handler when `custom_window_chrome: true`, using the
  same right-aligned 138×29 px layout.
- `cx_api.rs`: Add `update_caption_bar_height_script_value()` to push a
  measured height into `mod.widgets.CAPTION_BAR_HEIGHT` on the script heap.
- `window.rs` (DSL): Declare `mod.widgets.CAPTION_BAR_HEIGHT = 27.0` in the
  `script_mod!` block and change `caption_bar.height` from the hardcoded `27`
  to `(mod.widgets.CAPTION_BAR_HEIGHT)`. On `WindowGeomChange`, derive the
  default caption bar height from `window_chrome_buttons` using equal
  top/bottom padding (`pos.y * 2 + size.y`) and trigger a script reapply.
- `platform/src/lib.rs`: Export `LinuxWindowParams`, `WindowGeom`,
  and `SafeAreaInsets`.

* Fix calculation of title bar height based on buttons

ensure dynamic override actually propagates via Rust code

* clearly define system-calculated caption bar height vs manual override

* Fix window drag move bounds to match the caption bar area

remove excess debug logs
2026-04-01 23:11:37 +02:00
Admin
4fc9a06b06 variable weight fonts 2026-04-01 12:19:03 +02:00
Admin
3f2baab26d xr llama and slug 2026-04-01 12:19:03 +02:00
Admin
cb3b36d241 llama + xr 2026-04-01 12:19:03 +02:00
Admin
95c822450b fixup 2026-04-01 12:19:03 +02:00
Admin
f6cf4e5c13 refactor 2026-04-01 12:19:02 +02:00
Admin
5f20c2b6da xr works 2026-04-01 12:19:02 +02:00
Admin
c8280ee338 testing x client 2026-04-01 12:19:02 +02:00
Admin
1c7835fca9 working emitters 2026-04-01 12:19:02 +02:00
Admin
96bbe681d8 otw 2026-04-01 12:19:02 +02:00
Admin
e343aa00d4 xr networking 2026-04-01 12:19:02 +02:00
Admin
fcc003814e refactor 2026-04-01 12:19:02 +02:00
Kevin Boos
02704b27a9
PortalList: fix drag scrolling over widgets that handle events/hits (#1002)
Previously, PortalList's drag scrolling straight up didn't work
when the initial FingerDown event (touch/tap/click) landed on a widget
that is "interactive", meaning it could handle events. Not sure when that
concept was introduced, but it's kinda flawed given that all widgets
just defaulted to being `true` (always interactive). But imo that goes
against the ethos of simple event handling based on ordering of calls to
`handle_event()`, not to mention the whole `capture_overload` thing.

I think this is the solution that we've always wanted. The PortalList itself
now tracks when it is scrolling (and only starts a scroll once it is sure
enough finger/mouse movement has occurred, `TAP_COUNT_DISTANCE`),
and it does not deliver these interactive events to child widgets
while it is scrolling. This will make things a lot easier for the app dev too,
since that's how iOS and Android work too.

Details of changes to `portal_list.rs`:

- Always enter `ScrollState::Drag` on FingerDown regardless of whether
  the touch point is over an interactive widget. A `committed` flag and
  `drag_scroll_threshold` (defaulting to `TAP_COUNT_DISTANCE`) gate
  when scroll deltas actually apply, preventing micro-scrolling during
  taps/clicks on interactive items.
- Suppress event forwarding to child widgets once a drag scroll commits
  (finger moves past threshold), so children don't receive stale
  interaction events during scrolling.
- Suppress event forwarding when a finger-down/click arrives while a
  scroll animation (flick, pulldown, etc.) is in progress, so tapping
  to stop a scroll doesn't also activate a child widget.
- Add configurable `drag_scroll_threshold` property to PortalList.
2026-04-01 08:40:06 +02:00
Kevin Boos
507bcf35d1
Choose sane defaults for platform-specific title/caption bar config (#1000)
Primarily on Linux, ensure that we show the title/caption bar
and draw it within Makepad (i.e., client-side drawing) if the
DE/WM doesn't show it by default.
This should make things behave as expected on Linux X11 and Wayland
both.
2026-04-01 00:42:29 +02:00
Kevin Boos
3a6499b70d
Fix title bar, captions label centering, and windows buttons (#999)
no app-level overrides are needed now.

1. on Windows, the windows buttons now behave and are drawn
   just like all other apps -- proper bg coloring on hover and down,
   and the right sizing.

2. and for the caption label, it is centered properly (by accounting
   for the size of the windows_buttons button set), and then when the
   window is too narrow, it is left-aligned in the remaining space
   to ensure that it stil looks good.
2026-03-31 08:58:06 +02:00
Kevin Boos
f99dee329c
Remove busy-wait loops on Linux (x11 and wayland) (#998)
Tested working with Robrix and a few makepad examples
2026-03-31 08:57:51 +02:00
Kevin Boos
191ac72bf9
Introduce knowledge of device screen bounds/"safe inset areas" (#990)
* Introduce knowledge of device screen bounds/cutous/"safe inset areas"

Tested working on iOS, implemented for Android but not yet tested.

The approach may need to be improved, because it currently restricts
the whole app window to being fully within the safe areas.
We may not necessarily want that, or if we do, then we probably also
need to support setting the base color of the reserved system areas
(beneath the app bounds and above in the notification bar area).

* Use metal scissor rect to prevent SVGs/icons from being mis-drawn in safe areas

This prevents anything from being accidentally drawn in the safe
inset areas when the pass clear_color is transparent. Of course,
we can still draw the pass clear_color in those areas.

* Workaround: apply a scissor rect within safe inset area

Only apply it to clip any DrawSvg/DrawVector-specific draw calls
within the safe inset area.

This is unfortunately still just a hacky solution, because if we
actually do want to draw svg/vectors within that safe inset area,
then we won't be able to.

* Properly fix gpu artifacts when rendering SVGs

The `DrawSvg` vertex shader had a GPU fringe expansion pass designed for `fill_gpu()` mode, where fringe vertices encode per-vertex normals in the `v` and `stroke_dist` fields. SVG rendering used `fill_gpu()`, which produces **coincident-vertex fringe triangles** (body and outer fringe at the same CPU position, expanded on the GPU). These zero-area triangles caused **Metal GPU rasterization artifacts** — stray fragments appearing at unexpected screen positions.

**`draw/src/svg/render.rs`** — Switch SVG fill from `fill_gpu()` to `fill()`. Pre-computed fringe produces vertices at physically different positions (no coincident vertices).

**`draw/src/shader/draw_svg.rs`** — Remove the GPU fringe expansion code from the vertex shader. With pre-computed fringe, the `v` and `stroke_dist` fields are constants (`1.0` and `0.0`), not per-vertex normals. The expansion code was misinterpreting `v=1.0` as a horizontal normal, corrupting vertex positions.

**`libs/apple_sys/src/lib.rs`** — Added `MTLScissorRect` struct (unused now but available for future use).

**`src/home/rooms_sidebar.rs`** — Changed shadow offset from `vec2(1.0, 0.0)` to `vec2(0.0, 10.0)` so the `RoundedShadowView` shadow only draws below the header, eliminating the gray line at the top of the screen (issue 1).

* Expose safe area inset padding to app, don't forcibly apply it to root window

* Fixed safe area insets padding, with support for rotation

We now make these values available to the app dev (see below)
instead of forcibly inserting them as padding on all root windows.

This will allow each app to choose how and when they want to apply said pad values
(or if they want to at all) in an easy way, both at the Splash level
or more dynamically/programmatically at the Rust level.

Required quite a few changes to how things work in the iOS platform plumbing,
also described below in the generated summary:

On iOS and Android, Makepad apps render content behind device cutouts (Dynamic Island, camera notch), home indicators, and rounded screen corners because the framework has no awareness of safe area insets.

Added platform-level safe area inset querying on iOS and Android, exposed the values through both the Splash DSL (`mod.widgets.SAFE_INSET_PAD_*`) and Rust (`cx.display_context.safe_area_insets`), and ensured they update correctly on device rotation.

**New types:**
- `UIEdgeInsets` struct in `libs/apple_sys` for Objective-C interop
- `SafeAreaInsets` struct in `platform/src/event/window.rs` (top/right/bottom/left in logical points)
- Added `safe_area_insets` field to `WindowGeom` and `DisplayContext`

**iOS (`platform/src/os/apple/ios/`):**
- Query `[UIView safeAreaInsets]` from the MTKView in `check_window_geom()`
- Added `viewSafeAreaInsetsDidChange` callback on `MakepadViewController` to detect inset changes on rotation
- Populate `display_context` before `Event::Startup` so values are available during app script initialization
- Fixed MTKView setup: removed redundant `addSubview:` (conflicted with `setRootViewController:`) and added autoresizing mask — both required for safe area propagation on rotation

**Android (`platform/src/os/linux/android/`):**
- Added `SafeAreaInsets` variant to `FromJavaMessage` and corresponding JNI function
- Java side (`ResizingLayout.onApplyWindowInsets`): queries `WindowInsets.Type.systemBars() | displayCutout()` and sends insets to Rust (converted from px to dp)
- Added `safe_area_insets` field to `CxOs`, populated on `SafeAreaInsets` message and included in `WindowGeom` construction
- Added `surfaceOnSafeAreaInsets` native method to `MakepadNative.java`

**Splash DSL variables (`widgets/src/lib.rs`):**
- `mod.widgets.SAFE_INSET_PAD_TOP`
- `mod.widgets.SAFE_INSET_PAD_BOTTOM`
- `mod.widgets.SAFE_INSET_PAD_LEFT`
- `mod.widgets.SAFE_INSET_PAD_RIGHT`
- Values read from `display_context` at widget module initialization (during `Event::Startup`)
- Updated on the script heap via `Cx::update_safe_inset_script_values()` on `WindowGeomChange`

**Rotation support:**
- Added `pending_script_reapply` flag on `Cx` — set when safe area insets change, checked at the end of the platform event loop iteration
- Fires a deferred `LiveEdit` event to re-evaluate and re-apply all Splash widget definitions with updated inset values
- Implemented in both iOS and Android event loops

**StackNavigationView fix (`widgets/src/stack_navigation.rs`):**
- Full-screen stack views now position at `max(safe_area_insets.top, parent_rect.pos.y)` instead of hardcoded `y: 0`, respecting both mobile safe areas and desktop title bars

**All other platforms:**
- Added `..Default::default()` to all `WindowGeom` constructors (macOS, Windows, Linux X11/Wayland/Direct, web, tvOS, OpenHarmony) so the new `safe_area_insets` field defaults to zeros
2026-03-31 08:57:36 +02:00
Admin
b5f2562768 cleanup 2026-03-30 09:54:53 +02:00
Admin
966c8fda96 cleanup 2026-03-30 09:52:31 +02:00
Admin
2bb0fe88cc cleanup 2026-03-30 09:22:56 +02:00
Admin
27220ca062 lz4 opt 2026-03-30 01:06:33 +02:00
Admin
b99ce4fe48 missing 2026-03-30 00:55:55 +02:00
Admin
7fb8f420a4 lz4 wire protocol 2026-03-30 00:55:33 +02:00
Admin
cfd39ecc72 cleanup 2026-03-29 23:33:47 +02:00
Admin
a0732c853c cleanup 2026-03-29 23:21:47 +02:00
Admin
eddabcf8ca cleanup 2026-03-29 22:57:11 +02:00
Admin
d0785c5212 cleanup 2026-03-29 22:53:22 +02:00
Admin
ebcf0d58ac cleanup 2026-03-29 22:47:40 +02:00
Admin
3a29497923 optimize 2026-03-29 22:12:33 +02:00
Admin
bc70aa5ed7 optimisations 2026-03-29 21:46:25 +02:00
Admin
f8ffda732a optimisations 2026-03-29 21:36:19 +02:00
Admin
0fdc86b528 optimisations 2026-03-29 21:01:06 +02:00
Admin
d83941cf7a optimisations 2026-03-29 20:27:52 +02:00
Admin
4056a99c14 optimisations 2026-03-29 18:46:50 +02:00
Admin
afeadc8650 optimisations 2026-03-29 18:42:48 +02:00
Admin
ac3ed67fe6 optimisations 2026-03-29 18:32:46 +02:00
Admin
fcc98d6d69 fixing tracing 2026-03-29 18:12:16 +02:00
Admin
3e7fb23e95 fixing tracing 2026-03-29 18:06:14 +02:00
Admin
cf1b38f9d0 deptmap tweaks 2026-03-29 15:47:27 +02:00
Admin
d596d15d9e depth align trying 2026-03-29 11:10:52 +02:00
Admin
c352bf75e8 clean maps lock 2026-03-28 22:56:30 +01:00
Admin
efb78e542f refactor 2026-03-28 21:45:46 +01:00
Admin
bc64ac1164 fix refactor 2026-03-28 21:45:27 +01:00
Admin
ebdd3fe530 optimising 2026-03-28 20:11:51 +01:00
Admin
a495095c9a optimising 2026-03-28 20:03:37 +01:00
Admin
0cc533660e optimising 2026-03-28 19:56:09 +01:00
Admin
cf0b9d0153 working refactor 2026-03-28 18:46:43 +01:00