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);
49 bool check = connect(&m_TimerRecordVideo, SIGNAL(timeout()),
50 this, SLOT(slotRecordVideo()));
54CFrmViewer::~CFrmViewer()
56 qDebug(log) << Q_FUNC_INFO;
59QRectF CFrmViewer::GetAspectRationRect()
61 QRectF dstRect = rect();
62 qreal newW = dstRect.width();
63 qreal newH = dstRect.height();
67 qreal rateW =
static_cast<qreal
>(rect().width())
68 /
static_cast<qreal
>(m_DesktopSize.width());
69 qreal rateH =
static_cast<qreal
>(rect().height())
70 /
static_cast<qreal
>(m_DesktopSize.height());
73 newW = m_DesktopSize.width() * rateW;
74 newH = m_DesktopSize.height() * rateW;
75 newT = (
static_cast<qreal
>(rect().height()) - newH)
76 /
static_cast<qreal
>(2);
77 }
else if(rateW > rateH) {
78 newW = m_DesktopSize.width() * rateH;
79 newH = m_DesktopSize.height() * rateH;
80 newL = (
static_cast<qreal
>(rect().width()) - newW)
81 /
static_cast<qreal
>(2);
83 dstRect = QRectF(newL, newT, newW, newH);
87void CFrmViewer::paintDesktop()
89 QRectF dstRect = rect();
91 switch (m_AdaptWindows) {
93 case ADAPT_WINDOWS::Auto:
98 dstRect.setLeft((rect().width() - m_DesktopSize.width()) >> 1);
99 dstRect.setTop((rect().height() - m_DesktopSize.height()) >> 1);
100 dstRect.setWidth(m_DesktopSize.width());
101 dstRect.setHeight(m_DesktopSize.height());
105 dstRect = GetAspectRationRect();
112 if(m_Desktop.isNull())
return;
114 QPainter painter(
this);
118#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
119 painter.fillRect(rect(), QBrush(palette().color(QPalette::Window)));
121 painter.fillRect(rect(), QBrush(palette().color(QPalette::Background)));
126 painter.setRenderHint(QPainter::SmoothPixmapTransform);
127 painter.drawImage(dstRect, m_Desktop);
131void CFrmViewer::paintEvent(QPaintEvent *event)
139int CFrmViewer::TranslationMousePoint(QPointF inPos, QPointF &outPos)
141 qDebug(logMouse) <<
"TranslationPoint x:" << inPos.x() <<
";y:" << inPos.y();
143 switch (m_AdaptWindows) {
144 case ADAPT_WINDOWS::Auto:
154 outPos.setX(m_DesktopSize.width() * inPos.x() / width());
155 outPos.setY(m_DesktopSize.height() * inPos.y() / height());
159 QRectF r = GetAspectRationRect();
160 if(inPos.x() < r.left()
161 || inPos.x() > r.right()
162 || inPos.y() < r.top()
163 || inPos.y() > r.bottom())
165 outPos.setX(m_DesktopSize.width() * (inPos.x() - r.left()) / r.width());
166 outPos.setY(m_DesktopSize.height() * (inPos.y() - r.top()) / r.height());
176void CFrmViewer::mousePressEvent(QMouseEvent *event)
179#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
185 if(TranslationMousePoint(pos, pos))
return;
188 qDebug(logMouse) <<
"CFrmViewer::mousePressEvent"
189 <<
event <<
event->button() <<
event->buttons() << pos;
190 emit sigMousePressEvent(event, QPoint(pos.x(), pos.y()));
194void CFrmViewer::mouseReleaseEvent(QMouseEvent *event)
197#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
202 if(TranslationMousePoint(pos, pos))
return;
205 qDebug(logMouse) <<
"CFrmViewer::mouseReleaseEvent"
206 <<
event <<
event->button() <<
event->buttons() << pos;
207 emit sigMouseReleaseEvent(event, QPoint(pos.x(), pos.y()));
211void CFrmViewer::mouseMoveEvent(QMouseEvent *event)
214#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
219 if(TranslationMousePoint(pos, pos))
return;
222 qDebug(logMouse) <<
"CFrmViewer::mouseMoveEvent"
223 <<
event->button() <<
event->buttons() << pos;
224 emit sigMouseMoveEvent(event, QPoint(pos.x(), pos.y()));
225 emit sigMouseMoveEvent(event);
229void CFrmViewer::wheelEvent(QWheelEvent *event)
232#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
237 if(TranslationMousePoint(pos, pos))
return;
238 qDebug(logMouse) <<
"CFrmViewer::wheelEvent"
239 <<
event->buttons() <<
event->angleDelta() << pos;
240 emit sigWheelEvent(event, QPoint(pos.x(), pos.y()));
244void CFrmViewer::keyPressEvent(QKeyEvent *event)
246 qDebug(logKey) <<
"CFrmViewer::keyPressEvent" << event;
247 emit sigKeyPressEvent(event);
251void CFrmViewer::keyReleaseEvent(QKeyEvent *event)
253 qDebug(logKey) <<
"CFrmViewer::keyReleaseEvent" << event;
254 emit sigKeyReleaseEvent(event);
258QSize CFrmViewer::GetDesktopSize()
260 return m_DesktopSize;
265 return m_dbZoomFactor;
268int CFrmViewer::slotSetZoomFactor(
double newZoomFactor)
270 if(newZoomFactor < 0)
return -1;
271 if (qFuzzyCompare(m_dbZoomFactor, newZoomFactor))
273 m_dbZoomFactor = newZoomFactor;
277int CFrmViewer::ReSize(
int width,
int height)
285void CFrmViewer::slotSetAdaptWindows(ADAPT_WINDOWS aw)
288 if(!m_Desktop.isNull())
290 switch (m_AdaptWindows) {
293 slotSetZoomFactor(1);
295 ReSize(m_DesktopSize.width(), m_DesktopSize.height());
307 return m_AdaptWindows;
312 m_DesktopSize = QSize(width, height);
313 m_Desktop = QImage(width, height, QImage::Format_RGB32);
318 ReSize(width, height);
330 this->setWindowTitle(szName);
331 emit sigServerName(szName);
340 emit sigRecordVideo(m_Desktop);
349 if(r.width() != image.rect().width() || r.height() != image.rect().height())
351 qWarning(log) <<
"Image is error";
355 if(m_Desktop.isNull() || m_Desktop.rect() == r)
360 QPainter painter(&m_Desktop);
361 painter.drawImage(r, image);
366 emit sigRecordVideo(m_Desktop);
378 cursor().setPos(pos);
381#if ! (defined(Q_OS_WIN) || defined(Q_OS_APPLE) || defined(Q_OS_ANDROID) || defined(Q_OS_APPLE) || defined(Q_OS_MACOS))
382unsigned int getModifierMask(
unsigned int keysym)
385 unsigned int mask, keycode;
389 Display *dpy = XOpenDisplay(0);
390 xkb = XkbGetMap(dpy, XkbAllComponentsMask, XkbUseCoreKbd);
394 for (keycode = xkb->min_key_code; keycode <= xkb->max_key_code; keycode++) {
395 unsigned int state_out;
398 XkbTranslateKeyCode(xkb, keycode, 0, &state_out, &ks);
407 if (keycode > xkb->max_key_code)
410 act = XkbKeyAction(xkb, keycode, 0);
413 if (act->type != XkbSA_LockMods)
416 if (act->mods.flags & XkbSA_UseModMapMods)
417 mask = xkb->map->modmap[keycode];
419 mask = act->mods.mask;
422 XkbFreeKeyboard(xkb, XkbAllComponentsMask, True);
428void CFrmViewer::slotUpdateLedState(
unsigned int state)
430 qDebug(log,
"Got server LED state: 0x%08x", state);
442 memset(input, 0,
sizeof(input));
445 if (!!(state & CapsLock) != !!(GetKeyState(VK_CAPITAL) & 0x1)) {
446 input[count].type = input[count+1].type = INPUT_KEYBOARD;
447 input[count].ki.wVk = input[count+1].ki.wVk = VK_CAPITAL;
449 input[count].ki.dwFlags = 0;
450 input[count+1].ki.dwFlags = KEYEVENTF_KEYUP;
454 if (!!(state & NumLock) != !!(GetKeyState(VK_NUMLOCK) & 0x1)) {
455 input[count].type = input[count+1].type = INPUT_KEYBOARD;
456 input[count].ki.wVk = input[count+1].ki.wVk = VK_NUMLOCK;
458 input[count].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
459 input[count+1].ki.dwFlags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY;
463 if (!!(state & ScrollLock) != !!(GetKeyState(VK_SCROLL) & 0x1)) {
464 input[count].type = input[count+1].type = INPUT_KEYBOARD;
465 input[count].ki.wVk = input[count+1].ki.wVk = VK_SCROLL;
467 input[count].ki.dwFlags = 0;
468 input[count+1].ki.dwFlags = KEYEVENTF_KEYUP;
475 ret = SendInput(count, input,
sizeof(*input));
477 qCritical(log) <<
"Failed to update keyboard LED state:" << GetLastError();
478#elif defined(Q_OS_APPLE)
483#elif defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && !defined(Q_OS_APPLE)
484 unsigned int affect, values;
492 if (state & CapsLock)
495 mask = getModifierMask(XK_Num_Lock);
500 mask = getModifierMask(XK_Scroll_Lock);
502 if (state & ScrollLock)
504 Display *dpy = XOpenDisplay(0);
505 ret = XkbLockModifiers(dpy, XkbUseCoreKbd, affect, values);
507 qCritical(log) << tr(
"Failed to update keyboard LED state");
513QImage CFrmViewer::GrabImage(
int x,
int y,
int w,
int h)
515 int width = w, height = h;
517 width = m_DesktopSize.width();
519 height = m_DesktopSize.height();
520 return m_Desktop.copy(x, y, width, height);
523void CFrmViewer::slotRecordVideo(
bool bRecord, qreal nRate)
525 m_bRecordVideo = bRecord;
530 m_bRecordVideo =
false;
532 m_TimerRecordVideo.start(1000 / nRate);
534 m_TimerRecordVideo.stop();
537void CFrmViewer::slotRecordVideo()
539 emit sigRecordVideo(m_Desktop);
542void CFrmViewer::focusInEvent(QFocusEvent *event)
544 qDebug(log) << Q_FUNC_INFO <<
event <<
this;
548void CFrmViewer::focusOutEvent(QFocusEvent *event)
550 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 slotConnected()
Enable mouse and keyboard.
void slotSetName(const QString &szName)
Update desktop name.
void slotUpdateCursorPosition(const QPoint &pos)
Update cursor position.
double GetZoomFactor() const
Adjust the zoom factor.