Internal
Public Access
RDP session fixes: correct keyboard scancodes, clipboard sync, cursor shapes
Fix RDP keyboard input using FreeRDP's authoritative X11-keycode-to-scancode table instead of ad hoc bit math, which misread punctuation keys as unrelated letter keys (e.g. apostrophe as B) because X11 keycode numbering only coincidentally overlaps PC/AT scancodes. Add bidirectional clipboard sync (CF_UNICODETEXT) over the cliprdr channel, and RDP pointer/cursor shape sync so the local cursor reflects what the remote OS wants displayed (resize handles, text I-beam, etc.) instead of staying a static arrow. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -1,8 +1,10 @@
|
||||
#include "rdp_display_widget.h"
|
||||
|
||||
#include <QCursor>
|
||||
#include <QKeyEvent>
|
||||
#include <QMouseEvent>
|
||||
#include <QPainter>
|
||||
#include <QPixmap>
|
||||
#include <QResizeEvent>
|
||||
#include <QTimer>
|
||||
#include <QWheelEvent>
|
||||
@@ -16,7 +18,7 @@ QSize sanitizeSize(const QSize& size)
|
||||
}
|
||||
|
||||
RdpDisplayWidget::RdpDisplayWidget(QWidget* parent)
|
||||
: QWidget(parent), m_remoteSize(1280, 720)
|
||||
: QWidget(parent), m_remoteSize(1280, 720), m_cursorMode(CursorMode::Default)
|
||||
{
|
||||
setFocusPolicy(Qt::StrongFocus);
|
||||
setMouseTracking(true);
|
||||
@@ -61,6 +63,62 @@ void RdpDisplayWidget::clearFrame()
|
||||
update();
|
||||
}
|
||||
|
||||
void RdpDisplayWidget::setCursorImage(const QImage& image, const QPoint& hotspot)
|
||||
{
|
||||
m_cursorImage = image;
|
||||
m_cursorHotspot = hotspot;
|
||||
m_cursorMode = CursorMode::Custom;
|
||||
applyCursor();
|
||||
}
|
||||
|
||||
void RdpDisplayWidget::setCursorHidden()
|
||||
{
|
||||
m_cursorMode = CursorMode::Hidden;
|
||||
applyCursor();
|
||||
}
|
||||
|
||||
void RdpDisplayWidget::setCursorDefault()
|
||||
{
|
||||
m_cursorMode = CursorMode::Default;
|
||||
applyCursor();
|
||||
}
|
||||
|
||||
void RdpDisplayWidget::applyCursor()
|
||||
{
|
||||
if (m_cursorMode == CursorMode::Hidden) {
|
||||
setCursor(Qt::BlankCursor);
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_cursorMode == CursorMode::Default || m_cursorImage.isNull()) {
|
||||
unsetCursor();
|
||||
return;
|
||||
}
|
||||
|
||||
const QSize remote = effectiveRemoteSize();
|
||||
const QRectF target = renderRect();
|
||||
if (remote.isEmpty() || target.isEmpty()) {
|
||||
setCursor(QCursor(QPixmap::fromImage(m_cursorImage),
|
||||
m_cursorHotspot.x(),
|
||||
m_cursorHotspot.y()));
|
||||
return;
|
||||
}
|
||||
|
||||
const qreal scale = target.width() / remote.width();
|
||||
QImage scaledImage = m_cursorImage;
|
||||
if (!qFuzzyCompare(scale, 1.0)) {
|
||||
scaledImage = m_cursorImage.scaled(
|
||||
qMax(1, qRound(m_cursorImage.width() * scale)),
|
||||
qMax(1, qRound(m_cursorImage.height() * scale)),
|
||||
Qt::IgnoreAspectRatio,
|
||||
Qt::SmoothTransformation);
|
||||
}
|
||||
|
||||
const int hotX = qBound(0, qRound(m_cursorHotspot.x() * scale), scaledImage.width());
|
||||
const int hotY = qBound(0, qRound(m_cursorHotspot.y() * scale), scaledImage.height());
|
||||
setCursor(QCursor(QPixmap::fromImage(scaledImage), hotX, hotY));
|
||||
}
|
||||
|
||||
void RdpDisplayWidget::paintEvent(QPaintEvent* event)
|
||||
{
|
||||
Q_UNUSED(event);
|
||||
@@ -84,6 +142,7 @@ void RdpDisplayWidget::resizeEvent(QResizeEvent* event)
|
||||
QWidget::resizeEvent(event);
|
||||
const QSize size = sanitizeSize(event->size());
|
||||
emit viewportSizeChanged(size.width(), size.height());
|
||||
applyCursor();
|
||||
}
|
||||
|
||||
void RdpDisplayWidget::keyPressEvent(QKeyEvent* event)
|
||||
|
||||
Reference in New Issue
Block a user