home *** CD-ROM | disk | FTP | other *** search
/ PC Online 1998 September / PCO_0998.ISO / filesbbs / frei / vnc-java.arj / VNC-JAVA.ZIP / vncCanvas.java < prev    next >
Encoding:
Java Source  |  1998-05-11  |  10.3 KB  |  414 lines

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