Commit Graph

363 Commits

Author SHA1 Message Date
Mariano Abad
58ff3f9d2b drm: the polish list, and a correction to my own ABI floor
The version floor I added two commits ago was one release too low.
drmtap_open_render and drmtap_convert_dmabuf are 0.4.9, but drmtap_grab_desc is
0.4.10, so a genuine 0.4.9 library passed the version gate and was then refused
by the symbol gate with a message that called it a stale or pre-release build,
which it is not. The floor is 0.4.10 now, the release where the whole split API
exists, and the test lists 0.4.9 among the rejected versions with the reason.

ExportLedger is deleted. DRM_FD_ELISION was false, so should_send_fd returned
true at its first branch and about sixty lines of eviction and epoch machinery
were unreachable, untested, in a security sensitive file. Why it was disabled
is worth keeping, so here it is: eliding the fd on an fb_id the converter has
already imported looks free, but the kernel can recycle an fb_id onto a
different buffer with identical geometry and modifier, and the exporter cannot
see the dma-buf inode that would tell the difference, so the elision can serve
a stale EGLImage. Sending it is cheap, the converter imports once per buffer and
closes the surplus fd, and libdrmtap's own cache keys on fb_id AND inode and can
only re-import when it is handed a real fd. That reasoning now lives here
instead of in dead code.

The rest:

- num_planes is clamped on the consumer before it reaches the C descriptor. The
  producer normalizes it and must be root, so this is only defense in depth, but
  the wire is the one place the value arrives from another process.
- warm_availability returns early on X11. Nothing there can consume a DRM
  stream, and probing makes the ROOT service open DRM readers, so an X11 host
  running a drm build was paying that at every startup for a path it can never
  take.
- drm_cursor_id no longer clones the cursor. The cursor service polls it at
  frame cadence to compare eight bytes, and a 256x256 cursor is 256 KiB.
- The premultiplied ARGB pass-through is now documented as matching the XFixes
  path, since that is why it is correct rather than an oversight.
- cfg hygiene: input_service.rs uses all(target_os = "linux", feature = "drm")
  like every other site, and active_uid_cached is gated with the feature too,
  which also removes a dead-code warning from drm-off Linux builds.
- Nits: DrmConn is pub(crate) like its constructors, new_drm_listener is no
  longer async with nothing to await, and the two anyhow! plus return Err pairs
  are bail! as the codebase writes them.
- DRM_CAPTURE_SECURITY.md moves to docs/ with the other docs, and its "no
  privileged child process is ever spawned" claim is corrected: an empty
  helper_path is not a disable switch in the C, find_helper searches six fixed
  paths and would exec one if the direct export ever failed. It is unreachable
  here for two independent reasons, the root service holds CAP_SYS_ADMIN so the
  direct path succeeds and the package builds no helper at all, and the paths
  are root-writable only, so the accurate statement is that this package never
  installs one, not that it can never happen.
- The comments that narrated the review rather than the code are rewritten to
  say what the code does. One of them had also drifted: the convert context is
  opened before we answer with DrmStart, not before the handshake.

Both configs build with no new warnings, 100 tests pass.
2026-07-28 09:06:11 -03:00
Mariano Abad
eec14a0592 drm: refuse a libdrmtap that cannot do the split export
The root --service must never load libEGL/libGLESv2: the point of the split is
that it exports the scanout dma-buf and the unprivileged --server converts. Two
paths could still break that, both because the loader accepted a library too
old to export.

drm_prewarm() called grab() when the loaded .so had no drmtap_grab_desc, and
grab() maps and detiles, so the privileged process pulled in the vendor GL stack
at startup, before any consumer had asked for a frame. The per-connection
capture loop then did the same for every frame, through the CPU fallback.

The version guard could not prevent it: it compared the ABI major only, and this
library is still 0.x, so every release it has ever made passed. Add a floor at
0.4.9, where the split entry points landed, and require the three split symbols,
which also rejects a build that reports a new enough version without carrying
them. That is not hypothetical: a pre-release stamped 0.4.15 shipped without the
multi-GPU accessors. Both refusals fall back to PipeWire/portal and say which
file and which symbols, at warn level.

The split symbols are no longer Options, so the type system carries the
guarantee instead of a convention. What is left of the CPU path is only what it
was meant to be: the consumer has no render node of its own, or the seat exports
no transferable dma-buf. Both are facts about the hardware, with no alternative
that keeps the stream, and neither is a property of which file was on the load
path.

