blob: 0ebd33e7b375e412d057eaa36a5502b2fb3a521f [file] [log] [blame]
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +00001/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
2 *
3 * This is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License as published by
5 * the Free Software Foundation; either version 2 of the License, or
6 * (at your option) any later version.
7 *
8 * This software is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this software; if not, write to the Free Software
15 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
16 * USA.
17 */
18#include <stdio.h>
19#include <rdr/OutStream.h>
20#include <rfb/msgTypes.h>
Pierre Ossman316a3242014-01-15 12:40:20 +010021#include <rfb/encodings.h>
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000022#include <rfb/PixelFormat.h>
23#include <rfb/Rect.h>
24#include <rfb/ConnParams.h>
25#include <rfb/Decoder.h>
26#include <rfb/CMsgWriter.h>
27
28using namespace rfb;
29
30CMsgWriter::CMsgWriter(ConnParams* cp_, rdr::OutStream* os_)
31 : cp(cp_), os(os_)
32{
33}
34
35CMsgWriter::~CMsgWriter()
36{
37}
38
39void CMsgWriter::writeSetPixelFormat(const PixelFormat& pf)
40{
41 startMsg(msgTypeSetPixelFormat);
42 os->pad(3);
43 pf.write(os);
44 endMsg();
45}
46
47void CMsgWriter::writeSetEncodings(int nEncodings, rdr::U32* encodings)
48{
49 startMsg(msgTypeSetEncodings);
50 os->skip(1);
51 os->writeU16(nEncodings);
52 for (int i = 0; i < nEncodings; i++)
53 os->writeU32(encodings[i]);
54 endMsg();
55}
56
57// Ask for encodings based on which decoders are supported. Assumes higher
58// encoding numbers are more desirable.
59
60void CMsgWriter::writeSetEncodings(int preferredEncoding, bool useCopyRect)
61{
62 int nEncodings = 0;
63 rdr::U32 encodings[encodingMax+3];
Pierre Ossmanc754cce2011-11-14 15:44:11 +000064
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000065 if (cp->supportsLocalCursor)
66 encodings[nEncodings++] = pseudoEncodingCursor;
67 if (cp->supportsDesktopResize)
68 encodings[nEncodings++] = pseudoEncodingDesktopSize;
Pierre Ossman49f88222009-03-20 13:02:50 +000069 if (cp->supportsExtendedDesktopSize)
70 encodings[nEncodings++] = pseudoEncodingExtendedDesktopSize;
Peter Åstrandc39e0782009-01-15 12:21:42 +000071 if (cp->supportsDesktopRename)
72 encodings[nEncodings++] = pseudoEncodingDesktopName;
Pierre Ossmanc754cce2011-11-14 15:44:11 +000073
74 encodings[nEncodings++] = pseudoEncodingLastRect;
Pierre Ossmanc898d9a2011-11-14 16:22:23 +000075 encodings[nEncodings++] = pseudoEncodingContinuousUpdates;
Pierre Ossmanc754cce2011-11-14 15:44:11 +000076 encodings[nEncodings++] = pseudoEncodingFence;
77
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000078 if (Decoder::supported(preferredEncoding)) {
79 encodings[nEncodings++] = preferredEncoding;
80 }
Pierre Ossmanc754cce2011-11-14 15:44:11 +000081
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000082 if (useCopyRect) {
83 encodings[nEncodings++] = encodingCopyRect;
84 }
Pierre Ossman090e7d62009-03-12 10:16:07 +000085
86 /*
87 * Prefer encodings in this order:
88 *
89 * Tight, ZRLE, Hextile, *
90 */
91
92 if ((preferredEncoding != encodingTight) &&
93 Decoder::supported(encodingTight))
94 encodings[nEncodings++] = encodingTight;
95
96 if ((preferredEncoding != encodingZRLE) &&
97 Decoder::supported(encodingZRLE))
98 encodings[nEncodings++] = encodingZRLE;
99
100 if ((preferredEncoding != encodingHextile) &&
101 Decoder::supported(encodingHextile))
102 encodings[nEncodings++] = encodingHextile;
103
104 // Remaining encodings
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000105 for (int i = encodingMax; i >= 0; i--) {
Pierre Ossman090e7d62009-03-12 10:16:07 +0000106 switch (i) {
107 case encodingTight:
108 case encodingZRLE:
109 case encodingHextile:
110 break;
111 default:
112 if ((i != preferredEncoding) && Decoder::supported(i))
113 encodings[nEncodings++] = i;
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000114 }
115 }
Pierre Ossman090e7d62009-03-12 10:16:07 +0000116
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000117 if (cp->customCompressLevel && cp->compressLevel >= 0 && cp->compressLevel <= 9)
118 encodings[nEncodings++] = pseudoEncodingCompressLevel0 + cp->compressLevel;
Pierre Ossman3d2ccc42009-03-11 14:33:49 +0000119 if (!cp->noJpeg && cp->qualityLevel >= 0 && cp->qualityLevel <= 9)
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000120 encodings[nEncodings++] = pseudoEncodingQualityLevel0 + cp->qualityLevel;
121
122 writeSetEncodings(nEncodings, encodings);
123}
124
125void CMsgWriter::writeFramebufferUpdateRequest(const Rect& r, bool incremental)
126{
127 startMsg(msgTypeFramebufferUpdateRequest);
128 os->writeU8(incremental);
129 os->writeU16(r.tl.x);
130 os->writeU16(r.tl.y);
131 os->writeU16(r.width());
132 os->writeU16(r.height());
133 endMsg();
134}
135
136
137void CMsgWriter::keyEvent(rdr::U32 key, bool down)
138{
139 startMsg(msgTypeKeyEvent);
140 os->writeU8(down);
141 os->pad(2);
142 os->writeU32(key);
143 endMsg();
144}
145
146
147void CMsgWriter::pointerEvent(const Point& pos, int buttonMask)
148{
149 Point p(pos);
150 if (p.x < 0) p.x = 0;
151 if (p.y < 0) p.y = 0;
152 if (p.x >= cp->width) p.x = cp->width - 1;
153 if (p.y >= cp->height) p.y = cp->height - 1;
154
155 startMsg(msgTypePointerEvent);
156 os->writeU8(buttonMask);
157 os->writeU16(p.x);
158 os->writeU16(p.y);
159 endMsg();
160}
161
162
Adam Tkacacf6c6b2009-02-13 12:42:05 +0000163void CMsgWriter::clientCutText(const char* str, rdr::U32 len)
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000164{
165 startMsg(msgTypeClientCutText);
166 os->pad(3);
167 os->writeU32(len);
168 os->writeBytes(str, len);
169 endMsg();
170}