File indexing completed on 2024-05-05 09:12:57

0001 /*
0002     SPDX-FileCopyrightText: 2007-2013 Urs Wolfer <uwolfer@kde.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #ifndef VNCCLIENTTHREAD_H
0008 #define VNCCLIENTTHREAD_H
0009 
0010 #ifdef QTONLY
0011     #define i18n tr
0012 #else
0013     #include <KLocalizedString>
0014 #endif
0015 
0016 #include "remoteview.h"
0017 
0018 #include <QQueue>
0019 #include <QThread>
0020 #include <QImage>
0021 #include <QMutex>
0022 
0023 extern "C" {
0024 #include <rfb/rfbclient.h>
0025 }
0026 
0027 class ClientEvent
0028 {
0029 public:
0030     virtual ~ClientEvent();
0031 
0032     virtual void fire(rfbClient*) = 0;
0033 };
0034 
0035 class ReconfigureEvent: public ClientEvent
0036 {
0037 public:
0038     void fire(rfbClient*) override;
0039 };
0040 
0041 class KeyClientEvent : public ClientEvent
0042 {
0043 public:
0044     KeyClientEvent(int key, int pressed)
0045             : m_key(key), m_pressed(pressed) {}
0046 
0047     void fire(rfbClient*) override;
0048 
0049 private:
0050     int m_key;
0051     int m_pressed;
0052 };
0053 
0054 class PointerClientEvent : public ClientEvent
0055 {
0056 public:
0057     PointerClientEvent(int x, int y, int buttonMask)
0058             : m_x(x), m_y(y), m_buttonMask(buttonMask) {}
0059 
0060     void fire(rfbClient*) override;
0061 
0062 private:
0063     int m_x;
0064     int m_y;
0065     int m_buttonMask;
0066 };
0067 
0068 class ClientCutEvent : public ClientEvent
0069 {
0070 public:
0071     explicit ClientCutEvent(const QString &text)
0072             : text(text) {}
0073 
0074     void fire(rfbClient*) override;
0075 
0076 private:
0077     QString text;
0078 };
0079 
0080 class VncClientThread: public QThread
0081 {
0082     Q_OBJECT
0083 
0084 public:
0085     enum ColorDepth {
0086         bpp32,
0087         bpp16,
0088         bpp8
0089     };
0090     Q_ENUM(ColorDepth)
0091 
0092     explicit VncClientThread(QObject *parent = nullptr);
0093     ~VncClientThread() override;
0094     const QImage image(int x = 0, int y = 0, int w = 0, int h = 0);
0095     void setImage(const QImage &img);
0096     void emitUpdated(int x, int y, int w, int h);
0097     void emitGotCut(const QString &text);
0098     void stop();
0099     void setHost(const QString &host);
0100     void setPort(int port);
0101     void setQuality(RemoteView::Quality quality);
0102     void setDevicePixelRatio(qreal dpr);
0103     void setPassword(const QString &password) {
0104         m_password = password;
0105     }
0106     void setShowLocalCursor(bool show);
0107     const QString password() const {
0108         return m_password;
0109     }
0110     void setUsername(const QString &username) {
0111         m_username = username;
0112     }
0113     const QString username() const {
0114         return m_username;
0115     }
0116 
0117     RemoteView::Quality quality() const;
0118     ColorDepth colorDepth() const;
0119     uint8_t *frameBuffer;
0120 
0121 Q_SIGNALS:
0122     void imageUpdated(int x, int y, int w, int h);
0123     void gotCut(const QString &text);
0124     void gotCursor(const QCursor &cursor);
0125     void passwordRequest(bool includingUsername = false);
0126     void outputErrorMessage(const QString &message);
0127 
0128     /**
0129      * When we connect/disconnect/reconnect/etc., this signal will be emitted.
0130      *
0131      * @param status            Is the client connected?
0132      * @param details           A sentence describing what happened.
0133      */
0134     void clientStateChanged(RemoteView::RemoteStatus status, const QString &details);
0135 
0136 public Q_SLOTS:
0137     void mouseEvent(int x, int y, int buttonMask);
0138     void keyEvent(int key, bool pressed);
0139     void clientCut(const QString &text);
0140 
0141 protected:
0142     void run() override;
0143 
0144 private:
0145     void setClientColorDepth(rfbClient *cl, ColorDepth cd);
0146     void setColorDepth(ColorDepth colorDepth);
0147 
0148     // These static methods are callback functions for libvncclient. Each
0149     // of them calls back into the corresponding member function via some
0150     // TLS-based logic.
0151     static rfbBool newclientStatic(rfbClient *cl);
0152     static void updatefbStaticPartial(rfbClient *cl, int x, int y, int w, int h);
0153     static void updateFbStaticFinished(rfbClient *cl);
0154     static void cuttextStatic(rfbClient *cl, const char *text, int textlen);
0155     static char *passwdHandlerStatic(rfbClient *cl);
0156     static rfbCredential *credentialHandlerStatic(rfbClient *cl, int credentialType);
0157     static void outputHandlerStatic(const char *format, ...);
0158     static void cursorShapeHandlerStatic(rfbClient *cl, int xhot, int yhot, int width, int height, int bpp);
0159 
0160     // Member functions corresponding to the above static methods.
0161     rfbBool newclient();
0162     void updatefbPartial(int x, int y, int w, int h);
0163     void updatefbFinished();
0164     void cuttext(const char *text, int textlen);
0165     char *passwdHandler();
0166     rfbCredential *credentialHandler(int credentialType);
0167     void outputHandler(const char *format, va_list args);
0168 
0169     QImage m_image;
0170     rfbClient *cl;
0171     QString m_host;
0172     QString m_password;
0173     QString m_username;
0174     int m_port;
0175     bool m_showLocalCursor;
0176     QMutex mutex;
0177     RemoteView::Quality m_quality;
0178     qreal m_devicePixelRatio;
0179     ColorDepth m_colorDepth;
0180     QQueue<ClientEvent* > m_eventQueue;
0181     //color table for 8bit indexed colors
0182     QVector<QRgb> m_colorTable;
0183     QString outputErrorMessageString;
0184 
0185     QRect m_dirtyRect;
0186 
0187     volatile bool m_stopped;
0188     volatile bool m_passwordError;
0189 
0190     /**
0191      * Connection keepalive/reconnection support.
0192      */
0193     struct {
0194         /**
0195          * Number of seconds between probes. If zero, we will not attempt
0196          * to enable it.
0197          */
0198         int intervalSeconds;
0199         /**
0200          * Number of failed probes required to recognise a disconnect.
0201          */
0202         int failedProbes;
0203         /**
0204          * Was keepalive successfully set?
0205          */
0206         bool set;
0207         /**
0208          * Did keepalive detect a disconnect?
0209          */
0210         volatile bool failed;
0211     } m_keepalive;
0212 
0213     // Initialise the VNC client library object.
0214     bool clientCreate(bool reinitialising);
0215 
0216     // Uninitialise the VNC client library object.
0217     void clientDestroy();
0218 
0219     // Turn on keepalive support.
0220     void clientSetKeepalive();
0221 
0222     // Record a state change.
0223     void clientStateChange(RemoteView::RemoteStatus status, const QString &details);
0224     QString m_previousDetails;
0225 
0226 private Q_SLOTS:
0227     void checkOutputErrorMessage();
0228 };
0229 
0230 #endif