Commit Graph

13 Commits

Author SHA1 Message Date
tomasmark79 afa8e1843c M3: Wayland: stop retaining Ctrl zoom for pixel-only wheel input (#1569)
* M3: release Ctrl zoom for pixel-only Wayland wheel events

Use the reported scroll source to avoid unterminated finger gestures for wheel, wheel-tilt and continuous input. Exercise the production policy through egui, including modifier release and preserved finger momentum.

Assisted-by: OpenAI Codex

* M3: keep Cargo lockfile dependency ordering canonical

Record the dependency ordering produced by the completed workspace and wasm gates.

Assisted-by: OpenAI Codex

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-15 04:08:34 -04:00
tisca26 d1a4fb18c5 fix(ui): on macOS, dragging a tab moves the tab, not the window (#2347)
On macOS the tab strip is the title bar: a transparent title bar over a
full-size content view. AppKit asks the view under the pointer whether a
press there can move the window (`mouseDownCanMoveWindow`), and NSView
answers YES for a view that isn't opaque. winit's view didn't override it,
so AppKit moved the whole window for any drag that began in the 28 pt band
before egui saw it, and the tab reordering from #1551 never got the drag.

vendor/winit now answers with the window's `movable_by_window_background`
attribute (NO unless asked). The empty strip still moves the window through
`ViewportCommand::StartDrag`, and double-clicking it still maximizes. Patch
(12) in vendor/README.md, kept in the build by
`tests/winit_macos_title_bar_drag.rs`.

Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
2026-10-15 02:57:01 -04:00
gyurix f5452cf126 Linux: prefer server DPI over panel physical DPI in vendored winit (#1150)
* fix(x11): prefer server DPI over panel physical DPI in winit

Without Xft DPI, use the X server screen dimensions before the output physical density. Xorg can run a dense panel at 96 DPI; EDID sizes alone make only winit apps appear zoomed.

Supersedes #908: preserves Xft.dpi priority, configured HiDPI screens, and WINIT_X11_SCALE_FACTOR override (including randr). Falls back to RandR output density when server dimensions are missing.

Adds default_dpi_factor() with 4 unit tests plus vendored-copy guard test in apps/pdfcraft/tests/winit_x11_dpi.rs.

* vendor/README: record the winit X11 DPI patch as (11)

---------

Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-11 19:12:32 -04:00
cyfung1031 68e91d4815 macOS: the first Apple Korean key in a fresh PdfCraft composes (winit#4744) (#680)
* macOS: IME text committed after the marked text is cleared isn't lost (winit#4650)

winit 0.30.13 reports insertText as Ime::Commit only while marked text is
left, and after any commit it swallows the next key. Real paths where that
loses text:

- input methods that end a composition with unmarkText, then insertText
  (rust-windowing/winit#3925): the committed text was dropped;
- Apple Korean 2-Set, for the key typed after a syllable: on 한 then 5 it
  calls setMarkedText("한"), insertText("한"), setMarkedText(""),
  insertText("5"), so the 5 (or ;, or any key that ends the syllable) was
  dropped;
- a commit made outside a key press (a candidate clicked with the mouse,
  dictation): no key follows to reset the state, so the next key (for
  example Backspace) was swallowed.

vendor/winit now commits when a composition was started (pending_commit,
set in setMarkedText, cleared by the commit and when IME is disallowed);
other insertText calls still reach the app as KeyboardInput. A commit
outside keyDown clears the marked text and returns to the ground state.
validAttributesForMarkedText lists the underline and marked-clause
attributes, which some input methods need before they compose.

This is rust-windowing/winit#4650, the 0.30 backport of #4651 (merged on
winit master), plus the part of #4748 that fixes #4651's out-of-key-press
case (#4748's other parts are not included). One correction: upstream
spells the underline attribute "NSUnderlineStyle", but AppKit's
NSUnderlineStyleAttributeName is "NSUnderline" (printed on macOS 14), so
the AppKit value is used.

Checked with the real input methods on macOS 14.7.1 (a scratch winit app fed
key events through AppKit): with the patch 한+5 and 한+; commit the 5 and ;,
unmarkText-then-insertText commits, and Backspace after a commit outside a
key press is delivered; ABC typing, held keys, Japanese (日本, あ), Cangjie
(日) and Korean composition give the same events as before. A test fails if
a re-vendored winit loses the patch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* macOS: the first Apple Korean key in a fresh PdfCraft composes (winit#4744)

On the first key after PdfCraft starts, Apple Korean 2-Set can answer
interpretKeyEvents with insertText and the raw compatibility jamo instead of
setMarkedText. winit sends that key to the app as an ordinary key, and the
next keys compose without it: g k s Space typed ㅎㅏㄴ instead of 한 (Search,
form fields, comments; rust-windowing/winit#3095).

vendor/winit now ports rust-windowing/winit#4744: keyDown interprets that
one key a second time, synchronously, before any KeyboardInput is sent, and
only when every condition holds: Apple Korean, IME allowed and not yet
composing, no pending commit or marked text, no Command/Control/Option, not
a repeat, the key window's first responder, the only callback is one
insertText of that same single jamo, and focus and input source unchanged
afterwards. The decision is ImeStartup (ime_startup.rs, copied with its
seven tests); no timer, no key queue, no text rewriting. It sits on top of
the previous macOS IME change (pending_commit, in_key_down); the retry runs
inside in_key_down. Command maps to ModifiersState::SUPER in winit 0.30
(META on winit master).

Checked with the real input method on macOS 14.7.1 (scratch winit app, fresh
process each time): without the patch g k s Space gave ㅎ as a key, then
ㅏ and ㄴ committed separately, 3 runs out of 3; with it, ㅎ → 하 → 한 → 한
committed, 3 out of 3. All other traces (Japanese, Cangjie, ABC, held
keys, later Korean keys) are unchanged. ImeStartup's tests pass with
rustc --test. A test fails if a re-vendored winit loses the patch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-09 22:47:36 -04:00
cyfung1031 cf9f58fe87 macOS: Space in Apple Korean with no syllable in progress types one space (winit#4478) (#679)
* macOS: IME text committed after the marked text is cleared isn't lost (winit#4650)

winit 0.30.13 reports insertText as Ime::Commit only while marked text is
left, and after any commit it swallows the next key. Real paths where that
loses text:

- input methods that end a composition with unmarkText, then insertText
  (rust-windowing/winit#3925): the committed text was dropped;
- Apple Korean 2-Set, for the key typed after a syllable: on 한 then 5 it
  calls setMarkedText("한"), insertText("한"), setMarkedText(""),
  insertText("5"), so the 5 (or ;, or any key that ends the syllable) was
  dropped;
- a commit made outside a key press (a candidate clicked with the mouse,
  dictation): no key follows to reset the state, so the next key (for
  example Backspace) was swallowed.

vendor/winit now commits when a composition was started (pending_commit,
set in setMarkedText, cleared by the commit and when IME is disallowed);
other insertText calls still reach the app as KeyboardInput. A commit
outside keyDown clears the marked text and returns to the ground state.
validAttributesForMarkedText lists the underline and marked-clause
attributes, which some input methods need before they compose.

This is rust-windowing/winit#4650, the 0.30 backport of #4651 (merged on
winit master), plus the part of #4748 that fixes #4651's out-of-key-press
case (#4748's other parts are not included). One correction: upstream
spells the underline attribute "NSUnderlineStyle", but AppKit's
NSUnderlineStyleAttributeName is "NSUnderline" (printed on macOS 14), so
the AppKit value is used.

Checked with the real input methods on macOS 14.7.1 (a scratch winit app fed
key events through AppKit): with the patch 한+5 and 한+; commit the 5 and ;,
unmarkText-then-insertText commits, and Backspace after a commit outside a
key press is delivered; ABC typing, held keys, Japanese (日本, あ), Cangjie
(日) and Korean composition give the same events as before. A test fails if
a re-vendored winit loses the patch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* macOS: Space in Apple Korean with no syllable in progress types one space (winit#4478)

With Apple Korean 2-Set on macOS 14, Space with no syllable in progress
(a second space, or a space after a digit or punctuation) makes AppKit
call setMarkedText(" "), insertText(" "), then setMarkedText(""). winit
reports the insertText as Ime::Commit(" "), but the trailing empty
setMarkedText returns its state to the ground state, so keyDown also sends
the key as KeyboardInput with text " ". egui inserts both, and PdfCraft's
text fields got two spaces (the double space of alacritty/alacritty#8079).

vendor/winit now records that the key being handled committed IME text and
then doesn't also send it as KeyboardInput, unless AppKit forwards it as a
command through doCommandBySelector (Enter after a syllable still commits
the syllable and sends Enter). keyDown consumes the record on every key,
so keys typed after IME is disallowed are unaffected.

rust-windowing/winit#4478 aims at the same double space, but its changes
(clearing the marked text on commit, forwarding a later insertText, and
dropping doCommandBySelector's guard) don't reach this call order, and the
key loss it also fixes is already fixed by the previous change
(pending_commit). This is the narrow form for the call order observed
here; it should go upstream with #4478.

Checked with the real input methods on macOS 14.7.1 (scratch winit app, on top
of the previous change): the duplicate KeyboardInput Space is gone and
nothing else changes (Korean syllables, 한+Enter, 한+5, Japanese, Cangjie,
ABC, held keys, keys after IME is disallowed). A test fails if a
re-vendored winit loses the patch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Keep #678's emoji-picker branch: view.rs is main's plus this PR's Space fix (54b3d3c)

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-09 22:46:49 -04:00
cyfung1031 3aa03d3c91 macOS: emoji from the emoji picker reach text fields (winit#4749) (#678)
* macOS: IME text committed after the marked text is cleared isn't lost (winit#4650)

winit 0.30.13 reports insertText as Ime::Commit only while marked text is
left, and after any commit it swallows the next key. Real paths where that
loses text:

- input methods that end a composition with unmarkText, then insertText
  (rust-windowing/winit#3925): the committed text was dropped;
- Apple Korean 2-Set, for the key typed after a syllable: on 한 then 5 it
  calls setMarkedText("한"), insertText("한"), setMarkedText(""),
  insertText("5"), so the 5 (or ;, or any key that ends the syllable) was
  dropped;
- a commit made outside a key press (a candidate clicked with the mouse,
  dictation): no key follows to reset the state, so the next key (for
  example Backspace) was swallowed.

vendor/winit now commits when a composition was started (pending_commit,
set in setMarkedText, cleared by the commit and when IME is disallowed);
other insertText calls still reach the app as KeyboardInput. A commit
outside keyDown clears the marked text and returns to the ground state.
validAttributesForMarkedText lists the underline and marked-clause
attributes, which some input methods need before they compose.

This is rust-windowing/winit#4650, the 0.30 backport of #4651 (merged on
winit master), plus the part of #4748 that fixes #4651's out-of-key-press
case (#4748's other parts are not included). One correction: upstream
spells the underline attribute "NSUnderlineStyle", but AppKit's
NSUnderlineStyleAttributeName is "NSUnderline" (printed on macOS 14), so
the AppKit value is used.

Checked with the real input methods on macOS 14.7.1 (a scratch winit app fed
key events through AppKit): with the patch 한+5 and 한+; commit the 5 and ;,
unmarkText-then-insertText commits, and Backspace after a commit outside a
key press is delivered; ABC typing, held keys, Japanese (日本, あ), Cangjie
(日) and Korean composition give the same events as before. A test fails if
a re-vendored winit loses the patch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* macOS: emoji from the emoji picker reach text fields (winit#4749)

The macOS emoji picker (Fn/Globe-E, Control-Command-Space) inserts its text
with insertText:replacementRange: outside any key press and without a
composition. winit 0.30.13 reports insertText only as part of a key press or
a composition, so an emoji picked into Search, a form field or a comment
was dropped.

vendor/winit now reports text inserted outside a key press, with IME
allowed and no composition, as Ime::Commit, as rust-windowing/winit#4749
(the 0.30 backport of #4748) does. Builds on the pending_commit and
in_key_down state of the previous macOS IME change.

#4748's selectedRange change, which lets dictation start, is left out:
checked on macOS 14.7.1, a valid selection switches on press-and-hold for
every held key in a winit window, so holding e kept sending e key events
under an accent menu, and the accent picked with 1 arrived as a separate
commit after "eeee…1". Without it, held keys repeat as before.

Checked with a scratch winit app on macOS 14.7.1: an insertText outside a key
press now arrives as Ime::Commit; held keys, ABC, Japanese, Cangjie and
Korean typing give the same events as before. A test fails if a re-vendored
winit loses the patch or gains the selectedRange change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-09 22:45:51 -04:00
cyfung1031 3a86ce073d macOS: an unfinished composition doesn't come back in the next text field (winit#4745) (#677)
egui disallows IME when a text field loses focus, for example when the user
clicks the page while composing. winit 0.30.13 then clears its own marked
text but never tells the input method, which keeps the composition and
continues it once IME is allowed again. Checked with the real input methods
on macOS 14.7.1: Korean 하, IME off and on, then r k gave 학, then 하 and 가
(하 committed a second time if the app already kept it); Japanese か, IME
off and on, then s a gave 傘.

vendor/winit now calls NSTextInputContext::discardMarkedText when IME is
disallowed with marked text present, before its existing reset, as
rust-windowing/winit#4745 does on winit master. With the patch the same
sequences give 가 and さ. AppKit may call unmarkText from
discardMarkedText while IME is still enabled, so its Preedit("") comes
before Disabled; the RefCell borrow in the check ends before the call.
Everything else in the scratch app's traces (ABC, Japanese, Cangjie,
Korean) is unchanged. A test fails if a re-vendored winit loses the patch.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-09 22:44:58 -04:00
cyfung1031 ec6c904cf3 macOS: IME text committed after the marked text is cleared isn't lost (winit#4650) (#676)
winit 0.30.13 reports insertText as Ime::Commit only while marked text is
left, and after any commit it swallows the next key. Real paths where that
loses text:

- input methods that end a composition with unmarkText, then insertText
  (rust-windowing/winit#3925): the committed text was dropped;
- Apple Korean 2-Set, for the key typed after a syllable: on 한 then 5 it
  calls setMarkedText("한"), insertText("한"), setMarkedText(""),
  insertText("5"), so the 5 (or ;, or any key that ends the syllable) was
  dropped;
- a commit made outside a key press (a candidate clicked with the mouse,
  dictation): no key follows to reset the state, so the next key (for
  example Backspace) was swallowed.

vendor/winit now commits when a composition was started (pending_commit,
set in setMarkedText, cleared by the commit and when IME is disallowed);
other insertText calls still reach the app as KeyboardInput. A commit
outside keyDown clears the marked text and returns to the ground state.
validAttributesForMarkedText lists the underline and marked-clause
attributes, which some input methods need before they compose.

This is rust-windowing/winit#4650, the 0.30 backport of #4651 (merged on
winit master), plus the part of #4748 that fixes #4651's out-of-key-press
case (#4748's other parts are not included). One correction: upstream
spells the underline attribute "NSUnderlineStyle", but AppKit's
NSUnderlineStyleAttributeName is "NSUnderline" (printed on macOS 14), so
the AppKit value is used.

Checked with the real input methods on macOS 14.7.1 (a scratch winit app fed
key events through AppKit): with the patch 한+5 and 한+; commit the 5 and ;,
unmarkText-then-insertText commits, and Backspace after a commit outside a
key press is delivered; ABC typing, held keys, Japanese (日本, あ), Cangjie
(日) and Korean composition give the same events as before. A test fails if
a re-vendored winit loses the patch.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-09 22:44:34 -04:00
cyfung1031 84b241831b X11: the input method follows the text field that has focus (winit#4727) (#675)
egui calls Window::set_ime_allowed(true) when a text field gains focus and
set_ime_allowed(false) when it loses it. On X11, winit 0.30.13 handles each
change by destroying the window's X input context and creating a new one, and
leaves focusing the new context to the next FocusIn. PdfCraft's window keeps
the focus while the user moves between Search, form fields and the canvas, so
no FocusIn comes and the new context stays unfocused: the input method
(IBus, fcitx5) doesn't follow the field until the window loses and regains
focus.

vendor/winit's Ime::set_ime_allowed now returns create_context's result, and
the event processor, after draining the queued IME requests, focuses the last
context replaced for the active window, once, as
rust-windowing/winit#4727 does on winit master. No public API changes. A
test fails if a re-vendored winit loses the patch.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-09 22:42:29 -04:00
cyfung1031 9250e7542e Windows: a window closed maximized reopens without a white flash (winit#4587) (#674)
eframe creates PdfCraft's window hidden, restores the saved state
(app.ron, persist_window) and shows the window after the first frame is
drawn. For a window closed maximized, winit 0.30.13 applies the maximized
state with ShowWindow(SW_MAXIMIZE), which shows a hidden window: PdfCraft
appeared unpainted (white), was hidden again, then shown with SW_SHOW and
SW_MAXIMIZE once more. rust-windowing/winit#4586 also shows the window's
focus state going wrong on this path.

vendor/winit now skips the maximize while the window is hidden and shows a
hidden window that is maximized with one SW_MAXIMIZE, as
rust-windowing/winit#4587 (approved upstream) does on winit master. That is
the later, focus-safe form of #4575; #4575's other change (re-sending
SW_MINIMIZE on every flag change while minimized) is not taken. Transitions
between two visible states make the same ShowWindow calls as before. A test
fails if a re-vendored winit loses the patch.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-09 22:42:06 -04:00
cyfung1031 5437390e7e Windows: the Korean IME composition caret sits after the syllable (winit#4746) (#673)
When a composition has no target clause, winit 0.30.13 reads the cursor with
ImmGetCompositionStringW(GCS_CURSORPOS) without checking that the
WM_IME_COMPOSITION lParam has GCS_CURSORPOS set. The Microsoft Korean IME
never sets it (lParam 0x6018), so the read gives 0 and winit reports
Ime::Preedit("한", Some((0, 0))). egui 0.36.2 recognises that exact report on
Windows and drops the range, so PdfCraft draws no caret while Korean is being
composed.

vendor/winit now reads GCS_CURSORPOS only when the flag says the IME set it
and otherwise puts the cursor at the end of the composition, as
rust-windowing/winit#4746 does on winit master (Firefox and SDL do the same).
IMEs that report a cursor or a target clause (Japanese, Chinese) are
unchanged. A test fails if a re-vendored winit loses the patch.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-09 22:41:43 -04:00
cyfung1031 60a0518349 Wayland: IME keeps working after a seat loses a capability (winit#4747) (#672)
winit 0.30.13 destroys a seat's zwp_text_input_v3 in
SeatHandler::remove_capability, whichever capability went away (a touch
screen or tablet unplugged, a remote-desktop session ending), and only
new_capability recreates it. A seat that loses a capability without gaining
one leaves PdfCraft without a text input: IME (fcitx5, IBus) stops working
until PdfCraft is restarted.

The text input belongs to the seat, so vendor/winit now destroys it in
remove_seat only, as rust-windowing/winit#4747 does on winit master. A test
fails if a re-vendored winit loses the patch.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <echelon@gmail.com>
2026-10-09 22:39:50 -04:00
cyfung1031 24ba8385f8 Issue #324: on Windows 11, a window dragged to another monitor takes its scale (#544)
* Issue #324: vendor winit 0.30.13 as published

The crate as released on crates.io, without its asset files (docs/res/*.svg and
examples/data/*.png, AGENTS.md §1). Not used yet: the next commit patches it and
adds it to [patch.crates-io].

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

* Issue #324: on Windows 11, a window dragged to another monitor takes its scale

winit 0.30.13 handles WM_DPICHANGED by checking that the new window rect is on
the monitor `MonitorFromWindow` names. During a drag that is still the monitor
being left, so winit nudged the window back onto it, which sent another
WM_DPICHANGED: the window grew and stayed on the wrong monitor at the wrong
scale. From Windows 11 (build 22000) on, apply the rect Windows suggests, as
winit master does since 488c036a (rust-windowing/winit#4341); no 0.30 release
has it. Windows 10 keeps the old adjustment, as on winit master.

The vendored copy goes in [patch.crates-io]; a test fails if winit resolves
from crates.io again or the vendored copy loses the patch.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-09 12:19:41 -04:00