📄 vncviewer.java
字号:
//// Copyright (C) 2001-2004 HorizonLive.com, Inc. All Rights Reserved.// Copyright (C) 2002 Constantin Kaplinsky. 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.////// VncViewer.java - the VNC viewer applet. This class mainly just sets up the// user interface, leaving it to the VncCanvas to do the actual rendering of// a VNC desktop.//import java.awt.*;import java.awt.event.*;import java.io.*;import java.net.*;public class VncViewer extends java.applet.Applet implements java.lang.Runnable, WindowListener { boolean inAnApplet = true; boolean inSeparateFrame = false; // // main() is called when run as a java program from the command line. // It simply runs the applet inside a newly-created frame. // public static void main(String[] argv) { VncViewer v = new VncViewer(); v.mainArgs = argv; v.inAnApplet = false; v.inSeparateFrame = true; v.init(); v.start(); } String[] mainArgs; RfbProto rfb; Thread rfbThread; Frame vncFrame; Container vncContainer; ScrollPane desktopScrollPane; GridBagLayout gridbag; ButtonPanel buttonPanel; Label connStatusLabel; VncCanvas vc; OptionsFrame options; ClipboardFrame clipboard; RecordingFrame rec; // Control session recording. Object recordingSync; String sessionFileName; boolean recordingActive; boolean recordingStatusChanged; String cursorUpdatesDef; String eightBitColorsDef; // Variables read from parameter values. String socketFactory; String host; int port; String passwordParam; boolean showControls; boolean offerRelogin; boolean showOfflineDesktop; int deferScreenUpdates; int deferCursorUpdates; int deferUpdateRequests; // Reference to this applet for inter-applet communication. public static java.applet.Applet refApplet; // // init() // public void init() { readParameters(); refApplet = this; if (inSeparateFrame) { vncFrame = new Frame("TightVNC"); if (!inAnApplet) { vncFrame.add("Center", this); } vncContainer = vncFrame; } else { vncContainer = this; } recordingSync = new Object(); options = new OptionsFrame(this); clipboard = new ClipboardFrame(this); if (RecordingFrame.checkSecurity()) rec = new RecordingFrame(this); sessionFileName = null; recordingActive = false; recordingStatusChanged = false; cursorUpdatesDef = null; eightBitColorsDef = null; if (inSeparateFrame) vncFrame.addWindowListener(this); rfbThread = new Thread(this); rfbThread.start(); } public void update(Graphics g) { } // // run() - executed by the rfbThread to deal with the RFB socket. // public void run() { gridbag = new GridBagLayout(); vncContainer.setLayout(gridbag); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.anchor = GridBagConstraints.NORTHWEST; if (showControls) { buttonPanel = new ButtonPanel(this); gridbag.setConstraints(buttonPanel, gbc); vncContainer.add(buttonPanel); } try { connectAndAuthenticate(); doProtocolInitialisation(); // FIXME: Use auto-scaling not only in a separate frame. if (options.autoScale && inSeparateFrame) { Dimension screenSize; try { screenSize = vncContainer.getToolkit().getScreenSize(); } catch (Exception e) { screenSize = new Dimension(0, 0); } createCanvas(screenSize.width - 32, screenSize.height - 32); } else { createCanvas(0, 0); } gbc.weightx = 1.0; gbc.weighty = 1.0; if (inSeparateFrame) { // Create a panel which itself is resizeable and can hold // non-resizeable VncCanvas component at the top left corner. Panel canvasPanel = new Panel(); canvasPanel.setLayout(new FlowLayout(FlowLayout.LEFT, 0, 0)); canvasPanel.add(vc); // Create a ScrollPane which will hold a panel with VncCanvas // inside. desktopScrollPane = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED); gbc.fill = GridBagConstraints.BOTH; gridbag.setConstraints(desktopScrollPane, gbc); desktopScrollPane.add(canvasPanel); // Finally, add our ScrollPane to the Frame window. vncFrame.add(desktopScrollPane); vncFrame.setTitle(rfb.desktopName); vncFrame.pack(); vc.resizeDesktopFrame(); } else { // Just add the VncCanvas component to the Applet. gridbag.setConstraints(vc, gbc); add(vc); validate(); } if (showControls) buttonPanel.enableButtons(); moveFocusToDesktop(); processNormalProtocol(); } catch (NoRouteToHostException e) { fatalError("Network error: no route to server: " + host, e); } catch (UnknownHostException e) { fatalError("Network error: server name unknown: " + host, e); } catch (ConnectException e) { fatalError("Network error: could not connect to server: " + host + ":" + port, e); } catch (EOFException e) { if (showOfflineDesktop) { e.printStackTrace(); System.out.println("Network error: remote side closed connection"); if (vc != null) { vc.enableInput(false); } if (inSeparateFrame) { vncFrame.setTitle(rfb.desktopName + " [disconnected]"); } if (rfb != null && !rfb.closed()) rfb.close(); if (showControls && buttonPanel != null) { buttonPanel.disableButtonsOnDisconnect(); if (inSeparateFrame) { vncFrame.pack(); } else { validate(); } } } else { fatalError("Network error: remote side closed connection", e); } } catch (IOException e) { String str = e.getMessage(); if (str != null && str.length() != 0) { fatalError("Network Error: " + str, e); } else { fatalError(e.toString(), e); } } catch (Exception e) { String str = e.getMessage(); if (str != null && str.length() != 0) { fatalError("Error: " + str, e); } else { fatalError(e.toString(), e); } } } // // Create a VncCanvas instance. // void createCanvas(int maxWidth, int maxHeight) throws IOException { // Determine if Java 2D API is available and use a special // version of VncCanvas if it is present. vc = null; try { // This throws ClassNotFoundException if there is no Java 2D API. Class cl = Class.forName("java.awt.Graphics2D"); // If we could load Graphics2D class, then we can use VncCanvas2D. cl = Class.forName("VncCanvas2"); Class[] argClasses = { this.getClass(), Integer.TYPE, Integer.TYPE }; java.lang.reflect.Constructor cstr = cl.getConstructor(argClasses); Object[] argObjects = { this, new Integer(maxWidth), new Integer(maxHeight) }; vc = (VncCanvas)cstr.newInstance(argObjects); } catch (Exception e) { System.out.println("Warning: Java 2D API is not available"); } // If we failed to create VncCanvas2D, use old VncCanvas. if (vc == null) vc = new VncCanvas(this, maxWidth, maxHeight); } // // Process RFB socket messages. // If the rfbThread is being stopped, ignore any exceptions, // otherwise rethrow the exception so it can be handled. // void processNormalProtocol() throws Exception { try { vc.processNormalProtocol(); } catch (Exception e) { if (rfbThread == null) { System.out.println("Ignoring RFB socket exceptions" + " because applet is stopping"); } else { throw e; } } } // // Connect to the RFB server and authenticate the user. // void connectAndAuthenticate() throws Exception { showConnectionStatus("Initializing..."); if (inSeparateFrame) { vncFrame.pack(); vncFrame.show(); } else { validate(); } showConnectionStatus("Connecting to " + host + ", port " + port + "..."); rfb = new RfbProto(host, port, this); showConnectionStatus("Connected to server"); rfb.readVersionMsg(); showConnectionStatus("RFB server supports protocol version " + rfb.serverMajor + "." + rfb.serverMinor); rfb.writeVersionMsg(); showConnectionStatus("Using RFB protocol version " + rfb.clientMajor + "." + rfb.clientMinor); int secType = rfb.negotiateSecurity(); int authType; if (secType == RfbProto.SecTypeTight) { showConnectionStatus("Enabling TightVNC protocol extensions"); rfb.initCapabilities(); rfb.setupTunneling(); authType = rfb.negotiateAuthenticationTight(); } else { authType = secType; } switch (authType) { case RfbProto.AuthNone: showConnectionStatus("No authentication needed"); rfb.authenticateNone(); break; case RfbProto.AuthVNC: showConnectionStatus("Performing standard VNC authentication"); if (passwordParam != null) { rfb.authenticateVNC(passwordParam); } else { String pw = askPassword(); rfb.authenticateVNC(pw); } break; default: throw new Exception("Unknown authentication scheme " + authType); } } // // Show a message describing the connection status. // To hide the connection status label, use (msg == null). // void showConnectionStatus(String msg) { if (msg == null) { if (vncContainer.isAncestorOf(connStatusLabel)) { vncContainer.remove(connStatusLabel); } return; } System.out.println(msg); if (connStatusLabel == null) { connStatusLabel = new Label("Status: " + msg); connStatusLabel.setFont(new Font("Helvetica", Font.PLAIN, 12)); } else { connStatusLabel.setText("Status: " + msg); } if (!vncContainer.isAncestorOf(connStatusLabel)) { GridBagConstraints gbc = new GridBagConstraints(); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.fill = GridBagConstraints.HORIZONTAL; gbc.anchor = GridBagConstraints.NORTHWEST; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.insets = new Insets(20, 30, 20, 30); gridbag.setConstraints(connStatusLabel, gbc); vncContainer.add(connStatusLabel); } if (inSeparateFrame) { vncFrame.pack(); } else { validate(); } } // // Show an authentication panel. // String askPassword() throws Exception { showConnectionStatus(null); AuthPanel authPanel = new AuthPanel(this); GridBagConstraints gbc = new GridBagConstraints(); gbc.gridwidth = GridBagConstraints.REMAINDER; gbc.anchor = GridBagConstraints.NORTHWEST; gbc.weightx = 1.0; gbc.weighty = 1.0; gbc.ipadx = 100; gbc.ipady = 50; gridbag.setConstraints(authPanel, gbc); vncContainer.add(authPanel); if (inSeparateFrame) { vncFrame.pack(); } else { validate(); } authPanel.moveFocusToDefaultField(); String pw = authPanel.getPassword(); vncContainer.remove(authPanel); return pw; } // // Do the rest of the protocol initialisation. // void doProtocolInitialisation() throws IOException { rfb.writeClientInit(); rfb.readServerInit(); System.out.println("Desktop name is " + rfb.desktopName); System.out.println("Desktop size is " + rfb.framebufferWidth + " x " + rfb.framebufferHeight); setEncodings(); showConnectionStatus(null); } // // Send current encoding list to the RFB server. // int[] encodingsSaved; int nEncodingsSaved; void setEncodings() { setEncodings(false); } void autoSelectEncodings() { setEncodings(true); } void setEncodings(boolean autoSelectOnly) { if (options == null || rfb == null || !rfb.inNormalProtocol) return; int preferredEncoding = options.preferredEncoding; if (preferredEncoding == -1) { long kbitsPerSecond = rfb.kbitsPerSecond(); if (nEncodingsSaved < 1) { // Choose Tight or ZRLE encoding for the very first update. System.out.println("Using Tight/ZRLE encodings"); preferredEncoding = RfbProto.EncodingTight; } else if (kbitsPerSecond > 2000 && encodingsSaved[0] != RfbProto.EncodingHextile) { // Switch to Hextile if the connection speed is above 2Mbps. System.out.println("Throughput " + kbitsPerSecond + " kbit/s - changing to Hextile encoding"); preferredEncoding = RfbProto.EncodingHextile;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -