Rabbit Remote Control 0.1.0-bate14
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 "BackendLibVNCServer.h"
9#include "Channel.h"
10
11static Q_LOGGING_CATEGORY(log, "LibVNCServer.Backend")
12static Q_LOGGING_CATEGORY(logger, "LibVNCServer.Backend.log")
13static Q_LOGGING_CATEGORY(logKey, "LibVNCServer.Backend.Key")
14static Q_LOGGING_CATEGORY(logInputMethod, "LibVNCServer.Backend.InputMethod")
15static Q_LOGGING_CATEGORY(logMouse, "LibVNCServer.Backend.Mouse")
16
17const char* gThis = "This pointer";
18#define LOG_BUFFER_LENGTH 1024
19static void rfbQtClientLog(const char *format, ...)
20{
21 int nRet = 0;
22 va_list args;
23 char buf[LOG_BUFFER_LENGTH];
24
25 if(!rfbEnableClientLogging)
26 return;
27
28 va_start(args, format);
29 nRet = vsnprintf(buf, LOG_BUFFER_LENGTH, format, args);
30 va_end(args);
31 if(nRet < 0)
32 {
33 qCritical(log) << "vsnprintf fail";
34 return;
35 }
36 if(nRet >= LOG_BUFFER_LENGTH)
37 {
38 qCritical(log) << "vsprintf buf is short,"
39 << nRet << ">" << LOG_BUFFER_LENGTH
40 << ". Truncated it:" << nRet - LOG_BUFFER_LENGTH;
41 buf[LOG_BUFFER_LENGTH - 1] = 0;
42 }
43 qDebug(logger) << buf;
44}
45
46CBackendLibVNCServer::CBackendLibVNCServer(COperateLibVNCServer *pOperate)
47 : CBackendDesktop(pOperate),
48 m_pClient(nullptr),
49 m_pParameter(qobject_cast<CParameterLibVNCServer*>(pOperate->GetParameter()))
50#ifdef HAVE_LIBSSH
51 ,m_pThread(nullptr)
52#endif
53 , m_SecurityLevel(CSecurityLevel::Level::Risk)
54{
55 rfbClientLog = rfbQtClientLog;
56
57 if(!m_pParameter->GetLocalCursor())
58 {
59 emit sigUpdateCursor(QCursor(Qt::BlankCursor));
60 }
61}
62
63CBackendLibVNCServer::~CBackendLibVNCServer()
64{
65 qDebug(log) << "CConnectLibVNCServer::~CConnectLibVNCServer()";
66}
67
74CBackendLibVNCServer::OnInitReturnValue CBackendLibVNCServer::OnInit()
75{
76 qDebug(log) << "CConnectLibVNCServer::OnInit()";
77 if(m_pClient) Q_ASSERT(false);
78
79 m_pClient = rfbGetClient(8, 3, 4);
80 if(!m_pClient)
81 {
82 QString szErr;
83 szErr = tr("Protocol version error");
84 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
85 qCritical(log) << "rfbGetClient fail";
86 return OnInitReturnValue::Fail;
87 }
88
89 // Set parameters
90 m_pClient->programName = strdup(qApp->applicationName().toStdString().c_str());
91 m_pClient->appData.shareDesktop = m_pParameter->GetShared();
92 m_pClient->appData.viewOnly = m_pParameter->GetOnlyView();
93 m_pClient->appData.useRemoteCursor = m_pParameter->GetLocalCursor();
94
95 //Qt is support QImage::Format_RGB32, so we use default format QImage::Format_RGB32 in OnSize()
96 // m_pClient->appData.requestedDepth = m_pPara->nColorLevel;
97 // m_pClient->format.depth = m_pPara->nColorLevel;
98 // switch (m_pClient->format.depth) {
99 // case 8:
100 // m_pClient->format.depth = 8;
101 // m_pClient->format.bitsPerPixel = 8;
102 // m_pClient->format.blueMax = 3;
103 // m_pClient->format.blueShift = 6;
104 // m_pClient->format.greenMax = 7;
105 // m_pClient->format.greenShift = 3;
106 // m_pClient->format.redMax = 7;
107 // m_pClient->format.redShift = 0;
108 // break;
109 // case 16:
110 // m_pClient->format.depth = 15;
111 // m_pClient->format.bitsPerPixel = 16;
112 // m_pClient->format.redShift = 11;
113 // m_pClient->format.greenShift = 6;
114 // m_pClient->format.blueShift = 1;
115 // m_pClient->format.redMax = 31;
116 // m_pClient->format.greenMax = 31;
117 // m_pClient->format.blueMax = 31;
118 // break;
119 // case 32:
120 // default:
121 // m_pClient->format.depth = 24;
122 // m_pClient->format.bitsPerPixel = 32;
123 // m_pClient->format.blueShift = 0;
124 // m_pClient->format.redShift = 16;
125 // m_pClient->format.greenShift = 8;
126 // m_pClient->format.blueMax = 0xff;
127 // m_pClient->format.redMax = 0xff;
128 // m_pClient->format.greenMax = 0xff;
129 // break;
130 // }
131
132 m_pClient->appData.enableJPEG = m_pParameter->GetJpeg();
133 if(m_pClient->appData.enableJPEG)
134 m_pClient->appData.qualityLevel = m_pParameter->GetQualityLevel();
135 if(m_pParameter->GetEnableCompressLevel())
136 m_pClient->appData.compressLevel = m_pParameter->GetCompressLevel();
137
138 // Set callback function
139 m_pClient->MallocFrameBuffer = cb_resize;
140 m_pClient->GotFrameBufferUpdate = cb_update;
141 m_pClient->HandleKeyboardLedState = cb_kbd_leds;
142 m_pClient->Bell = cb_bell;
143 m_pClient->HandleTextChat = cb_text_chat;
144 m_pClient->GotXCutText = cb_got_selection;
145 m_pClient->GetCredential = cb_get_credential;
146 m_pClient->GetPassword = cb_get_password;
147 m_pClient->HandleCursorPos = cb_cursor_pos;
148 m_pClient->GotCursorShape = cb_got_cursor_shape;
149
150 m_pClient->canHandleNewFBSize = TRUE;
151 rfbClientSetClientData(m_pClient, (void*)gThis, this);
152
153 // Set sock
154 switch(m_pParameter->m_Proxy.GetUsedType())
155 {
156 case CParameterProxy::TYPE::None:
157 {
158 // Set server ip and port
159 if(m_pParameter->m_Net.GetHost().isEmpty())
160 {
161 QString szErr;
162 szErr = tr("The server is empty, please input it");
163 qCritical(log) << szErr;
164 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
165 return OnInitReturnValue::Fail;
166 }
167 auto &net = m_pParameter->m_Net;
168 m_pClient->serverHost = strdup(net.GetHost().toStdString().c_str());
169 m_pClient->serverPort = net.GetPort();
170
171 if(!rfbInitClient(m_pClient, nullptr, nullptr))
172 {
173 // Because delete m_pClient in rfbInitClient
174 m_pClient = nullptr;
175 QString szErr;
176 szErr = tr("Fail: Connect to %1:%2").arg(m_pParameter->m_Net.GetHost(),
177 QString::number(m_pParameter->m_Net.GetPort()));
178 qCritical(log) << szErr;
179 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
180 return OnInitReturnValue::Fail;
181 }
182
183 QString szInfo = QString("Connected to ") + m_pClient->desktopName;
184 qInfo(log) << szInfo;
185
186 emit sigSetDesktopSize(m_pClient->width, m_pClient->height);
187 emit sigServerName(m_pClient->desktopName);
188 emit sigInformation(szInfo);
189 emit sigSecurityLevel(m_SecurityLevel);
190 emit sigRunning();
191 return OnInitReturnValue::UseOnProcess;
192 }
193 /*case CParameterProxy::TYPE::SockesV5:
194 {
195 QNetworkProxy proxy;
196 proxy.setType(QNetworkProxy::Socks5Proxy);
197 auto &net = m_pParameter->m_Proxy.m_SockesV5;
198 proxy.setHostName(net.GetHost());
199 if(net.GetHost().isEmpty())
200 {
201 QString szErr;
202 szErr = tr("The proxy server is empty, please input it");
203 qCritical(log) << szErr;
204 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
205 return OnInitReturnValue::Fail;
206 }
207 proxy.setPort(net.GetPort());
208 auto &user = net.m_User;
209 proxy.setUser(user.GetUser());
210 proxy.setPassword(user.GetPassword());
211 m_tcpSocket.setProxy(proxy);
212 m_tcpSocket.connectToHost(m_pClient->serverHost, m_pClient->serverPort);
213 if (!m_tcpSocket.waitForConnected(3000))
214 return OnInitReturnValue::Fail;
215 //TODO: The is fail
216 m_pClient->sock = m_tcpSocket.socketDescriptor();
217 if(!rfbInitClient(m_pClient, nullptr, nullptr))
218 {
219 // Because delete m_pClient in rfbInitClient
220 m_pClient = nullptr;
221 QString szErr;
222 szErr = tr("Connect to %1:%2 fail").arg(m_pParameter->m_Net.GetHost(),
223 QString::number(m_pParameter->m_Net.GetPort()));
224 qCritical(log) << szErr;
225 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
226 return OnInitReturnValue::Fail;
227 }
228 break;
229 }//*/
230 /*TODO: add UltraVncRepeater
231 case (CParameterOperate::emProxy) CParameterLibVNCServer::emVncProxy::UltraVncRepeater:
232 m_pClient->destHost = strdup(m_pPara->GetProxyHost().toStdString().c_str());
233 m_pClient->destPort = m_pPara->GetProxyPort();//*/
234
236#ifdef HAVE_LIBSSH
237 case CParameterProxy::TYPE::SSHTunnel:
238 {
239 // Start ssh thread
240 if(!m_pThread) {
241 // Don' t delete it, It deletes itself when it ends. See: CSSHTunnelThread::CSSHTunnelThread()
242 m_pThread = new CSSHTunnelThread(
243 &m_pParameter->m_Proxy.m_SSH, &m_pParameter->m_Net, this);
244 }
245 if(!m_pThread)
246 return OnInitReturnValue::Fail;
247 bool check = connect(m_pThread, SIGNAL(sigServer(QString, quint16)),
248 this, SLOT(slotConnectProxyServer(QString, quint16)));
249 Q_ASSERT(check);
250#if defined(HAVE_UNIX_DOMAIN_SOCKET)
251 check = connect(m_pThread, SIGNAL(sigServer(QString)),
252 this, SLOT(slotConnectProxyServer(QString)));
253 Q_ASSERT(check);
254#endif
255 check = connect(m_pThread, SIGNAL(sigError(int,QString)),
256 this, SIGNAL(sigError(int,QString)));
257 Q_ASSERT(check);
258 check = connect(m_pThread, SIGNAL(sigStop()),
259 this, SIGNAL(sigStop()));
260 Q_ASSERT(check);
261 m_pThread->start();
262
263 return OnInitReturnValue::NotUseOnProcess;
264 }
265#endif // #ifdef HAVE_LIBSSH
267 default:
268 break;
269 }
270
271 return OnInitReturnValue::UseOnProcess;
272}
273
275{
276 qDebug(log) << "CConnectLibVNCServer::OnClean()";
277#ifdef HAVE_LIBSSH
278 if(m_pThread)
279 {
280 disconnect(m_pThread);
281 m_pThread->Exit();
282 m_pThread = nullptr;
283 }
284#endif
285 if(m_pClient)
286 {
287 //m_tcpSocket.close();
288 rfbClientCleanup(m_pClient);
289 m_pClient = nullptr;
290 }
291
292 emit sigFinished();
293 return 0;
294}
295
310{
311 //qDebug(log) << Q_FUNC_INFO;
312 int nRet = 0;
313 if(!m_pClient)
314 {
315 // Stop
316 return -1;
317 }
318
319 struct timeval timeout = {0, DEFAULT_TIMEOUT};
320 fd_set set;
321 FD_ZERO(&set);
322 if(RFB_INVALID_SOCKET != m_pClient->sock)
323 {
324 FD_SET(m_pClient->sock, &set);
325 }
326 rfbSocket eventFd = m_Event.GetFd();
327 if(RFB_INVALID_SOCKET != eventFd)
328 {
329 FD_SET(eventFd, &set);
330 }
331 rfbSocket fd = RFB_INVALID_SOCKET;
332 fd = std::max(eventFd, m_pClient->sock);
333 //qDebug(log) << "fd:" << fd << "select m_pClient->sock:" << (int)m_pClient->sock << "event:" << eventFd;
334 nRet = select(fd + 1, &set, NULL, NULL, &timeout);
335 //qDebug(log) << "select end";
336 if (nRet < 0) {
337 qCritical(log) << "select fail:" << nRet << "errno" << errno << strerror(errno);
338 return nRet;
339 }
340
341 /*if(0 == nRet)
342 {
343 //qDebug(log) << "Time out";
344 return 0;
345 }//*/
346
347 if(RFB_INVALID_SOCKET != eventFd && FD_ISSET(eventFd, &set))
348 {
349 //qDebug(log) << "fires event";
350 m_Event.Reset();
351 }
352
353 if(RFB_INVALID_SOCKET != m_pClient->sock
354 && FD_ISSET(m_pClient->sock, &set)) {
355 //qDebug(log) << "HandleRFBServerMessage";
356 if(!HandleRFBServerMessage(m_pClient))
357 {
358 qCritical(log) << "HandleRFBServerMessage fail";
359 return -2;
360 }
361 }
362
363 return 0;
364}
365
367{
368 return m_Event.WakeUp();
369}
370
372{
373 if(!m_pParameter || !m_pParameter->GetClipboard() || !m_pClient) return;
374 QClipboard* pClipboard = QApplication::clipboard();
375 if(pClipboard)
376 {
377 QString szText = pClipboard->text();
378 if(!szText.isEmpty() && m_pClient)
379 SendClientCutText(m_pClient,
380 (char*)szText.toStdString().c_str(),
381 szText.toStdString().length());
382 }
383}
384
385rfbBool CBackendLibVNCServer::cb_resize(rfbClient* client)
386{
387 //qDebug(log) << "CConnectLibVnc::cb_resize:" << client->width << client->height;
388 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(client, (void*)gThis);
389 if(pThis->OnSize()) return FALSE;
390 return TRUE;
391}
392
393void CBackendLibVNCServer::cb_update(rfbClient *client, int x, int y, int w, int h)
394{
395 if(0 == w || 0 == h)
396 return;
397 //qDebug(LibVNCServer, "CConnectLibVnc::cb_update:(%d, %d, %d, %d)", x, y, w, h);
398 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(client, (void*)gThis);
399 QRect rect(x, y, w, h);
400 QImage img = pThis->m_Image.copy(rect);
401 emit pThis->sigUpdateRect(rect, img);
402}
403
404void CBackendLibVNCServer::cb_got_selection(rfbClient *client, const char *text, int len)
405{
406 //qDebug(LibVNCServer, "CConnectLibVnc::cb_got_selection:%s", text);
407 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(client, (void*)gThis);
408 if(!pThis->m_pParameter->GetClipboard()) return;
409 QClipboard* pClipboard = QApplication::clipboard();
410 if(pClipboard)
411 pClipboard->setText(text);
412}
413
414void CBackendLibVNCServer::cb_kbd_leds(rfbClient *client, int value, int pad)
415{
416 qDebug(log) << "CConnectLibVnc::cb_kbd_leds";
417}
418
419void CBackendLibVNCServer::cb_bell(struct _rfbClient *client)
420{
421 qApp->beep();
422}
423
424void CBackendLibVNCServer::cb_text_chat(rfbClient *client, int value, char *text)
425{
426 qDebug(log) << "CConnectLibVnc::cb_text_chat";
427}
428
429rfbCredential* CBackendLibVNCServer::cb_get_credential(rfbClient *cl, int credentialType)
430{
431 qDebug(log) <<"CConnectLibVnc::cb_get_credential";
432 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(cl, (void*)gThis);
433 rfbCredential *c = (rfbCredential*)malloc(sizeof(rfbCredential));
434 c->userCredential.username = (char*)malloc(RFB_BUF_SIZE);
435 memset(c->userCredential.username, 0, RFB_BUF_SIZE);
436 c->userCredential.password = (char*)malloc(RFB_BUF_SIZE);
437 memset(c->userCredential.password, 0, RFB_BUF_SIZE);
438
439 if(credentialType != rfbCredentialTypeUser) {
440 qCritical(log) << "something else than username and password required for authentication";
441 return NULL;
442 }
443
444 qDebug(log) << "Username and password required for authentication!";
445
446 memcpy(c->userCredential.username,
447 pThis->m_pParameter->m_Net.m_User.GetUser().toStdString().c_str(),
448 pThis->m_pParameter->m_Net.m_User.GetUser().toStdString().length());
449 memcpy(c->userCredential.password,
450 pThis->m_pParameter->m_Net.m_User.GetPassword().toStdString().c_str(),
451 pThis->m_pParameter->m_Net.m_User.GetPassword().toStdString().length());
452
453 return c;
454}
455
456char* CBackendLibVNCServer::cb_get_password(rfbClient *client)
457{
458 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(client, (void*)gThis);
459 QString szPassword = pThis->m_pParameter->m_Net.m_User.GetPassword();
460 if(szPassword.isEmpty())
461 {
462 int nRet = QDialog::Rejected;
463 auto *net = &pThis->m_pParameter->m_Net;
464 emit pThis->sigBlockShowWidget("CDlgUserPassword", nRet, net);
465 if(QDialog::Accepted == nRet)
466 {
467 szPassword = net->m_User.GetPassword();
468 }
469 }
470 if(!szPassword.isEmpty())
471 pThis->m_SecurityLevel |= CSecurityLevel::Level::Authentication;
472 return strdup(szPassword.toStdString().c_str());
473}
474
475int CBackendLibVNCServer::OnSize()
476{
477 int nRet = 0;
478 int nWidth = m_pClient->width;
479 int nHeight = m_pClient->height;
480
481 m_Image = QImage(nWidth, nHeight, QImage::Format_RGB32);
482
483 m_pClient->frameBuffer = m_Image.bits();
484
485 m_pClient->format.bitsPerPixel = 32;
486 m_pClient->format.depth = m_Image.depth();
487 m_pClient->format.redShift = 16;
488 m_pClient->format.greenShift = 8;
489 m_pClient->format.blueShift = 0;
490 m_pClient->format.redMax = 255;
491 m_pClient->format.greenMax = 255;
492 m_pClient->format.blueMax = 255;
493 SetFormatAndEncodings(m_pClient);
494
495 emit sigSetDesktopSize(m_pClient->width, m_pClient->height);
496 return nRet;
497}
498
499rfbBool CBackendLibVNCServer::cb_cursor_pos(rfbClient *client, int x, int y)
500{
501 //qDebug(LibVNCServer, "CConnectLibVnc::cb_cursor_pos:%d,%d", x, y);
502 rfbBool bRet = true;
503
504 return bRet;
505}
506
507void CBackendLibVNCServer::cb_got_cursor_shape(rfbClient *client,
508 int xhot, int yhot,
509 int width, int height,
510 int bytesPerPixel)
511{
512 /*
513 qDebug(LibVNCServer, "CConnectLibVnc::cb_got_cursor_shape:x:%d, y:%d, width:%d, height:%d, bytesPerPixel:%d",
514 xhot, yhot, width, height, bytesPerPixel);//*/
515 if(!client->rcSource)
516 {
517 qCritical(log) << "client->rcSource is null";
518 return;
519 }
520 CBackendLibVNCServer* pThis = (CBackendLibVNCServer*)rfbClientGetClientData(client, (void*)gThis);
521 if ((width == 0) || (height == 0)) {
522 QImage cursor(1, 1, QImage::Format_ARGB32);
523 uchar* buffer = cursor.bits();
524 memset(buffer, 0, 4);
525 emit pThis->sigUpdateCursor(QCursor(QPixmap::fromImage(cursor), xhot, yhot));
526 } else {
527 switch (bytesPerPixel) {
528 case 4:
529 {
530 QImage cursor(width, height, QImage::Format_ARGB32);
531 uchar *buffer = cursor.bits();
532 memcpy(buffer, client->rcSource, width * height * 4);
533 uchar* pMask = client->rcMask;
534 if(pMask)
535 {
536 uchar* pDest = buffer;
537 for(int y = 0; y < height; y++)
538 {
539 for(int w = 0; w < width; w++)
540 {
541 if(*pMask++)
542 {
543 // NOTE: Do not manipulate the memory,
544 // because the host byte order may be different
545 QColor c = cursor.pixel(w, y);
546 c.setAlpha(0xff);
547 cursor.setPixelColor(w,y,c);
548 }
549 else
550 *((uint32_t*)pDest) = 0;
551
552 pDest += 4;
553 }
554 }
555 }
556 emit pThis->sigUpdateCursor(QCursor(QPixmap::fromImage(cursor), xhot, yhot));
557 break;
558 }
559 default:
560 break;
561 }
562 }
563}
564
565void CBackendLibVNCServer::mousePressEvent(QMouseEvent *event)
566{
567 if(!m_pClient) return;
568 if(m_pParameter && m_pParameter->GetOnlyView()) return;
569
570 unsigned char mask = 0;
571 if(event->button() & Qt::MouseButton::LeftButton)
572 mask |= 0x1;
573 if(event->button() & Qt::MouseButton::MiddleButton)
574 mask |= 0x2;
575 if(event->button() & Qt::MouseButton::RightButton)
576 mask |= 0x4;
577 if(event->button() & Qt::MouseButton::BackButton)
578 mask |= 0x80;
579 QPoint pos = event->pos();
580
581 qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->button() << pos << mask;
582
583 SendPointerEvent(m_pClient, pos.x(), pos.y(), mask);
584}
585
586void CBackendLibVNCServer::mouseReleaseEvent(QMouseEvent *event)
587{
588 if(!m_pClient) return;
589 if(m_pParameter && m_pParameter->GetOnlyView()) return;
590 int mask = 0;
591 QPoint pos = event->pos();
592 qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->button() << pos << mask;
593 SendPointerEvent(m_pClient, pos.x(), pos.y(), mask);
594}
595
596void CBackendLibVNCServer::mouseMoveEvent(QMouseEvent *event)
597{
598 if(!m_pClient) return;
599 if(m_pParameter && m_pParameter->GetOnlyView()) return;
600 int mask = 0;
601 if(event->buttons() & Qt::MouseButton::LeftButton)
602 mask |= 0x1;
603 if(event->buttons() & Qt::MouseButton::MiddleButton)
604 mask |= 0x2;
605 if(event->buttons() & Qt::MouseButton::RightButton)
606 mask |= 0x4;
607 if(event->buttons() & Qt::MouseButton::BackButton)
608 mask |= 0x80;
609 QPoint pos = event->pos();
610 qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->button() << pos << mask;
611 SendPointerEvent(m_pClient, pos.x(), pos.y(), mask);
612}
613
614// https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst#pointerevent
615void CBackendLibVNCServer::wheelEvent(QWheelEvent *event)
616{
617 if(!m_pClient) return;
618 if(m_pParameter && m_pParameter->GetOnlyView()) return;
619 int mask = 0;
620 if(event->buttons() & Qt::MouseButton::LeftButton)
621 mask |= 0x1;
622 if(event->buttons() & Qt::MouseButton::MiddleButton)
623 mask |= 0x2;
624 if(event->buttons() & Qt::MouseButton::RightButton)
625 mask |= 0x4;
626 if(event->buttons() & Qt::MouseButton::BackButton)
627 mask |= 0x80;
628
629 QPoint d = event->angleDelta();
630 if(d.y() > 0)
631 mask |= 0x8;
632 if(d.y() < 0)
633 mask |= 0x10;
634 if(d.x() < 0)
635 mask |= 0x20;
636 if(d.x() > 0)
637 mask |= 0x40;
638
639 QPointF pos;
640#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
641 pos = event->position();
642#else
643 pos = event->pos();
644#endif
645
646 qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->angleDelta() << pos;
647
648 SendPointerEvent(m_pClient, pos.x(), pos.y(), mask);
649}
650
658uint32_t TranslateRfbKey(quint32 inkey, bool modifier)
659{
660 quint32 k = 5000;
661
662 switch (inkey)
663 {
664 case Qt::Key_Backspace: k = XK_BackSpace; break;
665 case Qt::Key_Tab: k = XK_Tab; break;
666 case Qt::Key_Clear: k = XK_Clear; break;
667 case Qt::Key_Return: k = XK_Return; break;
668 case Qt::Key_Pause: k = XK_Pause; break;
669 case Qt::Key_Escape: k = XK_Escape; break;
670 case Qt::Key_Space: k = XK_space; break;
671 case Qt::Key_Delete: k = XK_Delete; break;
672 case Qt::Key_Period: k = XK_period; break;
673
674 /* International & multi-key character composition */
675 case Qt::Key_Multi_key: k = XK_Multi_key; break;
676 case Qt::Key_SingleCandidate: k = XK_SingleCandidate; break;
677 case Qt::Key_MultipleCandidate: k = XK_MultipleCandidate; break;
678 case Qt::Key_PreviousCandidate: k = XK_PreviousCandidate; break;
679
680 /* Japanese keyboard support */
681 case Qt::Key_Kanji: k = XK_Kanji; break;
682 case Qt::Key_Muhenkan: k = XK_Muhenkan; break;
683 case Qt::Key_Henkan: k = XK_Henkan; break;
684 case Qt::Key_Romaji: k = XK_Romaji; break;
685 case Qt::Key_Hiragana: k = XK_Hiragana; break;
686 case Qt::Key_Katakana: k = XK_Katakana; break;
687 case Qt::Key_Hiragana_Katakana: k = XK_Hiragana_Katakana;break;
688 case Qt::Key_Zenkaku: k = XK_Zenkaku; break;
689 case Qt::Key_Hankaku: k = XK_Hankaku; break;
690 case Qt::Key_Zenkaku_Hankaku: k = XK_Zenkaku_Hankaku; break;
691 case Qt::Key_Touroku: k = XK_Touroku; break;
692 case Qt::Key_Massyo: k = XK_Massyo; break;
693 case Qt::Key_Kana_Lock: k = XK_Kana_Lock; break;
694 case Qt::Key_Kana_Shift: k = XK_Kana_Shift; break;
695 case Qt::Key_Eisu_Shift: k = XK_Eisu_Shift; break;
696 case Qt::Key_Eisu_toggle: k = XK_Eisu_toggle; break;
697
698 //special keyboard char
699 case Qt::Key_Exclam: k = XK_exclam; break;
700 case Qt::Key_QuoteDbl: k = XK_quotedbl; break; //"
701 case Qt::Key_NumberSign: k = XK_numbersign; break; //#
702 case Qt::Key_Percent: k = XK_percent; break; //%
703 case Qt::Key_Dollar: k = XK_dollar; break; //$
704 case Qt::Key_Ampersand: k = XK_ampersand; break; //&
705 case Qt::Key_Apostrophe: k = XK_apostrophe; break;
706 case Qt::Key_ParenLeft: k = XK_parenleft; break; // (
707 case Qt::Key_ParenRight: k = XK_parenright; break; // )
708
709 case Qt::Key_Slash: k = XK_slash; break; // /
710 case Qt::Key_Asterisk: k = XK_asterisk; break; //*
711 case Qt::Key_Minus: k = XK_minus; break; //-
712 case Qt::Key_Plus: k = XK_plus; break; //+
713 case Qt::Key_Enter: k = XK_Return; break; //
714 case Qt::Key_Equal: k = XK_equal; break; //=
715 case Qt::Key_Comma: return XK_comma; //,
716
717 case Qt::Key_Colon: k = XK_colon;break; // :
718 case Qt::Key_Semicolon: k = XK_semicolon; break; //;
719 case Qt::Key_Less: k = XK_less; break; // <
720 case Qt::Key_Greater: k = XK_greater; break; // >
721 case Qt::Key_Question: k = XK_question; break; //?
722 case Qt::Key_At: k = XK_at; break; //@
723
724 case Qt::Key_BracketLeft: k = XK_bracketleft; break;
725 case Qt::Key_Backslash: k = XK_backslash;break;
726 case Qt::Key_BracketRight: k = XK_bracketright;break;
727 case Qt::Key_AsciiCircum: k = XK_asciicircum;break;
728 case Qt::Key_Underscore: k = XK_underscore;break;
729 case Qt::Key_QuoteLeft: k = XK_quoteleft;break;
730 case Qt::Key_BraceLeft: k = XK_braceleft;break;
731 case Qt::Key_Bar: k = XK_bar; break;
732 case Qt::Key_BraceRight: k = XK_braceright;break;
733 case Qt::Key_AsciiTilde: k = XK_asciitilde;break;
734 case Qt::Key_nobreakspace: k = XK_nobreakspace;break;
735 case Qt::Key_exclamdown: k = XK_exclamdown;break;
736 case Qt::Key_cent: k = XK_cent;break;
737 case Qt::Key_sterling: k = XK_sterling;break;
738 case Qt::Key_currency: k = XK_currency;break;
739 case Qt::Key_yen: k = XK_yen;break;
740 case Qt::Key_brokenbar: k = XK_brokenbar;break;
741 case Qt::Key_section: k = XK_section;break;
742 case Qt::Key_diaeresis: k = XK_diaeresis;break;
743 case Qt::Key_copyright: k = XK_copyright; break;
744 case Qt::Key_ordfeminine: k = XK_ordfeminine; break;
745 case Qt::Key_guillemotleft: k = XK_guillemotleft; break;
746 case Qt::Key_guillemotright: k = XK_guillemotright; break;
747 case Qt::Key_notsign: k = XK_notsign; break;
748 case Qt::Key_hyphen: k = XK_hyphen; break;
749 case Qt::Key_registered: k = XK_registered; break;
750
751 case Qt::Key_Up: k = XK_Up; break;
752 case Qt::Key_Down: k = XK_Down; break;
753 case Qt::Key_Right: k = XK_Right; break;
754 case Qt::Key_Left: k = XK_Left; break;
755 case Qt::Key_Insert: k = XK_Insert; break;
756 case Qt::Key_Home: k = XK_Home; break;
757 case Qt::Key_End: k = XK_End; break;
758 case Qt::Key_PageUp: k = XK_Page_Up; break;
759 case Qt::Key_PageDown: k = XK_Page_Down; break;
760 case Qt::Key_MediaPrevious: k = XK_Prior; break;
761 case Qt::Key_MediaNext: k = XK_Next; break;
762 case Qt::Key_MediaPlay: k = XK_Begin; break;
763
764 /* Misc Functions */
765 case Qt::Key_Select: k = XK_Select; break;
766 case Qt::Key_Printer: k = XK_Print; break;
767 case Qt::Key_Execute: k = XK_Execute; break;
768 case Qt::Key_Undo: k = XK_Undo; break;
769 case Qt::Key_Redo: k = XK_Redo; break;
770 case Qt::Key_Menu: k = XK_Menu;break;
771 case Qt::Key_Find: k = XK_Find; break;
772 case Qt::Key_Exit:
773 case Qt::Key_Cancel:
774 case Qt::Key_Stop:
775 k = XK_Cancel;
776 break;
777 case Qt::Key_Mode_switch: k = XK_Mode_switch; break;
778
779 case Qt::Key_F1: k = XK_F1; break;
780 case Qt::Key_F2: k = XK_F2; break;
781 case Qt::Key_F3: k = XK_F3; break;
782 case Qt::Key_F4: k = XK_F4; break;
783 case Qt::Key_F5: k = XK_F5; break;
784 case Qt::Key_F6: k = XK_F6; break;
785 case Qt::Key_F7: k = XK_F7; break;
786 case Qt::Key_F8: k = XK_F8; break;
787 case Qt::Key_F9: k = XK_F9; break;
788 case Qt::Key_F10: k = XK_F10; break;
789 case Qt::Key_F11: k = XK_F11; break;
790 case Qt::Key_F12: k = XK_F12; break;
791 case Qt::Key_F13: k = XK_F13; break;
792 case Qt::Key_F14: k = XK_F14; break;
793 case Qt::Key_F15: k = XK_F15; break;
794 case Qt::Key_F16: k = XK_F16; break;
795 case Qt::Key_F17: k = XK_F17; break;
796 case Qt::Key_F18: k = XK_F18; break;
797 case Qt::Key_F19: k = XK_F19; break;
798 case Qt::Key_F20: k = XK_F20; break;
799 case Qt::Key_F21: k = XK_F21; break;
800 case Qt::Key_F22: k = XK_F22; break;
801 case Qt::Key_F23: k = XK_F23; break;
802 case Qt::Key_F24: k = XK_F24; break;
803 case Qt::Key_F25: k = XK_F25; break;
804 case Qt::Key_F26: k = XK_F26; break;
805 case Qt::Key_F27: k = XK_F27; break;
806 case Qt::Key_F28: k = XK_F28; break;
807 case Qt::Key_F29: k = XK_F29; break;
808 case Qt::Key_F30: k = XK_F30; break;
809 case Qt::Key_F31: k = XK_F31; break;
810 case Qt::Key_F32: k = XK_F32; break;
811 case Qt::Key_F33: k = XK_F33; break;
812 case Qt::Key_F34: k = XK_F34; break;
813 case Qt::Key_F35: k = XK_F35; break;
814
815 case Qt::Key_NumLock: k = XK_Num_Lock; break;
816 case Qt::Key_CapsLock: k = XK_Caps_Lock; break;
817 case Qt::Key_ScrollLock: k = XK_Scroll_Lock; break;
818
819 case Qt::Key_Shift: k = XK_Shift_R; break; //k = XK_Shift_L; break;
820 case Qt::Key_Control: k = XK_Control_R; break;// k = XK_Control_L; break;
821 case Qt::Key_Alt: k = XK_Alt_R; break;//k = XK_Alt_L; break;
822 case Qt::Key_Meta: k = XK_Meta_R; break;//k = XK_Meta_L; break;*/
823
824 case Qt::Key_Super_L: k = XK_Super_L; break; /* left "windows" key */
825 case Qt::Key_Super_R: k = XK_Super_R; break; /* right "windows" key */
826
827 case Qt::Key_Help: k = XK_Help; break;
828 case Qt::Key_Print: k = XK_Print; break;
829 case Qt::Key_SysReq: k = XK_Sys_Req; break;
830 case Qt::Key_0: k = XK_0;break;
831 case Qt::Key_1: k = XK_1;break;
832 case Qt::Key_2: k = XK_2;break;
833 case Qt::Key_3: k = XK_3;break;
834 case Qt::Key_4: k = XK_4;break;
835 case Qt::Key_5: k = XK_5;break;
836 case Qt::Key_6: k = XK_6;break;
837 case Qt::Key_7: k = XK_7;break;
838 case Qt::Key_8: k = XK_8;break;
839 case Qt::Key_9: k = XK_9;break;
840 }
841
842 if (k == 5000)
843 {
844
845 if (!modifier)
846 {
847 switch (inkey)
848 {
849 case Qt::Key_A: k = XK_a;break;
850 case Qt::Key_B: k = XK_b;break;
851 case Qt::Key_C: k = XK_c;break;
852 case Qt::Key_D: k = XK_d;break;
853 case Qt::Key_E: k = XK_e;break;
854 case Qt::Key_F: k = XK_f;break;
855 case Qt::Key_G: k = XK_g;break;
856 case Qt::Key_H: k = XK_h;break;
857 case Qt::Key_I: k = XK_i;break;
858 case Qt::Key_J: k = XK_j;break;
859 case Qt::Key_K: k = XK_k;break;
860 case Qt::Key_L: k = XK_l;break;
861 case Qt::Key_M: k = XK_m;break;
862 case Qt::Key_N: k = XK_n;break;
863 case Qt::Key_O: k = XK_o;break;
864 case Qt::Key_P: k = XK_p;break;
865 case Qt::Key_Q: k = XK_q;break;
866 case Qt::Key_R: k = XK_r;break;
867 case Qt::Key_S: k = XK_s;break;
868 case Qt::Key_T: k = XK_t;break;
869 case Qt::Key_U: k = XK_u;break;
870 case Qt::Key_V: k = XK_v;break;
871 case Qt::Key_W: k = XK_w;break;
872 case Qt::Key_X: k = XK_x;break;
873 case Qt::Key_Y: k = XK_y;break;
874 case Qt::Key_Z: k = XK_z;break;
875 }
876 }
877 else
878 {
879 switch (inkey)
880 {
881 case Qt::Key_A: k = XK_A;break;
882 case Qt::Key_B: k = XK_B;break;
883 case Qt::Key_C: k = XK_C;break;
884 case Qt::Key_D: k = XK_D;break;
885 case Qt::Key_E: k = XK_E;break;
886 case Qt::Key_F: k = XK_F;break;
887 case Qt::Key_G: k = XK_G;break;
888 case Qt::Key_H: k = XK_H;break;
889 case Qt::Key_I: k = XK_I;break;
890 case Qt::Key_J: k = XK_J;break;
891 case Qt::Key_K: k = XK_K;break;
892 case Qt::Key_L: k = XK_L;break;
893 case Qt::Key_M: k = XK_M;break;
894 case Qt::Key_N: k = XK_N;break;
895 case Qt::Key_O: k = XK_O;break;
896 case Qt::Key_P: k = XK_P;break;
897 case Qt::Key_Q: k = XK_Q;break;
898 case Qt::Key_R: k = XK_R;break;
899 case Qt::Key_S: k = XK_S;break;
900 case Qt::Key_T: k = XK_T;break;
901 case Qt::Key_U: k = XK_U;break;
902 case Qt::Key_V: k = XK_V;break;
903 case Qt::Key_W: k = XK_W;break;
904 case Qt::Key_X: k = XK_X;break;
905 case Qt::Key_Y: k = XK_Y;break;
906 case Qt::Key_Z: k = XK_Z;break;
907 }
908 }
909 }
910
911 return k;
912}
913
914void CBackendLibVNCServer::keyPressEvent(QKeyEvent *event)
915{
916 if(!m_pClient) return;
917 if(m_pParameter && m_pParameter->GetOnlyView()) return;
918 bool modifier = false;
919 if (event->modifiers() & Qt::ShiftModifier)
920 modifier = true;
921 uint32_t k = TranslateRfbKey(event->key(), modifier);
922 qDebug(logKey) << Q_FUNC_INFO << event << k << modifier;
923 SendKeyEvent(m_pClient, k, TRUE);
924}
925
926void CBackendLibVNCServer::keyReleaseEvent(QKeyEvent *event)
927{
928 if(!m_pClient) return;
929 if(m_pParameter && m_pParameter->GetOnlyView()) return;
930 bool modifier = false;
931 if (event->modifiers() & Qt::ShiftModifier)
932 modifier = true;
933 uint32_t k = TranslateRfbKey(event->key(), modifier);
934 qDebug(logKey) << Q_FUNC_INFO << event << k << modifier;
935 SendKeyEvent(m_pClient, k, FALSE);
936}
937
938void CBackendLibVNCServer::InputMethodEvent(QInputMethodEvent *event)
939{
940}
941
943void CBackendLibVNCServer::slotConnectProxyServer(QString szHost, quint16 nPort)
944{
945 QString szErr;
946 auto &net = m_pParameter->m_Proxy.m_SSH.m_Net;
947 //qDebug(log) << "CConnectLibVNCServer::slotConnectServer" << nPort;
948 // Set server ip and port
949 m_pClient->serverHost = strdup(szHost.toStdString().c_str());
950 m_pClient->serverPort = nPort;
951 szErr = tr("Will connect to local socket server: %1:%2")
952 .arg(m_pClient->serverHost,
953 QString::number(m_pClient->serverPort));
954 qDebug(log) << szErr;
955 if(!rfbInitClient(m_pClient, nullptr, nullptr))
956 {
957 // Because delete m_pClient in rfbInitClient
958 m_pClient = nullptr;
959 QString szErr;
960 szErr = tr("Fail: Connect to %1:%2 <- %3:%4 <- %5:%6")
961 .arg(m_pParameter->m_Net.GetHost(),
962 QString::number(m_pParameter->m_Net.GetPort()),
963 net.GetHost(), QString::number(net.GetPort()),
964 szHost, QString::number(nPort)
965 );
966 qCritical(log) << szErr;
967 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
968 return;
969 }
970
971 QString szInfo = QString("Connected to %1 <- %2:%3 <- %4:%5")
972 .arg(m_pClient->desktopName,
973 net.GetHost(), QString::number(net.GetPort()),
974 szHost, QString::number(nPort));
975 qInfo(log) << szInfo;
976 slotTimeOut();
977 emit sigSetDesktopSize(m_pClient->width, m_pClient->height);
978 emit sigServerName(m_pClient->desktopName);
979 emit sigInformation(szInfo);
980 emit sigSecurityLevel(m_SecurityLevel |= CSecurityLevel::Level::Proxy);
981 emit sigRunning();
982}
983
984#if defined(HAVE_UNIX_DOMAIN_SOCKET)
986{
987 QString szErr;
988 //qDebug(log) << "CConnectLibVNCServer::slotConnectServer" << szFile;
989 // Set server ip and port
990 m_pClient->serverHost = strdup(szFile.toStdString().c_str());
991 szErr = tr("Will connect to local socket server: ") + szFile;
992 qDebug(log) << szErr;
993 if(!rfbInitClient(m_pClient, nullptr, nullptr))
994 {
995 // Because delete m_pClient in rfbInitClient
996 m_pClient = nullptr;
997 QString szErr;
998 szErr = tr("Fail: Connect to %1:%2 with %3")
999 .arg(m_pParameter->m_Net.GetHost(),
1000 QString::number(m_pParameter->m_Net.GetPort()),
1001 szFile);
1002 qCritical(log) << szErr;
1003 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
1004 return;
1005 }
1006
1007 QString szInfo = QString("Connected to ") + m_pClient->desktopName + " with " + szFile;
1008 qInfo(log) << szInfo;
1009
1010 slotTimeOut();
1011 emit sigSetDesktopSize(m_pClient->width, m_pClient->height);
1012 emit sigServerName(m_pClient->desktopName);
1013 emit sigInformation(szInfo);
1014 emit sigRunning();
1015}
1016#endif
Remote desktop interface.
void sigUpdateRect(const QRect &r, const QImage &image)
Notify the CFrmView update image.
virtual int OnClean() override
Clean.
void slotConnectProxyServer(QString szHost, quint16 nPort)
[connect local socket server]
virtual int WakeUp() override
Wake up backend thread(background thread).
virtual void slotClipBoardChanged() override
Be called when the clip board change.
virtual OnInitReturnValue OnInit() override
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.
CParameterUser m_User
[Instance user]
Data is forwarded over a local socket and SSH tunnel.
Security level.
Definition Stats.h:97