Repository navigation
[pull] master from rustdesk:master - #276
Merged
Merged
Conversation
…confirm before publishing (#16122) * drm: carry the cursor plane position on the frame header CursorSnapshot gains the plane position x/y. It rides DmabufDesc.cursor_pos and Data::DrmFrame.cursor_pos as a serde-default Option, so a producer that predates the field reads as None on the consumer, and a consumer that predates it ignores the key. The producer reads the cursor once per delivered frame, after the grab, so a WouldBlock retry does no cursor work; the position is a few ms newer than the frame, which the consumer tolerates because it only counts consecutive identical positions. The consumer destructures the field and does not use it yet. * input: remember the last absolute peer move and forget it on any other move The DRM cursor calibration subtracts a cursor plane origin from the point this process injected, so the point has to be the post-remap uinput one and nothing else: LATEST_PEER_INPUT_CURSOR stores an X-server coordinate on the relative arm. The new sample carries an Instant, a sequence number (two measurements against one sample are not independent) and the layout generation it was mapped against. A relative delta and a move this process makes itself forget it. display_service exposes the existing drift flag to readers. * drm: resolve the cursor calibration context once, with the capturer CalContext { rect, physical_size, built_gen } is computed in IpcDrmCapturer::new from the same wayland snapshot the transform comes from, and only when the snapshot is complete, the output is an identity match, the unfolded transform is 0 (180 included) and the geometry is valid. It is stored in Shared before the transform's Release store, so a receive thread that has seen the transform sees the context. Nothing reads it yet. * drm: measure the cursor hotspot and confirm it before publishing On a driver without HOTSPOT_X/Y the wire carries infer_hotspot's guess, which the bitmap cannot get right for a shape whose click point the theme put where the alpha does not mark it. This process injects the tip and the plane origin rides every frame: once both are still, tip - origin is the hotspot. Only a guessed shape is measured. The first measurement is a candidate and changes nothing visible. A second measurement confirms it only from another stable plane position and another peer sample, and then the retained candidate is the one value that reaches the cache, the served hotspot, the id remix and the delivery. Near what is served, nothing changes, even when the value is also near the wire, so a correction a few px from the wire does not flap; near the wire otherwise, the wire is served and the cached correction is dropped. A stable position is measured at most once, a layout generation change stops measurement once the display service's poll has seen it, and the cache is read only behind the context gate, so a correction measured upright never reaches a rotated output. Each of these gates has a test that goes red with the check removed or altered (file restored byte for byte afterwards): publish the first measurement -> retained candidate, same sample, still plane, local nudge same sample confirms -> same sample never confirms, local nudge confirm with the new value -> retained candidate, near wire, in band drop the near-wire arm -> near wire serves the wire drop the in-band arm -> in band changes nothing visible drop the re-store after clear-on-cap -> in band stays cached measure a kernel-measured hotspot -> never calibrated at the origin read the cache without a context -> not served without a context drop the once-per-position flag -> still plane measured once drop the transform gate -> context only for an upright output swap phys and extent -> the arithmetic, the scaled context drop the clear-on-cap -> cache bounded drop the partial-snapshot gate -> context only for an identity match drop the generation check -> closed intervals compare the wire before the served -> in band with both keeps the served correction * drm: a cached hotspot correction is served only under the generation it was confirmed in The calibration cache mapped a wire cursor id to its confirmed hotspot and nothing else. A pair of stops taken inside the layout poll window, after a monitor moved and before the poll saw it, could confirm a value measured against the old layout; the generation gate then stopped that stream, but the capturer rebuilt after the promotion seeded its served hotspot from the cache and replayed the value under the new layout, until another pair of its own replaced it (zhou, review of 25-sep). Each entry now carries the layout generation it was confirmed under, and a stream reads the cache under its own `built_gen` only: a value from another generation is not served, the wire hotspot is, until a pair on this generation confirms one. Checked at the read rather than by clearing on promotion, and an entry is replaced or dropped only by its own generation or a newer one, the bound included (at the cap the cache clears what the writer's generation or an older one confirmed, and caches nothing if only newer entries are left), so a receive thread still running on the old layout can neither serve its value to the rebuilt stream nor undo the value that stream confirmed. Tests: a_correction_confirmed_under_an_older_generation_is_not_served (two stops under one generation, the stream rebuilt under the next, its own pair, then the old stream writing late), the_bound_never_drops_an_entry_from_a_newer_generation. Mutations: reading without the generation filter, replacing or dropping a newer entry from an older generation, and at the cap either clearing everything or caching when only newer entries are left, each turn one of them red. * drm: calibrate only against samples injected under the layout's adopted uinput range `usable_sample` took the remap flag being clear as "the input mapping is ready". It is not: the display service bumps the layout generation and promotes the baseline before the uinput range update completes, and a failed or pending update leaves the device mapping absolute coordinates with the range of the previous layout. Every sample then carries the new generation while its point lands scaled by the old range; two stops share that error and agreement confirms it (zhou, review of 25-sep: a desktop narrowed from 4000 to 3800 px puts a hotx of 4 at 54, inside the bitmap). The display service now keeps the layout generation whose uinput range the device runs, and a count, raised when an apply starts and again when the device acknowledges it. Both move when `update_mouse_resolution` returns Ok, on the DRM session-init path (also run by the hotplug worker) and in the layout poll; the session-init path labels the range with the generation read before it computed the rect, and the raw DRM union it falls back to when the compositor cannot be asked with no generation, so no stream measures on it until the poll applies or finds a compositor range. A range that already fits the layout moves the generation only, so the samples injected under it stay valid. From the moment an apply starts, on any path, no generation is ready, the count is raised and the recorded rect is forgotten, so an apply that fails or times out (the device may still take the range late) leaves nothing ready, and only an acknowledged apply records a generation again. The poll and `update_uinput_resolution` run on different threads; they check, apply and record under one lock. `check_init`, which a display falling back to PipeWire runs inside a DRM session, records its apply the same way (cfg(feature = "drm") lines only; the drm-off build is unchanged). It has no fits check and applies on every run, as before, so each run moves the count. A path that read its generation before the poll bumped it records under the older one; no stream measures then until a later layout check records the current one. A sample is stamped under the ENIGO guard of its move, which an adoption also needs for its refresh, so a move stamped with the count of an adoption was injected after that adoption's refresh. The count is raised before the generation is published and read after it. A stream measures only while that generation is its own; each peer sample carries the count at injection and is a reference only under the current one; a candidate measured under one count starts over instead of confirming under the next. The remap flag is untouched. Tests: a_stale_input_mapping_publishes_nothing_until_fresh_samples_follow_the_adoption (generations equal, no drift, the device on the previous range: two stops publish and cache nothing; after the adoption a sample from before it does not count, and fresh ones confirm), a_sample_is_a_reference_only_under_the_adopted_input_mapping, a_candidate_does_not_confirm_across_an_input_mapping_change, an_acknowledged_range_is_an_adoption_and_a_fitting_one_is_not, the_raw_drm_union_labels_a_range_with_no_generation, an_apply_leaves_no_range_ready_until_it_is_acknowledged; the drm CI step runs input_map_tests. Mutations: dropping the adopted-generation gate, dropping the count gate, confirming across counts, an adoption that does not count, a fitting range that counts, the union labelled with the generation, and an apply that keeps the recorded rect or leaves a generation ready, each turn one of them red. The call sites (the lock, the calls before and after each apply on the three paths, the range-fits branches) run IPC and are covered by reading. * drm: forget the peer sample under the mouse lock on a move of this process The temporary-move thread (the display probe `fill_displays` runs in the PipeWire init, `check_init`) forgot the last absolute peer sample before it took ENIGO. A peer move holding ENIGO at that moment moved the pointer and recorded its sample after the forget, and the temporary move then landed on top: the pointer somewhere else, the sample still the peer point, with the current generation, count and a fresh sequence, so two such overlaps could confirm a wrong hotspot (zhou, review of e6103da). The forget now runs under the lock the peer move records its sample under, right before the move (`forget_sample_and_move`), so a peer move lands entirely before the forget or entirely after the move. The drm-off build keeps the line it had. The relative path of the peer already forgets under the ENIGO guard of its move. Test: a_move_of_this_process_forgets_the_sample_of_a_peer_move_it_waited_for (the peer holds a stand-in lock when the move asks for it; nothing is forgotten before the move has the lock; the peer records its sample and releases it, and after the move the sample is gone). Mutations: the forget taken before the lock (red in five runs of five) and no forget at all, each turn it red. The call site in the thread, which passes ENIGO, is covered by reading.
* fix(macos): clear Finder progress after clipboard transfers Signed-off-by: fufesou <linlong1266@gmail.com> * test(macos): cover single-response clipboard completion Verify progress completion, handle cleanup, and finalized file contents. Move function-only Finder imports into progress helpers. Signed-off-by: fufesou <linlong1266@gmail.com> * fix(macos): unpublish clipboard progress before renaming Complete and unpublish NSProgress before the final file rename to avoid stale Finder and Dock progress indicators. Signed-off-by: fufesou <linlong1266@gmail.com> * chore: add ref Signed-off-by: fufesou <linlong1266@gmail.com> --------- Signed-off-by: fufesou <linlong1266@gmail.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to subscribe to this conversation on GitHub.
Already have an account?
Sign in.
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
See Commits and Changes for more details.
Created by
pull[bot] (v2.0.0-alpha.4)
Can you help keep this open source service alive? 💖 Please sponsor : )