Commit Graph
11562 Commits
Author SHA1 Message Date
fufesou dbac98cdb5 Merge branch 'master' into keyboard-shortcuts 2026-10-05 07:21:06 -07:00
fufesou 260799d617 fix(shortcuts): guard Windows menu keys after Ctrl/Cmd swapping
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-05 06:23:32 -07:00
fufesou 4ba66a66b7 fix(keyboard): prevent Cmd shortcuts from opening remote Start
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-05 05:47:11 -07:00
memory_clearandfufesou c9c0b5d0ef Fix translation for voice call audio capture prompt (#16433)
* Fix translation for voice call audio capture prompt

* fix: translation, audio capture prompt, wrong "Share screen"

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

---------

Signed-off-by: fufesou <linlong1266@gmail.com>
Co-authored-by: fufesou <linlong1266@gmail.com>
2026-10-05 20:36:22 +08:00
5406950b02 fix(macos): open Screen Recording settings from Configure (#16452)
CGRequestScreenCaptureAccess shows its prompt only once per app. After
the user denies it, or after an update changes the code signature,
pressing Configure on the Screen Recording banner did nothing. Open the
Screen & System Audio Recording pane as well, so the button always
leads somewhere the user can grant access.

Co-authored-by: Eric Mason <17150+ericmason@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-05 20:15:32 +08:00
Mariano Abad 685fa2e4a1 fix(drm): the startup cache warm does not wake sleeping displays (#16437)
* fix(drm): the startup cache warm does not wake sleeping displays

Every `_drm` connection ran the display wake before the service answered with
its list, so the cache warm that each --server start runs (the service restarts
the --server every hour) woke displays that had idled off, with no client
connected (rustdesk#16356).

The --server now opens the handshake with DrmHello{wake}, and the service wakes
and settles only when asked. The warm asks without a wake; the availability
probes, the login refresh and the capture stream keep it, since a client is
waiting for them. Without a wake the service still clears the wake latch of a
connector it sees lit, as the warm did.

A warm that finds nothing lit leaves the cache without a verdict, where its own
wake used to make it Available. So a login that the DRM path can serve now
probes on a missing verdict before anything reads the cache (the greeter check,
the PipeWire prompt, the display list). That probe wakes the displays as the
warm did, but only when a client logs in.

* fix(drm): throttle the log of a peer that does not open with DrmHello

AGENTS.md: a log call that can fire at a rate a peer controls must not use
debug or higher unthrottled. Same 5 s interval as the rejected-IPC logs in
ipc/auth.rs.

* fix(drm): the startup warm keeps a list a login published while it queried

Per review: the warm samples the state generation before its query and
publishes only if no other probe published since, the check the two
background refreshes and the login refresh already use.

* fix(drm): log a failed login settlement task instead of dropping its error

Per review: the JoinError of the blocking task was discarded with `let _ =`.
2026-10-05 19:59:08 +08:00
fufesou 65dffcbd4c test: trim redundant keyboard shortcut coverage
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-05 03:53:07 -07:00
fufesou 1dcb24c9a4 fix: exclude GTK AltGr input from raw shortcut matching
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-05 00:29:44 -07:00
fufesou 5795a541f4 fix: exclude AltGraph from Flutter shortcut matching
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-04 23:31:55 -07:00
fufesou 85355144f1 fix: support legacy peers in privacy mode shortcut
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-04 21:40:18 -07:00
fufesou 496c83bd77 fix: dispatch macOS Web shortcuts without waiting for keyup
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-04 20:49:04 -07:00
fufesou 558ca359b8 fix: distinguish AltGraph from ordinary Alt shortcuts
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-04 20:48:56 -07:00
fufesou f3ead7e09d fix: coordinate Web shortcut dispatch and Alt modifier cleanup
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-04 19:00:13 -07:00
fufesou 1f1dc54a62 fix: guard Windows Alt release in Flutter legacy shortcuts
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-04 08:56:57 -07:00
fufesou f2dc0dee67 fix: initialize outgoing chat before shortcut dispatch
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-04 08:46:06 -07:00
fufesou 33b7b2e2b4 fix: prevent Alt menu activation in all keyboard modes
Extend Windows Alt-only shortcut neutralization to Translate and Legacy. Keep the temporary Ctrl packets in Map mode so Legacy modifier synchronization cannot release Alt before Ctrl.

Extend the existing regression across keyboard modes and decode scan, virtual and control-key events. Verify 36 native tests and 34 Windows menu replay cases.

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-04 08:05:59 -07:00
fufesou 783b26edb3 fix: prevent Windows menu activation from Alt-only shortcuts
Neutralize the forwarded Alt with a balanced temporary Ctrl press when a consumed local shortcut releases its only modifier in Windows Map mode. Keep physical modifier tracking and normal Alt pass-through unchanged.

Add a regression covering both Alt keys, trigger repeats and the eventual physical release. Verified with 36 native shortcut tests and real Windows menu/input checks.

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-04 07:26:05 -07:00
fufesou d2af68b737 refact: remove the useless comments
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-04 04:17:22 -07:00
fufesou 9b43e0e683 fix: release Flutter-held keys before focus-changing shortcuts
Drain ordinary keys owned by the original session before run-on-key-up
actions and native clipboard callbacks. Preserve Mute holds, pending-action
cancellation and Web clipboard key-down activation.

Document the required Web matcher counterpart in the bridge:
rustdesk/rustdesk-web-js@94abe431d6

Validation: 61 native Flutter tests, 32 Chrome/HTML tests, targeted analysis
and Windows debug build.

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-04 04:12:58 -07:00
fufesou d1da598581 fix: share filtered shortcut bindings with the Web matcher
Pass the active platform config to JavaScript at startup and after settings changes, preserving unsupported saved bindings in local storage.

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-04 03:36:08 -07:00
fufesou d1c708ea09 fix: filter native shortcut caches for mobile controllers
Suspend saved desktop-only actions on Android and iOS and hide unavailable iOS actions without changing persisted bindings. Keep native cache filtering aligned with Flutter platform capabilities.

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-04 03:17:57 -07:00
fufesou 4aa575b513 fix: filter active Flutter shortcuts by platform capabilities
Reuse the Settings action filter for saved bindings while preserving storage, default-seeding behavior and configurable Apple Ctrl+Alt+Del bindings.

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-04 03:12:34 -07:00
fufesou 3651784fe4 fix: release Flutter-held keys before view-only shortcuts
Track ordinary keys forwarded by the Dart matcher paths and await their releases before View Only or Show My Cursor disables input. Keep Mute key ownership and existing empty-cleanup timing unchanged.

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-04 03:10:55 -07:00
fufesou 6e48a18cd4 fix: retain forwarded key ownership across shortcut repeats
Ignore repeat presses for keys already forwarded to the peer, and release ordinary held keys before Show My Cursor enables view-only. Cover both paths with converter-level regressions.

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-04 03:06:47 -07:00
fufesou b8adc3cfc7 fix: exclude unsupported Wayland shortcuts from Flutter matching
Keep saved bindings intact while filtering the active config used by the Flutter matcher. Cover stored bindings and enable/pass-through flags in the existing shortcut tests.

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-04 02:26:18 -07:00
fufesou a65fcc5f0b fix: suspend saved relative mouse shortcuts on Wayland
Filter the native active binding cache without changing stored configuration, so the binding becomes available again under X11.

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-04 02:09:05 -07:00
fufesou 12dde59268 fix: preserve remote key state during local shortcuts
Keep unrelated held keys pressed for session actions that retain input. Preserve key release when focus or input handling changes, and avoid synthetic Alt taps during shortcut dispatch.

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-04 02:03:11 -07:00
fufesou cd7bd71722 Merge branch 'master' into keyboard-shortcuts 2026-10-04 00:05:51 -07:00
fufesou f9eb80536e fix: preserve keyboard input after shortcut dialogs
Run native clipboard shortcuts on key release and wait for remote modifier releases before dispatching.

Release remote modifiers when mobile local UI takes focus, and document the tested iPad Bluetooth Mute shortcut limitation.

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-03 17:03:33 -07:00
Zixun LI e5bc204fe4 fix(wayland): avoid clock waits in PipeWire capture (#16430) 2026-10-03 06:51:33 +08:00
fufesou 36621a3c44 fix: prevent held-key shortcut recording bypass
Signed-off-by: fufesou <linlong1266@gmail.com>
2026-10-02 16:32:24 +08:00
Cheolhee LeeandClaude Opus 5.5 fada664df7 fix(clipboard): unix, keep Windows directories searchable (#16406)
A directory pasted from Windows with FILE_ATTRIBUTE_READONLY or
FILE_ATTRIBUTE_HIDDEN (Git for Windows hides `.git`) was given mode 0444 or
0400 in the FUSE list, because the read-only and hidden branches came before
the directory branch. Without `x` the directory cannot be entered once a
mode-preserving copy lands it on disk. Windows does not restrict access to a
directory for either attribute, so give every directory 0755, as a plain one
already gets.

Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
1.5.0
2026-09-30 23:50:12 +08:00
fufesou 3a5b45a2fa fix: align shortcut availability with platform support
- Hide unsupported mobile and web shortcut actions
- Enable mobile scaling and Android voice call shortcuts
- Use openMonitorInTheSameTab() for display switching
- Preserve cursor position when switching displays on desktop and web

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-09-30 23:35:41 +08:00
21pages 9d3ae7acd2 fix(windows): restore Flutter view visibility after FancyZones placement (#16397)
* fix(windows): restore Flutter view visibility after FancyZones placement

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

* fix(windows): avoid stale resize targets during Flutter refresh

* fix(windows): update multi-window dependency for FancyZones

---------

Signed-off-by: 21pages <sunboeasy@gmail.com>
2026-09-30 23:30:33 +08:00
Cheolhee Lee a7f2260203 fix(clipboard): unix, don't wrap FILETIMEs past 2554 (#16385) 2026-09-29 10:18:58 +08:00
berce 40a4aa34c8 Don't retry the _pa ipc at a Linux login screen (#16390)
At a greeter the cm is not started, so the `_pa` socket never exists and
the audio service fails to connect and logs an error once per second for
as long as a client is connected. Wait in `pa_impl::run` while
`is_prelogin()` is true; audio starts once a user logs in.

Fixes #16012
2026-09-29 10:17:06 +08:00
fufesou 0c18a8cbc9 fix(flutter): restore multi-window rendering after reconnect (#16383)
Use the window's current display when lastUserDisplay is unset so
additional monitor windows restore their capture subscriptions.

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-09-29 10:16:55 +08:00
fufesou b88209b88a fix: hide relative mouse mode shortcuts on Wayland
Separate relative mouse mode availability from screenshot support.
Filter unsupported actions and defaults while preserving saved bindings

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-09-29 10:05:09 +08:00
fufesou ecd2547028 fix: use session peer platform for Ctrl+Alt+Del events
Fix Android-to-Linux Ctrl+Alt+Del delivery by using the session's peer
platform instead of the desktop global session, which defaults to Windows

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-09-28 21:54:55 +08:00
fufesou 303ba96b1f refact(shortcuts): empty default shortcuts for Cmd+Option+Shift+Del on macOS and iOS
Because Del may be ambiguous for new macOS users.
Cmd+Option+Shift+Backspace is "Empty Trash without confirmation" shortcut on macOS.

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-09-28 21:51:24 +08:00
rustdeskandClaude Opus 5.5 4812a9815b AGENTS.md: limit corner-case growth and test bloat
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 18:26:34 +08:00
b6b11fd9b1 fix(drm): apply the uinput range on one thread instead of holding a lock across the await (#16362)
* drm: apply the uinput range on one thread instead of holding a lock across the await

#16122 serialized the three paths that apply a uinput range in a DRM
session (the layout poll, `update_uinput_resolution` and `check_init`)
with a tokio Mutex held over the awaited `update_mouse_resolution`,
which AGENTS.md rules out ("Do not hold locks across `.await`"; greptile
on #16122). The serialization itself has to stay: the uinput service
keeps the range of whichever request reached it last and each apply
sends it over its own connection, so two overlapping applies can leave
the device on one range while the other one is recorded.

The check, the apply and what it records now run as one job on a
dedicated thread (`run_uinput_apply`), one job at a time in the order
asked, with the runtime of that thread for the IPC and its 3 s timeout.
The async paths await the answer and the display service loop blocks on
it; nothing holds a lock while it waits. The poll publishes its drift
flag inside its job, as it did under the lock. A thread that failed to
start or died is started again for a later job, so one failure does
not stop every later apply (the poll used to build a runtime per attempt
and retry). The drm-off build keeps the code it had.

Tests (in `input_map_tests`, which CI runs):
uinput_applies_run_one_at_a_time_in_the_order_asked,
a_uinput_apply_job_can_bound_its_ipc_with_a_timeout,
a_uinput_apply_thread_that_died_is_started_again. Mutations: every job
on its own thread, the apply runtime without timers, the answer never
sent, a dead thread not started again; each turns a test red. The call sites run IPC and are
covered by reading.

* drm: log a layout poll whose uinput apply job got no answer

The layout poll dropped the result of its job with let _ =, so a poll
whose job was dropped (the apply thread failed to start or went away)
left no trace, while update_uinput_resolution and check_init log it
(greptile and CodeRabbit on #16362). It logs now. The drift flag keeps
what the last poll that ran published; a later poll starts the thread
again and publishes it.

* drm: throttle the uinput apply thread failure logs

The layout poll hands the apply thread a job every 1.5s, so a thread that
cannot start logged two errors per poll for as long as a session lasted.
Keep one line per site every 10 minutes, with the count of the rest.

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

---------

Co-authored-by: rustdesk <71636191+rustdesk@users.noreply.github.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 17:27:08 +08:00
Cipher Professor d1722c5d6d fix(linux): use BUS_VIRTUAL for the virtual mouse device (#16382)
The uinput virtual mouse RustDesk creates on Linux reported bustype
BUS_USB. libinput's evdev_tag_external_mouse() tags any BUS_USB or
BUS_BLUETOOTH pointer device as an external mouse, so desktop
environments' "disable touchpad when an external mouse is present"
setting suspends the user's real touchpad whenever RustDesk creates
this device, even though nothing is physically plugged in.

Changed the constant to BUS_VIRTUAL (0x06, verified against the
current upstream kernel's include/uapi/linux/input.h), which
correctly identifies this as the software-only device it is.

Fixes #16318.

Signed-off-by: Mohsin Manzoor Bhat <mohsinmanzoor1913@gmail.com>
2026-09-28 17:03:42 +08:00
Mariano Abad 0d49ead0c3 fix(drm): turn a captured frame only when the plane did not rotate it (#16345)
* fix(drm): turn a captured frame only when the plane did not rotate it

A compositor rotates an output either in hardware, setting the primary
plane's `rotation` property, or in software, drawing the scanout already
turned. `wl_output` cannot tell the two apart, and `frame_transform`
guessed: 90/270 turned, 180 left alone, which is right for i915 + mutter
(rotate-180 in hardware, scanout upright) and wrong wherever the
compositor drew the scanout turned, where 180 comes out upside down.

Measured before changing it. virtio-gpu (no rotation property, mutter 46):
the scanout dump at 180 is the desktop upside down, at 90 and 270 the
logical desktop turned inside the native mode framebuffer. i915 + mutter
(GNOME 50) at 180: the plane reports rotate-180 and the dump is upright,
identical to the unrotated one. amdgpu + KWin 6 at 180: the plane stays at
rotate-0 and the dump is upside down.

The producer reads `drmtap_plane_rotation()` (libdrmtap 0.5.8, optional
symbol) right after each grab and stamps it on the frame, in the dma-buf
descriptor and in the CPU frame header, both `serde(default)` so an older
producer still parses. A plane that rotated scans out the logical desktop
whatever the output transform says: the compositor programs it from the
CRTC transform, which also folds in the connector's panel orientation that
`wl_output` never carries, so the consumer leaves such a frame alone. A
plane at rotate-0 scanned out what the compositor drew, and the frame is
turned by the whole output transform. `None` (a library before 0.5.8, or
nothing it could read) keeps the previous rule, so nothing changes until
the library says otherwise. The session is still sized from the output
transform: a plane that rotated 90 in hardware hands over the portrait
scanout those dims already name.

* build: pin libdrmtap 0.5.8 (rustdesk-org/libdrmtap 95d4d7454)

The rotation fix reads drmtap_plane_rotation(), added in libdrmtap 0.5.8. The mirror carries that commit since 2026-09-25, so the pin moves there.

* drm: pin the decoding of a frame from a producer older than the plane rotation

The root service and the --server are upgraded separately, so a frame
header or a dma-buf descriptor without `plane_rotation` must still
decode, as None, which keeps the previous rule. The tests built both
messages with the field set to None; this one decodes payloads that omit
it, and one that carries it (greptile on #16345). Serde already reads a
missing Option as None, so what the test pins is the wire name and the
None on absence, for both messages.

Mutation: renaming the field on the wire, in either message, turns it red.

* drm: take the plane rotation right after the grab, not after the copies

`drmtap_plane_rotation()` reads the rotation property of the plane the
last grab came from at the moment it is called. The cpu path asked only
after `DrmReader::grab()` had copied the frame into its buffer and the
producer had copied it again into the message, so on a large frame the
compositor had time to change the plane and the frame went out with the
rotation of the next one; `frame_transform` turns that frame by it with
nothing to absorb the skew (zhou, review of 26-sep).

`DrmReader` now reads the rotation right after a successful
`drmtap_grab_mapped` or `drmtap_grab_desc`, before any copy or release,
and `plane_rotation()` returns that snapshot, so both paths stamp a frame
with the rotation its own grab saw.

Test: a_frame_keeps_the_rotation_its_plane_had_when_it_was_grabbed, in
`plane_rotation_tests` (which CI already runs), drives the reader through
a fake library whose frame release turns the plane: the rotation read at
the grab survives on the cpu grab and on the dma-buf export. Mutations:
no snapshot on the cpu grab, none on the export, and the cpu snapshot
taken after the release, each turn it red.
2026-09-28 15:54:55 +08:00
fufesou e6a21d9719 fix(shortcuts): isolate window actions and prevent duplicate Alt presses
- Dispatch shortcut actions only to the originating session window.
- Clear local modifier state on focus loss without resending modifiers
  already released to Windows peers, preventing lost following input.
- Strengthen the regression assertion against extra Alt keydown events

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-09-28 14:19:15 +08:00
flusheDData be9b96cf65 Translate voice call instruction to Spanish (#16358) 2026-09-28 13:53:54 +08:00
Cheolhee LeeandClaude Opus 5.5 89fcf56c4e fix(clipboard): unix, don't let the next file's preload fail a request (#16364)
After serving a request for file N, `serve_file_contents` preloads the
next non-directory file with `load_handle()?`. When that file can no
longer be opened (deleted or renamed after the copy, or unreadable), its
error replaced N's reply, so every size and range request for N failed
although N itself is intact.

Keep the preload best-effort. Its failure is logged at trace, because it
can fire on every request for N, and N+1's own request still reports the
error.

Signed-off-by: chlee <sourcehatchery@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 11:46:34 +08:00
Cheolhee LeeandClaude Opus 5.5 8a76628007 fix(clipboard): unix, use the real Windows FILETIME epoch offset (#16366)
`LDAP_EPOCH_DELTA`, the offset from the FILETIME epoch (1601-01-01) to
the Unix epoch in 100 ns units, was 116444772610000000. The real offset
is 116444736000000000 (11644473600 s), so the old value is 3661 s
(1h01m01s) too large.

Unix peers encode and decode with the same constant, so the error cancels
between them, but Windows sends and reads real FILETIMEs: files copied
from Windows got a modified time 1h01m01s too early on Linux and macOS,
and files copied from Linux or macOS were sent one 1h01m01s too late.

Signed-off-by: chlee <sourcehatchery@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
2026-09-28 11:37:03 +08:00
fufesou 96456ca815 fix(shortcuts): prevent recording non-simultaneous key combinations
Build new captures from currently held keys instead of reusing released
letters. Preserve the last valid chord after release so it can be saved.

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-09-28 08:45:24 +08:00
fufesou c066574bed fix(mobile): correct Chat keyboard and input helper behavior
- Keep soft keyboard and helper hidden when Chat opens via shortcut
- Restore soft input on touch and remote focus after Chat closes
- Handle modifier releases while Chat owns focus
- Clear hidden virtual modifiers while preserving held keys and Pin behavior

Signed-off-by: fufesou <linlong1266@gmail.com>
2026-09-27 21:36:00 +08:00