9#include <QLoggingCategory>
13#elif ! (defined(Q_OS_ANDROID) || defined(Q_OS_WIN) || defined(Q_OS_APPLE))
15 #include <X11/XKBlib.h>
17 #include <X11/keysymdef.h>
22static Q_LOGGING_CATEGORY(log,
"Client.FrmViewer")
23static Q_LOGGING_CATEGORY(logRecord, "Client.FrmViewer.Record")
27 , m_bRecordVideo(false)
29 qDebug(log) << Q_FUNC_INFO;
30 setAttribute(Qt::WA_DeleteOnClose);
36 slotSetAdaptWindows(ADAPT_WINDOWS::ZoomToWindow);
39 setMouseTracking(
true);
40 setFocusPolicy(Qt::WheelFocus);
49CFrmViewer::~CFrmViewer()
51 qDebug(log) << Q_FUNC_INFO;
54QRectF CFrmViewer::GetAspectRationRect()
56 QRectF dstRect = rect();
57 qreal newW = dstRect.width();
58 qreal newH = dstRect.height();
62 qreal rateW =
static_cast<qreal
>(rect().width())
63 /
static_cast<qreal
>(m_DesktopSize.width());
64 qreal rateH =
static_cast<qreal
>(rect().height())
65 /
static_cast<qreal
>(m_DesktopSize.height());
68 newW = m_DesktopSize.width() * rateW;
69 newH = m_DesktopSize.height() * rateW;
70 newT = (
static_cast<qreal
>(rect().height()) - newH)
71 /
static_cast<qreal
>(2);
72 }
else if(rateW > rateH) {
73 newW = m_DesktopSize.width() * rateH;
74 newH = m_DesktopSize.height() * rateH;
75 newL = (
static_cast<qreal
>(rect().width()) - newW)
76 /
static_cast<qreal
>(2);
78 dstRect = QRectF(newL, newT, newW, newH);
82void CFrmViewer::paintDesktop()
84 QRectF dstRect = rect();
86 switch (m_AdaptWindows) {
88 case ADAPT_WINDOWS::Auto:
93 dstRect.setLeft((rect().width() - m_DesktopSize.width()) >> 1);
94 dstRect.setTop((rect().height() - m_DesktopSize.height()) >> 1);
95 dstRect.setWidth(m_DesktopSize.width());
96 dstRect.setHeight(m_DesktopSize.height());
100 dstRect = GetAspectRationRect();
107 if(m_Desktop.isNull())
return;
109 QPainter painter(
this);
113#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
114 painter.fillRect(rect(), QBrush(palette().color(QPalette::Window)));
116 painter.fillRect(rect(), QBrush(palette().color(QPalette::Background)));
121 painter.setRenderHint(QPainter::SmoothPixmapTransform);
122 painter.drawImage(dstRect, m_Desktop);
126void CFrmViewer::paintEvent(QPaintEvent *event)
134int CFrmViewer::TranslationMousePoint(QPointF inPos, QPointF &outPos)
138 switch (m_AdaptWindows) {
139 case ADAPT_WINDOWS::Auto:
149 outPos.setX(m_DesktopSize.width() * inPos.x() / width());
150 outPos.setY(m_DesktopSize.height() * inPos.y() / height());
154 QRectF r = GetAspectRationRect();
155 if(inPos.x() < r.left()
156 || inPos.x() > r.right()
157 || inPos.y() < r.top()
158 || inPos.y() > r.bottom())
160 outPos.setX(m_DesktopSize.width() * (inPos.x() - r.left()) / r.width());
161 outPos.setY(m_DesktopSize.height() * (inPos.y() - r.top()) / r.height());
171void CFrmViewer::mousePressEvent(QMouseEvent *event)
174#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
180 if(TranslationMousePoint(pos, pos))
return;
184 emit sigMousePressEvent(event, QPoint(pos.x(), pos.y()));
188void CFrmViewer::mouseReleaseEvent(QMouseEvent *event)
191#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
196 if(TranslationMousePoint(pos, pos))
return;
200 emit sigMouseReleaseEvent(event, QPoint(pos.x(), pos.y()));
204void CFrmViewer::mouseMoveEvent(QMouseEvent *event)
207#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
212 if(TranslationMousePoint(pos, pos))
return;
216 emit sigMouseMoveEvent(event, QPoint(pos.x(), pos.y()));
217 emit sigMouseMoveEvent(event);
221void CFrmViewer::wheelEvent(QWheelEvent *event)
224#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
229 if(TranslationMousePoint(pos, pos))
return;
231 emit sigWheelEvent(event, QPoint(pos.x(), pos.y()));
235void CFrmViewer::keyPressEvent(QKeyEvent *event)
238 emit sigKeyPressEvent(event);
242void CFrmViewer::keyReleaseEvent(QKeyEvent *event)
245 emit sigKeyReleaseEvent(event);
249void CFrmViewer::slotSystemCombination()
252 emit sigKeyPressEvent(
new QKeyEvent(QKeyEvent::KeyPress, Qt::Key_Control, Qt::NoModifier));
253 emit sigKeyPressEvent(
new QKeyEvent(QKeyEvent::KeyPress, Qt::Key_Alt, Qt::NoModifier));
254 emit sigKeyPressEvent(
new QKeyEvent(QKeyEvent::KeyPress, Qt::Key_Delete, Qt::NoModifier));
255 emit sigKeyPressEvent(
new QKeyEvent(QKeyEvent::KeyPress, Qt::Key_Control, Qt::NoModifier));
256 emit sigKeyPressEvent(
new QKeyEvent(QKeyEvent::KeyPress, Qt::Key_Alt, Qt::NoModifier));
257 emit sigKeyPressEvent(
new QKeyEvent(QKeyEvent::KeyPress, Qt::Key_Delete, Qt::NoModifier));
260QSize CFrmViewer::GetDesktopSize()
262 return m_DesktopSize;
267 return m_dbZoomFactor;
270int CFrmViewer::slotSetZoomFactor(
double newZoomFactor)
272 if(newZoomFactor < 0)
return -1;
273 if (qFuzzyCompare(m_dbZoomFactor, newZoomFactor))
275 m_dbZoomFactor = newZoomFactor;
279int CFrmViewer::ReSize(
int width,
int height)
287void CFrmViewer::slotSetAdaptWindows(ADAPT_WINDOWS aw)
290 if(!m_Desktop.isNull())
292 switch (m_AdaptWindows) {
295 slotSetZoomFactor(1);
297 ReSize(m_DesktopSize.width(), m_DesktopSize.height());
309 return m_AdaptWindows;
314 m_DesktopSize = QSize(width, height);
315 m_Desktop = QImage(width, height, QImage::Format_RGB32);
320 ReSize(width, height);
325void CFrmViewer::slotConnected()
332 this->setWindowTitle(szName);
333 emit sigServerName(szName);
342 emit sigRecordVideo(m_Desktop);
351 if(r.width() != image.rect().width() || r.height() != image.rect().height())
353 qWarning(log) <<
"Image is error";
357 if(m_Desktop.isNull() || m_Desktop.rect() == r)
364 QPainter painter(&m_Desktop);
365 painter.drawImage(r, image);
370 emit sigRecordVideo(m_Desktop);
382 cursor().setPos(pos);
385#if ! (defined(Q_OS_WIN) || defined(Q_OS_APPLE) || defined(Q_OS_ANDROID) || defined(__APPLE__))
386unsigned int getModifierMask(
unsigned int keysym)
389 unsigned int mask, keycode;
393 Display *dpy = XOpenDisplay(0);
394 xkb = XkbGetMap(dpy, XkbAllComponentsMask, XkbUseCoreKbd);
398 for (keycode = xkb->min_key_code; keycode <= xkb->max_key_code; keycode++) {
399 unsigned int state_out;
402 XkbTranslateKeyCode(xkb, keycode, 0, &state_out, &ks);
411 if (keycode > xkb->max_key_code)
414 act = XkbKeyAction(xkb, keycode, 0);
417 if (act->type != XkbSA_LockMods)
420 if (act->mods.flags & XkbSA_UseModMapMods)
421 mask = xkb->map->modmap[keycode];
423 mask = act->mods.mask;
426 XkbFreeKeyboard(xkb, XkbAllComponentsMask, True);
432void CFrmViewer::slotUpdateLedState(
unsigned int state)
434 qDebug(log,
"Got server LED state: 0x%08x", state);
446 memset(input, 0,
sizeof(input));
449 if (!!(state & CapsLock) != !!(GetKeyState(VK_CAPITAL) & 0x1)) {
450 input[count].type = input[count+1].type = INPUT_KEYBOARD;
451 input[count].ki.wVk = input[count+1].ki.wVk = VK_CAPITAL;
453 input[count].ki.dwFlags = 0;
454 input[count+1].ki.dwFlags = KEYEVENTF_KEYUP;
458 if (!!(state & NumLock) != !!(GetKeyState(VK_NUMLOCK) & 0x1)) {
459 input[count].type = input[count+1].type = INPUT_KEYBOARD;
460 input[count].ki.wVk = input[count+1].ki.wVk = VK_NUMLOCK;
462 input[count].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
463 input[count+1].ki.dwFlags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY;
467 if (!!(state & ScrollLock) != !!(GetKeyState(VK_SCROLL) & 0x1)) {
468 input[count].type = input[count+1].type = INPUT_KEYBOARD;
469 input[count].ki.wVk = input[count+1].ki.wVk = VK_SCROLL;
471 input[count].ki.dwFlags = 0;
472 input[count+1].ki.dwFlags = KEYEVENTF_KEYUP;
479 ret = SendInput(count, input,
sizeof(*input));
481 qCritical(log) <<
"Failed to update keyboard LED state:" << GetLastError();
482#elif defined(Q_OS_APPLE)
487#elif defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && !defined(Q_OS_APPLE)
488 unsigned int affect, values;
496 if (state & CapsLock)
499 mask = getModifierMask(XK_Num_Lock);
504 mask = getModifierMask(XK_Scroll_Lock);
506 if (state & ScrollLock)
508 Display *dpy = XOpenDisplay(0);
509 ret = XkbLockModifiers(dpy, XkbUseCoreKbd, affect, values);
511 qCritical(log) << tr(
"Failed to update keyboard LED state");
517QImage CFrmViewer::GrabImage(
int x,
int y,
int w,
int h)
519 int width = w, height = h;
521 width = m_DesktopSize.width();
523 height = m_DesktopSize.height();
524 return m_Desktop.copy(x, y, width, height);
527void CFrmViewer::slotRecordVideo(
bool bRecord)
529 m_bRecordVideo = bRecord;
A widget which displays output image from a CConnectDesktop and sends input keypresses and mouse acti...
void slotSetDesktopSize(int width, int height)
Update desktop size.
ADAPT_WINDOWS
The ADAPT_WINDOWS enum.
@ Original
Original desktop size, the left-top of the desktop is aligned with the left-top of the window.
@ Zoom
zoom windows = desktop size * factor
@ KeepAspectRationToWindow
Keep desktop aspectration adapt to windows.
@ OriginalCenter
Original desktop size, the center of the desktop is aligned with the center of the window.
@ ZoomToWindow
Desktop adapt to windows.
@ Disable
Disable adapt windows.
void slotUpdateCursor(const QCursor &cursor)
Update cursor.
void slotUpdateRect(const QRect &r, const QImage &image)
Update image.
void slotSetName(const QString &szName)
Update desktop name.
void slotUpdateCursorPosition(const QPoint &pos)
Update cursor position.
double GetZoomFactor() const
Adjust the zoom factor.