1 | /**************************************************************************** |
2 | ** |
3 | ** Copyright (C) 2016 The Qt Company Ltd. |
4 | ** Contact: https://www.qt.io/licensing/ |
5 | ** |
6 | ** This file is part of the QtGui module of the Qt Toolkit. |
7 | ** |
8 | ** $QT_BEGIN_LICENSE:LGPL$ |
9 | ** Commercial License Usage |
10 | ** Licensees holding valid commercial Qt licenses may use this file in |
11 | ** accordance with the commercial license agreement provided with the |
12 | ** Software or, alternatively, in accordance with the terms contained in |
13 | ** a written agreement between you and The Qt Company. For licensing terms |
14 | ** and conditions see https://www.qt.io/terms-conditions. For further |
15 | ** information use the contact form at https://www.qt.io/contact-us. |
16 | ** |
17 | ** GNU Lesser General Public License Usage |
18 | ** Alternatively, this file may be used under the terms of the GNU Lesser |
19 | ** General Public License version 3 as published by the Free Software |
20 | ** Foundation and appearing in the file LICENSE.LGPL3 included in the |
21 | ** packaging of this file. Please review the following information to |
22 | ** ensure the GNU Lesser General Public License version 3 requirements |
23 | ** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. |
24 | ** |
25 | ** GNU General Public License Usage |
26 | ** Alternatively, this file may be used under the terms of the GNU |
27 | ** General Public License version 2.0 or (at your option) the GNU General |
28 | ** Public license version 3 or any later version approved by the KDE Free |
29 | ** Qt Foundation. The licenses are as published by the Free Software |
30 | ** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 |
31 | ** included in the packaging of this file. Please review the following |
32 | ** information to ensure the GNU General Public License requirements will |
33 | ** be met: https://www.gnu.org/licenses/gpl-2.0.html and |
34 | ** https://www.gnu.org/licenses/gpl-3.0.html. |
35 | ** |
36 | ** $QT_END_LICENSE$ |
37 | ** |
38 | ****************************************************************************/ |
39 | |
40 | #ifndef QVNC_P_H |
41 | #define QVNC_P_H |
42 | |
43 | #include "qvncscreen.h" |
44 | |
45 | #include <QtCore/QLoggingCategory> |
46 | #include <QtCore/qbytearray.h> |
47 | #include <QtCore/qvarlengtharray.h> |
48 | #include <qpa/qplatformcursor.h> |
49 | |
50 | QT_BEGIN_NAMESPACE |
51 | |
52 | Q_DECLARE_LOGGING_CATEGORY(lcVnc) |
53 | |
54 | class QTcpSocket; |
55 | class QTcpServer; |
56 | |
57 | class QVncScreen; |
58 | class QVncServer; |
59 | class QVncClientCursor; |
60 | class QVncClient; |
61 | |
62 | // This fits with the VNC hextile messages |
63 | #define MAP_TILE_SIZE 16 |
64 | |
65 | class QVncDirtyMap |
66 | { |
67 | public: |
68 | QVncDirtyMap(QVncScreen *screen); |
69 | virtual ~QVncDirtyMap(); |
70 | |
71 | void reset(); |
72 | bool dirty(int x, int y) const; |
73 | virtual void setDirty(int x, int y, bool force = false) = 0; |
74 | void setClean(int x, int y); |
75 | |
76 | QVncScreen *screen; |
77 | int bytesPerPixel; |
78 | int numDirty; |
79 | int mapWidth; |
80 | int mapHeight; |
81 | |
82 | protected: |
83 | uchar *map; |
84 | uchar *buffer; |
85 | int bufferWidth; |
86 | int bufferHeight; |
87 | int bufferStride; |
88 | int numTiles; |
89 | }; |
90 | |
91 | template <class T> |
92 | class QVncDirtyMapOptimized : public QVncDirtyMap |
93 | { |
94 | public: |
95 | QVncDirtyMapOptimized(QVncScreen *screen) : QVncDirtyMap(screen) {} |
96 | ~QVncDirtyMapOptimized() {} |
97 | |
98 | void setDirty(int x, int y, bool force = false) override; |
99 | }; |
100 | |
101 | |
102 | class QRfbRect |
103 | { |
104 | public: |
105 | QRfbRect() {} |
106 | QRfbRect(quint16 _x, quint16 _y, quint16 _w, quint16 _h) { |
107 | x = _x; y = _y; w = _w; h = _h; |
108 | } |
109 | |
110 | void read(QTcpSocket *s); |
111 | void write(QTcpSocket *s) const; |
112 | |
113 | quint16 x; |
114 | quint16 y; |
115 | quint16 w; |
116 | quint16 h; |
117 | }; |
118 | |
119 | class QRfbPixelFormat |
120 | { |
121 | public: |
122 | static int size() { return 16; } |
123 | |
124 | void read(QTcpSocket *s); |
125 | void write(QTcpSocket *s); |
126 | |
127 | int bitsPerPixel; |
128 | int depth; |
129 | bool bigEndian; |
130 | bool trueColor; |
131 | int redBits; |
132 | int greenBits; |
133 | int blueBits; |
134 | int redShift; |
135 | int greenShift; |
136 | int blueShift; |
137 | }; |
138 | |
139 | class QRfbServerInit |
140 | { |
141 | public: |
142 | QRfbServerInit() { name = nullptr; } |
143 | ~QRfbServerInit() { delete[] name; } |
144 | |
145 | int size() const { return QRfbPixelFormat::size() + 8 + strlen(s: name); } |
146 | void setName(const char *n); |
147 | |
148 | void read(QTcpSocket *s); |
149 | void write(QTcpSocket *s); |
150 | |
151 | quint16 width; |
152 | quint16 height; |
153 | QRfbPixelFormat format; |
154 | char *name; |
155 | }; |
156 | |
157 | class QRfbSetEncodings |
158 | { |
159 | public: |
160 | bool read(QTcpSocket *s); |
161 | |
162 | quint16 count; |
163 | }; |
164 | |
165 | class QRfbFrameBufferUpdateRequest |
166 | { |
167 | public: |
168 | bool read(QTcpSocket *s); |
169 | |
170 | char incremental; |
171 | QRfbRect rect; |
172 | }; |
173 | |
174 | class QRfbKeyEvent |
175 | { |
176 | public: |
177 | bool read(QTcpSocket *s); |
178 | |
179 | char down; |
180 | int keycode; |
181 | int unicode; |
182 | }; |
183 | |
184 | class QRfbPointerEvent |
185 | { |
186 | public: |
187 | bool read(QTcpSocket *s); |
188 | |
189 | Qt::MouseButtons buttons; |
190 | quint16 x; |
191 | quint16 y; |
192 | }; |
193 | |
194 | class QRfbClientCutText |
195 | { |
196 | public: |
197 | bool read(QTcpSocket *s); |
198 | |
199 | quint32 length; |
200 | }; |
201 | |
202 | class QRfbEncoder |
203 | { |
204 | public: |
205 | QRfbEncoder(QVncClient *s) : client(s) {} |
206 | virtual ~QRfbEncoder() {} |
207 | |
208 | virtual void write() = 0; |
209 | |
210 | protected: |
211 | QVncClient *client; |
212 | }; |
213 | |
214 | class QRfbRawEncoder : public QRfbEncoder |
215 | { |
216 | public: |
217 | QRfbRawEncoder(QVncClient *s) : QRfbEncoder(s) {} |
218 | |
219 | void write() override; |
220 | |
221 | private: |
222 | QByteArray buffer; |
223 | }; |
224 | |
225 | template <class SRC> class QRfbHextileEncoder; |
226 | |
227 | template <class SRC> |
228 | class QRfbSingleColorHextile |
229 | { |
230 | public: |
231 | QRfbSingleColorHextile(QRfbHextileEncoder<SRC> *e) : encoder(e) {} |
232 | bool read(const uchar *data, int width, int height, int stride); |
233 | void write(QTcpSocket *socket) const; |
234 | |
235 | private: |
236 | QRfbHextileEncoder<SRC> *encoder; |
237 | }; |
238 | |
239 | template <class SRC> |
240 | class QRfbDualColorHextile |
241 | { |
242 | public: |
243 | QRfbDualColorHextile(QRfbHextileEncoder<SRC> *e) : encoder(e) {} |
244 | bool read(const uchar *data, int width, int height, int stride); |
245 | void write(QTcpSocket *socket) const; |
246 | |
247 | private: |
248 | struct Rect { |
249 | quint8 xy; |
250 | quint8 wh; |
251 | } Q_PACKED rects[8 * 16]; |
252 | |
253 | quint8 numRects; |
254 | QRfbHextileEncoder<SRC> *encoder; |
255 | |
256 | private: |
257 | inline int lastx() const { return rectx(r: numRects); } |
258 | inline int lasty() const { return recty(r: numRects); } |
259 | inline int rectx(int r) const { return rects[r].xy >> 4; } |
260 | inline int recty(int r) const { return rects[r].xy & 0x0f; } |
261 | inline int width(int r) const { return (rects[r].wh >> 4) + 1; } |
262 | inline int height(int r) const { return (rects[r].wh & 0x0f) + 1; } |
263 | |
264 | inline void setX(int r, int x) { |
265 | rects[r].xy = (x << 4) | (rects[r].xy & 0x0f); |
266 | } |
267 | inline void setY(int r, int y) { |
268 | rects[r].xy = (rects[r].xy & 0xf0) | y; |
269 | } |
270 | inline void setWidth(int r, int width) { |
271 | rects[r].wh = ((width - 1) << 4) | (rects[r].wh & 0x0f); |
272 | } |
273 | inline void setHeight(int r, int height) { |
274 | rects[r].wh = (rects[r].wh & 0xf0) | (height - 1); |
275 | } |
276 | |
277 | inline void setWidth(int width) { setWidth(numRects, width); } |
278 | inline void setHeight(int height) { setHeight(numRects, height); } |
279 | inline void setX(int x) { setX(numRects, x); } |
280 | inline void setY(int y) { setY(numRects, y); } |
281 | void next(); |
282 | }; |
283 | |
284 | template <class SRC> |
285 | class QRfbMultiColorHextile |
286 | { |
287 | public: |
288 | QRfbMultiColorHextile(QRfbHextileEncoder<SRC> *e) : encoder(e) {} |
289 | bool read(const uchar *data, int width, int height, int stride); |
290 | void write(QTcpSocket *socket) const; |
291 | |
292 | private: |
293 | inline quint8* rect(int r) { |
294 | return rects.data() + r * (bpp + 2); |
295 | } |
296 | inline const quint8* rect(int r) const { |
297 | return rects.constData() + r * (bpp + 2); |
298 | } |
299 | inline void setX(int r, int x) { |
300 | quint8 *ptr = rect(r) + bpp; |
301 | *ptr = (x << 4) | (*ptr & 0x0f); |
302 | } |
303 | inline void setY(int r, int y) { |
304 | quint8 *ptr = rect(r) + bpp; |
305 | *ptr = (*ptr & 0xf0) | y; |
306 | } |
307 | void setColor(SRC color); |
308 | inline int rectx(int r) const { |
309 | const quint8 *ptr = rect(r) + bpp; |
310 | return *ptr >> 4; |
311 | } |
312 | inline int recty(int r) const { |
313 | const quint8 *ptr = rect(r) + bpp; |
314 | return *ptr & 0x0f; |
315 | } |
316 | inline void setWidth(int r, int width) { |
317 | quint8 *ptr = rect(r) + bpp + 1; |
318 | *ptr = ((width - 1) << 4) | (*ptr & 0x0f); |
319 | } |
320 | inline void setHeight(int r, int height) { |
321 | quint8 *ptr = rect(r) + bpp + 1; |
322 | *ptr = (*ptr & 0xf0) | (height - 1); |
323 | } |
324 | |
325 | bool beginRect(); |
326 | void endRect(); |
327 | |
328 | static const int maxRectsSize = 16 * 16; |
329 | QVarLengthArray<quint8, maxRectsSize> rects; |
330 | |
331 | quint8 bpp; |
332 | quint8 numRects; |
333 | QRfbHextileEncoder<SRC> *encoder; |
334 | }; |
335 | |
336 | template <class SRC> |
337 | class QRfbHextileEncoder : public QRfbEncoder |
338 | { |
339 | public: |
340 | QRfbHextileEncoder(QVncServer *s); |
341 | void write(); |
342 | |
343 | private: |
344 | enum SubEncoding { |
345 | Raw = 1, |
346 | BackgroundSpecified = 2, |
347 | ForegroundSpecified = 4, |
348 | AnySubrects = 8, |
349 | SubrectsColoured = 16 |
350 | }; |
351 | |
352 | QByteArray buffer; |
353 | QRfbSingleColorHextile<SRC> singleColorHextile; |
354 | QRfbDualColorHextile<SRC> dualColorHextile; |
355 | QRfbMultiColorHextile<SRC> multiColorHextile; |
356 | |
357 | SRC bg; |
358 | SRC fg; |
359 | bool newBg; |
360 | bool newFg; |
361 | |
362 | friend class QRfbSingleColorHextile<SRC>; |
363 | friend class QRfbDualColorHextile<SRC>; |
364 | friend class QRfbMultiColorHextile<SRC>; |
365 | }; |
366 | |
367 | #if QT_CONFIG(cursor) |
368 | class QVncClientCursor : public QPlatformCursor |
369 | { |
370 | public: |
371 | QVncClientCursor(); |
372 | ~QVncClientCursor(); |
373 | |
374 | void write(QVncClient *client) const; |
375 | |
376 | void changeCursor(QCursor *widgetCursor, QWindow *window) override; |
377 | |
378 | void addClient(QVncClient *client); |
379 | uint removeClient(QVncClient *client); |
380 | |
381 | QImage cursor; |
382 | QPoint hotspot; |
383 | QVector<QVncClient *> clients; |
384 | }; |
385 | #endif // QT_CONFIG(cursor) |
386 | |
387 | class QVncServer : public QObject |
388 | { |
389 | Q_OBJECT |
390 | public: |
391 | QVncServer(QVncScreen *screen, quint16 port = 5900); |
392 | ~QVncServer(); |
393 | |
394 | enum ServerMsg { FramebufferUpdate = 0, |
395 | SetColourMapEntries = 1 }; |
396 | |
397 | void setDirty(); |
398 | |
399 | |
400 | inline QVncScreen* screen() const { return qvnc_screen; } |
401 | inline QVncDirtyMap* dirtyMap() const { return qvnc_screen->dirty; } |
402 | QImage screenImage() const; |
403 | void discardClient(QVncClient *client); |
404 | |
405 | private slots: |
406 | void newConnection(); |
407 | void init(); |
408 | |
409 | private: |
410 | QTcpServer *serverSocket; |
411 | QVector<QVncClient*> clients; |
412 | QVncScreen *qvnc_screen; |
413 | quint16 m_port; |
414 | }; |
415 | |
416 | QT_END_NAMESPACE |
417 | |
418 | #endif |
419 | |