* fix(linux): enable mouse side buttons in remote sessions
Flutter's Linux embedder never delivers X11 button 8/9 (back/forward)
events to Dart, so mouse side buttons were silently dropped in remote
sessions.
Intercept these buttons at the GDK level via button-press/release-event
handlers on all windows (main + sub-windows) and forward them through
a dedicated platform channel to the active InputModel session.
Also add a defensive XSetPointerMapping call during enigo init to
extend the X11 core pointer button map to 9 buttons on servers where
it is smaller (e.g. minimal X server configurations).
* fix: address review feedback for side button support
- Use XOpenDisplay/XCloseDisplay instead of reading Display* from
xdo_t's private struct layout at offset 0 (fragile ABI assumption)
- Track side button down ownership per button via a Map instead of a
single slot, preventing cross-button mismatch on overlapping presses
* fix: gate side buttons on view-only and fix teardown
- Skip side button events in view-only sessions (consistent with
other mouse entry points)
- Release held side buttons on session close to avoid stuck buttons
on the remote
- Drop unpaired 'up' events instead of falling back to the active
model, which could send to the wrong session
* docs: add clarifying comments from review feedback
- Note global scope of XSetPointerMapping and that it runs once
via lazy_static singleton
- Clarify sub-window callback is safe on X11-only builds
- Document per-isolate design of initSideButtonChannel
* fix: replace broken XSetPointerMapping with diagnostic check
XSetPointerMapping requires the length to match XGetPointerMapping's
return value - it cannot extend the button count. The previous code
would trigger a BadValue X error on servers with fewer than 9 buttons.
Replace with a diagnostic-only check that logs whether the core
pointer has enough buttons for side button simulation. RustDesk's
uinput "Mouse passthrough" device already provides the needed buttons
in practice.
Also add .catchError to fire-and-forget side button releases during
session teardown to prevent unhandled async errors.
* fix: ensure side button releases bypass permission checks
If permissions change between button down and up (e.g. keyboardPerm
revoked, view-only toggled), sendMouse's early return would suppress
the release, leaving a stuck button on the remote.
Add _sendMouseUnchecked that bypasses permission checks, used for:
- Side button 'up' events (matching a recorded 'down')
- Forced releases during session teardown
Gate all permission checks (isViewOnly, keyboardPerm, isViewCamera)
at the 'down' entry point before recording in _sideButtonDownModels.
* fix: add NULL guards and avoid blocking platform channel handler
- Add NULL checks for FL_VIEW cast and channel creation in
on_subwindow_created (review feedback from fufesou)
- Use fire-and-forget (unawaited) for _sendMouseUnchecked calls
inside the platform channel handler to avoid blocking platform
messages when sessionSendMouse is slow (review feedback from Copilot)
* fix: remove circular import and skip X11 check on Wayland
- Move initSideButtonChannel() call from initEnv() in main.dart to
the InputModel constructor, removing the circular import between
main.dart and input_model.dart
- Skip check_x11_button_map() when DISPLAY is not set to avoid
noisy warnings on pure Wayland environments
* flutter: improve address book pull error handling
Summary:
- Show error messages when fetching the address book list fails.
- After the initial fetch, switching back to the AB tab no longer re-fetches it, even if an error occurred or the error banner was dismissed.
Tested:
- Self-hosted server:
- normal
- 403 responses
- legacy address book mode
- Public server
- Verified that switching tabs no longer re-fetches AB after the initial fetch, regardless of whether an error occurred or the error banner was cleared.
Signed-off-by: 21pages <sunboeasy@gmail.com>
* use resp.statusCode in address book json decoding
Signed-off-by: 21pages <sunboeasy@gmail.com>
* flutter: clear address book list errors on reset
Signed-off-by: 21pages <sunboeasy@gmail.com>
* flutter: clear address book pull errors consistently
Signed-off-by: 21pages <sunboeasy@gmail.com>
---------
Signed-off-by: 21pages <sunboeasy@gmail.com>
Treat "Access to mobile devices is restricted in your country"
as a non-retriable connection error so the error dialog does not
trigger reconnect attempts.
Signed-off-by: 21pages <sunboeasy@gmail.com>
* docs: fix typos in documentation and code comments
- Fix 'seperated' -> 'separated' in remote_input.dart
- Fix 'seperators' -> 'separators' in fuse/cs.rs
- Update outdated 'OSX' -> 'macOS' in virtual display README
Signed-off-by: pallab-js <sonowalpallabjyoti@gmail.com>
* impl(cm): implement change_theme and change_language callbacks
These callbacks were previously empty TODO stubs.
Now they properly invoke the Sciter UI handlers to notify
the UI when theme or language changes occur.
Signed-off-by: pallab-js <sonowalpallabjyoti@gmail.com>
---------
Signed-off-by: pallab-js <sonowalpallabjyoti@gmail.com>
* tcp proxy
* fix per review
* fix per review
* Suppress secure_tcp info logs for TCP proxy requests
Signed-off-by: 21pages <sunboeasy@gmail.com>
* copilot review: redact tcp proxy logs, dedupe headers, and avoid body clone
Signed-off-by: 21pages <sunboeasy@gmail.com>
* format common.rs
Signed-off-by: 21pages <sunboeasy@gmail.com>
* copilot review: test function name
Signed-off-by: 21pages <sunboeasy@gmail.com>
* copilot review: format IPv6 tcp proxy log targets correctly
Signed-off-by: 21pages <sunboeasy@gmail.com>
* copilot review: normalize HTTP method before direct request dispatch
Signed-off-by: 21pages <sunboeasy@gmail.com>
* review: extract fallback helper, fix Content-Type override, add overall timeout
- Extract duplicated TCP proxy fallback logic into generic
`with_tcp_proxy_fallback` helper used by both `post_request` and
`http_request_sync`, eliminating code drift risk
- Allow caller-supplied Content-Type to override the default in
`parse_simple_header` instead of silently dropping it
- Take body by reference in `post_request_http` to avoid eager clone
when no fallback is needed
- Wrap entire `tcp_proxy_request` flow (connect + handshake + send +
receive) in an overall timeout to prevent indefinite stalls
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* review: make is_public case-insensitive and cover mixed-case rustdesk URLs
Signed-off-by: 21pages <sunboeasy@gmail.com>
* oidc: route auth requests through shared HTTP/tcp-proxy path while keeping TLS warmup
Signed-off-by: 21pages <sunboeasy@gmail.com>
* refactor: replace unused TryFrom<Response> with HbbHttpResponse::parse method
Remove TryFrom<Response> impl that was never called and replace the
private parse_hbb_http_response helper in account.rs with a public
parse() method on HbbHttpResponse, eliminating code duplication.
Signed-off-by: 21pages <sunboeasy@gmail.com>
---------
Signed-off-by: 21pages <sunboeasy@gmail.com>
Co-authored-by: 21pages <sunboeasy@gmail.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
* Fix Windows session-based logon and lock-screen detection
- scope LogonUI and locked-state checks to the current Windows session
- allow permanent password fallback for logon and lock-screen access
Signed-off-by: 21pages <sunboeasy@gmail.com>
* Log permanent-password fallback on logon screen
Signed-off-by: 21pages <sunboeasy@gmail.com>
---------
Signed-off-by: 21pages <sunboeasy@gmail.com>