Mercurial > hg > Applications > TreeVNC
view src/viewer_swing/java/com/glavsoft/viewer/Viewer.java @ 562:87ae979b88cd
-p mode use ScreenSelectionPanel. Blocking is not working yet, but we can debug it in -p mode.
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Sun, 02 Feb 2020 19:58:17 +0900 |
parents | e912db2ab778 |
children | 5bbe53b47d0a |
line wrap: on
line source
// Copyright (C) 2010, 2011, 2012, 2013 GlavSoft LLC. // All rights reserved. // //------------------------------------------------------------------------- // This file is part of the TightVNC software. Please visit our Web site: // // http://www.tightvnc.com/ // // This program 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 program 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 program; if not, write to the Free Software Foundation, Inc., // 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. //------------------------------------------------------------------------- // package com.glavsoft.viewer; import com.glavsoft.rfb.protocol.ProtocolSettings; import com.glavsoft.transport.Reader; import com.glavsoft.transport.Writer; import com.glavsoft.viewer.cli.Parser; import com.glavsoft.viewer.swing.ConnectionParams; import com.glavsoft.viewer.swing.ParametersHandler; import com.glavsoft.viewer.swing.SwingViewerWindow; import jp.ac.u_ryukyu.treevnc.BroadcastRFBListener; import jp.ac.u_ryukyu.treevnc.CreateConnectionParam; import jp.ac.u_ryukyu.treevnc.TreeRFBProto; import javax.swing.*; import java.awt.*; import java.awt.event.WindowEvent; import java.awt.event.WindowListener; import java.io.IOException; import java.io.InputStream; import java.net.Socket; import java.util.ArrayList; import java.util.Comparator; import java.util.jar.Attributes; import java.util.jar.Manifest; import java.util.logging.ConsoleHandler; import java.util.logging.Handler; import java.util.logging.Level; import java.util.logging.Logger; @SuppressWarnings("serial") public class Viewer extends JApplet implements Runnable, WindowListener , ViewerInterface { private Logger logger; public int paramsMask; public boolean allowAppletInteractiveConnections; public final ConnectionParams connectionParams; public String passwordFromParams; public boolean isSeparateFrame = true; public boolean isApplet = true; public final ProtocolSettings settings; public UiSettings uiSettings; private volatile boolean isAppletStopped = false; private ConnectionPresenter connectionPresenter; boolean isTreeVNC = false; public TreeRFBProto myRfb; public boolean noConnection; public int vncport = ConnectionParams.DEFAULT_RFB_PORT; private int fbWidth; private boolean showTree = false; public int width; public int height; public int fixingSizeWidth; public int fixingSizeHeight; private boolean useMulticast; static public BroadcastRFBListener broadcastRFBListener = new BroadcastRFBListener(); public static void main(String[] args) { Parser parser = new Parser(); ParametersHandler.completeParserOptions(parser); parser.parse(args); if (parser.isSet(ParametersHandler.ARG_HELP)) { printUsage(parser.optionsUsage()); System.exit(0); } Viewer viewer = new Viewer(parser); SwingUtilities.invokeLater(viewer); } public static void printUsage(String additional) { System.out.println("Usage: java -jar (progfilename) [hostname [port_number]] [Options]¥n" + " or¥n" + " java -jar (progfilename) [Options]¥n" + " or¥n java -jar (progfilename) -help¥n to view this help¥n¥n" + "Where Options are:¥n" + additional + "¥nOptions format: -optionName=optionValue. Ex. -host=localhost -port=5900 -viewonly=yes¥n" + "Both option name and option value are case insensitive."); } public Viewer() { logger = Logger.getLogger(getClass().getName()); connectionParams = new ConnectionParams(); settings = ProtocolSettings.getDefaultSettings(); uiSettings = new UiSettings(); } private Viewer(Parser parser) { this(); setLoggingLevel(parser.isSet(ParametersHandler.ARG_VERBOSE) ? Level.FINE : parser.isSet(ParametersHandler.ARG_VERBOSE_MORE) ? Level.FINER : Level.INFO); paramsMask = ParametersHandler.completeSettingsFromCLI(parser, connectionParams, settings, uiSettings); passwordFromParams = parser.getValueFor(ParametersHandler.ARG_PASSWORD); logger.info("TightVNC Viewer version " + ver()); isApplet = false; } private void setLoggingLevel(Level levelToSet) { final Logger appLogger = Logger.getLogger("com.glavsoft"); appLogger.setLevel(levelToSet); ConsoleHandler ch = null; for (Handler h : appLogger.getHandlers()) { if (h instanceof ConsoleHandler) { ch = (ConsoleHandler) h; break; } } if (null == ch) { ch = new ConsoleHandler(); appLogger.addHandler(ch); } // ch.setFormatter(new SimpleFormatter()); ch.setLevel(levelToSet); } @Override public void windowClosing(WindowEvent e) { if (e != null && e.getComponent() != null) { final Window w = e.getWindow(); if (w != null) { w.setVisible(false); w.dispose(); } } closeApp(); } /** * Closes App(lication) or stops App(let). */ public void closeApp() { if (connectionPresenter != null) { connectionPresenter.cancelConnection(); logger.info("Connections cancelled."); } if (isApplet) { if ( ! isAppletStopped) { logger.severe("Applet is stopped."); isAppletStopped = true; repaint(); stop(); } } else { System.exit(0); } } @Override public void paint(Graphics g) { if ( ! isAppletStopped) { super.paint(g); } else { getContentPane().removeAll(); g.clearRect(0, 0, getWidth(), getHeight()); g.drawString("Disconnected", 10, 20); } } @Override public void destroy() { closeApp(); super.destroy(); } @Override public void init() { paramsMask = ParametersHandler.completeSettingsFromApplet(this, connectionParams, settings, uiSettings); isSeparateFrame = ParametersHandler.isSeparateFrame; passwordFromParams = getParameter(ParametersHandler.ARG_PASSWORD); isApplet = true; allowAppletInteractiveConnections = ParametersHandler.allowAppletInteractiveConnections; repaint(); try { SwingUtilities.invokeAndWait(this); } catch (Exception e) { logger.severe(e.getMessage()); } } @Override public void start() { super.start(); } public boolean checkJsch() { try { Class.forName("com.jcraft.jsch.JSch"); return true; } catch (ClassNotFoundException e) { return false; } } public void setNoConnection(boolean c){ noConnection = c; } @Override public void run() { final boolean hasJsch = checkJsch(); final boolean allowInteractive = allowAppletInteractiveConnections || ! isApplet; connectionPresenter = new ConnectionPresenter(hasJsch, allowInteractive); connectionPresenter.setIsTreeVNC(isTreeVNC); connectionPresenter.setMulticast(useMulticast); connectionPresenter.setReconnectingId(myRfb.getId()); connectionPresenter.setNoConnection(noConnection); connectionPresenter.addModel("ConnectionParamsModel", connectionParams); connectionPresenter.startVNCConnection(this, false, null, null); } @Override public ConnectionPresenter getConnectionPresenter() { return connectionPresenter; } @Override public void setConnectionPresenter(ConnectionPresenter connectionPresenter) { this.connectionPresenter = connectionPresenter; } @Override public void windowOpened(WindowEvent e) { /* nop */ } @Override public void windowClosed(WindowEvent e) { /* nop */ } @Override public void windowIconified(WindowEvent e) { /* nop */ } @Override public void windowDeiconified(WindowEvent e) { /* nop */ } @Override public void windowActivated(WindowEvent e) { /* nop */ } @Override public void windowDeactivated(WindowEvent e) { /* nop */ } public static String ver() { final InputStream mfStream = Viewer.class.getClassLoader().getResourceAsStream( "META-INF/MANIFEST.MF"); if (null == mfStream) { System.out.println("No Manifest file found."); return "-1"; } try { Manifest mf = new Manifest(); mf.read(mfStream); Attributes atts = mf.getMainAttributes(); return atts.getValue(Attributes.Name.IMPLEMENTATION_VERSION); } catch (IOException e) { return "-2"; } } public void setSocket(Socket soc) { connectionParams.setConnectionParam(soc.getInetAddress().getHostAddress(),soc.getPort()); } public void setOpenPort(int parseInt) { } public void setTerminationType(boolean b) { myRfb.setTerminationType(b); } /** * Start client with new parent (including reconnection) * @param port * @param hostname * @throws IOException */ @Override public void connectToParenet(int port, String hostname) throws IOException { setTerminationType(false); closeApp(); connectionParams.setConnectionParam(hostname, port); run(); } public void setIsTreeVNC(boolean flag) { isTreeVNC = flag; } public TreeRFBProto getRfb() { return myRfb; } public boolean getCuiVersion() { return myRfb.getCuiVersion(); } public void setCuiVersion(boolean flag) { myRfb.setCuiVersion(flag); } public void setVncport(int vncport) { this.vncport = vncport; } /** * start new VNC server receiver with * inherited clients * @param hostName * @param newVNCServerId * @param x * @param y * @param width * @param height * @param scale */ @Override public void inhelitClients(String hostName, short newVNCServerId, int x, int y, int width, int height, int scale) { final ConnectionPresenter connectionPresenter = createNewConnectionPresenter(hostName, newVNCServerId, x, y, width, height, scale); isApplet = true; this.setNoConnection(false); final Viewer v = this; new Thread(new Runnable() { @Override public void run() { connectionPresenter.startVNCConnection(v, false, null, null); } }, "ServerChangeThread").start(); } public void changeToDirectConnectedServer(String hostName, Reader is, Writer os, int x, int y, int width, int height, int scale) { final ConnectionPresenter connectionPresenter = createNewConnectionPresenter(hostName, (short) -1, x, y, width, height, scale); connectionPresenter.startVNCConnection(this, true, is, os); } @Override public void setUseMulticast(boolean useMulticast) { this.useMulticast = useMulticast; } @Override public boolean getUseMulticast() { return useMulticast; } @Override public BroadcastRFBListener getRfbBroadcastListener() { return broadcastRFBListener; } @Override public boolean getIsRetinaDisplay(int shareScreenNumber) { GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); final GraphicsDevice[] devices = env.getScreenDevices(); GraphicsConfiguration conf = devices[shareScreenNumber].getDefaultConfiguration(); return ! conf.getDefaultTransform().isIdentity(); } private ConnectionPresenter createNewConnectionPresenter(String hostName, short newVNCServerId, int x, int y, int width, int height, int scale) { final boolean hasJsch = checkJsch(); final boolean allowInteractive = allowAppletInteractiveConnections || ! isApplet; final ConnectionPresenter connectionPresenter1 = new ConnectionPresenter(hasJsch, allowInteractive); ConnectionParams connectionParams = new ConnectionParams(); connectionParams.setConnectionParam(hostName, vncport); connectionPresenter1.addModel("ConnectionParamsModel", connectionParams); connectionPresenter1.setConnectionParams(connectionParams); connectionPresenter1.setReconnectingId(newVNCServerId); connectionPresenter1.setIsTreeVNC(true); connectionPresenter1.setNoConnection(false); connectionPresenter1.setX(x); connectionPresenter1.setY(y); connectionPresenter1.setSingleWidth(width); connectionPresenter1.setSingleHeight(height); connectionPresenter1.setRetinaScale(scale); connectionPresenter1.setMulticast(myRfb.multicastBlocking); // System.out.println("Sarver change accepted from id :" + newVNCServerId); return connectionPresenter1; } /** * start TreeVNC viewer */ public void startTreeViewer(String hostName, boolean cui, boolean addSerialNum) { TreeRFBProto rfb = new TreeRFBProto(false, this); rfb.setCuiVersion(cui); rfb.setAddSerialNum(addSerialNum); rfb.setHasViewer(true); rfb.createConnectionAndStart(this); CreateConnectionParam cp = new CreateConnectionParam(rfb); if (hostName!=null) { cp.setHostName(hostName); } else { cp.findTreeVncRoot(); // selected "Start Display Mode" or "Start as TreeVNC Root" for start selection panel if (cp.isDisplayMode() || cp.isRootMode()) { myRfb = rfb; myRfb.setIsTreeManager(true); return; } } if (rfb.isTreeManager()) { rfb.setId((short) rfb.getNewNodeId()); } cp.sendWhereToConnect(this); isTreeVNC = true; myRfb = rfb; settings.setViewOnly(true); // too avoid unnecessary upward traffic rfb.getAcceptThread().waitForShutdown(); } public void proxyStart(String[] argv, String hostName, int width, int height, boolean showTree, boolean checkDelay, boolean addSerialNum, boolean fixingSize, boolean filterSingleDisplay, boolean hasViewer) { fbWidth = width; this.showTree = showTree; Parser parser = new Parser(); ParametersHandler.completeParserOptions(parser); if (fbWidth == 0) parser.parse(argv); if (parser.isSet(ParametersHandler.ARG_HELP)) { printUsage(parser.optionsUsage()); System.exit(0); } // myRfb is null if use command line option "-d" "-p" // myRfb not null if use start panel if (myRfb == null) { myRfb = new TreeRFBProto(true, this); } myRfb.setCuiVersion(!hasViewer); myRfb.setHasViewer(hasViewer); myRfb.setShowTree(showTree); myRfb.setCheckDelay(checkDelay); myRfb.setAddSerialNum(addSerialNum); myRfb.setFixingSize(fixingSize); if(fixingSize) { myRfb.fixingSizeWidth = fixingSizeWidth; myRfb.fixingSizeHeight = fixingSizeHeight; } if (myRfb.getAcceptThread() == null) { myRfb.createConnectionAndStart(this); } else { myRfb.startTreeRootFindThread(); } setIsTreeVNC(true); if (hostName == null) { hostName = "localhost"; } connectionParams.setConnectionParam(hostName, vncport); isApplet = true; settings.setViewOnly(true); // to avoid unnecessary upward traffic ConnectionPresenter cp = createNewConnectionPresenter(hostName, myRfb.getId(), 0, 0, 0, 0, 1); createScreenSelectionPanel(null); myRfb.getAcceptThread().waitForShutdown(); } public void initRoot(TreeRFBProto myRfbProto, String hostName) { setIsTreeVNC(true); connectionParams.setConnectionParam(hostName, vncport); isApplet = true; myRfbProto.createConnectionAndStart(this); run(); } @Override public void setVisible(boolean b) { if(connectionPresenter == null) return; SwingViewerWindow v = connectionPresenter.getViewer(); if (v != null) v.setVisible(b); } @Override public Socket getVNCSocket() { return connectionPresenter.getSocket(); } @Override public boolean getShowTree() { return showTree; } @Override public void setWidth(int w) { width = w; } @Override public void setHeight(int h) { height = h; } @Override public void setFixingSize(int width, int height) { this.fixingSizeWidth = width; this.fixingSizeHeight = height; } @Override public ArrayList<FbRectangle> getScreenRectangles() { // New screen server has one or more screens. // Screens are numbered in the order from left. // put screens in an ArrayList. ArrayList<Rectangle> rectangles = new ArrayList<Rectangle>(); GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment(); GraphicsDevice[] gs = ge.getScreenDevices(); for (GraphicsDevice gd : gs) { int screenNumber = 0; for (GraphicsConfiguration r : gd.getConfigurations()) { Rectangle rect = r.getBounds(); //System.out.println("screen "+ screenNumber +":"+rect); rectangles.add(rect); screenNumber++; } } Point offset = getScreenOffset(rectangles); ArrayList<FbRectangle> fbRectangles = new ArrayList<FbRectangle>(); int screenNumber = 0; for (Rectangle rect : rectangles) { FbRectangle fbrect = new FbRectangle(rect.x, rect.y, rect.width, rect.height, screenNumber, retinaScale(screenNumber), getIsRetinaDisplay(screenNumber)); fbrect.setXfb(rect.x + offset.x); fbrect.setYfb(rect.y + offset.y); fbRectangles.add(fbrect); screenNumber++; } fbRectangles.sort(new Comparator<FbRectangle>() { @Override public int compare(FbRectangle t0, FbRectangle t1) { return t0.getX() < t1.getX() ? -1 : t0.getX() == t1.getX() ? 0 : 1; } }); int retinaOffsetX = 0; FbRectangle fbRectanglesPrev = fbRectangles.get(0); for (int i = 1; i < fbRectangles.size(); i++) { FbRectangle fbRect = fbRectangles.get(i); if (fbRect.getIsRetina()) { if (fbRectanglesPrev.x + fbRectanglesPrev.width <= fbRect.x) { // previous screen is touch with this screen, fix retina scale offset retinaOffsetX += fbRectanglesPrev.getWidth() * (fbRectanglesPrev.retinaScale - 1); } } fbRect.setXfb((int) (fbRect.getXfb() + retinaOffsetX)); fbRectanglesPrev = fbRect; } fbRectangles.sort(new Comparator<FbRectangle>() { @Override public int compare(FbRectangle t0, FbRectangle t1) { return t0.getY() < t1.getY() ? -1 : t0.getY() == t1.getY() ? 0 : 1; } }); int retinaOffsetY = 0; fbRectanglesPrev = fbRectangles.get(0); for (int i = 1; i < fbRectangles.size(); i++) { FbRectangle fbRect = fbRectangles.get(i); if (fbRect.getIsRetina()) { if (fbRectanglesPrev.y + fbRectanglesPrev.height <= fbRect.y) { // previous screen is touch with this screen, fix retina scale offset retinaOffsetY += fbRectanglesPrev.getHeight() * (fbRectanglesPrev.retinaScale - 1); } } fbRect.setYfb((int) (fbRect.getYfb() + retinaOffsetY)); fbRectanglesPrev = fbRect; } return fbRectangles; } public Point getScreenOffset(ArrayList<Rectangle> rectangles) { // position of screen may negative, but RFBscreen position is always positive // compute offset to make them positive int offsetx = 0; int offsety = 0; for (Rectangle rect : rectangles) { if (rect.x < offsetx) offsetx = rect.x; if (rect.y < offsety) offsety = rect.y; } return new Point(-offsetx,-offsety); } public int retinaScale(int shareScreenNumber) { int scale = 1; GraphicsEnvironment env = GraphicsEnvironment.getLocalGraphicsEnvironment(); final GraphicsDevice[] devices = env.getScreenDevices(); GraphicsConfiguration conf = devices[shareScreenNumber].getDefaultConfiguration(); scale = (int)conf.getDefaultTransform().getScaleX(); return scale; } @Override public void setFitScreen() { SwingViewerWindow v = connectionPresenter.getViewer(); if (v != null) { v.fitScreen(); } } }