Rabbit Remote Control 0.0.37
Loading...
Searching...
No Matches
BackendVnc.cpp
1// Author: Kang Lin <kl222@126.com>
2
3#include "BackendVnc.h"
4#include "OperateDesktop.h"
5
6#ifndef WIN32
7#include <string.h>
8#include "network/UnixSocket.h"
9#endif
10
11#include <rfb/CMsgWriter.h>
12#include <rfb/Hostname.h>
13#include "rfb/LogWriter.h"
14#include <rfb/util.h>
15#include <rfb/clipboardTypes.h>
16#include <rfb/LogWriter.h>
17#include <rfb/Logger_stdio.h>
18#include <rfb/fenceTypes.h>
19
20// the X11 headers on some systems
21#ifndef XK_VoidSymbol
22#define XK_LATIN1
23#define XK_MISCELLANY
24#define XK_XKB_KEYS
25#include <rfb/keysymdef.h>
26#endif
27
28#include "FramePixelBuffer.h"
29
30#include <QDir>
31#include <QMimeData>
32#include <QClipboard>
33#include <QApplication>
34#include <QLoggingCategory>
35#include <QThread>
36#include <QKeyEvent>
37#include <QMouseEvent>
38#include <QNetworkProxy>
39#include <QMutex>
40#include <QInputDialog>
41
42#include "rfb/Security.h"
43#include "rfb/Exception.h"
44#ifdef HAVE_GNUTLS
45#include "rfb/CSecurityTLS.h"
46#endif
47
48#ifdef HAVE_ICE
49 #include "Ice.h"
50 #include "ChannelIce.h"
51#endif
52
53#ifdef HAVE_LIBSSH
54 #include "ChannelSSHTunnel.h"
55#endif
56
57static Q_LOGGING_CATEGORY(log, "VNC.Connect")
58static Q_LOGGING_CATEGORY(logVNC, "VNC.Log")
59static Q_LOGGING_CATEGORY(logKey, "VNC.Connect.Key")
60static Q_LOGGING_CATEGORY(logMouse, "VNC.Connect.Mouse")
61
62class VncLogger: public rfb::Logger
63{
64public:
65 VncLogger(const char *name) : rfb::Logger(name)
66 {}
67 void write(int level, const char *logname, const char *text) override
68 {
69 if (level >= rfb::LogWriter::LEVEL_DEBUG) {
70 qDebug(logVNC) << logname << text;
71 } else if (level >= rfb::LogWriter::LEVEL_INFO) {
72 qInfo(logVNC) << logname << text;
73 } else if (level >= rfb::LogWriter::LEVEL_STATUS) {
74 qWarning(logVNC) << logname << text;
75 } else {
76 qCritical(logVNC) << logname << text;
77 }
78 }
79};
80
81static VncLogger g_logger("Rabbit");
82
83// 8 colours (1 bit per component)
84static const rfb::PixelFormat verylowColourPF(8, 3,false, true, 1, 1, 1, 2, 1, 0);
85// 64 colours (2 bits per component)
86static const rfb::PixelFormat lowColourPF(8, 6, false, true, 3, 3, 3, 4, 2, 0);
87// 256 colours (2-3 bits per component)
88static const rfb::PixelFormat mediumColourPF(8, 8, false, true, 7, 7, 3, 5, 2, 0);
89
90// RGB (4 bits per component)
91static const rfb::PixelFormat fullColourPF(32, 24, false, true, 255, 255, 255, 16, 8, 0);
92
93// Time new bandwidth estimates are weighted against (in ms)
94static const unsigned bpsEstimateWindow = 1000;
95
96CBackendVnc::CBackendVnc(COperateDesktop *pConnecter)
97 : CBackendDesktop(pConnecter),
98 m_pPara(nullptr)
99{
100 static bool initlog = false;
101 if(!initlog)
102 {
103 g_logger.registerLogger();
104 rfb::LogWriter::setLogParams("*:Rabbit:100");
105 /*rfb::initStdIOLoggers();
106 rfb::LogWriter::setLogParams("*:stderr:100");
107 QString szFile = RabbitCommon::CDir::Instance()->GetDirLog()
108 + QDir::separator()
109 + "TigerVnc.log";
110 rfb::initFileLogger(szFile.toStdString().c_str());
111 rfb::LogWriter::setLogParams("*:file:100");
112 */
113 initlog = true;
114 }
115 m_pPara = dynamic_cast<CParameterVnc*>(pConnecter->GetParameter());
116 Q_ASSERT(m_pPara);
117
118 if(!m_pPara->GetLocalCursor())
119 {
120 emit sigUpdateCursor(QCursor(Qt::BlankCursor));
121 }
122}
123
124CBackendVnc::~CBackendVnc()
125{
126 qDebug(log) << "CConnectVnc::~CConnectVnc()";
127}
128
129int CBackendVnc::SetPara()
130{
131 QDir d(os::getvncconfigdir());
132 if(!d.exists())
133 d.mkpath(os::getvncconfigdir());
134 QDir dstat(os::getvncstatedir());
135 if(!dstat.exists())
136 dstat.mkpath(os::getvncstatedir());
137 QDir dvnc(os::getvncdatadir());
138 if(!dvnc.exists())
139 dvnc.mkpath(os::getvncdatadir());
140
141 setServerName(m_pPara->m_Net.GetHost().toStdString().c_str());
142 setShared(m_pPara->GetShared());
143 supportsLocalCursor = m_pPara->GetLocalCursor();
144 supportsCursorPosition = m_pPara->GetCursorPosition();
145 supportsDesktopResize = m_pPara->GetSupportsDesktopResize();
146 supportsLEDState = m_pPara->GetLedState();
147
148 std::list<uint32_t> sec;
149 switch(m_pPara->m_Net.m_User.GetUsedType()) {
150 case CParameterUser::TYPE::None:
151 sec.push_back(rfb::secTypeNone);
152 break;
153 case CParameterUser::TYPE::OnlyPassword:
154 sec.push_back(rfb::secTypeVncAuth);
155 break;
156 case CParameterUser::TYPE::UserPassword:
157 sec.push_back(rfb::secTypePlain);
158 break;
160 sec.push_back(rfb::secTypeTLSVnc);
161 break;
162 case CParameterUser::TYPE::OnlyPasswordX509:
163 sec.push_back(rfb::secTypeX509Vnc);
164 break;
165 case CParameterUser::TYPE::UserPasswordX509None:
166 sec.push_back(rfb::secTypeTLSPlain);
167 break;
168 case CParameterUser::TYPE::UserPasswordX509:
169 sec.push_back(rfb::secTypeX509Plain);
170 break;
171 //TODO: add authentication
172 }
173 //*
174 qDebug(log) << "secTypes:" << security.GetEnabledSecTypes() << security.ToString()
175 << "new:" << sec; // << "Type:" << m_pPara->m_Net.m_User.GetType();//*/
176 security.SetSecTypes(sec);
177
178 // Set Preferred Encoding
179 setPreferredEncoding(m_pPara->GetPreferredEncoding());
180 setCompressLevel(m_pPara->GetCompressLevel());
181 setQualityLevel(m_pPara->GetQualityLevel());
182
183 // Set server pixmap format
184 updatePixelFormat();
185 return 0;
186}
187
188/*
189 * \return
190 * \li OnInitReturnValue::Fail: error
191 * \li OnInitReturnValue::UseOnProcess: Use OnProcess (non-Qt event loop)
192 * \li OnInitReturnValue::NotUseOnProcess: Don't use OnProcess (qt event loop)
193 */
194CBackendVnc::OnInitReturnValue CBackendVnc::OnInit()
195{
196 qDebug(log) << "CConnectVnc::OnInit()";
197 int nRet = 0;
198
199 if(m_pPara->GetIce())
200 nRet = IceInit();
201 else {
202#ifdef HAVE_LIBSSH
203 if(m_pPara->m_Proxy.GetUsedType() == CParameterProxy::TYPE::SSHTunnel) {
204 nRet = SSHInit();
205 if(nRet) return OnInitReturnValue::Fail; // error
206 return OnInitReturnValue::UseOnProcess;
207 }
208#endif
209 nRet = SocketInit();
210 }
211 if(nRet) return OnInitReturnValue::Fail; // error
212 // Don't use OnProcess (qt event loop)
213 return OnInitReturnValue::NotUseOnProcess;
214}
215
216int CBackendVnc::IceInit()
217{
218#ifdef HAVE_ICE
219 CIceSignal* pSignal = CICE::Instance()->GetSignal().data();
220 if(!pSignal || !pSignal->IsConnected())
221 {
222 qCritical(log) << "The g_pSignal is null. or signal don't connect server";
223 return -1;
224 }
225
226 qInfo(log, "Connected to signal server:%s:%d; user:%s",
227 CICE::Instance()->GetParameter()->getSignalServer().toStdString().c_str(),
228 CICE::Instance()->GetParameter()->getSignalPort(),
229 CICE::Instance()->GetParameter()->getSignalUser().toStdString().c_str());
230 auto channel = QSharedPointer<CChannelIce>(new CChannelIce(pSignal));
231 if(!channel)
232 {
233 qCritical(log) << "new CDataChannelIce fail";
234 return -2;
235 }
236 m_DataChannel = channel;
237 SetChannelConnect(channel);
238
239 rtc::Configuration config;
240 rtc::IceServer stun(CICE::Instance()->GetParameter()->getStunServer().toStdString().c_str(),
241 CICE::Instance()->GetParameter()->getStunPort());
242 rtc::IceServer turn(CICE::Instance()->GetParameter()->getTurnServer().toStdString().c_str(),
243 CICE::Instance()->GetParameter()->getTurnPort(),
244 CICE::Instance()->GetParameter()->getTurnUser().toStdString().c_str(),
245 CICE::Instance()->GetParameter()->getTurnPassword().toStdString().c_str());
246 config.iceServers.push_back(stun);
247 config.iceServers.push_back(turn);
248 channel->SetConfigure(config);
249
250 bool bRet = channel->open(CICE::Instance()->GetParameter()->getSignalUser(),
251 m_pPara->GetPeerUser(), true);
252 if(!bRet)
253 {
254 emit sigError(-1, "Open channel fail");
255 }
256
257#endif
258 return 0;
259}
260
261int CBackendVnc::SocketInit()
262{
263 int nRet = 0;
264 try{
265 QTcpSocket* pSock = new QTcpSocket(this);
266 if(!pSock)
267 return -1;
268 m_DataChannel = QSharedPointer<CChannel>(new CChannel(pSock));
269 if(!m_DataChannel) {
270 qCritical(log) << "New CChannel fail";
271 return -1;
272 }
273
274 SetChannelConnect(m_DataChannel);
275
276 if(!m_DataChannel->open(QIODevice::ReadWrite))
277 {
278 qCritical(log) << "Open channel fail";
279 return -1;
280 }
281
282 QNetworkProxy::ProxyType type = QNetworkProxy::NoProxy;
283 // Set sock
284 switch(m_pPara->m_Proxy.GetUsedType())
285 {
286 case CParameterProxy::TYPE::SockesV5:
287 type = QNetworkProxy::Socks5Proxy;
288 break;
289 case CParameterProxy::TYPE::System:
290 type = QNetworkProxy::DefaultProxy;
291 break;
292 case CParameterProxy::TYPE::Http:
293 type = QNetworkProxy::HttpProxy;
294 break;
295 case CParameterProxy::TYPE::None:
296 default:
297 break;
298 }
299
300 switch(type) {
301 case QNetworkProxy::DefaultProxy:
302 {
303 pSock->setProxy(QNetworkProxy::applicationProxy());
304 break;
305 }
306 case QNetworkProxy::HttpProxy:
307 case QNetworkProxy::Socks5Proxy:
308 {
309 QNetworkProxy proxy;
310 auto net = &m_pPara->m_Proxy.m_SockesV5;
311 if(QNetworkProxy::HttpProxy == type) {
312 net = &m_pPara->m_Proxy.m_Http;
313 }
314 if(net->GetHost().isEmpty())
315 {
316 QString szErr;
317 szErr = tr("The proxy server is empty, please input it");
318 qCritical(log) << szErr;
319 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
320 return -1;
321 }
322 proxy.setHostName(net->GetHost());
323 proxy.setPort(net->GetPort());
324 auto &user = net->m_User;
325 if(((user.GetUsedType() == CParameterUser::TYPE::UserPassword)
326 && (user.GetPassword().isEmpty() || user.GetUser().isEmpty()))
327 || ((user.GetUsedType() == CParameterUser::TYPE::PublicKey)
328 && user.GetPassphrase().isEmpty())) {
329 int nRet = QDialog::Rejected;
330 emit sigBlockShowWidget("CDlgUserPassword", nRet, net);
331 if(QDialog::Accepted != nRet)
332 {
333 return -1;
334 }
335 }
336 proxy.setUser(user.GetUser());
337 proxy.setPassword(user.GetPassword());
338 proxy.setType(type);
339 pSock->setProxy(proxy);
340 break;
341 }
342 default:
343 break;
344 }
345
346 if(m_pPara->m_Net.GetHost().isEmpty())
347 {
348 QString szErr;
349 szErr = tr("The server is empty, please input it");
350 qCritical(log) << szErr;
351 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
352 return -1;
353 }
354 pSock->connectToHost(m_pPara->m_Net.GetHost(), m_pPara->m_Net.GetPort());
355
356 QString serverHost;
357 serverHost = pSock->peerName();
358 qDebug(log) << "Server Host:" << serverHost;
359 setServerName(serverHost.toStdString().c_str());
360
361 return nRet;
362 } catch (rdr::Exception& e) {
363 qCritical(log) << "SocketInit exception:" << e.str();
364 emit sigError(-1, e.str());
365 nRet = -1;
366 }
367 return nRet;
368}
369
370int CBackendVnc::SSHInit()
371{
372#ifdef HAVE_LIBSSH
373 auto channel = QSharedPointer<CChannelSSHTunnel>(
374 new CChannelSSHTunnel(&m_pPara->m_Proxy.m_SSH, &m_pPara->m_Net, this));
375 if(!channel) {
376 qCritical(log) << "New CChannelSSHTunnel fail";
377 return -1;
378 }
379 m_DataChannel = channel;
380 SetChannelConnect(m_DataChannel);
381 if(!channel->open(QIODevice::ReadWrite))
382 {
383 QString szErr;
384 szErr = tr("Failed to open SSH tunnel:");
385 szErr += "(" + m_pPara->m_Proxy.m_SSH.m_Net.GetHost();
386 szErr += ":";
387 szErr += QString::number(m_pPara->m_Proxy.m_SSH.m_Net.GetPort());
388 szErr += " - ";
389 szErr += m_pPara->m_Net.GetHost();
390 szErr += ":";
391 szErr += QString::number(m_pPara->m_Net.GetPort()) + ")";
392 QString szMsg = szErr + "\n" + channel->errorString();
393 emit sigShowMessageBox(tr("Error"), szMsg, QMessageBox::Critical);
394 return -2;
395 }
396#endif
397 return 0;
398}
399
400int CBackendVnc::SetChannelConnect(QSharedPointer<CChannel> channel)
401{
402 bool check = false;
403 check = connect(channel.data(), SIGNAL(sigConnected()),
404 this, SLOT(slotConnected()));
405 Q_ASSERT(check);
406 check = connect(channel.data(), SIGNAL(sigDisconnected()),
407 this, SLOT(slotDisConnected()));
408 Q_ASSERT(check);
409 check = connect(channel.data(), SIGNAL(readyRead()),
410 this, SLOT(slotReadyRead()));
411 Q_ASSERT(check);
412 check = connect(channel.data(), SIGNAL(sigError(int, const QString&)),
413 this, SLOT(slotChannelError(int, const QString&)));
414 Q_ASSERT(check);
415 return 0;
416}
417
419{
420 qDebug(log) << "CConnectVnc::OnClean()";
421 close();
422 setStreams(nullptr, nullptr);
423 if(m_DataChannel) {
424 m_DataChannel->close();
425 }
426 return 0;
427}
428
443{
444 int nRet = 0;
445#ifdef HAVE_LIBSSH
446 if(m_pPara->m_Proxy.GetUsedType() == CParameterProxy::TYPE::SSHTunnel) {
447 CChannelSSHTunnel* channel = (CChannelSSHTunnel*)m_DataChannel.data();
448 if(channel)
449 nRet = channel->Process();
450 }
451#endif
452
453 return nRet;
454}
455
457{
458#ifdef HAVE_LIBSSH
459 if(m_pPara->m_Proxy.GetUsedType() == CParameterProxy::TYPE::SSHTunnel) {
460 CChannelSSHTunnel* channel = (CChannelSSHTunnel*)m_DataChannel.data();
461 if(channel)
462 channel->WakeUp();
463 }
464#endif
465 return 0;
466}
467
468void CBackendVnc::slotConnected()
469{
470 qDebug(log) << Q_FUNC_INFO;
471 if(m_pPara->GetIce())
472 qInfo(log) << "Connected to peer " + m_pPara->GetPeerUser();
473 else {
474 auto &net = m_pPara->m_Net;
475 QString szInfo = "Connected to "
476 + net.GetHost() + ":" + QString::number(net.GetPort());
477#ifdef HAVE_LIBSSH
478 if(CParameterProxy::TYPE::SSHTunnel == m_pPara->m_Proxy.GetUsedType())
479 {
480 auto &sshNet = m_pPara->m_Proxy.m_SSH.m_Net;
481 szInfo += " with ssh turnnel: " + sshNet.GetHost()
482 + ":" + QString::number(sshNet.GetPort());
483 }
484#endif
485 qInfo(log) << szInfo;
486 }
487 int nRet = SetPara();
488 if(nRet)
489 {
490 emit sigStop();
491 return;
492 }
493 m_InStream = QSharedPointer<rdr::InStream>(new CInStreamChannel(m_DataChannel.data()));
494 m_OutStream = QSharedPointer<rdr::OutStream>(new COutStreamChannel(m_DataChannel.data()));
495 if(!(m_InStream && m_OutStream))
496 {
497 qCritical(log) << "m_InStream or m_OutStream is null";
498 emit sigStop();
499 return;
500 }
501 setStreams(m_InStream.data(), m_OutStream.data());
502 initialiseProtocol();
503}
504
505void CBackendVnc::slotDisConnected()
506{
507 QString szInfo;
508 szInfo = "CConnectVnc::slotDisConnected() from "
509 + m_pPara->m_Net.GetHost() + ":"
510 + QString::number(m_pPara->m_Net.GetPort());
511#ifdef HAVE_LIBSSH
512 if(CParameterProxy::TYPE::SSHTunnel == m_pPara->m_Proxy.GetUsedType())
513 {
514 auto &net = m_pPara->m_Proxy.m_SSH.m_Net;
515 szInfo += " with ssh turnnel: " + net.GetHost()
516 + ":" + QString::number(net.GetPort());
517 }
518#endif
519 qInfo(log) << szInfo;
520}
521
522void CBackendVnc::slotReadyRead()
523{
524 //qDebug(log) << "CConnectVnc::slotReadyRead";
525 QString szErr("processMsg exception: ");
526 int nRet = -1;
527 try {
528 getOutStream()->flush();
529
530 getOutStream()->cork(true);
531 while(processMsg())
532 ;
533 getOutStream()->cork(false);
534 return;
535 } catch (rfb::AuthFailureException& e) {
536 szErr = tr("Logon to ");
537 szErr += m_pPara->m_Net.GetHost();
538 szErr += ":";
539 szErr += QString::number(m_pPara->m_Net.GetPort());
540 szErr += tr(" fail.");
541 QString szMsg = szErr + "\n" + tr("Please check that the username and password are correct.") + "\n";
542 emit sigShowMessageBox(tr("Error"), szMsg, QMessageBox::Critical);
543
544 szErr += " [";
545 szErr += e.str();
546 szErr += "]";
547 } catch (rfb::ConnFailedException& e) {
548 QString szErr;
549 szErr = tr("Connect to ");
550 szErr += m_pPara->m_Net.GetHost();
551 szErr += ":";
552 szErr += QString::number(m_pPara->m_Net.GetPort());
553 szErr += tr(" fail.");
554 szErr += " [";
555 szErr += e.str();
556 szErr += "]";
557 emit sigShowMessageBox(tr("Error"), szErr, QMessageBox::Critical);
558 } catch (rdr::EndOfStream& e) {
559 szErr += e.str();
560 } catch(rdr::GAIException &e) {
561 nRet = e.err;
562 szErr += "[" + QString::number(e.err) + "] " + e.str();
563 } catch(rdr::SystemException &e) {
564 nRet = e.err;
565 szErr += "[" + QString::number(e.err) + "] " + e.str();
566 } catch (rdr::Exception& e) {
567 szErr += e.str();
568 } catch (std::exception &e) {
569 szErr += e.what();
570 } catch(...) {
571 szErr += "unknown exception";
572 }
573 qCritical(log) << szErr;
574 emit sigError(nRet, szErr);
575 emit sigStop();
576}
577
578void CBackendVnc::slotChannelError(int nErr, const QString& szErr)
579{
580 qDebug(log) << "Channel error:" << nErr << "-" << szErr;
581 emit sigError(nErr, szErr);
582 emit sigStop();
583}
584
585// initDone() is called when the serverInit message has been received. At
586// this point we create the desktop window and display it. We also tell the
587// server the pixel format and encodings to use and request the first update.
588void CBackendVnc::initDone()
589{
590 Q_ASSERT(m_pPara);
591 qDebug(log, "initDone:\n%s", ConnectInformation().toStdString().c_str());
592
593 emit sigSetDesktopSize(server.width(), server.height());
594 QString szName = QString::fromUtf8(server.name());
595 emit sigServerName(szName);
596
597 //Set viewer frame buffer
598 setFramebuffer(new CFramePixelBuffer(server.width(), server.height()));
599
600 // Force a switch to the format and encoding we'd like
601 // Set Preferred Encoding
602 setPreferredEncoding(m_pPara->GetPreferredEncoding());
603 updatePixelFormat();
604
605 emit sigRunning();
606}
607
608void CBackendVnc::resizeFramebuffer()
609{
610 rfb::ModifiablePixelBuffer* buffer = getFramebuffer();
611
612 qDebug(log) << "CConnectVnc::resizeFramebuffer: new:"
613 << server.width() << server.height()
614 << "old:" << buffer->width() << buffer->height();
615
616 if(server.width() == buffer->width() && server.height() == buffer->height())
617 return;
618
619 //Set viewer frame buffer
620 setFramebuffer(new CFramePixelBuffer(server.width(), server.height()));
621 emit sigSetDesktopSize(server.width(), server.height());
622}
623
624void CBackendVnc::setColourMapEntries(int firstColour, int nColours, uint16_t *rgbs)
625{
626 qCritical(log) << "Invalid SetColourMapEntries from server!";
627}
628
629void CBackendVnc::bell()
630{
631 qApp->beep();
632}
633
634void CBackendVnc::setLEDState(unsigned int state)
635{
636 qDebug(log) << "CConnectVnc::setLEDState" << state;
637 CConnection::setLEDState(state);
638 emit sigUpdateLedState(state);
639}
640
641void CBackendVnc::setCursor(int width, int height, const rfb::Point &hotspot, const uint8_t *data)
642{
643 //qDebug(log) << "CConnectVnc::setCursor x:" << hotspot.x << ";y:" << hotspot.y;
644 if ((width == 0) || (height == 0)) {
645 QImage cursor(1, 1, QImage::Format_ARGB32);
646 uint8_t *buffer = cursor.bits();
647 memset(buffer, 0, 4);
648 emit sigUpdateCursor(QCursor(QPixmap::fromImage(cursor), hotspot.x, hotspot.y));
649 } else {
650 QImage cursor(width, height, QImage::Format_ARGB32);
651 uint8_t *buffer = cursor.bits();
652 memcpy(buffer, data, width * height * 4);
653 emit sigUpdateCursor(QCursor(QPixmap::fromImage(cursor), hotspot.x, hotspot.y));
654 }
655}
656
657void CBackendVnc::setCursorPos(const rfb::Point &pos)
658{
659 //qDebug(log) << "CConnectVnc::setCursorPos x:" << pos.x << ";y:" << pos.y;
660 emit sigUpdateCursorPosition(QPoint(pos.x, pos.y));
661}
662
663void CBackendVnc::fence(uint32_t flags, unsigned int len, const uint8_t data[])
664{
665 //qDebug(log, "CConnectVnc::fence:flags:0x%X; len:%d", flags, len);
666 CMsgHandler::fence(flags, len, data);
667 if (!(flags & rfb::fenceFlagRequest))
668 return;
669
670 // We handle everything synchronously so we trivially honor these modes
671 flags = flags & (rfb::fenceFlagBlockBefore | rfb::fenceFlagBlockAfter);
672 writer()->writeFence(flags, len, data);
673 return;
674}
675
676void CBackendVnc::getUserPasswd(bool secure, std::string *user, std::string *password)
677{
678 if(password)
679 {
680 auto &user = m_pPara->m_Net.m_User;
681 *password = user.GetPassword().toStdString();
682 if(user.GetPassword().isEmpty())
683 {
684 int nRet = QDialog::Rejected;
685 auto *net = &m_pPara->m_Net;
686 emit sigBlockShowWidget("CDlgUserPassword", nRet, net);
687 if(QDialog::Accepted == nRet)
688 {
689 *password = user.GetPassword().toStdString();
690 }
691 }
692 }
693}
694
695int CBackendVnc::getX509File(std::string *ca, std::string *crl)
696{
697 auto &user = m_pPara->m_Net.m_User;
698 if(ca)
699 *ca = user.GetCAFile().toStdString().c_str();
700 if(crl)
701 *crl = user.GetCRLFile().toStdString().c_str();
702 return 0;
703}
704
705bool CBackendVnc::showMsgBox(rfb::MsgBoxFlags flags, const char *title, const char *text)
706{
707 qDebug(log) << title << text;
708 QMessageBox::StandardButton nRet = QMessageBox::No;
709 QMessageBox::StandardButtons fgBtn = QMessageBox::No;
710 bool bCheckBox = 0;
711 if((int)flags & (int)rfb::MsgBoxFlags::M_OK)
712 fgBtn |= QMessageBox::Ok;
713
714 if((int)flags & (int)rfb::MsgBoxFlags::M_OKCANCEL)
715 fgBtn |= QMessageBox::Ok | QMessageBox::Cancel;
716 if((int)flags & (int)rfb::MsgBoxFlags::M_YESNO)
717 fgBtn |= QMessageBox::Yes | QMessageBox::No;
718
719 emit sigBlockShowMessageBox(QString(title), QString(text),
720 fgBtn, nRet, bCheckBox);
721 if(QMessageBox::Ok == nRet
722 || QMessageBox::Yes == nRet)
723 return true;
724 return false;
725}
726
727// setName() is called when the desktop name changes
728void CBackendVnc::setName(const char *name)
729{
730 qDebug(log) << "CConnectVnc::setName:" << name;
731 CConnection::setName(name);
732 QString szName = QString::fromUtf8(server.name());
733 emit sigServerName(szName);
734}
735
736// framebufferUpdateStart() is called at the beginning of an update.
737// Here we try to send out a new framebuffer update request so that the
738// next update can be sent out in parallel with us decoding the current
739// one.
740void CBackendVnc::framebufferUpdateStart()
741{
742 //qDebug(log) << "CConnectVnc::framebufferUpdateStart()";
743 CConnection::framebufferUpdateStart();
744}
745
746// framebufferUpdateEnd() is called at the end of an update.
747// For each rectangle, the FdInStream will have timed the speed
748// of the connection, allowing us to select format and encoding
749// appropriately, and then request another incremental update.
750void CBackendVnc::framebufferUpdateEnd()
751{
752 //qDebug(log) << "CConnectVnc::framebufferUpdateEnd()";
753 rfb::CConnection::framebufferUpdateEnd();
754
755 if(m_pPara /*&& m_pPara->GetBufferEndRefresh()*/)
756 {
757 const QImage& img = dynamic_cast<CFramePixelBuffer*>(getFramebuffer())->getImage();
758 emit sigUpdateRect(img);
759 }
760}
761
762// requestNewUpdate() requests an update from the server, having set the
763// format and encoding appropriately.
764void CBackendVnc::updatePixelFormat()
765{
766 Q_ASSERT(m_pPara);
767
768 if(!m_pPara) return;
769 rfb::PixelFormat pf;
770
771 switch (m_pPara->GetColorLevel()) {
772 case CParameterVnc::Full:
773 pf = fullColourPF;
774 break;
775 case CParameterVnc::Medium:
776 pf = mediumColourPF;
777 break;
778 case CParameterVnc::Low:
779 pf = lowColourPF;
780 break;
781 case CParameterVnc::VeryLow:
782 pf = verylowColourPF;
783 break;
784 }
785
786 char str[256];
787 pf.print(str, 256);
788 qInfo(log) << "Update pixel format:" << str;
789 setPF(pf);
790}
791
792void CBackendVnc::mousePressEvent(QMouseEvent *event)
793{
794 if(!writer()) return;
795 if(m_pPara && m_pPara->GetOnlyView()) return;
796
797 uint8_t mask = 0;
798 if(event->button() & Qt::MouseButton::LeftButton)
799 mask |= 0x1;
800 if(event->button() & Qt::MouseButton::MiddleButton)
801 mask |= 0x2;
802 if(event->button() & Qt::MouseButton::RightButton)
803 mask |= 0x4;
804 if(event->button() & Qt::MouseButton::BackButton)
805 mask |= 0x80;
806
807 QPoint pos = event->pos();
808 rfb::Point p(pos.x(), pos.y());
809
810 qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->button() << pos << mask;
811
812 try{
813 writer()->writePointerEvent(p, mask);
814 } catch (rdr::Exception& e) {
815 emit sigError(-1, e.str());
816 }
817}
818
819void CBackendVnc::mouseReleaseEvent(QMouseEvent *event)
820{
821 if(!writer()) return;
822 if(m_pPara && m_pPara->GetOnlyView()) return;
823 uint8_t mask = 0;
824 QPoint pos = event->pos();
825 rfb::Point p(pos.x(), pos.y());
826 qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->button() << pos << mask;
827 try{
828 writer()->writePointerEvent(p, mask);
829 } catch (rdr::Exception& e) {
830 emit sigError(-1, e.str());
831 }
832}
833
834void CBackendVnc::mouseMoveEvent(QMouseEvent *event)
835{
836 if(!writer()) return;
837 if(m_pPara && m_pPara->GetOnlyView()) return;
838
839 QPoint pos = event->pos();
840 rfb::Point p(pos.x(), pos.y());
841 uint8_t mask = 0;
842 if(event->buttons() & Qt::MouseButton::LeftButton)
843 mask |= 0x1;
844 if(event->buttons() & Qt::MouseButton::MiddleButton)
845 mask |= 0x2;
846 if(event->buttons() & Qt::MouseButton::RightButton)
847 mask |= 0x4;
848 if(event->buttons() & Qt::MouseButton::BackButton)
849 mask |= 0x80;
850
851 qDebug(logMouse) << Q_FUNC_INFO << event->buttons() << event->button() << pos << mask;
852
853 try{
854 writer()->writePointerEvent(p, mask);
855 } catch (rdr::Exception& e) {
856 emit sigError(-1, e.str());
857 }
858}
859
860// https://github.com/rfbproto/rfbproto/blob/master/rfbproto.rst#pointerevent
861void CBackendVnc::wheelEvent(QWheelEvent *event)
862{
863 if(!writer()) return;
864 if(m_pPara && m_pPara->GetOnlyView()) return;
865 uint8_t mask = 0;
866 if(event->buttons() & Qt::MouseButton::LeftButton)
867 mask |= 0x1;
868 if(event->buttons() & Qt::MouseButton::MiddleButton)
869 mask |= 0x2;
870 if(event->buttons() & Qt::MouseButton::RightButton)
871 mask |= 0x4;
872 if(event->buttons() & Qt::MouseButton::BackButton)
873 mask |= 0x80;
874
875 QPoint d = event->angleDelta();
876 if(d.y() > 0)
877 mask |= 0x8;
878 if(d.y() < 0)
879 mask |= 0x10;
880 if(d.x() < 0)
881 mask |= 0x20;
882 if(d.x() > 0)
883 mask |= 0x40;
884
885 QPointF pos;
886#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
887 pos = event->position();
888#else
889 pos = event->pos();
890#endif
891
892 rfb::Point p(pos.x(), pos.y());
893 //*
894 qDebug(logMouse) << Q_FUNC_INFO << event->buttons()
895#if QT_VERSION > QT_VERSION_CHECK(6, 0, 0)
896 << event->button()
897#endif
898 << pos << mask; //*/
899
900 try{
901 writer()->writePointerEvent(p, mask);
902 } catch (rdr::Exception& e) {
903 emit sigError(-1, e.str());
904 }
905}
906
907void CBackendVnc::keyPressEvent(QKeyEvent *event)
908{
909 if(!writer()) return;
910 if(m_pPara && m_pPara->GetOnlyView()) return;
911 bool modifier = false;
912 if (event->modifiers() & Qt::ShiftModifier)
913 modifier = true;
914
915 uint32_t k = TranslateRfbKey(event->key(), modifier);
916 qDebug(logKey) << Q_FUNC_INFO << event << k << modifier;
917
918 try{
919 writer()->writeKeyEvent(k, 0, true);
920 } catch (rdr::Exception& e) {
921 emit sigError(-1, e.str());
922 }
923}
924
925void CBackendVnc::keyReleaseEvent(QKeyEvent *event)
926{
927 if(m_pPara && m_pPara->GetOnlyView()) return;
928 if(!writer()) return;
929 bool modifier = false;
930 if (event->modifiers() & Qt::ShiftModifier)
931 modifier = true;
932
933 uint32_t k = TranslateRfbKey(event->key(), modifier);
934 qDebug(logKey) << Q_FUNC_INFO << event << k << modifier;
935
936 try{
937 writer()->writeKeyEvent(k, 0, false);
938 } catch (rdr::Exception& e) {
939 emit sigError(-1, e.str());
940 }
941}
942
943QString CBackendVnc::ConnectInformation()
944{
945 const int len = 128;
946 char buf[len];
947 QString szInfo;
948 szInfo = QString("Desktop name: ") + server.name() + "\n";
949 szInfo += QString("Size: %1 x %2").arg(server.width()).arg(server.height()) + "\n";
950
951 // TRANSLATORS: Will be filled in with a string describing the
952 // protocol pixel format in a fairly language neutral way
953 server.pf().print(buf, len);
954 szInfo += QString("Pixel format: ") + buf + "\n";
955 szInfo += QString("Requested encoding: ") + rfb::encodingName(getPreferredEncoding()) + "\n";
956 szInfo += QString("Protocol version: %1.%2").arg(server.majorVersion).arg(server.minorVersion) + "\n";
957 szInfo += QString("Security method: ") + rfb::secTypeName(csecurity->getType()) + "\n";
958 szInfo += QString("Support local cursor: %1").arg(supportsLocalCursor) + "\n";
959 szInfo += QString("Support cursor position: %1").arg(supportsCursorPosition) + "\n";
960 szInfo += QString("Support desktop resize: %1").arg(supportsDesktopResize) + "\n";
961 szInfo += QString("Support LED state: %1").arg(supportsLEDState) + "\n";
962 szInfo += QString("Led state: %1").arg(server.ledState()) + "\n";
963 szInfo += QString("Supports QEMU KeyEvent: %1").arg(server.supportsQEMUKeyEvent) + "\n";
964 szInfo += QString("Supports Set Desktop Size: %1").arg(server.supportsSetDesktopSize) + "\n";
965 szInfo += QString("Support fance: %1").arg(server.supportsFence) + "\n";
966 szInfo += QString("Support continue updates: %1").arg(server.supportsContinuousUpdates) + "\n";
967
968 return szInfo;
969}
970
978quint32 CBackendVnc::TranslateRfbKey(quint32 inkey, bool modifier)
979{
980 quint32 k = 5000;
981
982 switch (inkey)
983 {
984 case Qt::Key_Backspace: k = XK_BackSpace; break;
985 case Qt::Key_Tab: k = XK_Tab; break;
986 case Qt::Key_Clear: k = XK_Clear; break;
987 case Qt::Key_Return: k = XK_Return; break;
988 case Qt::Key_Pause: k = XK_Pause; break;
989 case Qt::Key_Escape: k = XK_Escape; break;
990 case Qt::Key_Space: k = XK_space; break;
991 case Qt::Key_Delete: k = XK_Delete; break;
992 case Qt::Key_Period: k = XK_period; break;
993
994 /* International & multi-key character composition */
995 case Qt::Key_Multi_key: k = XK_Multi_key; break;
996 case Qt::Key_Codeinput: k = XK_Codeinput; break;
997 case Qt::Key_SingleCandidate: k = XK_SingleCandidate; break;
998 case Qt::Key_MultipleCandidate: k = XK_MultipleCandidate; break;
999 case Qt::Key_PreviousCandidate: k = XK_PreviousCandidate; break;
1000
1001 /* Japanese keyboard support */
1002 case Qt::Key_Kanji: k = XK_Kanji; break;
1003 case Qt::Key_Muhenkan: k = XK_Muhenkan; break;
1004 case Qt::Key_Henkan: k = XK_Henkan; break;
1005 case Qt::Key_Romaji: k = XK_Romaji; break;
1006 case Qt::Key_Hiragana: k = XK_Hiragana; break;
1007 case Qt::Key_Katakana: k = XK_Katakana; break;
1008 case Qt::Key_Hiragana_Katakana: k = XK_Hiragana_Katakana;break;
1009 case Qt::Key_Zenkaku: k = XK_Zenkaku; break;
1010 case Qt::Key_Hankaku: k = XK_Hankaku; break;
1011 case Qt::Key_Zenkaku_Hankaku: k = XK_Zenkaku_Hankaku; break;
1012 case Qt::Key_Touroku: k = XK_Touroku; break;
1013 case Qt::Key_Massyo: k = XK_Massyo; break;
1014 case Qt::Key_Kana_Lock: k = XK_Kana_Lock; break;
1015 case Qt::Key_Kana_Shift: k = XK_Kana_Shift; break;
1016 case Qt::Key_Eisu_Shift: k = XK_Eisu_Shift; break;
1017 case Qt::Key_Eisu_toggle: k = XK_Eisu_toggle; break;
1018
1019 //special keyboard char
1020 case Qt::Key_Exclam: k = XK_exclam; break;
1021 case Qt::Key_QuoteDbl: k = XK_quotedbl; break; //"
1022 case Qt::Key_NumberSign: k = XK_numbersign; break; //#
1023 case Qt::Key_Percent: k = XK_percent; break; //%
1024 case Qt::Key_Dollar: k = XK_dollar; break; //$
1025 case Qt::Key_Ampersand: k = XK_ampersand; break; //&
1026 case Qt::Key_Apostrophe: k = XK_apostrophe; break;
1027 case Qt::Key_ParenLeft: k = XK_parenleft; break; // (
1028 case Qt::Key_ParenRight: k = XK_parenright; break; // )
1029
1030 case Qt::Key_Slash: k = XK_slash; break; // /
1031 case Qt::Key_Asterisk: k = XK_asterisk; break; //*
1032 case Qt::Key_Minus: k = XK_minus; break; //-
1033 case Qt::Key_Plus: k = XK_plus; break; //+
1034 case Qt::Key_Enter: k = XK_Return; break; //
1035 case Qt::Key_Equal: k = XK_equal; break; //=
1036 case Qt::Key_Comma: return XK_comma; //,
1037
1038 case Qt::Key_Colon: k = XK_colon;break; // :
1039 case Qt::Key_Semicolon: k = XK_semicolon; break; //;
1040 case Qt::Key_Less: k = XK_less; break; // <
1041 case Qt::Key_Greater: k = XK_greater; break; // >
1042 case Qt::Key_Question: k = XK_question; break; //?
1043 case Qt::Key_At: k = XK_at; break; //@
1044
1045 case Qt::Key_BracketLeft: k = XK_bracketleft; break;
1046 case Qt::Key_Backslash: k = XK_backslash;break;
1047 case Qt::Key_BracketRight: k = XK_bracketright;break;
1048 case Qt::Key_AsciiCircum: k = XK_asciicircum;break;
1049 case Qt::Key_Underscore: k = XK_underscore;break;
1050 case Qt::Key_QuoteLeft: k = XK_quoteleft;break;
1051 case Qt::Key_BraceLeft: k = XK_braceleft;break;
1052 case Qt::Key_Bar: k = XK_bar; break;
1053 case Qt::Key_BraceRight: k = XK_braceright;break;
1054 case Qt::Key_AsciiTilde: k = XK_asciitilde;break;
1055 case Qt::Key_nobreakspace: k = XK_nobreakspace;break;
1056 case Qt::Key_exclamdown: k = XK_exclamdown;break;
1057 case Qt::Key_cent: k = XK_cent;break;
1058 case Qt::Key_sterling: k = XK_sterling;break;
1059 case Qt::Key_currency: k = XK_currency;break;
1060 case Qt::Key_yen: k = XK_yen;break;
1061 case Qt::Key_brokenbar: k = XK_brokenbar;break;
1062 case Qt::Key_section: k = XK_section;break;
1063 case Qt::Key_diaeresis: k = XK_diaeresis;break;
1064 case Qt::Key_copyright: k = XK_copyright; break;
1065 case Qt::Key_ordfeminine: k = XK_ordfeminine; break;
1066 case Qt::Key_guillemotleft: k = XK_guillemotleft; break;
1067 case Qt::Key_guillemotright: k = XK_guillemotright; break;
1068 case Qt::Key_notsign: k = XK_notsign; break;
1069 case Qt::Key_hyphen: k = XK_hyphen; break;
1070 case Qt::Key_registered: k = XK_registered; break;
1071
1072 case Qt::Key_Up: k = XK_Up; break;
1073 case Qt::Key_Down: k = XK_Down; break;
1074 case Qt::Key_Right: k = XK_Right; break;
1075 case Qt::Key_Left: k = XK_Left; break;
1076 case Qt::Key_Insert: k = XK_Insert; break;
1077 case Qt::Key_Home: k = XK_Home; break;
1078 case Qt::Key_End: k = XK_End; break;
1079 case Qt::Key_PageUp: k = XK_Page_Up; break;
1080 case Qt::Key_PageDown: k = XK_Page_Down; break;
1081 case Qt::Key_MediaPrevious: k = XK_Prior; break;
1082 case Qt::Key_MediaNext: k = XK_Next; break;
1083 case Qt::Key_MediaPlay: k = XK_Begin; break;
1084
1085 /* Misc Functions */
1086 case Qt::Key_Select: k = XK_Select; break;
1087 case Qt::Key_Printer: k = XK_Print; break;
1088 case Qt::Key_Execute: k = XK_Execute; break;
1089 case Qt::Key_Undo: k = XK_Undo; break;
1090 case Qt::Key_Redo: k = XK_Redo; break;
1091 case Qt::Key_Menu: k = XK_Menu; break;
1092 case Qt::Key_Find: k = XK_Find; break;
1093 case Qt::Key_Exit:
1094 case Qt::Key_Cancel:
1095 case Qt::Key_Stop:
1096 k = XK_Cancel;
1097 break;
1098 case Qt::Key_Mode_switch: k = XK_Mode_switch; break;
1099
1100 case Qt::Key_F1: k = XK_F1; break;
1101 case Qt::Key_F2: k = XK_F2; break;
1102 case Qt::Key_F3: k = XK_F3; break;
1103 case Qt::Key_F4: k = XK_F4; break;
1104 case Qt::Key_F5: k = XK_F5; break;
1105 case Qt::Key_F6: k = XK_F6; break;
1106 case Qt::Key_F7: k = XK_F7; break;
1107 case Qt::Key_F8: k = XK_F8; break;
1108 case Qt::Key_F9: k = XK_F9; break;
1109 case Qt::Key_F10: k = XK_F10; break;
1110 case Qt::Key_F11: k = XK_F11; break;
1111 case Qt::Key_F12: k = XK_F12; break;
1112 case Qt::Key_F13: k = XK_F13; break;
1113 case Qt::Key_F14: k = XK_F14; break;
1114 case Qt::Key_F15: k = XK_F15; break;
1115 case Qt::Key_F16: k = XK_F16; break;
1116 case Qt::Key_F17: k = XK_F17; break;
1117 case Qt::Key_F18: k = XK_F18; break;
1118 case Qt::Key_F19: k = XK_F19; break;
1119 case Qt::Key_F20: k = XK_F20; break;
1120 case Qt::Key_F21: k = XK_F21; break;
1121 case Qt::Key_F22: k = XK_F22; break;
1122 case Qt::Key_F23: k = XK_F23; break;
1123 case Qt::Key_F24: k = XK_F24; break;
1124 case Qt::Key_F25: k = XK_F25; break;
1125 case Qt::Key_F26: k = XK_F26; break;
1126 case Qt::Key_F27: k = XK_F27; break;
1127 case Qt::Key_F28: k = XK_F28; break;
1128 case Qt::Key_F29: k = XK_F29; break;
1129 case Qt::Key_F30: k = XK_F30; break;
1130 case Qt::Key_F31: k = XK_F31; break;
1131 case Qt::Key_F32: k = XK_F32; break;
1132 case Qt::Key_F33: k = XK_F33; break;
1133 case Qt::Key_F34: k = XK_F34; break;
1134 case Qt::Key_F35: k = XK_F35; break;
1135
1136 case Qt::Key_NumLock: k = XK_Num_Lock; break;
1137 case Qt::Key_CapsLock: k = XK_Caps_Lock; break;
1138 case Qt::Key_ScrollLock: k = XK_Scroll_Lock; break;
1139
1140 case Qt::Key_Shift: k = XK_Shift_R; break; //k = XK_Shift_L; break;
1141 case Qt::Key_Control: k = XK_Control_R; break;// k = XK_Control_L; break;
1142 case Qt::Key_Alt: k = XK_Alt_R; break;//k = XK_Alt_L; break;
1143 case Qt::Key_Meta: k = XK_Meta_R; break;//k = XK_Meta_L; break;*/
1144
1145 case Qt::Key_Super_L: k = XK_Super_L; break; /* left "windows" key */
1146 case Qt::Key_Super_R: k = XK_Super_R; break; /* right "windows" key */
1147
1148 case Qt::Key_Hyper_L: k = XK_Hyper_L; break;
1149 case Qt::Key_Hyper_R: k = XK_Hyper_R; break;
1150
1151 case Qt::Key_Help: k = XK_Help; break;
1152 case Qt::Key_Print: k = XK_Print; break;
1153 case Qt::Key_SysReq: k = XK_Sys_Req; break;
1154 case Qt::Key_0: k = XK_0;break;
1155 case Qt::Key_1: k = XK_1;break;
1156 case Qt::Key_2: k = XK_2;break;
1157 case Qt::Key_3: k = XK_3;break;
1158 case Qt::Key_4: k = XK_4;break;
1159 case Qt::Key_5: k = XK_5;break;
1160 case Qt::Key_6: k = XK_6;break;
1161 case Qt::Key_7: k = XK_7;break;
1162 case Qt::Key_8: k = XK_8;break;
1163 case Qt::Key_9: k = XK_9;break;
1164 }
1165
1166 if (k == 5000)
1167 {
1168
1169 if (!modifier)
1170 {
1171 switch (inkey)
1172 {
1173 case Qt::Key_A: k = XK_a;break;
1174 case Qt::Key_B: k = XK_b;break;
1175 case Qt::Key_C: k = XK_c;break;
1176 case Qt::Key_D: k = XK_d;break;
1177 case Qt::Key_E: k = XK_e;break;
1178 case Qt::Key_F: k = XK_f;break;
1179 case Qt::Key_G: k = XK_g;break;
1180 case Qt::Key_H: k = XK_h;break;
1181 case Qt::Key_I: k = XK_i;break;
1182 case Qt::Key_J: k = XK_j;break;
1183 case Qt::Key_K: k = XK_k;break;
1184 case Qt::Key_L: k = XK_l;break;
1185 case Qt::Key_M: k = XK_m;break;
1186 case Qt::Key_N: k = XK_n;break;
1187 case Qt::Key_O: k = XK_o;break;
1188 case Qt::Key_P: k = XK_p;break;
1189 case Qt::Key_Q: k = XK_q;break;
1190 case Qt::Key_R: k = XK_r;break;
1191 case Qt::Key_S: k = XK_s;break;
1192 case Qt::Key_T: k = XK_t;break;
1193 case Qt::Key_U: k = XK_u;break;
1194 case Qt::Key_V: k = XK_v;break;
1195 case Qt::Key_W: k = XK_w;break;
1196 case Qt::Key_X: k = XK_x;break;
1197 case Qt::Key_Y: k = XK_y;break;
1198 case Qt::Key_Z: k = XK_z;break;
1199 }
1200 }
1201 else
1202 {
1203 switch (inkey)
1204 {
1205 case Qt::Key_A: k = XK_A;break;
1206 case Qt::Key_B: k = XK_B;break;
1207 case Qt::Key_C: k = XK_C;break;
1208 case Qt::Key_D: k = XK_D;break;
1209 case Qt::Key_E: k = XK_E;break;
1210 case Qt::Key_F: k = XK_F;break;
1211 case Qt::Key_G: k = XK_G;break;
1212 case Qt::Key_H: k = XK_H;break;
1213 case Qt::Key_I: k = XK_I;break;
1214 case Qt::Key_J: k = XK_J;break;
1215 case Qt::Key_K: k = XK_K;break;
1216 case Qt::Key_L: k = XK_L;break;
1217 case Qt::Key_M: k = XK_M;break;
1218 case Qt::Key_N: k = XK_N;break;
1219 case Qt::Key_O: k = XK_O;break;
1220 case Qt::Key_P: k = XK_P;break;
1221 case Qt::Key_Q: k = XK_Q;break;
1222 case Qt::Key_R: k = XK_R;break;
1223 case Qt::Key_S: k = XK_S;break;
1224 case Qt::Key_T: k = XK_T;break;
1225 case Qt::Key_U: k = XK_U;break;
1226 case Qt::Key_V: k = XK_V;break;
1227 case Qt::Key_W: k = XK_W;break;
1228 case Qt::Key_X: k = XK_X;break;
1229 case Qt::Key_Y: k = XK_Y;break;
1230 case Qt::Key_Z: k = XK_Z;break;
1231 }
1232 }
1233 }
1234
1235 return k;
1236
1237}
1238
1239void CBackendVnc::slotClipBoardChanged()
1240{
1241 //qDebug(log) << "CConnectVnc::slotClipBoardChanged()";
1242 if(!m_pPara->GetClipboard() || !getOutStream() || !writer()) return;
1243 QClipboard* pClip = QApplication::clipboard();
1244 if(pClip->ownsClipboard()) return;
1245 announceClipboard(true);
1246}
1247
1248void CBackendVnc::handleClipboardRequest()
1249{
1250 //qDebug(log) << "CConnectVnc::handleClipboardRequest";
1251 if(!m_pPara->GetClipboard() || !getOutStream() || !writer()) return;
1252 const QClipboard *clipboard = QApplication::clipboard();
1253 const QMimeData *mimeData = clipboard->mimeData();
1254
1255 /*if (mimeData->hasImage()) {
1256 // setPixmap(qvariant_cast<QPixmap>(mimeData->imageData()));
1257 } else */if (mimeData->hasText()) {
1258 QString szText = mimeData->text();
1259 qDebug(log)
1260 << "CConnectVnc::handleClipboardRequest:szText:" << szText;
1261 try{
1262 sendClipboardData(szText.toStdString().c_str());
1263 } catch (rdr::Exception& e) {
1264 qCritical(log) << "sendClipboardData exception" << e.str();
1265 }
1266 } /*else if (mimeData->hasHtml()) {
1267 QString szHtml = mimeData->html();
1268 qDebug(log)
1269 << "CConnectVnc::handleClipboardRequest:html:" << szHtml;
1270 try{
1271 sendClipboardData(mimeData->html().toStdString().c_str());
1272 } catch (rdr::Exception& e) {
1273 qCritical(log) << "sendClipboardData exception" << e.str();
1274 }
1275 }*/ else {
1276 qCritical(log) << "Cannot display data";
1277 }
1278}
1279
1280void CBackendVnc::handleClipboardAnnounce(bool available)
1281{
1282 //qDebug(log) << "CConnectVnc::handleClipboardAnnounce";
1283 if(!m_pPara->GetClipboard() || !getOutStream() || !writer()) return;
1284 if(available)
1285 this->requestClipboard();
1286}
1287
1288void CBackendVnc::handleClipboardData(const char *data)
1289{
1290 //qDebug(log) << "CConnectVnc::handleClipboardData";
1291 if(!m_pPara->GetClipboard() || !getOutStream() || !writer()) return;
1292
1293 QMimeData* pData = new QMimeData();
1294 pData->setText(QString::fromUtf8(data));
1295 emit sigSetClipboard(pData);
1296}
1297
1298void CBackendVnc::authSuccess()
1299{
1300 qDebug(log) << "CConnectVnc::authSuccess";
1301}
Remote desktop interface.
void sigUpdateRect(const QRect &r, const QImage &image)
Notify the CFrmView update image.
quint32 TranslateRfbKey(quint32 inkey, bool modifier)
CBackendVnc::TranslateRfbKey.
virtual int OnClean() override
Clean.
virtual int WakeUp() override
Wake up Backend thread(background thread)
virtual OnInitReturnValue OnInit() override
Initialization.
virtual int OnProcess() override
Specific operation processing of plug-in connection.
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 sigBlockShowMessageBox(const QString &szTitle, const QString &szMessage, QMessageBox::StandardButtons buttons, QMessageBox::StandardButton &nRet, bool &checkBox, QString checkBoxContext=QString())
Block background threads and display message dialogs in foreground threads (QMessageBox)
void sigRunning()
Emitted when the plugin is successfully started.
void sigBlockShowWidget(const QString &className, int &nRet, void *pContext)
Blocks the background thread and displays the window in the foreground thread.
The ICE channel interface class.
Definition ChannelIce.h:27
ssh tunnel class
The channel interface class.
Definition Channel.h:27
static CICE * Instance()
Single instance.
Definition Ice.cpp:55
The ICE signal interface class.
Definition IceSignal.h:26
Remote desktop operate interface.
virtual CParameterBase * GetParameter()
Get parameter.
CParameterUser m_User
[Instance user]
@ OnlyPasswordX509None
Internet X.509 Public Key Infrastructure Certificate and Certificate Revocation List (CRL) Profile.