Verified against the real library on i915. With 0.4.15 the export path captures
a tiled XR30 scanout and libEGL stays out of /proc/self/maps, while the old
grab() branch maps it, so the finding reproduces. A stub reporting 0.4.8 and a
stub reporting 0.4.15 without the split symbols are both refused, each with its
own diagnostic. The mirrored repr(C) layouts are unchanged across 0.4.9 to
0.4.15, checked field by field against include/drmtap.h at both ends, so the
floor costs no compatibility that was real.
2026-07-28 08:28:53 -03:00
Mariano Abad
510ac3b3a9 drm: move the drm CI out of the stock workflow, and stop touching scrap/Cargo.toml
The instruction was that nothing outside the feature should change while the
feature is off, and the runtime code honors that, but the build plumbing did not.
Start undoing that.

ci.yml goes back to upstream byte for byte. The drm test step it carried now lives
in a new workflow that only fires when a drm path changes, so a PR that does not
touch this backend pays nothing for it.

That new workflow also runs the whole rustdesk-crate test set with the feature on
rather than filtering by the `_drm` test names, because the name filter skipped
the sibling assertion that bounds `size_of::<Data>()`, which the new DmabufDesc
variant grows.

It gains a second job that fetches libdrmtap at the pinned commit, builds the .so
and then asserts the contract the runtime depends on: every symbol the loader
resolves, derived from the loader source so the two cannot drift, plus evidence
that the EGL detile path is really compiled in. libdrmtap degrades to a CPU-only
stub when the egl/glesv2 pkg-config files are absent on a build host, and nothing
downstream noticed. Note the check looks for the dlopen target name and the import
call, not for DT_NEEDED: EGL is loaded lazily on purpose so the privileged process
never links the vendor GL stack, so an ELF-level check reports a false negative on
a correct library.

libs/scrap/Cargo.toml keeps only the added feature: the unrelated blank line before
[dependencies.hwcodec] is restored, and the comment no longer describes DRMTAP_REF,
which no longer exists. The feature is now drm = ["wayland"] because all three drm
modules live inside the wayland arm of common/mod.rs, so scrap/drm alone compiled
nothing; it worked only because the root crate always enables scrap/wayland.
2026-07-28 06:32:17 -03:00
Mariano Abad
805e4bcd65 drm: tighten the render-node count and the loader diagnostics
Four corrections from a review pass over the previous two commits.

Count only a render node whose name is renderD followed by a numeric minor.
The prefix test also matched something like renderD.backup, which would have
inflated the count and pushed a genuinely single-GPU host onto the CPU path.

Log the load only after every required symbol resolved. load() still returns
None when one is missing, so announcing success first could print "libdrmtap
loaded" and then "libdrmtap not available" for the same library.

Name only the capability each absent symbol costs: a library missing just
drmtap_render_node loses exporting-GPU selection, one missing just
drmtap_list_devices loses multi-GPU enumeration, and the previous wording
claimed both were gone in either case.

Fix the security document's audit step. The dlopen names the symlink by
absolute path and the package registers no linker directory, so a leftover
object beside it is not loaded on its own; what matters is where the symlink
points, and a leftover only matters as what a stray ldconfig would repoint it
to. Ask the auditor to read the symlink target instead.
2026-07-25 22:35:15 -03:00
Mariano Abad
e6fe6683d0 drm: name the libdrmtap that was really loaded, and say so when it is stale
Two hours went into a corrupted capture whose only symptom was a clean log
saying "libdrmtap loaded: /usr/lib/rustdesk/libdrmtap.so.0 (v0.4.15)". The
library behind that soname symlink was a pre-release 0.4.15 that reported the
version but did not export drmtap_render_node, so the service silently stopped
naming the exporting GPU. The log named the symlink it asked for, which is not
evidence of anything, and the version it printed came from the library itself,
which was the part that lied.

Log the file the absolute candidate actually resolves to, and warn when a
library reports 0.4.15 or newer while missing drmtap_render_node or
drmtap_list_devices, naming that file: a version that claims features the
symbols do not back means a stale or pre-release build, and the effect is
invisible otherwise. Only the absolute candidate is resolved, because dlopen
does not search the process CWD for a bare soname while canonicalize would.

Also correct two places that no longer matched the code: the security document
still described an /etc/ld.so.conf.d drop-in and an ldconfig trigger that
build.py deliberately does not ship (the .so is dlopened by absolute path and
the package makes the soname symlink itself), and the comment above the render
node lookup still said an unnamed exporter always falls back to auto-selection.
2026-07-25 22:14:26 -03:00
Mariano Abad
236d9668b1 drm: bump the pinned libdrmtap to v0.4.15 2026-07-24 08:50:17 -03:00
Mariano Abad
b9bf7d0603 drm: advertise the displays of every GPU, not just the first card
A drmtap context is bound to a single DRM device, so the service enumerated one
auto-detected card and advertised only its monitors. On a multi-GPU host every
display driven by another card was invisible to the client, and its card-local
CRTC id could not have been opened through the wrong device anyway.

