Rabbit Remote Control 0.1.0-bate16
Loading...
Searching...
No Matches
FrmViewer.cpp
1// Author: Kang Lin <kl222@126.com>
2
3#include "FrmViewer.h"
4
5#include <QPainter>
6#include <QKeyEvent>
7#include <QTouchEvent>
8
9#include <QResizeEvent>
10#include <QGestureRecognizer>
11#include <QGestureEvent>
12#include <QPanGesture>
13#include <QPinchGesture>
14#include <QCursor>
15#include <QLoggingCategory>
16
17#if defined(Q_OS_WIN)
18 #include <Windows.h>
19#elif ! (defined(Q_OS_ANDROID) || defined(Q_OS_WIN) || defined(Q_OS_APPLE) || defined(Q_OS_MACOS))
20 #include <X11/Xlib.h>
21 #include <X11/XKBlib.h>
22 #define XK_MISCELLANY
23 #include <X11/keysymdef.h>
24#endif
25
26#undef KeyPress
27
28static Q_LOGGING_CATEGORY(log, "Client.FrmViewer")
29static Q_LOGGING_CATEGORY(logKey, "Client.FrmViewer.Key")
30static Q_LOGGING_CATEGORY(logMouse, "Client.FrmViewer.Mouse")
31static Q_LOGGING_CATEGORY(logInputMethod, "Client.FrmViewer.InputMethod")
32static Q_LOGGING_CATEGORY(logTouch, "Client.FrmViewer.Touch")
33
34CFrmViewer::CFrmViewer(QWidget *parent)
35 : QWidget(parent)
36 , m_bRecordVideo(false)
37{
38 qDebug(log) << Q_FUNC_INFO;
39 setAttribute(Qt::WA_DeleteOnClose);
40 setAttribute(Qt::WA_AcceptTouchEvents);
41
42 //qDebug(log) << "autoFillBackground:" << autoFillBackground();
43 //setAutoFillBackground(true);
44 //setAttribute(Qt::WA_OpaquePaintEvent);
45 //setAttribute(Qt::WA_NoSystemBackground);
46
47 slotSetAdaptWindows(ADAPT_WINDOWS::ZoomToWindow);
48 slotSetZoomFactor(1);
49
50 setMouseTracking(true);
51 setFocusPolicy(Qt::WheelFocus);
52 setFocus();
53
54 // When the operate is not run, don't accept keyboard and mouse event
55 // When the COperate::sigRunning() set true. accept keyboard and mouse event
56 // \see COperate::sigRunning()
57 setEnabled(false);
58
59 bool check = connect(&m_TimerRecordVideo, SIGNAL(timeout()),
60 this, SLOT(slotRecordVideo()));
61 Q_ASSERT(check);
62}
63
64CFrmViewer::~CFrmViewer()
65{
66 qDebug(log) << Q_FUNC_INFO;
67}
68
69QRectF CFrmViewer::GetAspectRationRect()
70{
71 QRectF dstRect = rect();
72 qreal newW = dstRect.width();
73 qreal newH = dstRect.height();
74 qreal newT = 0;
75 qreal newL = 0;
76
77 qreal rateW = static_cast<qreal>(rect().width())
78 / static_cast<qreal>(m_DesktopSize.width());
79 qreal rateH = static_cast<qreal>(rect().height())
80 / static_cast<qreal>(m_DesktopSize.height());
81 if(rateW < rateH)
82 {
83 newW = m_DesktopSize.width() * rateW;
84 newH = m_DesktopSize.height() * rateW;
85 newT = (static_cast<qreal>(rect().height()) - newH)
86 / static_cast<qreal>(2);
87 } else if(rateW > rateH) {
88 newW = m_DesktopSize.width() * rateH;
89 newH = m_DesktopSize.height() * rateH;
90 newL = (static_cast<qreal>(rect().width()) - newW)
91 / static_cast<qreal>(2);
92 }
93 dstRect = QRectF(newL, newT, newW, newH);
94 return dstRect;
95}
96
97void CFrmViewer::paintDesktop()
98{
99 QRectF dstRect = rect();
100
101 switch (m_AdaptWindows) {
103 case ADAPT_WINDOWS::Auto:
106 break;
108 dstRect.setLeft((rect().width() - m_DesktopSize.width()) >> 1);
109 dstRect.setTop((rect().height() - m_DesktopSize.height()) >> 1);
110 dstRect.setWidth(m_DesktopSize.width());
111 dstRect.setHeight(m_DesktopSize.height());
112 break;
114 {
115 dstRect = GetAspectRationRect();
116 break;
117 }
118 default:
119 break;
120 }
121
122 if(m_Desktop.isNull()) return;
123
124 QPainter painter(this);
125 // Clear background
126 if(ADAPT_WINDOWS::KeepAspectRationToWindow == m_AdaptWindows)
127 {
128#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
129 painter.fillRect(rect(), QBrush(palette().color(QPalette::Window)));
130#else
131 painter.fillRect(rect(), QBrush(palette().color(QPalette::Background)));
132#endif
133 } //*/
134
135 // 设置平滑模式
136 painter.setRenderHint(QPainter::SmoothPixmapTransform);
137 painter.drawImage(dstRect, m_Desktop);
138
139}
140
141void CFrmViewer::paintEvent(QPaintEvent *event)
142{
143 //qqDebug(log) << "CFrmViewer::paintEvent";
144 Q_UNUSED(event)
145
146 paintDesktop();
147}
148
149int CFrmViewer::PointToRemote(const QPointF &inPos, QPointF &outPos)
150{
151 //qDebug(logMouse) << "PointToRemote x:" << inPos.x() << ";y:" << inPos.y();
152
153 switch (m_AdaptWindows) {
154 case ADAPT_WINDOWS::Auto:
157 outPos = inPos;
158 break;
160 outPos.setX(inPos.x() / GetZoomFactor());
161 outPos.setY(inPos.y() / GetZoomFactor());
162 break;
164 outPos.setX(m_DesktopSize.width() * inPos.x() / width());
165 outPos.setY(m_DesktopSize.height() * inPos.y() / height());
166 break;
168 {
169 QRectF r = GetAspectRationRect();
170 if(inPos.x() < r.left()
171 || inPos.x() > r.right()
172 || inPos.y() < r.top()
173 || inPos.y() > r.bottom())
174 return -1;
175 outPos.setX(m_DesktopSize.width() * (inPos.x() - r.left()) / r.width());
176 outPos.setY(m_DesktopSize.height() * (inPos.y() - r.top()) / r.height());
177 break;
178 }
179 default:
180 qWarning(log) << "Unsupported:" << m_AdaptWindows;
181 break;
182 }
183
184 return 0;
185}
186
187int CFrmViewer::PointFromRemote(const QPointF &inPos, QPointF &outPos)
188{
189 //qDebug(logMouse) << "PointFromRemote x:" << inPos.x() << ";y:" << inPos.y();
190
191 switch (m_AdaptWindows) {
192 case ADAPT_WINDOWS::Auto:
194 outPos = inPos;
195 break;
197 outPos.setX(inPos.x() * GetZoomFactor());
198 outPos.setY(inPos.y() * GetZoomFactor());
199 break;
201 outPos.setX(width() * inPos.x() / m_DesktopSize.width());
202 outPos.setY(height() * inPos.y() / m_DesktopSize.height());
203 break;
205 {
206 QRectF r = GetAspectRationRect();
207 outPos.setX(r.width() * inPos.x() / m_DesktopSize.width() + r.left());
208 outPos.setY(r.height() * inPos.y() / m_DesktopSize.height() + r.top());
209 break;
210 }
211 default:
212 qWarning(log) << "Unsupported:" << m_AdaptWindows;
213 break;
214 }
215 return 0;
216}
217
218void CFrmViewer::mousePressEvent(QMouseEvent *event)
219{
220 QPointF pos =
221#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
222 event->position();
223#else
224 event->pos();
225#endif
226
227 if(PointToRemote(pos, pos)) return;
228 // event->buttons() 产生事件时,按键的状态
229 // event->button() 触发当前事件的按键
230 /*
231 qDebug(logMouse) << "CFrmViewer::mousePressEvent"
232 << event << event->button() << event->buttons() << pos;//*/
233 emit sigMousePressEvent(event, QPoint(pos.x(), pos.y()));
234 event->accept();
235 if(testAttribute(Qt::WA_InputMethodEnabled)
236 && event->button() == Qt::LeftButton) {
237 qDebug(logInputMethod) << Q_FUNC_INFO << "Update micro focus";
238 updateMicroFocus();
239 }
240}
241
242void CFrmViewer::mouseReleaseEvent(QMouseEvent *event)
243{
244 QPointF pos =
245#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
246 event->position();
247#else
248 event->pos();
249#endif
250 if(PointToRemote(pos, pos)) return;
251 // event->buttons() 产生事件时,按键的状态
252 // event->button() 触发当前事件的按键
253 /*
254 qDebug(logMouse) << "CFrmViewer::mouseReleaseEvent"
255 << event << event->button() << event->buttons() << pos;//*/
256 emit sigMouseReleaseEvent(event, QPoint(pos.x(), pos.y()));
257 event->accept();
258}
259
260void CFrmViewer::mouseMoveEvent(QMouseEvent *event)
261{
262 QPointF pos =
263#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
264 event->position();
265#else
266 event->pos();
267#endif
268 QPointF outPos = pos;
269 if(PointToRemote(pos, outPos)) return;
270 // event->buttons() 产生事件时,按键的状态
271 // event->button() 触发当前事件的按键
272 /*
273 qDebug(logMouse) << "CFrmViewer::mouseMoveEvent"
274 << event->button() << event->buttons()
275 << pos << "outPos:" << outPos
276 << "mapToGlobal(pos):" << mapToGlobal(pos.toPoint());//*/
277 emit sigMouseMoveEvent(event, QPoint(outPos.x(), outPos.y()));
278 emit sigMouseMoveEvent(event);
279 event->accept();
280}
281
282void CFrmViewer::wheelEvent(QWheelEvent *event)
283{
284 QPointF pos =
285#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
286 event->position();
287#else
288 event->pos();
289#endif
290 if(PointToRemote(pos, pos)) return;
291 /*
292 qDebug(logMouse) << "CFrmViewer::wheelEvent"
293 << event->buttons() << event->angleDelta() << pos;//*/
294 emit sigWheelEvent(event, QPoint(pos.x(), pos.y()));
295 event->accept();
296}
297
298void CFrmViewer::keyPressEvent(QKeyEvent *event)
299{
300 //qDebug(logKey) << "CFrmViewer::keyPressEvent" << event;
301 emit sigKeyPressEvent(event);
302 event->accept();
303}
304
305void CFrmViewer::keyReleaseEvent(QKeyEvent *event)
306{
307 //qDebug(logKey) << "CFrmViewer::keyReleaseEvent" << event;
308 emit sigKeyReleaseEvent(event);
309 event->accept();
310}
311
312void CFrmViewer::inputMethodEvent(QInputMethodEvent *event)
313{
314 /*
315 qDebug(logInputMethod)
316 << Q_FUNC_INFO << event
317 << event->preeditString() << event->commitString()
318 << event->replacementStart() << event->replacementLength();//*/
319 emit sigInputMethodEvent(event);
320 event->accept();
321 /*
322 if(event->commitString().isEmpty()) return;
323 QPoint p(cursor().pos().x() + fontMetrics().horizontalAdvance(event->commitString()), cursor().pos().y());
324 qDebug(logKey) << cursor().pos() << fontMetrics().horizontalAdvance(event->commitString());
325 slotUpdateCursorPosition(p);//*/
326}
327
328QVariant CFrmViewer::inputMethodQuery(Qt::InputMethodQuery query) const
329{
330 //qDebug(logInputMethod) << Q_FUNC_INFO << query;
331 switch ( query )
332 {
333 case Qt::ImCursorRectangle: {
334 QPoint p = mapFromGlobal(cursor().pos());
335 QRect r(p.x(), p.y() , 1, fontMetrics().height());
336 //qDebug(logInputMethod) << "Qt::ImCursorRectangle:" << r;
337 return r;
338 }
339 // case Qt::ImCursorPosition: {
340 // QPoint p = cursor().pos();
341 // qDebug(logInputMethod) << "Qt::ImCursorPosition:" << p;
342 // return p;
343 // }
344 default:
345 break;
346 }
347 QVariant r = QWidget::inputMethodQuery(query);
348 //qDebug(logInputMethod) << Q_FUNC_INFO << query << r;
349 return r;
350}
351
353{
354 //qDebug(logInputMethod) << Q_FUNC_INFO << bEnable;
355 setAttribute(Qt::WA_InputMethodEnabled, bEnable);
356}
357
358QSize CFrmViewer::GetDesktopSize()
359{
360 return m_DesktopSize;
361}
362
364{
365 return m_dbZoomFactor;
366}
367
368int CFrmViewer::slotSetZoomFactor(double newZoomFactor)
369{
370 if(newZoomFactor < 0) return -1;
371 if (qFuzzyCompare(m_dbZoomFactor, newZoomFactor))
372 return 0;
373 m_dbZoomFactor = newZoomFactor;
374 return 0;
375}
376
377int CFrmViewer::ReSize(int width, int height)
378{
379 int w = width * GetZoomFactor();
380 int h = height * GetZoomFactor();
381 resize(w, h);
382 return 0;
383}
384
385void CFrmViewer::slotSetAdaptWindows(ADAPT_WINDOWS aw)
386{
387 m_AdaptWindows = aw;
388 if(!m_Desktop.isNull())
389 {
390 switch (m_AdaptWindows) {
393 slotSetZoomFactor(1);
395 ReSize(m_DesktopSize.width(), m_DesktopSize.height());
396 break;
397 default:
398 break;
399 }
400 }
401 update();
402 //setFocus();
403}
404
405CFrmViewer::ADAPT_WINDOWS CFrmViewer::GetAdaptWindows()
406{
407 return m_AdaptWindows;
408}
409
410void CFrmViewer::slotSetDesktopSize(int width, int height)
411{
412 m_DesktopSize = QSize(width, height);
413 m_Desktop = QImage(width, height, QImage::Format_RGB32);
414
415 if(ADAPT_WINDOWS::Original == m_AdaptWindows
416 || ADAPT_WINDOWS::OriginalCenter == m_AdaptWindows
417 || ADAPT_WINDOWS::Zoom == m_AdaptWindows)
418 ReSize(width, height);
419
420 return;
421}
422
424{
425 setEnabled(true);
426}
427
428void CFrmViewer::slotSetName(const QString& szName)
429{
430 this->setWindowTitle(szName);
431 emit sigServerName(szName);
432}
433
434void CFrmViewer::slotUpdateRect(const QImage& image)
435{
436 //qDebug(log) << "void CFrmViewer::slotUpdateRect(const QImage& image)" << image;
437 m_Desktop = image;
438
439 if(m_bRecordVideo)
440 emit sigRecordVideo(m_Desktop);
441
442 update();
443 return;
444}
445
446void CFrmViewer::slotUpdateRect(const QRect& r, const QImage& image)
447{
448#if DEBUG
449 if(r.width() != image.rect().width() || r.height() != image.rect().height())
450 {
451 qWarning(log) << "Image is error";
452 }
453#endif
454 //qDebug(log) << "void CFrmViewer::slotUpdateRect(const QRect& r, const QImage& image)" << r << image;
455 if(m_Desktop.isNull() || m_Desktop.rect() == r)
456 {
457 m_Desktop = image;
458 //qDebug(log) << "Update image size is same old image size";
459 } else {
460 QPainter painter(&m_Desktop);
461 painter.drawImage(r, image);
462 //qDebug(log) << "Update image size isn't same old image size" << r << image.rect() << image;
463 }
464
465 if(m_bRecordVideo)
466 emit sigRecordVideo(m_Desktop);
467
468 update();
469}
470
471void CFrmViewer::slotUpdateCursor(const QCursor& cursor)
472{
473 //qDebug(logInputMethod) << Q_FUNC_INFO << cursor << cursor.pos();
474 setCursor(cursor);
475 if(testAttribute(Qt::WA_InputMethodEnabled)) {
476 qDebug(logInputMethod) << Q_FUNC_INFO << "Update micro focus";
477 updateMicroFocus();
478 }
479 return;
480}
481
483{
484 //qDebug(logInputMethod) << Q_FUNC_INFO << pos;
485 QPointF outPos;
486 if(PointFromRemote(pos, outPos)) return;
487 cursor().setPos(mapToGlobal(outPos.toPoint()));
488 /*
489 qDebug(logInputMethod) << "Cursor Point:" << pos << "Out:" << outPos
490 << "cursor().pos():" << cursor().pos();//*/
491 if(testAttribute(Qt::WA_InputMethodEnabled)) {
492 qDebug(logInputMethod) << Q_FUNC_INFO << "Update micro focus";
493 updateMicroFocus();
494 }
495}
496
497#if ! (defined(Q_OS_WIN) || defined(Q_OS_APPLE) || defined(Q_OS_ANDROID) || defined(Q_OS_APPLE) || defined(Q_OS_MACOS))
498unsigned int getModifierMask(unsigned int keysym)
499{
500 XkbDescPtr xkb;
501 unsigned int mask, keycode;
502 XkbAction *act;
503
504 mask = 0;
505 Display *dpy = XOpenDisplay(0);
506 xkb = XkbGetMap(dpy, XkbAllComponentsMask, XkbUseCoreKbd);
507 if (xkb == nullptr)
508 return 0;
509
510 for (keycode = xkb->min_key_code; keycode <= xkb->max_key_code; keycode++) {
511 unsigned int state_out;
512 KeySym ks;
513
514 XkbTranslateKeyCode(xkb, keycode, 0, &state_out, &ks);
515 if (ks == NoSymbol)
516 continue;
517
518 if (ks == keysym)
519 break;
520 }
521
522 // KeySym not mapped?
523 if (keycode > xkb->max_key_code)
524 goto out;
525
526 act = XkbKeyAction(xkb, keycode, 0);
527 if (act == nullptr)
528 goto out;
529 if (act->type != XkbSA_LockMods)
530 goto out;
531
532 if (act->mods.flags & XkbSA_UseModMapMods)
533 mask = xkb->map->modmap[keycode];
534 else
535 mask = act->mods.mask;
536
537out:
538 XkbFreeKeyboard(xkb, XkbAllComponentsMask, True);
539
540 return mask;
541}
542#endif
543
544void CFrmViewer::slotUpdateLedState(unsigned int state)
545{
546 qDebug(log, "Got server LED state: 0x%08x", state);
547
548 if (!hasFocus())
549 return;
550
551 //TODO: test led
552
553#if defined(WIN32)
554 INPUT input[6];
555 UINT count;
556 UINT ret;
557
558 memset(input, 0, sizeof(input));
559 count = 0;
560
561 if (!!(state & CapsLock) != !!(GetKeyState(VK_CAPITAL) & 0x1)) {
562 input[count].type = input[count+1].type = INPUT_KEYBOARD;
563 input[count].ki.wVk = input[count+1].ki.wVk = VK_CAPITAL;
564 //input[count].ki.wScan = input[count+1].ki.wScan = SCAN_FAKE;
565 input[count].ki.dwFlags = 0;
566 input[count+1].ki.dwFlags = KEYEVENTF_KEYUP;
567 count += 2;
568 }
569
570 if (!!(state & NumLock) != !!(GetKeyState(VK_NUMLOCK) & 0x1)) {
571 input[count].type = input[count+1].type = INPUT_KEYBOARD;
572 input[count].ki.wVk = input[count+1].ki.wVk = VK_NUMLOCK;
573 //input[count].ki.wScan = input[count+1].ki.wScan = SCAN_FAKE;
574 input[count].ki.dwFlags = KEYEVENTF_EXTENDEDKEY;
575 input[count+1].ki.dwFlags = KEYEVENTF_KEYUP | KEYEVENTF_EXTENDEDKEY;
576 count += 2;
577 }
578
579 if (!!(state & ScrollLock) != !!(GetKeyState(VK_SCROLL) & 0x1)) {
580 input[count].type = input[count+1].type = INPUT_KEYBOARD;
581 input[count].ki.wVk = input[count+1].ki.wVk = VK_SCROLL;
582 //input[count].ki.wScan = input[count+1].ki.wScan = SCAN_FAKE;
583 input[count].ki.dwFlags = 0;
584 input[count+1].ki.dwFlags = KEYEVENTF_KEYUP;
585 count += 2;
586 }
587
588 if (count == 0)
589 return;
590
591 ret = SendInput(count, input, sizeof(*input));
592 if (ret < count)
593 qCritical(log) << "Failed to update keyboard LED state:" << GetLastError();
594#elif defined(Q_OS_APPLE)
595
596 // No support for Scroll Lock //
597 ;
598
599#elif defined(Q_OS_LINUX) && !defined(Q_OS_ANDROID) && !defined(Q_OS_APPLE)
600 unsigned int affect, values;
601 unsigned int mask;
602
603 Bool ret;
604
605 affect = values = 0;
606
607 affect |= LockMask;
608 if (state & CapsLock)
609 values |= LockMask;
610
611 mask = getModifierMask(XK_Num_Lock);
612 affect |= mask;
613 if (state & NumLock)
614 values |= mask;
615
616 mask = getModifierMask(XK_Scroll_Lock);
617 affect |= mask;
618 if (state & ScrollLock)
619 values |= mask;
620 Display *dpy = XOpenDisplay(0);
621 ret = XkbLockModifiers(dpy, XkbUseCoreKbd, affect, values);
622 if (!ret)
623 qCritical(log) << tr("Failed to update keyboard LED state");
624 XFlush(dpy);
625 XCloseDisplay(dpy);
626#endif
627}
628
629QImage CFrmViewer::GrabImage(int x, int y, int w, int h)
630{
631 int width = w, height = h;
632 if(-1 == w)
633 width = m_DesktopSize.width();
634 if(-1 == w)
635 height = m_DesktopSize.height();
636 return m_Desktop.copy(x, y, width, height);
637}
638
639void CFrmViewer::slotRecordVideo(bool bRecord, qreal nRate)
640{
641 m_bRecordVideo = bRecord;
642 if(0 == nRate) {
643 qWarning(log) << "The video frame rate is 0. it is not record static remote desktop."
644 << "If need record static remote desktop,"
645 << "please 'Record->Video->Encoding mode' don't select 'Constant quality' in settings dialog,"
646 << "then set 'Record->Video->Video frame'";
647 return;
648 }
649
650 m_bRecordVideo = false;
651 if(bRecord) {
652 qreal ms = 1000 / nRate;
653 //qDebug(log) << "Rate:" << nRate << ms << "ms";
654 m_TimerRecordVideo.start(ms);
655 }
656 else
657 m_TimerRecordVideo.stop();
658}
659
660void CFrmViewer::slotRecordVideo()
661{
662 emit sigRecordVideo(m_Desktop);
663}
664
665void CFrmViewer::focusInEvent(QFocusEvent *event)
666{
667 qDebug(log) << Q_FUNC_INFO << event << this;
668 emit sigViewerFocusIn(this);
669}
670
671void CFrmViewer::focusOutEvent(QFocusEvent *event)
672{
673 qDebug(log) << Q_FUNC_INFO << event << this;
674}
675
678{
679 int nRet = 0;
680
681 return nRet;
682}
683
684
686{
687 switch (event->type())
688 {
689 case QEvent::TouchBegin:
690 case QEvent::TouchUpdate:
691 case QEvent::TouchEnd:
692 {
693 QTouchEvent* e = (QTouchEvent*)event;
694 qDebug(logTouch) << "QEvent::TouchBegin";
695 touchEvent(e);
696 break;
697 }
698 case QEvent::Gesture:
699 {
700 gestureEvent(static_cast<QGestureEvent*>(event));
701 break;
702 }
703 default:
704 break;
705 }
706 return QWidget::event(event);
707}
708
709bool CFrmViewer::touchEvent(QTouchEvent* event)
710{
711 const QList<QTouchEvent::TouchPoint> touchPoints = event->touchPoints();
712
713 for (const QTouchEvent::TouchPoint &touchPoint : touchPoints) {
714 qDebug(logTouch) << "Touch Point ID:" << touchPoint.id()
715 << "State:" << touchPoint.state()
716 << "Position:" << touchPoint.pos();
717 switch (touchPoint.state()) {
718 case Qt::TouchPointPressed: {
719 qDebug(logTouch) << "手指按下!ID:" << touchPoint.id() << "Pos:" << touchPoint.pos();
720
721 break;
722 }
723 case Qt::TouchPointMoved:
724 qDebug(logTouch) << "手指移动... ID:" << touchPoint.id() << "Current Pos:" << touchPoint.pos();
725
726 break;
727 case Qt::TouchPointReleased:
728 qDebug(logTouch) << "手指抬起。 ID:" << touchPoint.id() << "Final Pos:" << touchPoint.pos();
729
730 break;
731 default:
732 break;
733 }
734 }
735
736 // 注意:在这里设置事件状态是可选的,如果你希望事件继续传播,就不要设置为 Accepted
737 // event->accept();
738 return false;
739}
740
741bool CFrmViewer::gestureEvent(QGestureEvent* event)
742{
743 if (QGesture *pinch = event->gesture(Qt::PinchGesture)) {
744 QPinchGesture *pinchGesture = static_cast<QPinchGesture *>(pinch);
745
746 // 处理缩放
747 if (pinchGesture->state() == Qt::GestureUpdated) {
748 // scaleFactor() 会告诉你缩放了多少
749 qreal scale = pinchGesture->scaleFactor();
750 qDebug() << "正在缩放! 缩放因子:" << scale;
751 // 在这里应用缩放逻辑
752 }
753 }
754
755 if (QGesture *pan = event->gesture(Qt::PanGesture)) {
756 QPanGesture *panGesture = static_cast<QPanGesture *>(pan);
757 // 处理平移/拖动
758 if (panGesture->state() == Qt::GestureUpdated) {
759 QPointF delta = panGesture->delta();
760 qDebug() << "正在平移! 偏移量:" << delta;
761 // 在这里应用平移逻辑
762 }
763 }
764
765 return false; // 表示手势事件已处理
766}
A widget which displays output image from a CConnectDesktop and sends input keypresses and mouse acti...
Definition FrmViewer.h:50
virtual bool event(QEvent *event) override
[Full Screen]
void slotSetDesktopSize(int width, int height)
Update desktop size.
ADAPT_WINDOWS
The ADAPT_WINDOWS enum.
Definition FrmViewer.h:62
@ Original
Original desktop size, the left-top of the desktop is aligned with the left-top of the window.
Definition FrmViewer.h:66
@ Zoom
zoom windows = desktop size * factor
Definition FrmViewer.h:70
@ KeepAspectRationToWindow
Keep desktop aspectration adapt to windows.
Definition FrmViewer.h:74
@ OriginalCenter
Original desktop size, the center of the desktop is aligned with the center of the window.
Definition FrmViewer.h:68
@ ZoomToWindow
Desktop adapt to windows.
Definition FrmViewer.h:72
@ Disable
Disable adapt windows.
Definition FrmViewer.h:63
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 slotRunning()
Enable mouse and keyboard.
void slotSetName(const QString &szName)
Update desktop name.
void slotUpdateCursorPosition(const QPoint &pos)
Update cursor position.
void slotEnableInputMethod(bool bEnable)
Enable input method.
Q_INVOKABLE int OnFullScreen(bool bFull)
Full Screen.
double GetZoomFactor() const
Adjust the zoom factor.