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(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);
254void CFrmViewer::slotSystemCombination()
257 emit sigKeyPressEvent(
new QKeyEvent(QKeyEvent::KeyPress, Qt::Key_Control, Qt::NoModifier));
258 emit sigKeyPressEvent(
new QKeyEvent(QKeyEvent::KeyPress, Qt::Key_Alt, Qt::NoModifier));
259 emit sigKeyPressEvent(
new QKeyEvent(QKeyEvent::KeyPress, Qt::Key_Delete, Qt::NoModifier));
260 emit sigKeyPressEvent(
new QKeyEvent(QKeyEvent::KeyPress, Qt::Key_Control, Qt::NoModifier));
261 emit sigKeyPressEvent(
new QKeyEvent(QKeyEvent::KeyPress, Qt::Key_Alt, Qt::NoModifier));
262 emit sigKeyPressEvent(
new QKeyEvent(QKeyEvent::KeyPress, Qt::Key_Delete, Qt::NoModifier));
265QSize CFrmViewer::GetDesktopSize()
267 return m_DesktopSize;
272 return m_dbZoomFactor;
275int CFrmViewer::slotSetZoomFactor(
double newZoomFactor)
277 if(newZoomFactor < 0)
return -1;
278 if (qFuzzyCompare(m_dbZoomFactor, newZoomFactor))
280 m_dbZoomFactor = newZoomFactor;
284int CFrmViewer::ReSize(
int width,
int height)
292void CFrmViewer::slotSetAdaptWindows(ADAPT_WINDOWS aw)
295 if(!m_Desktop.isNull())
297 switch (m_AdaptWindows) {
300 slotSetZoomFactor(1);
302 ReSize(m_DesktopSize.width(), m_DesktopSize.height());
314 return m_AdaptWindows;
319 m_DesktopSize = QSize(width, height);
320 m_Desktop = QImage(width, height, QImage::Format_RGB32);
325 ReSize(width, height);
330void CFrmViewer::slotConnected()
337 this->setWindowTitle(szName);
338 emit sigServerName(szName);
347 emit sigRecordVideo(m_Desktop);
356 if(r.width() != image.rect().width() || r.height() != image.rect().height())
358 qWarning(log) <<
"Image is error";
362 if(m_Desktop.isNull() || m_Desktop.rect() == r)
369 QPainter painter(&m_Desktop);
370 painter.drawImage(r, image);
375 emit sigRecordVideo(m_Desktop);
387 cursor().setPos(pos);
390#if ! (defined(Q_OS_WIN) || defined(Q_OS_APPLE) || defined(Q_OS_ANDROID) || defined(__APPLE__))
391unsigned int getModifierMask(
unsigned int keysym)
394 unsigned int mask, keycode;
398 Display *dpy = XOpenDisplay(0);
399 xkb = XkbGetMap(dpy, XkbAllComponentsMask, XkbUseCoreKbd);
403 for (keycode = xkb->min_key_code; keycode <= xkb->max_key_code; keycode++) {
404 unsigned int state_out;
407 XkbTranslateKeyCode(xkb, keycode, 0, &state_out, &ks);
416 if (keycode > xkb->max_key_code)
419 act = XkbKeyAction(xkb, keycode, 0);
422 if (act->type != XkbSA_LockMods)
425 if (act->mods.flags & XkbSA_UseModMapMods)
426 mask = xkb->map->modmap[keycode];
428 mask = act->mods.mask;
431 XkbFreeKeyboard(xkb, XkbAllComponentsMask, True);
437void CFrmViewer::slotUpdateLedState(
unsigned int state)
439 qDebug(log,
"Got server LED state: 0x%08x", state);
451 memset(input, 0,
sizeof(input));
454 if (!!(state & CapsLock) != !!(GetKeyState(VK_CAPITAL) & 0x1)) {
455 input[count].type = input[count+1].type = INPUT_KEYBOARD;
456 input[count].ki.wVk = input[count+1].ki.wVk = VK_CAPITAL;
458 input[count].ki.dwFlags = 0;
459 input[count+1].ki.dwFlags = KEYEVENTF_KEYUP;
463 if (!!(state & NumLock) != !!(GetKeyState(VK_NUMLOCK) & 0x1)) {
464 input[count].type = input[count+1].type = INPUT_KEYBOARD;
465 input[count].ki.wVk = input[count+1].ki.wVk = VK_NUMLOCK;
467 input[count].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
468 input[count+1].ki.dwFlags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY;
472 if (!!(state & ScrollLock) != !!(GetKeyState(VK_SCROLL) & 0x1)) {
473 input[count].type = input[count+1].type = INPUT_KEYBOARD;
474 input[count].ki.wVk = input[count+1].ki.wVk = VK_SCROLL;
476 input[count].ki.dwFlags = 0;
477 input[count+1].ki.dwFlags = KEYEVENTF_KEYUP;
484 ret = SendInput(count, input,
sizeof(*input));
486 qCritical(log) <<
"Failed to update keyboard LED state:" << GetLastError();
487#elif defined(Q_OS_APPLE)
492#elif defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && !defined(Q_OS_APPLE)
493 unsigned int affect, values;
501 if (state & CapsLock)
504 mask = getModifierMask(XK_Num_Lock);
509 mask = getModifierMask(XK_Scroll_Lock);
511 if (state & ScrollLock)
513 Display *dpy = XOpenDisplay(0);
514 ret = XkbLockModifiers(dpy, XkbUseCoreKbd, affect, values);
516 qCritical(log) << tr(
"Failed to update keyboard LED state");
522QImage CFrmViewer::GrabImage(
int x,
int y,
int w,
int h)
524 int width = w, height = h;
526 width = m_DesktopSize.width();
528 height = m_DesktopSize.height();
529 return m_Desktop.copy(x, y, width, height);
532void CFrmViewer::slotRecordVideo(
bool bRecord)
534 m_bRecordVideo = bRecord;
用于显示从 CConnectDesktop 输出的图像,和向 CConnectDesktop 发送键盘、鼠标事件。
void slotSetDesktopSize(int width, int height)
Update desktop size
@ Original
原始桌面大小,桌面的左上点与窗口的左上点对齐
@ KeepAspectRationToWindow
保持长宽比缩放到窗口大小,窗口是固定的
@ OriginalCenter
原始桌面大小,桌面中心点与窗口中心点对齐
@ ZoomToWindow
桌面缩放到窗口大小,窗口是固定的
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
调整缩放系数。 调整完成后需要调用 SetAdaptWindows(FrmViewer::Zoom) 缩放窗口大小。