9#include <QLoggingCategory>
13#elif ! (defined(Q_OS_ANDROID) || defined(Q_OS_WIN) || defined(Q_OS_APPLE) || defined(Q_OS_MACOS))
15 #include <X11/XKBlib.h>
17 #include <X11/keysymdef.h>
22static Q_LOGGING_CATEGORY(log,
"Client.FrmViewer")
23static Q_LOGGING_CATEGORY(logKey, "Client.FrmViewer.Key")
24static Q_LOGGING_CATEGORY(logMouse, "Client.FrmViewer.Mouse")
28 , m_bRecordVideo(false)
30 qDebug(log) << Q_FUNC_INFO;
31 setAttribute(Qt::WA_DeleteOnClose);
37 slotSetAdaptWindows(ADAPT_WINDOWS::ZoomToWindow);
40 setMouseTracking(
true);
41 setFocusPolicy(Qt::WheelFocus);
50CFrmViewer::~CFrmViewer()
52 qDebug(log) << Q_FUNC_INFO;
55QRectF CFrmViewer::GetAspectRationRect()
57 QRectF dstRect = rect();
58 qreal newW = dstRect.width();
59 qreal newH = dstRect.height();
63 qreal rateW =
static_cast<qreal
>(rect().width())
64 /
static_cast<qreal
>(m_DesktopSize.width());
65 qreal rateH =
static_cast<qreal
>(rect().height())
66 /
static_cast<qreal
>(m_DesktopSize.height());
69 newW = m_DesktopSize.width() * rateW;
70 newH = m_DesktopSize.height() * rateW;
71 newT = (
static_cast<qreal
>(rect().height()) - newH)
72 /
static_cast<qreal
>(2);
73 }
else if(rateW > rateH) {
74 newW = m_DesktopSize.width() * rateH;
75 newH = m_DesktopSize.height() * rateH;
76 newL = (
static_cast<qreal
>(rect().width()) - newW)
77 /
static_cast<qreal
>(2);
79 dstRect = QRectF(newL, newT, newW, newH);
83void CFrmViewer::paintDesktop()
85 QRectF dstRect = rect();
87 switch (m_AdaptWindows) {
89 case ADAPT_WINDOWS::Auto:
94 dstRect.setLeft((rect().width() - m_DesktopSize.width()) >> 1);
95 dstRect.setTop((rect().height() - m_DesktopSize.height()) >> 1);
96 dstRect.setWidth(m_DesktopSize.width());
97 dstRect.setHeight(m_DesktopSize.height());
101 dstRect = GetAspectRationRect();
108 if(m_Desktop.isNull())
return;
110 QPainter painter(
this);
114#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
115 painter.fillRect(rect(), QBrush(palette().color(QPalette::Window)));
117 painter.fillRect(rect(), QBrush(palette().color(QPalette::Background)));
122 painter.setRenderHint(QPainter::SmoothPixmapTransform);
123 painter.drawImage(dstRect, m_Desktop);
127void CFrmViewer::paintEvent(QPaintEvent *event)
135int CFrmViewer::TranslationMousePoint(QPointF inPos, QPointF &outPos)
137 qDebug(logMouse) <<
"TranslationPoint x:" << inPos.x() <<
";y:" << inPos.y();
139 switch (m_AdaptWindows) {
140 case ADAPT_WINDOWS::Auto:
150 outPos.setX(m_DesktopSize.width() * inPos.x() / width());
151 outPos.setY(m_DesktopSize.height() * inPos.y() / height());
155 QRectF r = GetAspectRationRect();
156 if(inPos.x() < r.left()
157 || inPos.x() > r.right()
158 || inPos.y() < r.top()
159 || inPos.y() > r.bottom())
161 outPos.setX(m_DesktopSize.width() * (inPos.x() - r.left()) / r.width());
162 outPos.setY(m_DesktopSize.height() * (inPos.y() - r.top()) / r.height());
172void CFrmViewer::mousePressEvent(QMouseEvent *event)
175#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
181 if(TranslationMousePoint(pos, pos))
return;
184 qDebug(logMouse) <<
"CFrmViewer::mousePressEvent"
185 <<
event <<
event->button() <<
event->buttons() << pos;
186 emit sigMousePressEvent(event, QPoint(pos.x(), pos.y()));
190void CFrmViewer::mouseReleaseEvent(QMouseEvent *event)
193#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
198 if(TranslationMousePoint(pos, pos))
return;
201 qDebug(logMouse) <<
"CFrmViewer::mouseReleaseEvent"
202 <<
event <<
event->button() <<
event->buttons() << pos;
203 emit sigMouseReleaseEvent(event, QPoint(pos.x(), pos.y()));
207void CFrmViewer::mouseMoveEvent(QMouseEvent *event)
210#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
215 if(TranslationMousePoint(pos, pos))
return;
218 qDebug(logMouse) <<
"CFrmViewer::mouseMoveEvent"
219 <<
event->button() <<
event->buttons() << pos;
220 emit sigMouseMoveEvent(event, QPoint(pos.x(), pos.y()));
221 emit sigMouseMoveEvent(event);
225void CFrmViewer::wheelEvent(QWheelEvent *event)
228#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
233 if(TranslationMousePoint(pos, pos))
return;
234 qDebug(logMouse) <<
"CFrmViewer::wheelEvent"
235 <<
event->buttons() <<
event->angleDelta() << pos;
236 emit sigWheelEvent(event, QPoint(pos.x(), pos.y()));
240void CFrmViewer::keyPressEvent(QKeyEvent *event)
242 qDebug(logKey) <<
"CFrmViewer::keyPressEvent" << event;
243 emit sigKeyPressEvent(event);
247void CFrmViewer::keyReleaseEvent(QKeyEvent *event)
249 qDebug(logKey) <<
"CFrmViewer::keyReleaseEvent" << event;
250 emit sigKeyReleaseEvent(event);
254QSize CFrmViewer::GetDesktopSize()
256 return m_DesktopSize;
261 return m_dbZoomFactor;
264int CFrmViewer::slotSetZoomFactor(
double newZoomFactor)
266 if(newZoomFactor < 0)
return -1;
267 if (qFuzzyCompare(m_dbZoomFactor, newZoomFactor))
269 m_dbZoomFactor = newZoomFactor;
273int CFrmViewer::ReSize(
int width,
int height)
281void CFrmViewer::slotSetAdaptWindows(ADAPT_WINDOWS aw)
284 if(!m_Desktop.isNull())
286 switch (m_AdaptWindows) {
289 slotSetZoomFactor(1);
291 ReSize(m_DesktopSize.width(), m_DesktopSize.height());
303 return m_AdaptWindows;
308 m_DesktopSize = QSize(width, height);
309 m_Desktop = QImage(width, height, QImage::Format_RGB32);
314 ReSize(width, height);
319void CFrmViewer::slotConnected()
326 this->setWindowTitle(szName);
327 emit sigServerName(szName);
336 emit sigRecordVideo(m_Desktop);
345 if(r.width() != image.rect().width() || r.height() != image.rect().height())
347 qWarning(log) <<
"Image is error";
351 if(m_Desktop.isNull() || m_Desktop.rect() == r)
358 QPainter painter(&m_Desktop);
359 painter.drawImage(r, image);
364 emit sigRecordVideo(m_Desktop);
376 cursor().setPos(pos);
379#if ! (defined(Q_OS_WIN) || defined(Q_OS_APPLE) || defined(Q_OS_ANDROID) || defined(Q_OS_APPLE) || defined(Q_OS_MACOS))
380unsigned int getModifierMask(
unsigned int keysym)
383 unsigned int mask, keycode;
387 Display *dpy = XOpenDisplay(0);
388 xkb = XkbGetMap(dpy, XkbAllComponentsMask, XkbUseCoreKbd);
392 for (keycode = xkb->min_key_code; keycode <= xkb->max_key_code; keycode++) {
393 unsigned int state_out;
396 XkbTranslateKeyCode(xkb, keycode, 0, &state_out, &ks);
405 if (keycode > xkb->max_key_code)
408 act = XkbKeyAction(xkb, keycode, 0);
411 if (act->type != XkbSA_LockMods)
414 if (act->mods.flags & XkbSA_UseModMapMods)
415 mask = xkb->map->modmap[keycode];
417 mask = act->mods.mask;
420 XkbFreeKeyboard(xkb, XkbAllComponentsMask, True);
426void CFrmViewer::slotUpdateLedState(
unsigned int state)
428 qDebug(log,
"Got server LED state: 0x%08x", state);
440 memset(input, 0,
sizeof(input));
443 if (!!(state & CapsLock) != !!(GetKeyState(VK_CAPITAL) & 0x1)) {
444 input[count].type = input[count+1].type = INPUT_KEYBOARD;
445 input[count].ki.wVk = input[count+1].ki.wVk = VK_CAPITAL;
447 input[count].ki.dwFlags = 0;
448 input[count+1].ki.dwFlags = KEYEVENTF_KEYUP;
452 if (!!(state & NumLock) != !!(GetKeyState(VK_NUMLOCK) & 0x1)) {
453 input[count].type = input[count+1].type = INPUT_KEYBOARD;
454 input[count].ki.wVk = input[count+1].ki.wVk = VK_NUMLOCK;
456 input[count].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
457 input[count+1].ki.dwFlags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY;
461 if (!!(state & ScrollLock) != !!(GetKeyState(VK_SCROLL) & 0x1)) {
462 input[count].type = input[count+1].type = INPUT_KEYBOARD;
463 input[count].ki.wVk = input[count+1].ki.wVk = VK_SCROLL;
465 input[count].ki.dwFlags = 0;
466 input[count+1].ki.dwFlags = KEYEVENTF_KEYUP;
473 ret = SendInput(count, input,
sizeof(*input));
475 qCritical(log) <<
"Failed to update keyboard LED state:" << GetLastError();
476#elif defined(Q_OS_APPLE)
481#elif defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && !defined(Q_OS_APPLE)
482 unsigned int affect, values;
490 if (state & CapsLock)
493 mask = getModifierMask(XK_Num_Lock);
498 mask = getModifierMask(XK_Scroll_Lock);
500 if (state & ScrollLock)
502 Display *dpy = XOpenDisplay(0);
503 ret = XkbLockModifiers(dpy, XkbUseCoreKbd, affect, values);
505 qCritical(log) << tr(
"Failed to update keyboard LED state");
511QImage CFrmViewer::GrabImage(
int x,
int y,
int w,
int h)
513 int width = w, height = h;
515 width = m_DesktopSize.width();
517 height = m_DesktopSize.height();
518 return m_Desktop.copy(x, y, width, height);
521void CFrmViewer::slotRecordVideo(
bool bRecord)
523 m_bRecordVideo = bRecord;
526void CFrmViewer::focusInEvent(QFocusEvent *event)
528 qDebug(log) << Q_FUNC_INFO <<
event <<
this;
532void CFrmViewer::focusOutEvent(QFocusEvent *event)
534 qDebug(log) << Q_FUNC_INFO <<
event <<
this;
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 sigViewerFocusIn(QWidget *pView)
The view is focus.
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.