⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vnccanvas.java

📁 JAVA版vpn客户端,是在web上实现远程访问的最佳方式.
💻 JAVA
📖 第 1 页 / 共 4 页
字号:
////  Copyright (C) 2004 Horizon Wimba.  All Rights Reserved.//  Copyright (C) 2001-2003 HorizonLive.com, Inc.  All Rights Reserved.//  Copyright (C) 2001,2002 Constantin Kaplinsky.  All Rights Reserved.//  Copyright (C) 2000 Tridia Corporation.  All Rights Reserved.//  Copyright (C) 1999 AT&T Laboratories Cambridge.  All Rights Reserved.////  This is free software; you can redistribute it and/or modify//  it under the terms of the GNU General Public License as published by//  the Free Software Foundation; either version 2 of the License, or//  (at your option) any later version.////  This software is distributed in the hope that it will be useful,//  but WITHOUT ANY WARRANTY; without even the implied warranty of//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the//  GNU General Public License for more details.////  You should have received a copy of the GNU General Public License//  along with this software; if not, write to the Free Software//  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,//  USA.//import java.awt.*;import java.awt.event.*;import java.awt.image.*;import java.io.*;import java.lang.*;import java.util.zip.*;//// VncCanvas is a subclass of Canvas which draws a VNC desktop on it.//class VncCanvas extends Canvas  implements KeyListener, MouseListener, MouseMotionListener {  VncViewer viewer;  RfbProto rfb;  ColorModel cm8, cm24;  Color[] colors;  int bytesPixel;  int maxWidth = 0, maxHeight = 0;  int scalingFactor;  int scaledWidth, scaledHeight;  Image memImage;  Graphics memGraphics;  Image rawPixelsImage;  MemoryImageSource pixelsSource;  byte[] pixels8;  int[] pixels24;  // ZRLE encoder's data.  byte[] zrleBuf;  int zrleBufLen = 0;  byte[] zrleTilePixels8;  int[] zrleTilePixels24;  ZlibInStream zrleInStream;  boolean zrleRecWarningShown = false;  // Zlib encoder's data.  byte[] zlibBuf;  int zlibBufLen = 0;  Inflater zlibInflater;  // Tight encoder's data.  final static int tightZlibBufferSize = 512;  Inflater[] tightInflaters;  // Since JPEG images are loaded asynchronously, we have to remember  // their position in the framebuffer. Also, this jpegRect object is  // used for synchronization between the rfbThread and a JVM's thread  // which decodes and loads JPEG images.  Rectangle jpegRect;  // True if we process keyboard and mouse events.  boolean inputEnabled;  //  // The constructors.  //  public VncCanvas(VncViewer v, int maxWidth_, int maxHeight_)    throws IOException {    viewer = v;    maxWidth = maxWidth_;    maxHeight = maxHeight_;    rfb = viewer.rfb;    scalingFactor = viewer.options.scalingFactor;    tightInflaters = new Inflater[4];    cm8 = new DirectColorModel(8, 7, (7 << 3), (3 << 6));    cm24 = new DirectColorModel(24, 0xFF0000, 0x00FF00, 0x0000FF);    colors = new Color[256];    for (int i = 0; i < 256; i++)      colors[i] = new Color(cm8.getRGB(i));    setPixelFormat();    inputEnabled = false;    if (!viewer.options.viewOnly)      enableInput(true);    // Keyboard listener is enabled even in view-only mode, to catch    // 'r' or 'R' key presses used to request screen update.    addKeyListener(this);  }  public VncCanvas(VncViewer v) throws IOException {    this(v, 0, 0);  }  //  // Callback methods to determine geometry of our Component.  //  public Dimension getPreferredSize() {    return new Dimension(scaledWidth, scaledHeight);  }  public Dimension getMinimumSize() {    return new Dimension(scaledWidth, scaledHeight);  }  public Dimension getMaximumSize() {    return new Dimension(scaledWidth, scaledHeight);  }  //  // All painting is performed here.  //  public void update(Graphics g) {    paint(g);  }  public void paint(Graphics g) {    synchronized(memImage) {      if (rfb.framebufferWidth == scaledWidth) {        g.drawImage(memImage, 0, 0, null);      } else {        paintScaledFrameBuffer(g);      }    }    if (showSoftCursor) {      int x0 = cursorX - hotX, y0 = cursorY - hotY;      Rectangle r = new Rectangle(x0, y0, cursorWidth, cursorHeight);      if (r.intersects(g.getClipBounds())) {	g.drawImage(softCursor, x0, y0, null);      }    }  }  public void paintScaledFrameBuffer(Graphics g) {    g.drawImage(memImage, 0, 0, scaledWidth, scaledHeight, null);  }  //  // Override the ImageObserver interface method to handle drawing of  // JPEG-encoded data.  //  public boolean imageUpdate(Image img, int infoflags,                             int x, int y, int width, int height) {    if ((infoflags & (ALLBITS | ABORT)) == 0) {      return true;		// We need more image data.    } else {      // If the whole image is available, draw it now.      if ((infoflags & ALLBITS) != 0) {	if (jpegRect != null) {	  synchronized(jpegRect) {	    memGraphics.drawImage(img, jpegRect.x, jpegRect.y, null);	    scheduleRepaint(jpegRect.x, jpegRect.y,			    jpegRect.width, jpegRect.height);	    jpegRect.notify();	  }	}      }      return false;		// All image data was processed.    }  }  //  // Start/stop receiving mouse events. Keyboard events are received  // even in view-only mode, because we want to map the 'r' key to the  // screen refreshing function.  //  public synchronized void enableInput(boolean enable) {    if (enable && !inputEnabled) {      inputEnabled = true;      addMouseListener(this);      addMouseMotionListener(this);      if (viewer.showControls) {	viewer.buttonPanel.enableRemoteAccessControls(true);      }      createSoftCursor();	// scaled cursor    } else if (!enable && inputEnabled) {      inputEnabled = false;      removeMouseListener(this);      removeMouseMotionListener(this);      if (viewer.showControls) {	viewer.buttonPanel.enableRemoteAccessControls(false);      }      createSoftCursor();	// non-scaled cursor    }  }  public void setPixelFormat() throws IOException {    if (viewer.options.eightBitColors) {      rfb.writeSetPixelFormat(8, 8, false, true, 7, 7, 3, 0, 3, 6);      bytesPixel = 1;    } else {      rfb.writeSetPixelFormat(32, 24, false, true, 255, 255, 255, 16, 8, 0);      bytesPixel = 4;    }    updateFramebufferSize();  }  void updateFramebufferSize() {    // Useful shortcuts.    int fbWidth = rfb.framebufferWidth;    int fbHeight = rfb.framebufferHeight;    // Calculate scaling factor for auto scaling.    if (maxWidth > 0 && maxHeight > 0) {      int f1 = maxWidth * 100 / fbWidth;      int f2 = maxHeight * 100 / fbHeight;      scalingFactor = Math.min(f1, f2);      if (scalingFactor > 100)	scalingFactor = 100;      System.out.println("Scaling desktop at " + scalingFactor + "%");    }    // Update scaled framebuffer geometry.    scaledWidth = (fbWidth * scalingFactor + 50) / 100;    scaledHeight = (fbHeight * scalingFactor + 50) / 100;    // Create new off-screen image either if it does not exist, or if    // its geometry should be changed. It's not necessary to replace    // existing image if only pixel format should be changed.    if (memImage == null) {      memImage = viewer.vncContainer.createImage(fbWidth, fbHeight);      memGraphics = memImage.getGraphics();    } else if (memImage.getWidth(null) != fbWidth ||	       memImage.getHeight(null) != fbHeight) {      synchronized(memImage) {	memImage = viewer.vncContainer.createImage(fbWidth, fbHeight);	memGraphics = memImage.getGraphics();      }    }    // Images with raw pixels should be re-allocated on every change    // of geometry or pixel format.    if (bytesPixel == 1) {      pixels24 = null;      pixels8 = new byte[fbWidth * fbHeight];      pixelsSource =	new MemoryImageSource(fbWidth, fbHeight, cm8, pixels8, 0, fbWidth);      zrleTilePixels24 = null;      zrleTilePixels8 = new byte[64 * 64];    } else {      pixels8 = null;      pixels24 = new int[fbWidth * fbHeight];      pixelsSource =	new MemoryImageSource(fbWidth, fbHeight, cm24, pixels24, 0, fbWidth);      zrleTilePixels8 = null;      zrleTilePixels24 = new int[64 * 64];    }    pixelsSource.setAnimated(true);    rawPixelsImage = Toolkit.getDefaultToolkit().createImage(pixelsSource);    // Update the size of desktop containers.    if (viewer.inSeparateFrame) {      if (viewer.desktopScrollPane != null)	resizeDesktopFrame();    } else {      setSize(scaledWidth, scaledHeight);    }    viewer.moveFocusToDesktop();  }  void resizeDesktopFrame() {    setSize(scaledWidth, scaledHeight);    // FIXME: Find a better way to determine correct size of a    // ScrollPane.  -- const    Insets insets = viewer.desktopScrollPane.getInsets();    viewer.desktopScrollPane.setSize(scaledWidth +				     2 * Math.min(insets.left, insets.right),				     scaledHeight +				     2 * Math.min(insets.top, insets.bottom));    viewer.vncFrame.pack();    // Try to limit the frame size to the screen size.    Dimension screenSize = viewer.vncFrame.getToolkit().getScreenSize();    Dimension frameSize = viewer.vncFrame.getSize();    Dimension newSize = frameSize;    // Reduce Screen Size by 30 pixels in each direction;    // This is a (poor) attempt to account for    //     1) Menu bar on Macintosh (should really also account for    //        Dock on OSX).  Usually 22px on top of screen.    //     2) Taxkbar on Windows (usually about 28 px on bottom)    //     3) Other obstructions.    screenSize.height -= 30;    screenSize.width  -= 30;    boolean needToResizeFrame = false;    if (frameSize.height > screenSize.height) {      newSize.height = screenSize.height;      needToResizeFrame = true;    }    if (frameSize.width > screenSize.width) {      newSize.width = screenSize.width;      needToResizeFrame = true;    }    if (needToResizeFrame) {      viewer.vncFrame.setSize(newSize);    }    viewer.desktopScrollPane.doLayout();  }  //  // processNormalProtocol() - executed by the rfbThread to deal with the  // RFB socket.  //  public void processNormalProtocol() throws Exception {    // Start/stop session recording if necessary.    viewer.checkRecordingStatus();    rfb.writeFramebufferUpdateRequest(0, 0, rfb.framebufferWidth,				      rfb.framebufferHeight, false);    //    // main dispatch loop    //    while (true) {      // Read message type from the server.      int msgType = rfb.readServerMessageType();      // Process the message depending on its type.      switch (msgType) {      case RfbProto.FramebufferUpdate:	rfb.readFramebufferUpdate();	boolean cursorPosReceived = false;	for (int i = 0; i < rfb.updateNRects; i++) {	  rfb.readFramebufferUpdateRectHdr();	  int rx = rfb.updateRectX, ry = rfb.updateRectY;	  int rw = rfb.updateRectW, rh = rfb.updateRectH;	  if (rfb.updateRectEncoding == rfb.EncodingLastRect)	    break;	  if (rfb.updateRectEncoding == rfb.EncodingNewFBSize) {	    rfb.setFramebufferSize(rw, rh);	    updateFramebufferSize();	    break;	  }	  if (rfb.updateRectEncoding == rfb.EncodingXCursor ||	      rfb.updateRectEncoding == rfb.EncodingRichCursor) {	    handleCursorShapeUpdate(rfb.updateRectEncoding, rx, ry, rw, rh);	    continue;	  }	  if (rfb.updateRectEncoding == rfb.EncodingPointerPos) {	    softCursorMove(rx, ry);	    cursorPosReceived = true;	    continue;	  }          rfb.startTiming();	  switch (rfb.updateRectEncoding) {	  case RfbProto.EncodingRaw:	    handleRawRect(rx, ry, rw, rh);	    break;	  case RfbProto.EncodingCopyRect:	    handleCopyRect(rx, ry, rw, rh);	    break;	  case RfbProto.EncodingRRE:	    handleRRERect(rx, ry, rw, rh);	    break;	  case RfbProto.EncodingCoRRE:	    handleCoRRERect(rx, ry, rw, rh);	    break;	  case RfbProto.EncodingHextile:	    handleHextileRect(rx, ry, rw, rh);	    break;	  case RfbProto.EncodingZRLE:	    handleZRLERect(rx, ry, rw, rh);	    break;	  case RfbProto.EncodingZlib:            handleZlibRect(rx, ry, rw, rh);	    break;	  case RfbProto.EncodingTight:	    handleTightRect(rx, ry, rw, rh);	    break;	  default:	    throw new Exception("Unknown RFB rectangle encoding " +				rfb.updateRectEncoding);	  }          rfb.stopTiming();	}	boolean fullUpdateNeeded = false;	// Start/stop session recording if necessary. Request full	// update if a new session file was opened.	if (viewer.checkRecordingStatus())	  fullUpdateNeeded = true;	// Defer framebuffer update request if necessary. But wake up	// immediately on keyboard or mouse event. Also, don't sleep	// if there is some data to receive, or if the last update	// included a PointerPos message.	if (viewer.deferUpdateRequests > 0 &&	    rfb.is.available() == 0 && !cursorPosReceived) {	  synchronized(rfb) {	    try {	      rfb.wait(viewer.deferUpdateRequests);	    } catch (InterruptedException e) {

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -