File indexing completed on 2024-04-21 04:58:36

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