blob: ebf08d327dfb4525ec8756f8512c520980486594 [file] [log] [blame]
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +00001/* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved.
Pierre Ossmanc754cce2011-11-14 15:44:11 +00002 * Copyright 2009-2011 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 <rfb/PixelFormat.h>
20#include <rfb/msgTypes.h>
21#include <rfb/Exception.h>
22#include <rdr/InStream.h>
23#include <rfb/CMsgReaderV3.h>
24#include <rfb/CMsgHandler.h>
25#include <rfb/util.h>
Pierre Ossmancbd1b2c2009-03-20 16:05:04 +000026#include <rfb/ScreenSet.h>
Adam Tkac20e0d712008-11-14 14:48:21 +000027#include <stdio.h>
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000028
29using namespace rfb;
30
31CMsgReaderV3::CMsgReaderV3(CMsgHandler* handler, rdr::InStream* is)
32 : CMsgReader(handler, is), nUpdateRectsLeft(0)
33{
34}
35
36CMsgReaderV3::~CMsgReaderV3()
37{
38}
39
40void CMsgReaderV3::readServerInit()
41{
42 int width = is->readU16();
43 int height = is->readU16();
44 handler->setDesktopSize(width, height);
45 PixelFormat pf;
46 pf.read(is);
47 handler->setPixelFormat(pf);
48 CharArray name(is->readString());
49 handler->setName(name.buf);
50 handler->serverInit();
51}
52
53void CMsgReaderV3::readMsg()
54{
55 if (nUpdateRectsLeft == 0) {
56
57 int type = is->readU8();
58 switch (type) {
59 case msgTypeFramebufferUpdate: readFramebufferUpdate(); break;
60 case msgTypeSetColourMapEntries: readSetColourMapEntries(); break;
61 case msgTypeBell: readBell(); break;
62 case msgTypeServerCutText: readServerCutText(); break;
Pierre Ossmanc754cce2011-11-14 15:44:11 +000063 case msgTypeServerFence: readFence(); break;
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000064
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000065 default:
66 fprintf(stderr, "unknown message type %d\n", type);
67 throw Exception("unknown message type");
68 }
69
70 } else {
71
72 int x = is->readU16();
73 int y = is->readU16();
74 int w = is->readU16();
75 int h = is->readU16();
Peter Åstrand98fe98c2010-02-10 07:43:02 +000076 int encoding = is->readS32();
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000077
78 switch (encoding) {
79 case pseudoEncodingDesktopSize:
80 handler->setDesktopSize(w, h);
81 break;
Pierre Ossman49f88222009-03-20 13:02:50 +000082 case pseudoEncodingExtendedDesktopSize:
83 readExtendedDesktopSize(x, y, w, h);
84 break;
Peter Åstrandc39e0782009-01-15 12:21:42 +000085 case pseudoEncodingDesktopName:
86 readSetDesktopName(x, y, w, h);
87 break;
Constantin Kaplinskya2adc8d2006-05-25 05:01:55 +000088 case pseudoEncodingCursor:
89 readSetCursor(w, h, Point(x,y));
90 break;
91 case pseudoEncodingLastRect:
92 nUpdateRectsLeft = 1; // this rectangle is the last one
93 break;
94 default:
95 readRect(Rect(x, y, x+w, y+h), encoding);
96 break;
97 };
98
99 nUpdateRectsLeft--;
100 if (nUpdateRectsLeft == 0) handler->framebufferUpdateEnd();
101 }
102}
103
104void CMsgReaderV3::readFramebufferUpdate()
105{
106 is->skip(1);
107 nUpdateRectsLeft = is->readU16();
108 handler->framebufferUpdateStart();
109}
Pierre Ossmane49a7bf2009-03-20 10:02:31 +0000110
111void CMsgReaderV3::readSetDesktopName(int x, int y, int w, int h)
112{
113 char* name = is->readString();
114
115 if (x || y || w || h) {
116 fprintf(stderr, "Ignoring DesktopName rect with non-zero position/size\n");
117 } else {
118 handler->setName(name);
119 }
120
121 delete [] name;
122}
123
Pierre Ossman49f88222009-03-20 13:02:50 +0000124void CMsgReaderV3::readExtendedDesktopSize(int x, int y, int w, int h)
125{
Pierre Ossmancbd1b2c2009-03-20 16:05:04 +0000126 unsigned int screens, i;
127 rdr::U32 id, flags;
128 int sx, sy, sw, sh;
129 ScreenSet layout;
Pierre Ossman49f88222009-03-20 13:02:50 +0000130
131 screens = is->readU8();
132 is->skip(3);
133
Pierre Ossmancbd1b2c2009-03-20 16:05:04 +0000134 for (i = 0;i < screens;i++) {
135 id = is->readU32();
136 sx = is->readU16();
137 sy = is->readU16();
138 sw = is->readU16();
139 sh = is->readU16();
140 flags = is->readU32();
Pierre Ossman49f88222009-03-20 13:02:50 +0000141
Pierre Ossmancbd1b2c2009-03-20 16:05:04 +0000142 layout.add_screen(Screen(id, sx, sy, sw, sh, flags));
143 }
144
145 handler->setExtendedDesktopSize(x, y, w, h, layout);
Pierre Ossman49f88222009-03-20 13:02:50 +0000146}
147
Pierre Ossmanc754cce2011-11-14 15:44:11 +0000148void CMsgReaderV3::readFence()
149{
150 rdr::U32 flags;
151 rdr::U8 len;
152 char data[64];
153
154 is->skip(3);
155
156 flags = is->readU32();
157
158 len = is->readU8();
159 if (len > sizeof(data)) {
160 fprintf(stderr, "Ignoring fence with too large payload\n");
161 is->skip(len);
162 return;
163 }
164
165 is->readBytes(data, len);
166
167 handler->fence(flags, len, data);
168}