Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/idanim/idvnc/idvncviewer/vncCanvas.java


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