Skip to content

Commit

Permalink
[v15] Re-enable and fix sticky windows key (#38699)
Browse files Browse the repository at this point in the history
* Bump the rust group with 2 updates (#37739)

Bumps the rust group with 2 updates: [tokio](https://github.com/tokio-rs/tokio) and [time](https://github.com/time-rs/time).


Updates `tokio` from 1.35.1 to 1.36.0
- [Release notes](https://github.com/tokio-rs/tokio/releases)
- [Commits](tokio-rs/tokio@tokio-1.35.1...tokio-1.36.0)

Updates `time` from 0.3.31 to 0.3.34
- [Release notes](https://github.com/time-rs/time/releases)
- [Changelog](https://github.com/time-rs/time/blob/main/CHANGELOG.md)
- [Commits](time-rs/time@v0.3.31...v0.3.34)

---
updated-dependencies:
- dependency-name: tokio
  dependency-type: direct:production
  update-type: version-update:semver-minor
  dependency-group: rust
- dependency-name: time
  dependency-type: direct:production
  update-type: version-update:semver-patch
  dependency-group: rust
...

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>

* Adds the extended keycode where appropriate and updates to the latest IronRDP master commit hash. (#37962)

* Adds the extended keycode where appropriate and updates to the latest IronRDP master commit hash.

* cleaning up disconnect result

* Pipes disconnect messages through to the client.

This required a change to the state management for DesktopSession. State
is still quite complex to get right here, but this is a step in the right
direction.

* Updates desktopPlaybackHandle to the new authenticated websocket paradigm as it was forgotten in #37520

* prettier formatting

* adding clarifying comments

* Further refactoring to make DesktopSession's state machine more comprehensible

* Remove unnecessary items from dependency lists

* Fix sticky windows key (#38198)

* Adds the extended keycode where appropriate and updates to the latest IronRDP master commit hash.

* cleaning up disconnect result

* Pipes disconnect messages through to the client.

This required a change to the state management for DesktopSession. State
is still quite complex to get right here, but this is a step in the right
direction.

* Updates desktopPlaybackHandle to the new authenticated websocket paradigm as it was forgotten in #37520

* prettier formatting

* adding clarifying comments

* Further refactoring to make DesktopSession's state machine more comprehensible

* Remove unnecessary items from dependency lists

* Adds the KeyboardHandler class
that manages the keyboard events, including new functionality to handle
withholding the Windows/Alt keys to prevent such keys from "sticking"
when the user switches between windows.

This technique works to stop the sticking, though there is still an edge
case where the user cmd/alt-tabs super quickly, in a manner that the browser
sees both the down and up events for the Windows key, despite the user's
intention being to change windows. In the case of the Windows key, this
causes the start menu to pop open, and the user must press the Windows key
again to close it. This is not a showstopper, but it is a bit annoying.
A similar problem would occur with the Alt key, where such behavior would
cause the current window (on the Windows machine) to focus on the menu bar.

The next commit will be to add a timeout mechanism for the relevant keyup events
in order to mitigate this edge case.

* Adds a delayUp cache for delaying the up event
of the sticky windows key. This is to prevent the edge case
where the user presses cmd/alt-tab really quickly in a manner
that causes the down + up events to be registered in spite of
the user's intention to be to change out of the window.

* Refactoring KeyboardHandler

* Convert caches into Maps

* Moves the rest of keyboard functionality into KeyboardHandler, rearranges methods, adds an onUnmount for clearing all the intervals on unmount

* Moves KeyboardHandler to its own file

* simplifies withholding logic by including a Withholder class with a single array that manages all the withheld keystrokes

* Makes useEffect symmetrical

* Rename onUnmount to dispose

* sp

* Adds unit tests for Withholder

* Splitting Withholder out into its own file

* nits

* CR

* make fix-license

---------

Signed-off-by: dependabot[bot] <[email protected]>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
  • Loading branch information
Isaiah Becker-Mayer and dependabot[bot] authored Feb 28, 2024
1 parent 91ef337 commit 2e52c95
Show file tree
Hide file tree
Showing 21 changed files with 1,265 additions and 659 deletions.
44 changes: 26 additions & 18 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 10 additions & 10 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,13 @@ codegen-units = 1
[workspace.dependencies]
# Note: To use a local IronRDP repository as a crate (for example, ironrdp-cliprdr), define the dependency as follows:
# ironrdp-cliprdr = { path = "/path/to/local/IronRDP/crates/ironrdp-cliprdr" }
ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "d24000a2aeab74f2610a0b01c629f7a4ef3c77ef" }
ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "d24000a2aeab74f2610a0b01c629f7a4ef3c77ef" }
ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "d24000a2aeab74f2610a0b01c629f7a4ef3c77ef" }
ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "d24000a2aeab74f2610a0b01c629f7a4ef3c77ef" }
ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "d24000a2aeab74f2610a0b01c629f7a4ef3c77ef" }
ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "d24000a2aeab74f2610a0b01c629f7a4ef3c77ef" }
ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "d24000a2aeab74f2610a0b01c629f7a4ef3c77ef" }
ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "d24000a2aeab74f2610a0b01c629f7a4ef3c77ef" }
ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "d24000a2aeab74f2610a0b01c629f7a4ef3c77ef", features = ["rustls"]}
ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "d24000a2aeab74f2610a0b01c629f7a4ef3c77ef" }
ironrdp-cliprdr = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" }
ironrdp-connector = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" }
ironrdp-graphics = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" }
ironrdp-pdu = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" }
ironrdp-rdpdr = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" }
ironrdp-rdpsnd = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" }
ironrdp-session = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" }
ironrdp-svc = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" }
ironrdp-tls = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08", features = ["rustls"]}
ironrdp-tokio = { git = "https://github.com/Devolutions/IronRDP", rev = "c944674ecbb0952f9e7ecb964a6c79cdca669a08" }
2 changes: 1 addition & 1 deletion lib/srv/desktop/rdp/rdpclient/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ rand_chacha = "0.3.1"
rsa = "0.9.6"
sspi = { git = "https://github.com/Devolutions/sspi-rs", rev="d54bdfcafa0e10d9d78224ebacc4f2a0992a6b79", features = ["network_client"] }
static_init = "1.0.3"
tokio = { version = "1.35", features = ["full"] }
tokio = { version = "1.36", features = ["full"] }
tokio-boring = { git = "https://github.com/gravitational/boring", rev="605253d99d5e363e178bcf97e1d4622e33844cd5", optional = true }
utf16string = "0.2.0"
uuid = { version = "1.6.1", features = ["v4"] }
Expand Down
46 changes: 39 additions & 7 deletions lib/srv/desktop/rdp/rdpclient/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ import "C"

