Rabbit Remote Control 0.1.0-bate16
Loading...
Searching...
No Matches
BackendLibVNCServer.cpp
1#include <QApplication>
2#include <QImage>
3#include <QClipboard>
4#include <QNetworkProxy>
5#include <QInputDialog>
6#include <QLoggingCategory>
7
8#include "Channel.h"
9#include "ConvertKeyCode.h"
10#include "BackendLibVNCServer.h"
11
12static Q_LOGGING_CATEGORY(log, "LibVNCServer.Backend")
13static Q_LOGGING_CATEGORY(logger, "LibVNCServer.Backend.log")
14static Q_LOGGING_CATEGORY(logKey, "LibVNCServer.Backend.Key")
15static Q_LOGGING_CATEGORY(logInputMethod, "LibVNCServer.Backend.InputMethod")
16static Q_LOGGING_CATEGORY(logMouse, "LibVNCServer.Backend.Mouse")
17
18const char* gThis = "This pointer";
19#define LOG_BUFFER_LENGTH 1024
20static void rfbQtClientLog(const char *format, ...)
21{
22 int nRet = 0;
23 va_list args;
24 char buf[LOG_BUFFER_LENGTH];
25
26 if(!rfbEnableClientLogging)
27 return;
28
29 va_start(args, format);
30 nRet = vsnprintf(buf, LOG_BUFFER_LENGTH, format, args);
31 va_end(args);
32 if(nRet < 0)
33 {
34 qCritical(log) << "vsnprintf fail";
35 return;
36 }
37 if(nRet >= LOG_BUFFER_LENGTH)
38 {
39 qCritical(log) << "vsprintf buf is short,"
40 << nRet << ">" << LOG_BUFFER_LENGTH
41 << ". Truncated it:" << nRet - LOG_BUFFER_LENGTH;
42 buf[LOG_BUFFER_LENGTH - 1] = 0;
43 }
44 qDebug(logger) << buf;
45}
46
47CBackendLibVNCServer::CBackendLibVNCServer(COperateLibVNCServer *pOperate)
48 : CBackendDesktop(pOperate),
49 m_pClient(nullptr),
50 m_pParameter(qobject_cast<CParameterLibVNCServer*>(pOperate->GetParameter()))
51#ifdef HAVE_LIBSSH
52 ,m_pThread(nullptr)
53#endif
54 , m_SecurityLevel(CSecurityLevel::Level::Risk)
55{
56 rfbClientLog = rfbQtClientLog;
57
58 if(!m_pParameter->GetLocalCursor())
59 {
60 emit sigUpdateCursor(QCursor(Qt::BlankCursor));
61 }
62}
63
64CBackendLibVNCServer::~CBackendLibVNCServer()
65{
66 qDebug(log) << "CConnectLibVNCServer::~CConnectLibVNCServer()";
67}
68
75CBackendLibVNCServer::OnStartReturnValue CBackendLibVNCServer::OnStart()
76{
77 qDebug(log) << "CConnectLibVNCServer::OnStart()";
78 if(m_pClient) Q_ASSERT(false);
79
80 m_pClient = rfbGetClient(8, 3, 4);
81 if(!m_pClient)
82 {
83 QString szErr;
84 szErr = tr("Protocol version error");
85 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
86 qCritical(log) << "rfbGetClient fail";
87 return OnStartReturnValue::Fail;
88 }
89
90 // Set parameters
91 m_pClient->programName = strdup(qApp->applicationName().toStdString().c_str());
92 m_pClient->appData.shareDesktop = m_pParameter->GetShared();
93 m_pClient->appData.viewOnly = m_pParameter->GetOnlyView();
94 m_pClient->appData.useRemoteCursor = m_pParameter->GetLocalCursor();
95
96 //Qt is support QImage::Format_RGB32, so we use default format QImage::Format_RGB32 in OnSize()
97 // m_pClient->appData.requestedDepth = m_pPara->nColorLevel;
98 // m_pClient->format.depth = m_pPara->nColorLevel;
99 // switch (m_pClient->format.depth) {
100 // case 8:
101 // m_pClient->format.depth = 8;
102 // m_pClient->format.bitsPerPixel = 8;
103 // m_pClient->format.blueMax = 3;
104 // m_pClient->format.blueShift = 6;
105 // m_pClient->format.greenMax = 7;
106 // m_pClient->format.greenShift = 3;
107 // m_pClient->format.redMax = 7;
108 // m_pClient->format.redShift = 0;
109 // break;
110 // case 16:
111 // m_pClient->format.depth = 15;
112 // m_pClient->format.bitsPerPixel = 16;
113 // m_pClient->format.redShift = 11;
114 // m_pClient->format.greenShift = 6;
115 // m_pClient->format.blueShift = 1;
116 // m_pClient->format.redMax = 31;
117 // m_pClient->format.greenMax = 31;
118 // m_pClient->format.blueMax = 31;
119 // break;
120 // case 32:
121 // default:
122 // m_pClient->format.depth = 24;
123 // m_pClient->format.bitsPerPixel = 32;
124 // m_pClient->format.blueShift = 0;
125 // m_pClient->format.redShift = 16;
126 // m_pClient->format.greenShift = 8;
127 // m_pClient->format.blueMax = 0xff;
128 // m_pClient->format.redMax = 0xff;
129 // m_pClient->format.greenMax = 0xff;
130 // break;
131 // }
132
133 m_pClient->appData.enableJPEG = m_pParameter->GetJpeg();
134 if(m_pClient->appData.enableJPEG)
135 m_pClient->appData.qualityLevel = m_pParameter->GetQualityLevel();
136 if(m_pParameter->GetEnableCompressLevel())
137 m_pClient->appData.compressLevel = m_pParameter->GetCompressLevel();
138
139 // Set callback function
140 m_pClient->MallocFrameBuffer = cb_resize;
141 m_pClient->GotFrameBufferUpdate = cb_update;
142 m_pClient->HandleKeyboardLedState = cb_kbd_leds;
143 m_pClient->Bell = cb_bell;
144 m_pClient->HandleTextChat = cb_text_chat;
145 m_pClient->GotXCutText = cb_got_selection;
146 m_pClient->GetCredential = cb_get_credential;
147 m_pClient->GetPassword = cb_get_password;
148 m_pClient->HandleCursorPos = cb_cursor_pos;
149 m_pClient->GotCursorShape = cb_got_cursor_shape;
150
151 m_pClient->canHandleNewFBSize = TRUE;
152 rfbClientSetClientData(m_pClient, (void*)gThis, this);
153
154 // Set sock
155 switch(m_pParameter->m_Proxy.GetUsedType())
156 {
157 case CParameterProxy::TYPE::None:
158 {
159 // Set server ip and port
160 if(m_pParameter->m_Net.GetHost().isEmpty())
161 {
162 QString szErr;
163 szErr = tr("The server is empty, please input it");
164 qCritical(log) << szErr;
165 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
166 return OnStartReturnValue::Fail;
167 }
168 auto &net = m_pParameter->m_Net;
169 m_pClient->serverHost = strdup(net.GetHost().toStdString().c_str());
170 m_pClient->serverPort = net.GetPort();
171
172 if(!rfbInitClient(m_pClient, nullptr, nullptr))
173 {
174 // Because delete m_pClient in rfbInitClient
175 m_pClient = nullptr;
176 QString szErr;
177 szErr = tr("Fail: Connect to %1:%2").arg(m_pParameter->m_Net.GetHost(),
178 QString::number(m_pParameter->m_Net.GetPort()));
179 qCritical(log) << szErr;
180 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
181 return OnStartReturnValue::Fail;
182 }
183
184 QString szInfo = QString("Connected to ") + m_pClient->desktopName;
185 qInfo(log) << szInfo;
186
187 emit sigSetDesktopSize(m_pClient->width, m_pClient->height);
188 emit sigServerName(m_pClient->desktopName);
189 emit sigInformation(szInfo);
190 emit sigSecurityLevel(m_SecurityLevel);
191 emit sigRunning();
192 return OnStartReturnValue::UseOnProcess;
193 }
194 /*case CParameterProxy::TYPE::SockesV5:
195 {
196 QNetworkProxy proxy;
197 proxy.setType(QNetworkProxy::Socks5Proxy);
198 auto &net = m_pParameter->m_Proxy.m_SockesV5;
199 proxy.setHostName(net.GetHost());
200 if(net.GetHost().isEmpty())
201 {
202 QString szErr;
203 szErr = tr("The proxy server is empty, please input it");
204 qCritical(log) << szErr;
205 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
206 return OnStartReturnValue::Fail;
207 }
208 proxy.setPort(net.GetPort());
209 auto &user = net.m_User;
210 proxy.setUser(user.GetUser());
211 proxy.setPassword(user.GetPassword());
212 m_tcpSocket.setProxy(proxy);
213 m_tcpSocket.connectToHost(m_pClient->serverHost, m_pClient->serverPort);
214 if (!m_tcpSocket.waitForConnected(3000))
215 return OnStartReturnValue::Fail;
216 //TODO: The is fail
217 m_pClient->sock = m_tcpSocket.socketDescriptor();
218 if(!rfbInitClient(m_pClient, nullptr, nullptr))
219 {
220 // Because delete m_pClient in rfbInitClient
221 m_pClient = nullptr;
222 QString szErr;
223 szErr = tr("Connect to %1:%2 fail").arg(m_pParameter->m_Net.GetHost(),
224 QString::number(m_pParameter->m_Net.GetPort()));
225 qCritical(log) << szErr;
226 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
227 return OnStartReturnValue::Fail;
228 }
229 break;
230 }//*/
231 /*TODO: add UltraVncRepeater
232 case (CParameterOperate::emProxy) CParameterLibVNCServer::emVncProxy::UltraVncRepeater:
233 m_pClient->destHost = strdup(m_pPara->GetProxyHost().toStdString().c_str());
234 m_pClient->destPort = m_pPara->GetProxyPort();//*/
235
237#ifdef HAVE_LIBSSH
238 case CParameterProxy::TYPE::SSHTunnel:
239 {
240 // Start ssh thread
241 if(!m_pThread) {
242 // Don' t delete it, It deletes itself when it ends. See: CSSHTunnelThread::CSSHTunnelThread()
243 m_pThread = new CSSHTunnelThread(
244 &m_pParameter->m_Proxy.m_SSH, &m_pParameter->m_Net, this);
245 }
246 if(!m_pThread)
247 return OnStartReturnValue::Fail;
248 bool check = connect(m_pThread, SIGNAL(sigServer(QString, quint16)),
249 this, SLOT(slotConnectProxyServer(QString, quint16)));
250 Q_ASSERT(check);
251#if defined(HAVE_UNIX_DOMAIN_SOCKET)
252 check = connect(m_pThread, SIGNAL(sigServer(QString)),
253 this, SLOT(slotConnectProxyServer(QString)));
254 Q_ASSERT(check);
255#endif
256 check = connect(m_pThread, SIGNAL(sigError(int,QString)),
257 this, SIGNAL(sigError(int,QString)));
258 Q_ASSERT(check);
259 check = connect(m_pThread, SIGNAL(sigStop()),
260 this, SIGNAL(sigStop()));
261 Q_ASSERT(check);
262 m_pThread->start();
263
264 return OnStartReturnValue::NotUseOnProcess;
265 }
266#endif // #ifdef HAVE_LIBSSH
268 default:
269 break;
270 }
271
272 return OnStartReturnValue::UseOnProcess;
273}
274
276{
277 qDebug(log) << "CConnectLibVNCServer::OnStop()";
278#ifdef HAVE_LIBSSH
279 if(m_pThread)
280 {
281 disconnect(m_pThread);
282 m_pThread->Exit();
283 m_pThread = nullptr;
284 }
285#endif
286 if(m_pClient)
287 {
288 //m_tcpSocket.close();
289 rfbClientCleanup(m_pClient);
290 m_pClient = nullptr;
291 }
292
293 emit sigFinished();
294 return 0;
295}
296
311{
312 //qDebug(log) << Q_FUNC_INFO;
313 int nRet = 0;
314 if(!m_pClient)
315 {
316 // Stop
317 return -1;
318 }
319
320 struct timeval timeout = {0, DEFAULT_TIMEOUT};
321 fd_set set;
322 FD_ZERO(&set);
323 if(RFB_INVALID_SOCKET != m_pClient->sock)
324 {
325 FD_SET(m_pClient->sock, &set);
326 }
327 rfbSocket eventFd = m_Event.GetFd();
328 if(RFB_INVALID_SOCKET != eventFd)
329 {
330 FD_SET(eventFd, &set);
331 }
332 rfbSocket fd = RFB_INVALID_SOCKET;
333 fd = std::max(eventFd, m_pClient->sock);
334 //qDebug(log) << "fd:" << fd << "select m_pClient->sock:" << (int)m_pClient->sock << "event:" << eventFd;
335 nRet = select(fd + 1, &set, NULL, NULL, &timeout);
336 //qDebug(log) << "select end";
337 if (nRet < 0) {
338 qCritical(log) << "select fail:" << nRet << "errno" << errno << strerror(errno);
339 return nRet;
340 }
341
342 /*if(0 == nRet)
343 {
344 //qDebug(log) << "Time out";
345 return 0;
346 }//*/
347
348 if(RFB_INVALID_SOCKET != eventFd && FD_ISSET(eventFd, &set))
349 {
350 //qDebug(log) << "fires event";
351 m_Event.Reset();
352 }
353
354 if(RFB_INVALID_SOCKET != m_pClient->sock
355 && FD_ISSET(m_pClient->sock, &set)) {
356 //qDebug(log) << "HandleRFBServerMessage";
357 if(!HandleRFBServerMessage(m_pClient))
358 {
359 qCritical(log) << "HandleRFBServerMessage fail";
360 return -2;
361 }
362 }
363
364 return 0;
365}
366
368{
369 return m_Event.WakeUp();
370}
371
373{
374 if(!m_pParameter || !m_pParameter->GetClipboard() || !m_pClient) return;
375 QClipboard* pClipboard = QApplication::clipboard();
376 if(pClipboard)
377 {
378 QString szText = pClipboard->text();
379 if(!szText.isEmpty() && m_pClient)
380 SendClientCutText(m_pClient,
381 (char*)szText.toStdString().c_str(),
382 szText.toStdString().length());
383 }
384}
385
386rfbBool CBackendLibVNCServer::cb_resize(rfbClient* client)
387{
388 //qDebug(log) << "CConnectLibVnc::cb_resize:" << client->width << client->height;
389 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(client, (void*)gThis);
390 if(pThis->OnSize()) return FALSE;
391 return TRUE;
392}
393
394void CBackendLibVNCServer::cb_update(rfbClient *client, int x, int y, int w, int h)
395{
396 if(0 == w || 0 == h)
397 return;
398 //qDebug(log, "CConnectLibVnc::cb_update:(%d, %d, %d, %d)", x, y, w, h);
399 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(client, (void*)gThis);
400 QRect rect(x, y, w, h);
401 QImage img = pThis->m_Image.copy(rect);
402 emit pThis->sigUpdateRect(rect, img);
403}
404
405void CBackendLibVNCServer::cb_got_selection(rfbClient *client, const char *text, int len)
406{
407 //qDebug(log, "CConnectLibVnc::cb_got_selection:%s", text);
408 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(client, (void*)gThis);
409 if(!pThis->m_pParameter->GetClipboard()) return;
410 QClipboard* pClipboard = QApplication::clipboard();
411 if(pClipboard)
412 pClipboard->setText(text);
413}
414
415void CBackendLibVNCServer::cb_kbd_leds(rfbClient *client, int value, int pad)
416{
417 qDebug(log) << "CConnectLibVnc::cb_kbd_leds";
418}
419
420void CBackendLibVNCServer::cb_bell(struct _rfbClient *client)
421{
422 qApp->beep();
423}
424
425void CBackendLibVNCServer::cb_text_chat(rfbClient *client, int value, char *text)
426{
427 qDebug(log) << "CConnectLibVnc::cb_text_chat";
428}
429
430rfbCredential* CBackendLibVNCServer::cb_get_credential(rfbClient *cl, int credentialType)
431{
432 qDebug(log) <<"CConnectLibVnc::cb_get_credential";
433 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(cl, (void*)gThis);
434 rfbCredential *c = (rfbCredential*)malloc(sizeof(rfbCredential));
435 c->userCredential.username = (char*)malloc(RFB_BUF_SIZE);
436 memset(c->userCredential.username, 0, RFB_BUF_SIZE);
437 c->userCredential.password = (char*)malloc(RFB_BUF_SIZE);
438 memset(c->userCredential.password, 0, RFB_BUF_SIZE);
439
440 if(credentialType != rfbCredentialTypeUser) {
441 qCritical(log) << "something else than username and password required for authentication";
442 return NULL;
443 }
444
445 qDebug(log) << "Username and password required for authentication!";
446
447 memcpy(c->userCredential.username,
448 pThis->m_pParameter->m_Net.m_User.GetUser().toStdString().c_str(),
449 pThis->m_pParameter->m_Net.m_User.GetUser().toStdString().length());
450 memcpy(c->userCredential.password,
451 pThis->m_pParameter->m_Net.m_User.GetPassword().toStdString().c_str(),
452 pThis->m_pParameter->m_Net.m_User.GetPassword().toStdString().length());
453
454 return c;
455}
456
457char* CBackendLibVNCServer::cb_get_password(rfbClient *client)
458{
459 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(client, (void*)gThis);
460 QString szPassword = pThis->m_pParameter->m_Net.m_User.GetPassword();
461 if(szPassword.isEmpty())
462 {
463 int nRet = QDialog::Rejected;
464 auto *net = &pThis->m_pParameter->m_Net;
465 emit pThis->sigBlockShowWidget("CDlgUserPassword", nRet, net);
466 if(QDialog::Accepted == nRet)
467 {
468 szPassword = net->m_User.GetPassword();
469 }
470 }
471 if(!szPassword.isEmpty())
472 pThis->m_SecurityLevel |= CSecurityLevel::Level::Authentication;
473 return strdup(szPassword.toStdString().c_str());
474}
475
476int CBackendLibVNCServer::OnSize()
477{
478 int nRet = 0;
479 int nWidth = m_pClient->width;
480 int nHeight = m_pClient->height;
481
482 m_Image = QImage(nWidth, nHeight, QImage::Format_RGB32);
483
484 m_pClient->frameBuffer = m_Image.bits();
485
486 m_pClient->format.bitsPerPixel = 32;
487 m_pClient->format.depth = m_Image.depth();
488 m_pClient->format.redShift = 16;
489 m_pClient->format.greenShift = 8;
490 m_pClient->format.blueShift = 0;
491 m_pClient->format.redMax = 255;
492 m_pClient->format.greenMax = 255;
493 m_pClient->format.blueMax = 255;
494 SetFormatAndEncodings(m_pClient);
495
496 emit sigSetDesktopSize(m_pClient->width, m_pClient->height);
497 return nRet;
498}
499
500rfbBool CBackendLibVNCServer::cb_cursor_pos(rfbClient *client, int x, int y)
501{
502 //qDebug(log, "CConnectLibVnc::cb_cursor_pos:%d,%d", x, y);
503 rfbBool bRet = true;
504
505 return bRet;
506}
507
508void CBackendLibVNCServer::cb_got_cursor_shape(rfbClient *client,
509 int xhot, int yhot,
510 int width, int height,
511 int bytesPerPixel)
512{
513 /*
514 qDebug(log, "CConnectLibVnc::cb_got_cursor_shape:x:%d, y:%d, width:%d, height:%d, bytesPerPixel:%d",
515 xhot, yhot, width, height, bytesPerPixel);//*/
516 if(!client->rcSource)
517 {
518 qCritical(log) << "client->rcSource is null";
519 return;
520 }
521 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(client, (void*)gThis);
522 if ((width == 0) || (height == 0)) {
523 QImage cursor(1, 1, QImage::Format_ARGB32);
524 uchar* buffer = cursor.bits();
525 memset(buffer, 0, 4);
526 emit pThis->sigUpdateCursor(QCursor(QPixmap::fromImage(cursor), xhot, yhot));
527 } else {
528 switch (bytesPerPixel) {
529 case 4:
530 {
531 QImage cursor(width, height, QImage::Format_ARGB32);
532 uchar *buffer = cursor.bits();
533 memcpy(buffer, client->rcSource, width * height * 4);
534 uchar* pMask = client->rcMask;
535 if(pMask)
536 {
537 uchar* pDest = buffer;
538 for(int y = 0; y < height; y++)
539 {
540 for(int w = 0; w < width; w++)
541 {
542 if(*pMask++)
543 {
544 // NOTE: Do not manipulate the memory,
545 // because the host byte order may be different
546 QColor c = cursor.pixel(w, y);
547 c.setAlpha(0xff);
548 cursor.setPixelColor(w,y,c);
549 }
550 else
551 *((uint32_t*)pDest) = 0;
552
553 pDest += 4;
554 }
555 }
556 }
557 emit pThis->sigUpdateCursor(QCursor(QPixmap::fromImage(cursor), xhot, yhot));
558 break;
559 }
560 default:
561 break;
562 }
563 }
564}
565
566void CBackendLibVNCServer::mousePressEvent(QMouseEvent *event)
567{
568 if(!m_pClient) return;
569 if(m_pParameter && m_pParameter->GetOnlyView()) return;
570
571 unsigned char mask = 0;
572 if(event->button() & Qt::MouseButton::LeftButton)
573 mask |= 0x1;
574 if(event->button() & Qt::MouseButton::MiddleButton)
575 mask |= 0x2;
576 if(event->button() & Qt::MouseButton::RightButton)
577 mask |= 0x4;
578 if(event->button() & Qt::MouseButton::BackButton)
579 mask |= 0x80;
580 QPoint pos = event->pos();
581
582 //qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->button() << pos << mask;
583
584 SendPointerEvent(m_pClient, pos.x(), pos.y(), mask);
585}
586
587void CBackendLibVNCServer::mouseReleaseEvent(QMouseEvent *event)
588{
589 if(!m_pClient) return;
590 if(m_pParameter && m_pParameter->GetOnlyView()) return;
591 int mask = 0;
592 QPoint pos = event->pos();
593 //qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->button() << pos << mask;
594 SendPointerEvent(m_pClient, pos.x(), pos.y(), mask);
595}
596
597void CBackendLibVNCServer::mouseMoveEvent(QMouseEvent *event)
598{
599 if(!m_pClient) return;
600 if(m_pParameter && m_pParameter->GetOnlyView()) return;
601 int mask = 0;
602 if(event->buttons() & Qt::MouseButton::LeftButton)
603 mask |= 0x1;
604 if(event->buttons() & Qt::MouseButton::MiddleButton)
605 mask |= 0x2;
606 if(event->buttons() & Qt::MouseButton::RightButton)
607 mask |= 0x4;
608 if(event->buttons() & Qt::MouseButton::BackButton)
609 mask |= 0x80;
610 QPoint pos = event->pos();
611 //qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->button() << pos << mask;
612 SendPointerEvent(m_pClient, pos.x(), pos.y(), mask);
613}
614
615// https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst#pointerevent
616void CBackendLibVNCServer::wheelEvent(QWheelEvent *event)
617{
618 if(!m_pClient) return;
619 if(m_pParameter && m_pParameter->GetOnlyView()) return;
620 int mask = 0;
621 if(event->buttons() & Qt::MouseButton::LeftButton)
622 mask |= 0x1;
623 if(event->buttons() & Qt::MouseButton::MiddleButton)
624 mask |= 0x2;
625 if(event->buttons() & Qt::MouseButton::RightButton)
626 mask |= 0x4;
627 if(event->buttons() & Qt::MouseButton::BackButton)
628 mask |= 0x80;
629
630 QPoint d = event->angleDelta();
631 if(d.y() > 0)
632 mask |= 0x8;
633 if(d.y() < 0)
634 mask |= 0x10;
635 if(d.x() < 0)
636 mask |= 0x20;
637 if(d.x() > 0)
638 mask |= 0x40;
639
640 QPointF pos;
641#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
642 pos = event->position();
643#else
644 pos = event->pos();
645#endif
646
647 //qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->angleDelta() << pos;
648
649 SendPointerEvent(m_pClient, pos.x(), pos.y(), mask);
650}
651
652void CBackendLibVNCServer::keyPressEvent(QKeyEvent *event)
653{
654 if(!m_pClient) return;
655 if(m_pParameter && m_pParameter->GetOnlyView()) return;
656 bool modifier = false;
657 if (event->modifiers() & Qt::ShiftModifier)
658 modifier = true;
659 uint32_t k = CConvertKeyCode::QtToRfbKey(event->key(), modifier);
660 //qDebug(logKey) << Q_FUNC_INFO << event << k << modifier;
661 SendKeyEvent(m_pClient, k, TRUE);
662}
663
664void CBackendLibVNCServer::keyReleaseEvent(QKeyEvent *event)
665{
666 if(!m_pClient) return;
667 if(m_pParameter && m_pParameter->GetOnlyView()) return;
668 bool modifier = false;
669 if (event->modifiers() & Qt::ShiftModifier)
670 modifier = true;
671 uint32_t k = CConvertKeyCode::QtToRfbKey(event->key(), modifier);
672 //qDebug(logKey) << Q_FUNC_INFO << event << k << modifier;
673 SendKeyEvent(m_pClient, k, FALSE);
674}
675
676void CBackendLibVNCServer::InputMethodEvent(QInputMethodEvent *event)
677{
678 //qDebug(logInputMethod) << Q_FUNC_INFO << event;
679 if(!m_pClient) return;
680 if(m_pParameter && m_pParameter->GetOnlyView()) return;
681
682 QString szText = event->commitString();
683 if (szText.isEmpty())
684 return;
685
686 //qDebug(logInputMethod) << Q_FUNC_INFO << szText;
687
688 QVector<uint32_t> ucs4 = szText.toUcs4();
689 foreach (uint32_t cp, ucs4) {
690 quint32 keysym = static_cast<quint32>(cp); // 直接用 Unicode code point 作为 keysym
691 SendKeyEvent(m_pClient, keysym, TRUE);
692 SendKeyEvent(m_pClient, keysym, FALSE);
693 }
694}
695
697void CBackendLibVNCServer::slotConnectProxyServer(QString szHost, quint16 nPort)
698{
699 QString szErr;
700 auto &net = m_pParameter->m_Proxy.m_SSH.m_Net;
701 //qDebug(log) << "CConnectLibVNCServer::slotConnectServer" << nPort;
702 // Set server ip and port
703 m_pClient->serverHost = strdup(szHost.toStdString().c_str());
704 m_pClient->serverPort = nPort;
705 szErr = tr("Will connect to local socket server: %1:%2")
706 .arg(m_pClient->serverHost,
707 QString::number(m_pClient->serverPort));
708 qDebug(log) << szErr;
709 if(!rfbInitClient(m_pClient, nullptr, nullptr))
710 {
711 // Because delete m_pClient in rfbInitClient
712 m_pClient = nullptr;
713 QString szErr;
714 szErr = tr("Fail: Connect to %1:%2 <- %3:%4 <- %5:%6")
715 .arg(m_pParameter->m_Net.GetHost(),
716 QString::number(m_pParameter->m_Net.GetPort()),
717 net.GetHost(), QString::number(net.GetPort()),
718 szHost, QString::number(nPort)
719 );
720 qCritical(log) << szErr;
721 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
722 return;
723 }
724
725 QString szInfo = QString("Connected to %1 <- %2:%3 <- %4:%5")
726 .arg(m_pClient->desktopName,
727 net.GetHost(), QString::number(net.GetPort()),
728 szHost, QString::number(nPort));
729 qInfo(log) << szInfo;
730 slotTimeOut();
731 emit sigSetDesktopSize(m_pClient->width, m_pClient->height);
732 emit sigServerName(m_pClient->desktopName);
733 emit sigInformation(szInfo);
734 emit sigSecurityLevel(m_SecurityLevel |= CSecurityLevel::Level::Proxy);
735 emit sigRunning();
736}
737
738#if defined(HAVE_UNIX_DOMAIN_SOCKET)
740{
741 QString szErr;
742 //qDebug(log) << "CConnectLibVNCServer::slotConnectServer" << szFile;
743 // Set server ip and port
744 m_pClient->serverHost = strdup(szFile.toStdString().c_str());
745 szErr = tr("Will connect to local socket server: ") + szFile;
746 qDebug(log) << szErr;
747 if(!rfbInitClient(m_pClient, nullptr, nullptr))
748 {
749 // Because delete m_pClient in rfbInitClient
750 m_pClient = nullptr;
751 QString szErr;
752 szErr = tr("Fail: Connect to %1:%2 with %3")
753 .arg(m_pParameter->m_Net.GetHost(),
754 QString::number(m_pParameter->m_Net.GetPort()),
755 szFile);
756 qCritical(log) << szErr;
757 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
758 return;
759 }
760
761 QString szInfo = QString("Connected to ") + m_pClient->desktopName + " with " + szFile;
762 qInfo(log) << szInfo;
763
764 slotTimeOut();
765 emit sigSetDesktopSize(m_pClient->width, m_pClient->height);
766 emit sigServerName(m_pClient->desktopName);
767 emit sigInformation(szInfo);
768 emit sigRunning();
769}
770#endif
Remote desktop interface.
void sigUpdateRect(const QRect &r, const QImage &image)
Notify the CFrmView update image.
virtual OnStartReturnValue OnStart() override
void slotConnectProxyServer(QString szHost, quint16 nPort)
[connect local socket server]
virtual int WakeUp() override
Wake up backend thread(background thread).
virtual int OnStop() override
Clean.
virtual void slotClipBoardChanged() override
Be called when the clip board change.
virtual int OnProcess() override
Specific operation processing of plug-in connection.
void sigInformation(const QString &szInfo)
Triggering from a background thread displays information in the main thread without blocking the back...
void sigStop()
Notify the user to stop.
void sigShowMessageBox(const QString &szTitle, const QString &szMessage, const QMessageBox::Icon &icon=QMessageBox::Information)
Trigger the display of a message dialog (QMessageBox) in the main thread from a background thread wit...
void sigError(const int nError, const QString &szError=QString())
Triggered when an error is generated.
void sigRunning()
Emitted when the plugin is successfully started.
void sigFinished()
Successful stopped signal.
virtual void slotTimeOut()
a non-Qt event loop (that is, normal loop processing), It call OnProcess(), and start timer.
Definition Backend.cpp:111
void sigSecurityLevel(CSecurityLevel::Levels level)
Triggered when the security level changes.
void sigBlockShowWidget(const QString &className, int &nRet, void *pContext)
Blocks the background thread and displays the window in the foreground thread.
static quint32 QtToRfbKey(int inkey, bool modifier)
CConvertKeyCode::QtToRfbKey.
CParameterUser m_User
[Instance user]
Data is forwarded over a local socket and SSH tunnel.
Security level.
Definition Stats.h:97