blob: 9fe431ce12c4ef4c3efef1b59aab47c76171b9f8 [file] [log] [blame]
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +00001/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
Pierre Ossman7638e9c2014-01-16 13:12:40 +01002 * Copyright 2009-2014 Pierre Ossman for Cendio AB
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +00003 *
4 * This is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
8 *
9 * This software is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this software; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
17 * USA.
18 */
19#include <stdio.h>
20#include <rdr/OutStream.h>
21#include <rfb/msgTypes.h>
Pierre Ossman7638e9c2014-01-16 13:12:40 +010022#include <rfb/fenceTypes.h>
Pierre Ossman5ae28212017-05-16 14:30:38 +020023#include <rfb/qemuTypes.h>
Pierre Ossman7638e9c2014-01-16 13:12:40 +010024#include <rfb/Exception.h>
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000025#include <rfb/PixelFormat.h>
26#include <rfb/Rect.h>
Pierre Ossmanb14a6bc2018-06-18 15:44:26 +020027#include <rfb/ServerParams.h>
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000028#include <rfb/CMsgWriter.h>
29
30using namespace rfb;
31
Pierre Ossmanb14a6bc2018-06-18 15:44:26 +020032CMsgWriter::CMsgWriter(ServerParams* server_, rdr::OutStream* os_)
33 : server(server_), os(os_)
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000034{
35}
36
37CMsgWriter::~CMsgWriter()
38{
39}
40
Pierre Ossman7638e9c2014-01-16 13:12:40 +010041void CMsgWriter::writeClientInit(bool shared)
42{
43 os->writeU8(shared);
44 endMsg();
45}
46
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000047void CMsgWriter::writeSetPixelFormat(const PixelFormat& pf)
48{
49 startMsg(msgTypeSetPixelFormat);
50 os->pad(3);
51 pf.write(os);
52 endMsg();
53}
54
55void CMsgWriter::writeSetEncodings(int nEncodings, rdr::U32* encodings)
56{
57 startMsg(msgTypeSetEncodings);
58 os->skip(1);
59 os->writeU16(nEncodings);
60 for (int i = 0; i < nEncodings; i++)
61 os->writeU32(encodings[i]);
62 endMsg();
63}
64
Pierre Ossman7638e9c2014-01-16 13:12:40 +010065void CMsgWriter::writeSetDesktopSize(int width, int height,
66 const ScreenSet& layout)
67{
Pierre Ossmanb14a6bc2018-06-18 15:44:26 +020068 if (!server->supportsSetDesktopSize)
Pierre Ossman7638e9c2014-01-16 13:12:40 +010069 throw Exception("Server does not support SetDesktopSize");
70
71 startMsg(msgTypeSetDesktopSize);
72 os->pad(1);
73
74 os->writeU16(width);
75 os->writeU16(height);
76
77 os->writeU8(layout.num_screens());
78 os->pad(1);
79
80 ScreenSet::const_iterator iter;
81 for (iter = layout.begin();iter != layout.end();++iter) {
82 os->writeU32(iter->id);
83 os->writeU16(iter->dimensions.tl.x);
84 os->writeU16(iter->dimensions.tl.y);
85 os->writeU16(iter->dimensions.width());
86 os->writeU16(iter->dimensions.height());
87 os->writeU32(iter->flags);
88 }
89
90 endMsg();
91}
92
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000093void CMsgWriter::writeFramebufferUpdateRequest(const Rect& r, bool incremental)
94{
95 startMsg(msgTypeFramebufferUpdateRequest);
96 os->writeU8(incremental);
97 os->writeU16(r.tl.x);
98 os->writeU16(r.tl.y);
99 os->writeU16(r.width());
100 os->writeU16(r.height());
101 endMsg();
102}
103
Pierre Ossman7638e9c2014-01-16 13:12:40 +0100104void CMsgWriter::writeEnableContinuousUpdates(bool enable,
105 int x, int y, int w, int h)
106{
Pierre Ossmanb14a6bc2018-06-18 15:44:26 +0200107 if (!server->supportsContinuousUpdates)
Pierre Ossman7638e9c2014-01-16 13:12:40 +0100108 throw Exception("Server does not support continuous updates");
109
110 startMsg(msgTypeEnableContinuousUpdates);
111
112 os->writeU8(!!enable);
113
114 os->writeU16(x);
115 os->writeU16(y);
116 os->writeU16(w);
117 os->writeU16(h);
118
119 endMsg();
120}
121
122void CMsgWriter::writeFence(rdr::U32 flags, unsigned len, const char data[])
123{
Pierre Ossmanb14a6bc2018-06-18 15:44:26 +0200124 if (!server->supportsFence)
Pierre Ossman7638e9c2014-01-16 13:12:40 +0100125 throw Exception("Server does not support fences");
126 if (len > 64)
127 throw Exception("Too large fence payload");
128 if ((flags & ~fenceFlagsSupported) != 0)
129 throw Exception("Unknown fence flags");
130
131 startMsg(msgTypeClientFence);
132 os->pad(3);
133
134 os->writeU32(flags);
135
136 os->writeU8(len);
137 os->writeBytes(data, len);
138
139 endMsg();
140}
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000141
Pierre Ossman59da99f2016-02-05 10:43:12 +0100142void CMsgWriter::writeKeyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down)
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000143{
Pierre Ossmanb14a6bc2018-06-18 15:44:26 +0200144 if (!server->supportsQEMUKeyEvent || !keycode) {
Pierre Ossman5ae28212017-05-16 14:30:38 +0200145 /* This event isn't meaningful without a valid keysym */
146 if (!keysym)
147 return;
148
149 startMsg(msgTypeKeyEvent);
150 os->writeU8(down);
151 os->pad(2);
152 os->writeU32(keysym);
153 endMsg();
154 } else {
155 startMsg(msgTypeQEMUClientMessage);
156 os->writeU8(qemuExtendedKeyEvent);
157 os->writeU16(down);
158 os->writeU32(keysym);
159 os->writeU32(keycode);
160 endMsg();
161 }
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000162}
163
164
Pierre Ossman59da99f2016-02-05 10:43:12 +0100165void CMsgWriter::writePointerEvent(const Point& pos, int buttonMask)
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000166{
167 Point p(pos);
168 if (p.x < 0) p.x = 0;
169 if (p.y < 0) p.y = 0;
Pierre Ossmanb14a6bc2018-06-18 15:44:26 +0200170 if (p.x >= server->width()) p.x = server->width() - 1;
171 if (p.y >= server->height()) p.y = server->height() - 1;
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000172
173 startMsg(msgTypePointerEvent);
174 os->writeU8(buttonMask);
175 os->writeU16(p.x);
176 os->writeU16(p.y);
177 endMsg();
178}
179
180
Pierre Ossman59da99f2016-02-05 10:43:12 +0100181void CMsgWriter::writeClientCutText(const char* str, rdr::U32 len)
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +0000182{
183 startMsg(msgTypeClientCutText);
184 os->pad(3);
185 os->writeU32(len);
186 os->writeBytes(str, len);
187 endMsg();
188}
Pierre Ossman7638e9c2014-01-16 13:12:40 +0100189
190void CMsgWriter::startMsg(int type)
191{
192 os->writeU8(type);
193}
194
195void CMsgWriter::endMsg()
196{
197 os->flush();
198}