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 our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support changing the mouse pointer #37882
Conversation
The PR changelog entry failed validation: Changelog entry not found in the PR body. Please add a "no-changelog" label to the PR, or changelog lines starting with |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Suggestion for changelog:
Implemented dynamic mouse pointer updates to reflect context-specific actions, e.g. window resizing.
web/packages/teleport/src/components/TdpClientCanvas/TdpClientCanvas.tsx
Outdated
Show resolved
Hide resolved
web/packages/teleport/src/components/TdpClientCanvas/TdpClientCanvas.tsx
Outdated
Show resolved
Hide resolved
Are we software rendering the pointer on canvas now? I thought you mentioned that this was just using the CSS cursor property which seems like it would be more efficient. |
…Canvas.tsx Co-authored-by: Isaiah Becker-Mayer <isaiah@goteleport.com>
Co-authored-by: Isaiah Becker-Mayer <isaiah@goteleport.com>
…Canvas.tsx Co-authored-by: Isaiah Becker-Mayer <isaiah@goteleport.com>
@zmb3 we do render it to temp canvas once, to convert raw pixels received from RDP to png - only format widely supported by browsers as cursor. We then set it as cursor for the canvas we render the whole desktop on. |
@@ -97,6 +97,47 @@ function TdpClientCanvas(props: Props) { | |||
} | |||
}, [client, clientOnPngFrame]); | |||
|
|||
let previousCursor = 'auto'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do you need useRef
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It won't hurt for sure, I've added it
'url(' + | ||
cursor.toDataURL() + | ||
') ' + | ||
pointer.hotspot_x + | ||
' ' + | ||
pointer.hotspot_y + | ||
', auto'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think you can rewrite this with string interpoloation:
canvas.style.cursor = `url('${cursor.toDataURL()') ${pointer.hotspot_x} ${pointer.hotspot_y} auto`
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yep, you can, changed
} ${pointer.hotspot_y}, auto`; | ||
}; | ||
|
||
client.on(TdpClientEvent.POINTER, updatePointer); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nit: for consistency, I'd use client.addListenter
(or client.off
in line 133).
const cursor = document.createElement('canvas'); | ||
cursor.width = pointer.data.width; | ||
cursor.height = pointer.data.height; | ||
cursor.getContext('2d').putImageData(pointer.data, 0, 0); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This probably doesn't change much in this case, but pointer.data
returns a color space that we can pass to the canvas:
cursor
.getContext('2d', { colorSpace: pointer.data.colorSpace })
.putImageData(pointer.data, 0, 0);
if (client && updatePointer) { | ||
const canvas = canvasRef.current; | ||
const updatePointer = (pointer: { | ||
data: ImageData | boolean; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'd add a short JSDoc comment explaining that if data
is boolean
then true
means that we want to show a cursor and false
means we want to hide it.
@@ -401,6 +438,7 @@ export type Props = { | |||
canvasOnMouseWheelScroll?: (cli: TdpClient, e: WheelEvent) => void; | |||
canvasOnContextMenu?: () => boolean; | |||
style?: CSSProperties; | |||
updatePointer: boolean; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we can make this property optional, you won't have to pass false
to DesktopPlayer
.
updatePointer: boolean; | |
updatePointer?: boolean; |
@@ -184,6 +184,7 @@ impl FastPathProcessor { | |||
cb_context: &JsValue, | |||
draw_cb: &js_sys::Function, | |||
respond_cb: &js_sys::Function, | |||
update_pointer_cb: &js_sys::Function, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's document the signature of this function like we do for the others
teleport/web/packages/teleport/src/ironrdp/src/lib.rs
Lines 174 to 180 in 894920c
/// `tdp_fast_path_frame: Uint8Array` | |
/// | |
/// `cb_context: tdp.Client` | |
/// | |
/// `draw_cb: (bitmapFrame: BitmapFrame) => void` | |
/// | |
/// `respond_cb: (responseFrame: ArrayBuffer) => void` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It might also be worth documenting the meanings of the different options for the data
param.
@probakowski See the table below for backport results.
|
This change allows server to send mouse pointer updates to properly indicate e.g. resizing with arrows.
Closes #29964
changelog: Implemented dynamic mouse pointer updates to reflect context-specific actions, e.g. window resizing.