view src/viewer_swing/java/com/glavsoft/viewer/Viewer.java @ 427:ed15f0bd8dfa

Remove shareScrrenNumber for ScreenChangeRequest Message
author Tatsuki IHA <e125716@ie.u-ryukyu.ac.jp>
date Mon, 01 Feb 2016 04:39:53 +0900
parents c225c7963778
children f6a828dd37b0
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.*;

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.jar.Attributes;
import java.util.jar.Manifest;
import java.util.logging.*;

import jp.ac.u_ryukyu.treevnc.CreateConnectionParam;
import jp.ac.u_ryukyu.treevnc.TreeRFBProto;

@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 int x;
    private int y;
    private int frameSizeWidth;
    private int frameSizeHeight;

    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.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 vs
     * @param hostName
     * @param newVNCServerId
     */
    @Override
    public void inhelitClients(String hostName, short newVNCServerId) {
        final ConnectionPresenter connectionPresenter = createNewConnectionPresenter(hostName, newVNCServerId);
        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) {
        final ConnectionPresenter connectionPresenter = createNewConnectionPresenter(hostName, (short) -1);
        connectionPresenter.startVNCConnection(this, true, is, os);
    };

    private ConnectionPresenter createNewConnectionPresenter(String hostName, short newVNCServerId) {
        final boolean hasJsch = checkJsch();
        final boolean allowInteractive = allowAppletInteractiveConnections || ! isApplet;
        final ConnectionPresenter connectionPresenter = new ConnectionPresenter(hasJsch, allowInteractive);
        connectionPresenter.setNoConnection(noConnection);
        ConnectionParams connectionParams = new ConnectionParams();
        connectionParams.setConnectionParam(hostName, vncport);
        connectionPresenter.addModel("ConnectionParamsModel", connectionParams);
        connectionPresenter.setConnectionParams(connectionParams);
        connectionPresenter.setReconnectingId(newVNCServerId);
        connectionPresenter.setIsTreeVNC(true);
        connectionPresenter.setNoConnection(false);
        return connectionPresenter;
    }

    /**
     * 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;
            }
        }
        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) {
        fbWidth = width;
        this.showTree = showTree;
        // input into arguments Decision
        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.setShowTree(showTree);
        myRfb.setCheckDelay(checkDelay);
        myRfb.setAddSerialNum(addSerialNum);
        myRfb.setFixingSize(fixingSize);
        if(fixingSize) {
            myRfb.fixingSizeWidth = fixingSizeWidth;
            myRfb.fixingSizeHeight = fixingSizeHeight;
        }
        myRfb.setFilterSingleDisplay(filterSingleDisplay);
        myRfb.setCuiVersion(false);
        myRfb.setHasViewer(true); // this flag will be overwrited after this method. Do we have to set here?
        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); // too avoid unnecessary upward traffic

        ArrayList<Rectangle> rectangles = getScreenRectangles();
        int leftScreenNumber = 0;
        int singleWidth = (int) rectangles.get(leftScreenNumber).getWidth();
        int singleHeight = (int) rectangles.get(leftScreenNumber).getHeight();
        getRfb().setSingleDisplaySize(singleWidth, singleHeight);

        run();
    }

    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<Rectangle> getScreenRectangles() {
        // before change the screen server, data from previous server
        // should be stopped.
        setCuiVersion(false);
        // 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) {
            for (GraphicsConfiguration r : gd.getConfigurations()) {
                rectangles.add(r.getBounds());
            }
        }
        return rectangles;
    }


    @Override
    public void setFitScreen() {
        SwingViewerWindow v = connectionPresenter.getViewer();
        if (v != null) {
            v.zoomToFit();
        }
    }

}