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