Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Fix regaining control after a remote cursor movement#13353

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Open
logiclrd wants to merge3 commits intorustdesk:master
base:master
Choose a base branch
Loading
fromlogiclrd:self-get-control

Conversation

@logiclrd
Copy link
Contributor

@logiclrdlogiclrd commentedOct 30, 2025
edited
Loading

I have encountered a bug related to remote cursor movement. When a remote cursor movement is detected, thecursorModel is updated so thatgotMouseControl isfalse. The_checkPeerControlProtected method in input_model.dart includes logic to allow you to regain control if the cursor moves more than a certain distance. However, this logic doesn't work as expected because after each check, it latches the new mouse position. As a result, the mouse movement isn't cumulative. The cursor must movekMouseControlDistance pixelsin a single event in order to regain control. It turns out, at least on my Windows 10 machine, that it takes considerable effort to move the mouse fast enough to trigger this. So what ends up happening is that input is just locked until the cursor leaves the RustDesk remote view window. Then, later, when the mouse cursor re-enters the view, it's usually more thankMouseControlDistance pixels away from where it left the window so theselfGetControl logic finally triggers.

This PR fixes the bug by removing the line that latches each new mouse event location every time theselfGetControl test fails. As a result, now once the mouse has moved acumulativekMouseControlDistance pixels, control is regained.

In addition, theselfGetControl calculation uses an imprecise model that checks the distance moved on the X and Y axes separately. As such, it is possible to move the mouse up to 1.414 (sqrt(2)) timeskMouseControlDistance beforeselfGetControl activates, if the movement is diagonal. This PR updates the calculation to compute the actual distance travelled, so that it triggers afterkMouseControlDistance in any direction, not just orthogonal directions. (The comparison is done between the square of the distance and the square of the threshold, to avoid performing a square root computation. On any computer less than 30 years old I'm fairly certain this optimization is beyond unnecessary, but it's the principle of the matter. 😛 In another PR, Copilot actually told me to use this exact optimization in another context earlier today, for what it's worth.)

… distance rather than checking each axis separately.
@rustdesk
Copy link
Owner

The cursor must move kMouseControlDistance pixels in a single event in order to regain control

I do not think we should change this behavior.

@logiclrd
Copy link
ContributorAuthor

The cursor must move kMouseControlDistance pixels in a single event in order to regain control

I do not think we should change this behavior.

Really? It looks 100% like a bug on my end. I move the mouse around andnothing happens. I have to fling the mouse to get it to trigger.

@logiclrd
Copy link
ContributorAuthor

Here's a video of my experience:

self-get-control.mp4

@logiclrd
Copy link
ContributorAuthor

And this is with the changes in this PR:

self-get-control-2.mp4

if (selfGetControl) {
cursorModel.gotMouseControl=true;
}else {
lastMousePos= ui.Offset(x, y);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

This is intented.

local control is only regained ifkMouseControlDistance is exceeded in a single mouse event.

As you guessed,
the user on the controlling side has to move the mouse a significant amount (in a short time) to take control.

Copy link
ContributorAuthor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others.Learn more.

Mm, okay. To me, intuitively, it seemed to make more sense that control would be regained when the mouse had moved more than a certain amount from the starting position. But it's intentional that the mouse position is irrelevant, and that control is regained when themouse speed exceeds a certain threshold?

If so, then I think two things:

  1. The current setting requires me to move the mousefar too quickly for it to be discoverable. I would absolutely just assume that I was locked out and had no way to regain control.

  2. Theinstantaneous mouse speed is probably not the best metric for this. You say that it must move a significant amount "in a short time", but using the instantaneous speed means that the definition of "a short time" is the hardware's reporting interval. I did a quick look-up and haven't verified the numbers, but from what I read, the typical baseline for this is 8 ms, and high-precision gaming mice can have intervals well into the sub-millisecond range.

There's absolutely no way I'm going to move my mouse cursorkMouseControlDistance pixels in 125 microseconds.

If the design here (subject to tuning the travel radius) isn't desired, then I propose an alternative: Maintain a queue of timestamped mouse movements as well as the sum of their distance. On each new event that is subject toselfGetControl checking, append a new entry and delete any entries outside of a determined interval (say 250 ms). Then,selfGetControl is true if the sum exceeds a threshold.

This algorithm will behave identically no matter what direction the mouse is moving (even if the path is curved) and no matter what the rate of mouse position updates is.

Updated input_model.dart to import mouse_speed_analyzer.dart and to incorporate an instance into InputModel.Updated the _checkPeerControlProtected method of InputModel to use the MouseSpeedAnalyzer to track mousement and determine if/when it exceeds the threshold to regain control.
@logiclrd
Copy link
ContributorAuthor

logiclrd commentedNov 5, 2025
edited
Loading

I've got an updated implementation that does what I outlined in the thread earlier: It tracks a short history of the mouse's movement and tallies up theactual distance travelled in a particular span of time. It triggers the self-get-control functionality when the velocity of the mouse, irrespective of direction, exceeds a configured threshold. The configuration is presently hardcoded but could be exposed as user-configurable options in the future.

The implementation adds a class MouseSpeedAnalyzer which uses a Queue of mouse events. When the mouse cursor is locked, each event gets added to the queue. Events are timestamped, and the timestamp is used to determine when events should be removed from the other end of the queue. As such, if the MouseSpeedAnalyzer is configured with a 250ms window, then the queue never contains more than a 250ms span of mouse events, so its size is well-bounded.

This video shows it in action:

mouse-speed-analyzer.mp4

You can see that it doesn't matter what direction the mouse cursor is moving in, or even if it is a straight line. If it has travelled the requisite distance within the time window, then control is regained.

As described earlier, this algorithm is resilient to different systems having potentially different mouse reporting rates. It doesn't matter how quickly or slowly the mouse events come in for the purpose of calculating the travel distance over time.

Sign up for freeto join this conversation on GitHub. Already have an account?Sign in to comment

Reviewers

@fufesoufufesoufufesou left review comments

Assignees

No one assigned

Labels

None yet

Projects

None yet

Milestone

No milestone

Development

Successfully merging this pull request may close these issues.

3 participants

@logiclrd@rustdesk@fufesou

[8]ページ先頭

©2009-2025 Movatter.jp