The service now enumerates every card (drmtap_list_devices, libdrmtap 0.4.15),
opens one reader per device, and merges their displays into the one list, each
tagged with its own card node and render node. DrmStart resolves the chosen
index to that display's device + CRTC and the worker reopens the right card;
the converter already binds the display's render node. Both new fields are
serde(default) and empty means the single auto-detected device, so a pre-0.4.15
.so and a mismatched-build peer keep the previous behaviour exactly.

Enumeration replaces the single-reader open in the pre-warm, the udev hotplug
refresh, and the per-connection handshake, so a hotplug on any card is picked up
and an all-monitors-off state now correctly publishes an empty list. The
per-connection cache refresh re-enumerates all cards rather than only the
connection's device, so serving one display never drops the others from the
next handshake.

Verified on a Jetson Orin (its two DRM devices, only card2 driving a display):
list_devices reports card2/renderD129 with one display, enumeration produces
exactly that display tagged to card2, and card1 (no active CRTC) is skipped -
no phantom, no regression on the single-display case.
2026-07-24 08:50:17 -03:00
Mariano Abad
919f3b5097 drm: convert each display on the GPU that exports it
The unprivileged converter opened its render context with
drmtap_open_render(NULL), letting libdrmtap auto-select. On a multi-GPU host
that can land on a different GPU than the one driving the display, and importing
a scanout across vendors can fail permanently on an incompatible tiling
modifier.

The service already knows the exporting device, so it now names its render node
(drmtap_render_node, libdrmtap 0.4.15) in each DrmDisplayInfo, and the consumer
opens the converter on that node. The field is serde(default) and empty means
auto-select, so a service and a server from mismatched builds still interoperate
and a pre-0.4.15 .so degrades to exactly the previous behaviour. The path is
realpath-gated to /dev/dri before it is opened, the same gate the capture device
gets, since it arrives over IPC. When the named node cannot be opened the
converter returns None and the existing need_cpu fallback runs the convert on the
exporting GPU service-side, which is the most correct place for it anyway.

Added a wire-compat test that a pre-render_node DrmDisplayInfo payload still
decodes (empty node) and a current one round-trips the node.
2026-07-24 08:50:17 -03:00
Mariano Abad
dd6ee24833 drm: bump the pinned libdrmtap to v0.4.14
Point the DRM capture build at the libdrmtap v0.4.14 release commit
(816766dedaba3140c613712ce97aa2614e8899e7) instead of v0.4.13, in build.py and
the flutter-build workflow, and correct the scrap Cargo.toml note to describe
the actual DRMTAP_SHA anchor. 0.4.14 keeps the same public API, so the dlopen
consumer needs no change.
2026-07-24 08:50:17 -03:00
Mariano Abad
9edfc11ba6 drm: dlopen libdrmtap by absolute path + unit-test the _drm admission and re-auth (review 5e, 6a)
5e: the deb dropped /usr/lib/rustdesk into /etc/ld.so.conf.d so the private libdrmtap
could be found by soname -- a system-wide search-path entry that lets it shadow a
system library for every binary on the host, which Debian Policy 10.2 forbids. Resolve
it by absolute path (/usr/lib/rustdesk/libdrmtap.so.0) at the dlopen site instead, with
the bare sonames kept only as a dev fallback, and drop the ld.so.conf.d file and the
ldconfig/try-restart postinst entirely (the .so is present at its absolute path right
after unpack, so the pre-warm resolves with no linker-cache step). The dlopen site is
this PR's own code, so this is in scope, not a follow-up.

