source: other-projects/trunk/gs3-release-maker/tasks/sshtaskdef/src/mindbright/vnc/vncCanvas.java@ 14627

Last change on this file since 14627 was 14627, checked in by oranfry, 17 years ago

initial import of the gs3-release-maker

File size: 10.5 KB
Line 
1//
2// Copyright (C) 1997, 1998 Olivetti & Oracle Research Laboratory
3//
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//
19package mindbright.vnc;
20
21import java.awt.*;
22import java.awt.image.*;
23import java.io.*;
24
25import mindbright.application.MindVNC;
26
27//
28// vncCanvas is a subclass of Canvas which draws a VNC desktop on it.
29//
30
31public class vncCanvas extends Canvas
32{
33 MindVNC v;
34 rfbProto rfb;
35 ColorModel cm;
36 Color[] colors;
37 Image rawPixelsImage;
38 animatedMemoryImageSource amis;
39 byte[] pixels;
40 Graphics sg, sg2;
41 Image paintImage;
42 Graphics pig, pig2;
43 boolean needToResetClip;
44 boolean connected;
45
46 public vncCanvas(MindVNC v1) throws IOException {
47 v = v1;
48 rfb = v.rfb;
49
50 cm = new DirectColorModel(8, 7, (7 << 3), (3 << 6));
51
52 rfb.writeSetPixelFormat(8, 8, false, true, 7, 7, 3, 0, 3, 6);
53
54 colors = new Color[256];
55
56 for (int i = 0; i < 256; i++) {
57 colors[i] = new Color(cm.getRGB(i));
58 }
59
60 pixels = new byte[rfb.framebufferWidth * rfb.framebufferHeight];
61
62 amis = new animatedMemoryImageSource(rfb.framebufferWidth,
63 rfb.framebufferHeight, cm, pixels);
64 rawPixelsImage = createImage(amis);
65
66 paintImage = v.createImage(rfb.framebufferWidth, rfb.framebufferHeight);
67
68 pig = paintImage.getGraphics();
69 }
70
71 public Dimension preferredSize() {
72 return new Dimension(rfb.framebufferWidth, rfb.framebufferHeight);
73 }
74
75 public Dimension minimumSize() {
76 return new Dimension(rfb.framebufferWidth, rfb.framebufferHeight);
77 }
78
79 public void update(Graphics g) {
80 }
81
82 public void paint(Graphics g) {
83 g.drawImage(paintImage, 0, 0, this);
84 }
85
86 //
87 // processNormalProtocol() - executed by the rfbThread to deal with the
88 // RFB socket.
89 //
90
91 public void processNormalProtocol() throws IOException {
92
93 rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth,
94 rfb.framebufferHeight, false);
95
96 sg = getGraphics();
97
98 needToResetClip = false;
99
100 //
101 // main dispatch loop
102 //
103 connected = true;
104
105 while (connected) {
106 int msgType = rfb.readServerMessageType();
107
108 switch (msgType) {
109 case rfb.FramebufferUpdate:
110 rfb.readFramebufferUpdate();
111
112 for (int i = 0; i < rfb.updateNRects; i++) {
113 rfb.readFramebufferUpdateRectHdr();
114
115 if (needToResetClip && (rfb.updateRectEncoding != rfb.EncodingRaw)) {
116 try {
117 sg.setClip(0, 0, rfb.framebufferWidth, rfb.framebufferHeight);
118 pig.setClip(0, 0, rfb.framebufferWidth, rfb.framebufferHeight);
119 } catch (NoSuchMethodError e) {
120 }
121 needToResetClip = false;
122 }
123
124 switch (rfb.updateRectEncoding) {
125
126 case rfb.EncodingRaw:
127 drawRawRect(rfb.updateRectX, rfb.updateRectY,
128 rfb.updateRectW, rfb.updateRectH);
129 break;
130
131 case rfb.EncodingCopyRect:
132 rfb.readCopyRect();
133 pig.copyArea(rfb.copyRectSrcX, rfb.copyRectSrcY,
134 rfb.updateRectW, rfb.updateRectH,
135 rfb.updateRectX - rfb.copyRectSrcX,
136 rfb.updateRectY - rfb.copyRectSrcY);
137 if (v.options.copyRectFast) {
138 sg.copyArea(rfb.copyRectSrcX, rfb.copyRectSrcY,
139 rfb.updateRectW, rfb.updateRectH,
140 rfb.updateRectX - rfb.copyRectSrcX,
141 rfb.updateRectY - rfb.copyRectSrcY);
142 } else {
143 sg.drawImage(paintImage, 0, 0, this);
144 }
145 break;
146
147 case rfb.EncodingRRE:
148 {
149 int nSubrects = rfb.is.readInt();
150 int bg = rfb.is.read();
151 int pixel, x, y, w, h;
152 sg.translate(rfb.updateRectX, rfb.updateRectY);
153 sg.setColor(colors[bg]);
154 sg.fillRect(0, 0, rfb.updateRectW, rfb.updateRectH);
155 pig.translate(rfb.updateRectX, rfb.updateRectY);
156 pig.setColor(colors[bg]);
157 pig.fillRect(0, 0, rfb.updateRectW, rfb.updateRectH);
158 for (int j = 0; j < nSubrects; j++) {
159 pixel = rfb.is.read();
160 x = rfb.is.readUnsignedShort();
161 y = rfb.is.readUnsignedShort();
162 w = rfb.is.readUnsignedShort();
163 h = rfb.is.readUnsignedShort();
164 sg.setColor(colors[pixel]);
165 sg.fillRect(x, y, w, h);
166 pig.setColor(colors[pixel]);
167 pig.fillRect(x, y, w, h);
168 }
169 sg.translate(-rfb.updateRectX, -rfb.updateRectY);
170 pig.translate(-rfb.updateRectX, -rfb.updateRectY);
171 break;
172 }
173
174 case rfb.EncodingCoRRE:
175 {
176 int nSubrects = rfb.is.readInt();
177 int bg = rfb.is.read();
178 int pixel, x, y, w, h;
179
180 sg.translate(rfb.updateRectX, rfb.updateRectY);
181 sg.setColor(colors[bg]);
182 sg.fillRect(0, 0, rfb.updateRectW, rfb.updateRectH);
183 pig.translate(rfb.updateRectX, rfb.updateRectY);
184 pig.setColor(colors[bg]);
185 pig.fillRect(0, 0, rfb.updateRectW, rfb.updateRectH);
186
187 for (int j = 0; j < nSubrects; j++) {
188 pixel = rfb.is.read();
189 x = rfb.is.read();
190 y = rfb.is.read();
191 w = rfb.is.read();
192 h = rfb.is.read();
193
194 sg.setColor(colors[pixel]);
195 sg.fillRect(x, y, w, h);
196 pig.setColor(colors[pixel]);
197 pig.fillRect(x, y, w, h);
198 }
199 sg.translate(-rfb.updateRectX, -rfb.updateRectY);
200 pig.translate(-rfb.updateRectX, -rfb.updateRectY);
201
202 break;
203 }
204
205 case rfb.EncodingHextile:
206 {
207 int bg = 0, fg = 0, sx, sy, sw, sh;
208
209 for (int ty = rfb.updateRectY;
210 ty < rfb.updateRectY + rfb.updateRectH;
211 ty += 16) {
212 for (int tx = rfb.updateRectX;
213 tx < rfb.updateRectX + rfb.updateRectW;
214 tx += 16) {
215
216 int tw = 16, th = 16;
217
218 if (rfb.updateRectX + rfb.updateRectW - tx < 16)
219 tw = rfb.updateRectX + rfb.updateRectW - tx;
220 if (rfb.updateRectY + rfb.updateRectH - ty < 16)
221 th = rfb.updateRectY + rfb.updateRectH - ty;
222
223 int subencoding = rfb.is.read();
224
225 if ((subencoding & rfb.HextileRaw) != 0) {
226 drawRawRect(tx, ty, tw, th);
227 continue;
228 }
229
230 if (needToResetClip) {
231 try {
232 sg.setClip(0, 0,
233 rfb.framebufferWidth, rfb.framebufferHeight);
234 pig.setClip(0, 0,
235 rfb.framebufferWidth, rfb.framebufferHeight);
236 } catch (NoSuchMethodError e) {
237 }
238 needToResetClip = false;
239 }
240
241 if ((subencoding & rfb.HextileBackgroundSpecified) != 0)
242 bg = rfb.is.read();
243
244 sg.setColor(colors[bg]);
245 sg.fillRect(tx, ty, tw, th);
246 pig.setColor(colors[bg]);
247 pig.fillRect(tx, ty, tw, th);
248
249 if ((subencoding & rfb.HextileForegroundSpecified) != 0)
250 fg = rfb.is.read();
251
252 if ((subencoding & rfb.HextileAnySubrects) == 0)
253 continue;
254
255 int nSubrects = rfb.is.read();
256
257 sg.translate(tx, ty);
258 pig.translate(tx, ty);
259
260 if ((subencoding & rfb.HextileSubrectsColoured) != 0) {
261
262 for (int j = 0; j < nSubrects; j++) {
263 fg = rfb.is.read();
264 int b1 = rfb.is.read();
265 int b2 = rfb.is.read();
266 sx = b1 >> 4;
267 sy = b1 & 0xf;
268 sw = (b2 >> 4) + 1;
269 sh = (b2 & 0xf) + 1;
270
271 sg.setColor(colors[fg]);
272 sg.fillRect(sx, sy, sw, sh);
273 pig.setColor(colors[fg]);
274 pig.fillRect(sx, sy, sw, sh);
275 }
276
277 } else {
278
279 sg.setColor(colors[fg]);
280 pig.setColor(colors[fg]);
281
282 for (int j = 0; j < nSubrects; j++) {
283 int b1 = rfb.is.read();
284 int b2 = rfb.is.read();
285 sx = b1 >> 4;
286 sy = b1 & 0xf;
287 sw = (b2 >> 4) + 1;
288 sh = (b2 & 0xf) + 1;
289
290 sg.fillRect(sx, sy, sw, sh);
291 pig.fillRect(sx, sy, sw, sh);
292 }
293 }
294
295 sg.translate(-tx, -ty);
296 pig.translate(-tx, -ty);
297 }
298 }
299 break;
300 }
301
302 default:
303 throw new IOException("Unknown RFB rectangle encoding " +
304 rfb.updateRectEncoding);
305 }
306 }
307 rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth,
308 rfb.framebufferHeight, true);
309 break;
310
311 case rfb.SetColourMapEntries:
312 throw new IOException("Can't handle SetColourMapEntries message");
313
314 case rfb.Bell:
315 System.out.print((char)7);
316 break;
317
318 case rfb.ServerCutText:
319 String s = rfb.readServerCutText();
320 v.clipboard.setCutText(s);
321 break;
322
323 case -1: // EOF, disconnect
324 connected = false;
325 break;
326
327 default:
328 throw new IOException("Unknown RFB message type " + msgType);
329 }
330 }
331 }
332
333
334 //
335 // Draw a raw rectangle.
336 //
337
338 void drawRawRect(int x, int y, int w, int h) throws IOException {
339 if (v.options.drawEachPixelForRawRects) {
340 for (int j = y; j < (y + h); j++) {
341 for (int k = x; k < (x + w); k++) {
342 int pixel = rfb.is.read();
343 sg.setColor(colors[pixel]);
344 sg.fillRect(k, j, 1, 1);
345 pig.setColor(colors[pixel]);
346 pig.fillRect(k, j, 1, 1);
347 }
348 }
349 return;
350 }
351
352 for (int j = y; j < (y + h); j++) {
353 rfb.is.readFully(pixels, j * rfb.framebufferWidth + x, w);
354 }
355
356 amis.newPixels(x, y, w, h);
357
358 try {
359 sg.setClip(x, y, w, h);
360 pig.setClip(x, y, w, h);
361 needToResetClip = true;
362 } catch (NoSuchMethodError e) {
363 sg2 = sg.create();
364 sg.clipRect(x, y, w, h);
365 pig2 = pig.create();
366 pig.clipRect(x, y, w, h);
367 }
368
369 sg.drawImage(rawPixelsImage, 0, 0, this);
370 pig.drawImage(rawPixelsImage, 0, 0, this);
371
372 if (sg2 != null) {
373 sg.dispose(); // reclaims resources more quickly
374 sg = sg2;
375 sg2 = null;
376 pig.dispose();
377 pig = pig2;
378 pig2 = null;
379 }
380 }
381
382
383 //
384 // Handle events.
385 //
386 // Because of a "feature" in the AWT implementation over X, the vncCanvas
387 // sometimes loses focus and the only way to get it back is to call
388 // requestFocus() explicitly. However we need to be careful when calling
389 // requestFocus() on Windows or other click-to-type systems. What we do is
390 // call requestFocus() whenever there is mouse movement over the window,
391 // AND the focus is already in the applet.
392 //
393
394 public boolean handleEvent(Event evt) {
395 if ((rfb != null) && rfb.inNormalProtocol) {
396 try {
397 switch (evt.id) {
398 case Event.MOUSE_MOVE:
399 case Event.MOUSE_DOWN:
400 case Event.MOUSE_DRAG:
401 case Event.MOUSE_UP:
402 if (v.gotFocus) {
403 requestFocus();
404 }
405 rfb.writePointerEvent(evt);
406 break;
407 case Event.KEY_PRESS:
408 case Event.KEY_RELEASE:
409 case Event.KEY_ACTION:
410 case Event.KEY_ACTION_RELEASE:
411 rfb.writeKeyEvent(evt);
412 break;
413 }
414 } catch (Exception e) {
415 e.printStackTrace();
416 }
417 return true;
418 }
419 return false;
420 }
421}
Note: See TracBrowser for help on using the repository browser.