import (
"context"
"fmt"
"os"
"runtime/cgo"
"sync"
Expand Down Expand Up @@ -253,16 +254,24 @@ func (c *Client) readClientSize() error {
}

if c.requestedWidth > types.MaxRDPScreenWidth || c.requestedHeight > types.MaxRDPScreenHeight {
return trace.BadParameter(
err = trace.BadParameter(
"screen size of %d x %d is greater than the maximum allowed by RDP (%d x %d)",
s.Width, s.Height, types.MaxRDPScreenWidth, types.MaxRDPScreenHeight,
)
if err := c.sendTDPNotification(err.Error(), tdp.SeverityError); err != nil {
return trace.Wrap(err)
}
return trace.Wrap(err)
}

return nil
}
}

func (c *Client) sendTDPNotification(message string, severity tdp.Severity) error {
return c.cfg.Conn.WriteMessage(tdp.Notification{Message: message, Severity: severity})
}

func (c *Client) startRustRDP(ctx context.Context) error {
c.cfg.Log.Info("Rust RDP loop starting")
defer c.cfg.Log.Info("Rust RDP loop finished")
Expand Down Expand Up @@ -292,7 +301,7 @@ func (c *Client) startRustRDP(ctx context.Context) error {
return trace.BadParameter("user key was nil")
}

if res := C.client_run(
res := C.client_run(
C.uintptr_t(c.handle),
C.CGOConnectParams{
go_addr: addr,
Expand All @@ -308,14 +317,37 @@ func (c *Client) startRustRDP(ctx context.Context) error {
allow_directory_sharing: C.bool(c.cfg.AllowDirectorySharing),
show_desktop_wallpaper: C.bool(c.cfg.ShowDesktopWallpaper),
},
); res.err_code != C.ErrCodeSuccess {
if res.message == nil {
return trace.Errorf("unknown error: %v", res.err_code)
}
)

var message string
if res.message != nil {
message = C.GoString(res.message)
defer C.free_string(res.message)
return trace.Errorf("%s", C.GoString(res.message))
}

// If the client exited with an error, send a tdp error notification and return it.
if res.err_code != C.ErrCodeSuccess {
var err error

if message != "" {
err = trace.Errorf("RDP client exited with an error: %v", message)
} else {
err = trace.Errorf("RDP client exited with an unknown error")
}

c.sendTDPNotification(err.Error(), tdp.SeverityError)
return err
}

if message != "" {
message = fmt.Sprintf("RDP client exited gracefully with message: %v", message)
} else {
message = "RDP client exited gracefully"
}

c.cfg.Log.Info(message)
c.sendTDPNotification(message, tdp.SeverityInfo)

return nil
}

Expand Down
Loading

0 comments on commit 2e52c95

Please sign in to comment.