6a: extract the _drm admission bound and the per-frame re-auth decision into pure
helpers (drm_conn_admitted, drm_peer_authorized) and unit-test them: admission admits
strictly below MAX_DRM_CONNS and rejects at/above it; re-auth passes root always,
passes a non-root peer only while it equals the active-session uid, and fails closed on
a switched-away, unknown-session, or unknown-peer case. (The /proc/exe-mismatch
rejection is exercised by the accept-time authorize call; unit-testing it in isolation
would need a second process with a different exe, so it stays an integration concern.)
2026-07-24 08:50:17 -03:00
Mariano Abad
75af53b9bf drm: address review findings 3.1, 4.2, 4.3, 4.4, 4.7 + minors
3.1: snapshot the stock flutter bundle before the CI drm relink and restore it
before makepkg, so the official Arch package ships the stock cdylib, not the
drm-enabled one. 4.2: wrap the drm block in a failure-tolerant subshell so a
drm-only failure no longer aborts the stock deb/rpm/arch publish. 4.3: narrow the
publish glob to rustdesk-[0-9]*.deb so the consent-bypass unattended-wayland deb
stays an artifact, not on the public release. 4.4: rewrite the three stale
DRM_CAPTURE_SECURITY.md statements to the split (default path passes a read-only
scanout dma-buf fd over SCM_RIGHTS with an import-once cache; export validation is
metadata-only; BGRA-over-the-wire is the fallback) and document that grab_desc's
fd is O_RDONLY (DRM_RDWR dropped upstream, dup preserves it). 4.7: only
short-circuit to the DRM cursor when it is authoritative (visible, or hidden in a
pure-DRM session); fall through to the normal cursor path in a mixed
DRM+PipeWire session. minors: thread the deb variant by feature not glob; TODO
for the ld.so.conf.d system path; drop a stray blank line. All gated or
whitespace so the drm-off build stays byte-identical.
2026-07-24 08:50:17 -03:00
Mariano Abad
3ac9b2e4cf drm: do not reject a non-BGRA scanout on the export side
grab_desc exports the raw scanout dma-buf; the unprivileged converter handles
every format libdrmtap supports (10-bit XR30/AR30 with tone mapping, HDR, CCS)
down to RGBA. The fourcc gate copied from the CPU-mapped grab() wrongly closed
the _drm stream for a 10-bit XR30 primary (0x30335258) that convert_dmabuf
converts fine -- observed live on an i915 seat scanning out XRGB2101010. Keep
the gate only on grab(), whose frame.format is already the converted BGRA.
2026-07-24 08:50:17 -03:00
Mariano Abad
6cc426e9f5 drm: address the phase-2 split review
1- do not depend on the libdrmtap-sys crate for the pin: its build.rs statically
compiles the whole libdrmtap C tree and a CAP_SYS_ADMIN helper and links
-ldrm/-lseccomp/-lcap, which defeats the runtime-dlopen model. keep drm a pure
dlopen backend and pin the .so by the build.py DRMTAP_REF release tag, guarded by
a strict vX.Y.Z regex. drops the now-moot Cargo.lock freshness CI checks.
2- render-node-less consumers no longer lose the stream: the --server signals
need_cpu on DrmStart when it cannot open a convert context, and the --service
streams the CPU-converted frame path for that connection instead of a dma-buf fd
the consumer cannot detile (which used to fall through to a PipeWire path nobody
can approve on an unattended seat).
3- mark PipeWire initialized only after every per-display capturer is created, so
a partial failure retries instead of the flag falsely reporting a complete init.
4- reject a degenerate (zero width/height) or short CPU frame before it reaches
PixelBuffer::new (which derives stride as data.len()/height, dividing by zero).
5- keep the export-ledger epoch at DRM_DISPLAY_GENERATION so a hotplug invalidates
cached buffers (elision stays off until the recycled-fb_id inode case is handled).
6- validate the udev uevent source (kernel nl_pid, multicast) with recvmsg so a
local process cannot unicast a spoofed drm-change event to the root listener.
2026-07-24 08:50:16 -03:00
Mariano Abad
3b6914b1b2 feat(drm): phase-2 split, pass the dma-buf fd instead of the converted frame
move the egl detile and rgba pack out of the root --service and into the
unprivileged --server. the root now calls only drmtap_open + drmtap_grab_desc
and exports a raw dma-buf fd; the fd rides the _drm channel over SCM_RIGHTS with
a small descriptor (geometry, per-plane offsets/pitches, modifier, hdr) instead
of the full rgba frame, dropping the per-frame copy. the --server imports the fd
with drmtap_open_render + drmtap_convert_dmabuf, keyed by the import-once egl
cache, and the render context is created and dropped on the recv thread.

the _drm transport moves off Framed<BytesCodec> (which cannot carry a fd) to a
bespoke sendmsg/recvmsg framing (DrmConn) that attaches one SCM_RIGHTS cmsg only
when a fd is present and rejects a truncated ancillary message. the split
symbols are bound optionally so an older libdrmtap still loads the cpu path, and
the whole thing degrades to the cpu BGRA path or PipeWire when no render node is
available. pins libdrmtap-sys to =0.4.13 with the Cargo.lock checksum. folds in
the DP-MST, ldconfig-restart and per-display PipeWire-fallback review fixes and a
udev hotplug refresh.
2026-07-24 08:50:16 -03:00
Mariano Abad
77a14339ad feat(drm): opt-in DRM/KMS screen capture for Linux/Wayland
adds an opt-in `drm` feature for unattended remote access on Wayland: it
captures below the compositor via libdrmtap, so there is no
xdg-desktop-portal consent dialog and it works at the login screen.

off by default. when the feature is off the build is byte-identical.
everything is gated behind feature = "drm" or lives only in the separate
rustdesk-unattended-wayland deb, whose package name is the informed consent.

architecture (agreed with the maintainer): the capture runs inside the root
--service, which already holds the privilege it needs, and streams frames to
the user --server over a service-scoped _drm ipc channel. libdrmtap is loaded
with dlopen at runtime (no link-time dependency, so the base build is
unchanged and it still runs on ubuntu 18), and the .so is built in ci from the
rustdesk-org/libdrmtap fork and shipped only in the drm deb. no setcap helper.

- service: DrmReader reads scanout directly via the dlopen loader; an
  IpcDrmCapturer serves _drm consumers with a per-connection capture worker;
  durable availability cache + pre-warm to avoid enumerate/re-probe restarts
- capture: multi-display (targets the selected crtc), hardware cursor over
  _drm, transient-errno retry with a bounded stall, rejects non-32bpp scanouts
  before the frame copy
- robustness: only active, crtc-bound outputs are offered (an unbound
  crtc_id=0 connector is filtered and a client-selected 0 is refused, both
  fall back to pipewire); a per-display rapid-rebuild guard demotes a flapping
  display to pipewire; per-display (not global) zero-frame failure tracking
- root-service hardening: bounded frame allocation and a concurrent-connection
  cap so a malformed scanout or a buggy consumer cannot OOM or thread-exhaust
  the service; a negative availability verdict expires so displays that appear
  after startup recover without a --server restart; exactly-one .so selection
  in the packaging so a stale object is never silently shipped
- build: libdrmtap.so cloned at build time from rustdesk-org/libdrmtap main
  and bundled only for the --drm deb; ci builds a separate
  rustdesk-unattended-wayland deb (incl. an ubuntu 18.04 container)
- DRM_CAPTURE_SECURITY.md: threat model and hardening notes
2026-07-24 08:50:16 -03:00
CHarris
b4af82157b fix: refresh wayland uinput range on compositor layout change (#15628)
* fix: refresh wayland uinput range on compositor layout change

The uinput absolute range is computed once at session init. If the
compositor layout changes mid-session (monitor scale or position
change, or a portal virtual output appearing once capture starts),
injected coordinates are rescaled by the stale range and land offset.

Poll the live desktop bounding box from the display service loop while
subscribed (one wayland roundtrip, throttled to 1.5s, no subprocesses)
and re-apply the uinput resolution when it changes. Also read a fresh
layout when computing the initial range in check_init, since the cache
is not cleared when a session closes through the restore-token path.

This is the X component of #15601. The stale advertised origins (the Y
component) are not touched here: re-advertising DisplayInfo mid-session
trips the portal re-negotiation and can drop displays.

Signed-off-by: Cody Harris <codyharris7188@gmail.com>

* fix: bound the mouse resolution IPC wait during session init

Wrap update_mouse_resolution in the same 3s timeout the periodic
refresh uses, so a hung IPC response can't stall check_init.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix: build timeout future inside runtime, split linux lazy_static

Constructing the timeout future eagerly as the block_on argument panics
with 'there is no reactor running'; move it into the async block so it is
built inside the runtime context. Also move WAYLAND_UINPUT_RECT into its
own cfg-gated lazy_static block, an attribute on a single item inside the
shared block does not compile.

* fix: confirm uinput mouse device adopted new range before caching rect

send_refresh() now waits for the mouse service to ack that it recreated the
device with the new range instead of firing and forgetting, and
update_mouse_resolution() propagates that result. The layout poller only
caches the rect after the device actually adopts the range, so a failed
refresh errors and retries on the next check. The ack read is bounded by
IPC_REQUEST_TIMEOUT, matching the keyboard get-key-state path.

* fix: propagate refresh failures instead of caching a stale range

- input_service: error when the custom-mouse downcast fails so the poller
  retries instead of caching an unconfirmed refresh
- uinput: on device recreation failure, keep the current device and the
  IPC connection and withhold the ack so the client retries, instead of
  killing the mouse handler

* fix: remap injected wayland coords onto the live layout after a monitor moves

The range refresh corrects the uinput ABS bounds, but a single-display client
sends whole-desktop coordinates offset by the origin of the display it follows,
taken from the layout advertised at session init. When another monitor is
rescaled or moved that origin shifts, so the coordinate lands offset before it
reaches uinput and the range refresh cannot recover it.

Snapshot the per-display layout at init, poll the live layout on the existing
1.5s throttle, and when they differ remap each injected move into the followed
display's current rectangle (matched by connector name, index fallback when the
compositor reports none). No-op and lock-free while the layout is unchanged.

---------

Signed-off-by: Cody Harris <codyharris7188@gmail.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-07-24 18:35:49 +08:00
jinqiang zhang
cf2b28faf9 fix linux llvm22 build (#15565)
bindgen-0.65 is incompatible with llvm 22, we should upgrade to a
newer bindgen version

error message:

```
error[E0609]: no field `g_w` on type `vpx_codec_enc_cfg`
  --> libs/scrap/src/common/vpxcodec.rs:66:19
   |
66 |                 c.g_w = config.width;
   |                   ^^^ unknown field
   |
   = note: available field is: `_address`
```
2026-07-15 13:27:15 +08:00
rustdesk
9d1ab3fba3 fix the AOM tile-control argument type 2026-07-01 11:47:08 +08:00
Dennis Ameling
8f50ea64dc Add Windows arm64 support (#15139)
* Add initial arm64 build logic

Signed-off-by: Dennis Ameling <dennis@dennisameling.com>

* Upgrade Flutter to 3.44.0 and introduce Windows arm64 in CI

Signed-off-by: Dennis Ameling <dennis@dennisameling.com>

* Bump bridge build to Flutter 3.44 as well

Signed-off-by: Dennis Ameling <dennis@dennisameling.com>

* Fix install flutter step for Win arm64

* Bump install-llvm-action to v2 for arm64 support

* Fix libsodium logic to only install through vcpkg on win arm64

* Fix Flutter installations on Win

* Flutter XCode: only build the current arch as it defaults to universal

Signed-off-by: Dennis Ameling <dennis@dennisameling.com>

* Ensure that we really have arm64 Dart + Flutter engine in CI

Signed-off-by: Dennis Ameling <dennis@dennisameling.com>

* Enable hwcodec feature now that upstream supports building it

Signed-off-by: Dennis Ameling <dennis@dennisameling.com>

* CI: improve logic for getting Flutter arm64 SDK

Signed-off-by: Dennis Ameling <dennis@dennisameling.com>

* Apply PR feedback (only bump Flutter version on Win arm64)

* Exclude MSI build on arm64

* CI: build the MSI for Windows arm64 (WiX v4 ARM64 platform + native CustomActions)

* Address PR feedback

* Update Cargo.toml

* Update Cargo.lock

* Update Cargo.lock

* Add Flutter 3.44 DialogThemeData background colors

Signed-off-by: 21pages <sunboeasy@gmail.com>

---------

Signed-off-by: Dennis Ameling <dennis@dennisameling.com>
Signed-off-by: 21pages <sunboeasy@gmail.com>
Co-authored-by: RustDesk <71636191+rustdesk@users.noreply.github.com>
Co-authored-by: 21pages <sunboeasy@gmail.com>
2026-06-18 22:37:15 +08:00
fufesou
0797ebb695 Refact/privacy mode 1 multi monitors (#15321)
* refact: privacy mdoe 1, multi-monitors

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix: harden privacy mode overlay & capture cleanup

Signed-off-by: fufesou <linlong1266@gmail.com>

* Fix privacy mode edge cases after multi-monitor overlay changes

Signed-off-by: fufesou <linlong1266@gmail.com>

* Add missing changes

Signed-off-by: fufesou <linlong1266@gmail.com>

---------

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-06-18 21:27:44 +08:00
RustDesk
6665242edf Revert "refact: privacy mdoe 1, multi-monitors (#15318)" (#15320)
This reverts commit 3cdf1cce54.
2026-06-17 21:46:40 +08:00
fufesou
3cdf1cce54 refact: privacy mdoe 1, multi-monitors (#15318)
* refact: privacy mdoe 1, multi-monitors

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix: harden privacy mode overlay & capture cleanup

Signed-off-by: fufesou <linlong1266@gmail.com>

---------

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-06-17 21:43:57 +08:00
IronCodeStudios
377547fa11 scrap/wayland: insert videoconvert to fix screencast on COSMIC / DMA-BUF portals (#15063)
On Wayland compositors whose xdg-desktop-portal backend exposes screencast
frames as DMA-BUF buffers — notably xdg-desktop-portal-cosmic 0.1.0 on
Pop!_OS 24.04 / COSMIC — inbound screen capture fails. PipeWireRecorder
links pipewiresrc directly to an appsink whose caps only accept
video/x-raw BGRx/RGBx in system memory. That format set is too narrow for
the portal's buffer-type / modifier negotiation, which collapses with:

  pw.link: negotiating -> error no more output formats (-22)
  gstpipewiresrc: stream error: no more output formats
  gstbasesrc: streaming stopped, reason not-negotiated (-4)
  ERROR src/server/wayland.rs: Failed scrap Element failed to change its state

Inserting a videoconvert element between pipewiresrc and appsink widens
the negotiable format set to any system-memory video/x-raw format, giving
the portal room to settle on a format it can deliver via its SHM path.
videoconvert then converts to the BGRx/RGBx the appsink expects.

Verified on Pop!_OS 24.04 / COSMIC with gst-launch, before and after:

  # fails (current behaviour):
  gst-launch-1.0 pipewiresrc path=N ! video/x-raw,format=BGRx ! fakesink
  # works (with this change):
  gst-launch-1.0 pipewiresrc path=N ! videoconvert ! video/x-raw,format=BGRx ! fakesink

After the change, inbound connections capture and stream the desktop
normally and the "Failed scrap" error no longer occurs.

Co-authored-by: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-17 16:02:23 +08:00
John Eismeier
4a50bc6fc2 Propose fix some typos (#14857)
Signed-off-by: John E <jeis4wpi@outlook.com>
2026-04-21 16:27:39 +08:00
Leo Louis
a8dc6fc632 Fix capture method return type in Recorder trait (#14748) 2026-04-13 13:04:43 +08:00
Leo Louis
771cb4ebd7 Update capture function return type for PixelProvider (#14747) 2026-04-13 13:03:35 +08:00
Nicola Spieser Buiss
9345fb754a fix: correct typos and improve code clarity (#14341)
- Fix 'clipbard' typos in clipboard.rs (function names, comments, strings)
- Fix 'seperate' typo in x11/server.rs comment
- Replace !is_ok() with idiomatic is_err() in updater.rs
- Fix double backtick typo in updater.rs comment

Co-authored-by: Ocean <ocean@Mac-mini-von-Ocean.local>
2026-02-17 14:29:50 +08:00
fufesou
7f804a0e45 refact: wayland, pipewire display offset cache to file (#13542)
Signed-off-by: fufesou <linlong1266@gmail.com>
2025-11-18 14:16:59 +08:00
fufesou
b2dff336ce fix: wayland controlled side, cursor misalignment (#13537)
Signed-off-by: fufesou <linlong1266@gmail.com>
2025-11-18 00:37:15 +08:00
Jonathan Gilbert
a903f710ea Eliminate build warnings from the Scrap crate (#13383)
* Updated build.rs to tell RustC that dxgi, quartz and x11 are expected configurations.
Added lifetime annotations to various methods in common/aom.rs and common/vpxcodec.rs.
Updated common/vpx.rs to allow unused_imports in the generated bindings.
Updated dxgi/mag.rs to allow non_snake_case identifiers like "dwFilterMode".

* Added lifetime annotations to methods in common/hwcodec.rs and common/vram.rs.

* Switched syntax for the rustc-check-cfg directive emitted by build.rs in the scrap crate to use syntax compatible with Rust toolchain version 1.75. The double-colon syntax requires 1.77 or newer, but the older single-colon syntax works fine on newer versions for this directive.

* Update libs/scrap/build.rs

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Revert apparently-erroneous AI suggestion. It's usually pretty good, but not always right it seems. :-)

This reverts commit bf862b13f6.

* Removed redundant configuration directives from libs/scrap/build.rs.

---------

Co-authored-by: RustDesk <71636191+rustdesk@users.noreply.github.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-11-04 10:19:13 +08:00
21pages
d106d97b99 mobile verify both webpki and installed CA (#13272)
Signed-off-by: 21pages <sunboeasy@gmail.com>
2025-10-30 13:59:00 +08:00
21pages
7c8329c5c6 fix mac hwcodec check (#13320)
Signed-off-by: 21pages <sunboeasy@gmail.com>
2025-10-28 16:29:42 +08:00
21pages
c9940957f0 fix camera large error log (#13227)
Signed-off-by: 21pages <sunboeasy@gmail.com>
2025-10-20 13:23:41 +08:00
Nathan Saslavsky
eacb07988d Add Wayland multi-monitor screen capture functionality (#12900)
* Add Wayland multi-monitor screen capture functionality

* fix wayland capture issues by reverting to CapturerPtr, the problem was that calling Display::all in get_capturer_for_display was dropping the pipewire capturer and causing the video to freeze.

* If running as AppImage or flatpak, ignore the 'multiple' argument

* Comment out warning log with unclear purpose Comment out warning log with unclear purpose

---------

Co-authored-by: fufesou <13586388+fufesou@users.noreply.github.com>
2025-09-22 21:53:14 +08:00
IwantHappiness
15d471e520 Remove needless macros format! (#11456) 2025-09-03 22:17:11 +08:00
fufesou
a22f2108c6 refact: suppress warns on macos (#12449)
Signed-off-by: fufesou <linlong1266@gmail.com>
2025-08-18 15:09:11 +08:00
21pages
69af5f2fa6 update hwcodec (#12303)
* Test necessary codecs in single thread
* Terminate test process with parent process

Signed-off-by: 21pages <sunboeasy@gmail.com>
2025-07-15 18:49:45 +08:00
fufesou
fd4e0146e1 fix: replace sh with CMD_SH (#12173)
Signed-off-by: fufesou <linlong1266@gmail.com>
2025-06-26 15:54:16 +08:00
fufesou
a5a3352655 fix: linux, nokhwa, camera index (#12045)
Signed-off-by: fufesou <linlong1266@gmail.com>
2025-06-14 13:19:59 +08:00
lichon
05a812247a fix: use default camera, first element in query result might not be a camera (#12010) 2025-06-12 13:35:42 +08:00
fufesou
c626c2414d feat: take screenshot (#11591)
* feat: take screenshot

Signed-off-by: fufesou <linlong1266@gmail.com>

* screenshot, vram temp switch capturer

Signed-off-by: fufesou <linlong1266@gmail.com>

* fix: misspelling

Signed-off-by: fufesou <linlong1266@gmail.com>

* screenshot, taking

Signed-off-by: fufesou <linlong1266@gmail.com>

* screenshot, rgba stride

Signed-off-by: fufesou <linlong1266@gmail.com>

* Bumps 1.4.0

Signed-off-by: fufesou <linlong1266@gmail.com>

---------

Signed-off-by: fufesou <linlong1266@gmail.com>
2025-04-30 17:23:35 +08:00
21pages
d1c8b331c5 Option allow-d3d-render and fix ios ci (#11107)
* option `allow-d3d-render`, default false

Add this option because it fails on some machines

Signed-off-by: 21pages <sunboeasy@gmail.com>

* only add nokhwa to windows and linux dependencies

Signed-off-by: 21pages <sunboeasy@gmail.com>

---------

Signed-off-by: 21pages <sunboeasy@gmail.com>
2025-03-13 09:34:13 +08:00
21pages
f0f999dc27 view camera (#11040)
* view camera

Signed-off-by: 21pages <sunboeasy@gmail.com>

* `No cameras` prompt if no cameras available,  `peerGetSessionsCount` use
connType as parameter

Signed-off-by: 21pages <sunboeasy@gmail.com>

* fix, use video_service_name rather than display_idx as key in qos,etc

Signed-off-by: 21pages <sunboeasy@gmail.com>

---------

Signed-off-by: 21pages <sunboeasy@gmail.com>
Co-authored-by: Adwin White <adwinw01@gmail.com>
Co-authored-by: RustDesk <71636191+rustdesk@users.noreply.github.com>
2025-03-10 21:06:53 +08:00
zuiyu
561bc18f49 Fix unused import with dxgiformat (#11032) 2025-03-06 09:49:04 +08:00
fufesou
f08cb0412d fix: windows, dll, pre-loading attack (#10608)
Signed-off-by: fufesou <linlong1266@gmail.com>
2025-01-26 19:39:38 +08:00
21pages
5fa8c25e65 opt qos (#10459)
* Adjust bitrate and fps based on TestDelay messages.
* Bitrate is adjusted every 3 seconds, fps is adjusted every second and when receiving test lag.
* Latency optimized at high resolutions. However, when the network is poor, the delay when just connecting or sliding static pages is still obvious.

Signed-off-by: 21pages <sunboeasy@gmail.com>
2025-01-20 17:59:36 +08:00
Xiaobo Liu
8f329ebc1a scrap: style (#10445) 2025-01-07 11:21:43 +08:00
Xiaobo Liu
4a3c11e711 scrap: fixed build warnning (#10442)
```shell
warning: elided lifetime has a name
   --> src/common/mod.rs:192:21
    |
187 |     pub fn to<'a>(
    |               -- lifetime `'a` declared here
...
192 |     ) -> ResultType<EncodeInput> {
    |                     ^^^^^^^^^^^ this elided lifetime gets resolved as `'a`
    |
    = note: `#[warn(elided_named_lifetimes)]` on by default
```
2025-01-07 11:14:20 +08:00
21pages
40999c3211 fix ffmpeg videotoolbox wrong log (#10413)
* Fix ffmpeg videotoolbox wrong log when changing bitrate
* Let qsv support abr, and it's safe for qsv to changing bitrate.

Signed-off-by: 21pages <sunboeasy@gmail.com>
2025-01-02 22:19:30 +08:00
21pages
e163b75407 update hwcodec (#10304)
Signed-off-by: 21pages <sunboeasy@gmail.com>
2024-12-17 12:07:34 +08:00