All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.sikuli.vnc.VNCClient Maven / Gradle / Ivy

There is a newer version: 2.0.5
Show newest version
/* Copyright (c) 2017, Sikuli.org, sikulix.com
 *
 * 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301,
 * USA.
 */
package org.sikuli.vnc;

import com.tigervnc.network.TcpSocket;
import com.tigervnc.rdr.FdInStreamBlockCallback;
import com.tigervnc.rfb.*;
import com.tigervnc.rfb.Exception;
import com.tigervnc.rfb.Point;
import com.tigervnc.vncviewer.CConn;

import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.Closeable;
import java.io.IOException;

class VNCClient extends CConnection implements FdInStreamBlockCallback, Closeable
{
    static ThreadLocal UPG = new ThreadLocal<>();

    static {
        CConn.upg = new UserPasswdGetter()
        {
            @Override
            public boolean getUserPasswd(StringBuffer stringBuffer, StringBuffer stringBuffer1)
            {
                UserPasswdGetter upg = UPG.get();
                return false;
            }
        };
    }

    private final TcpSocket sock;
    private boolean shuttingDown = false;
    private PixelFormat serverPF;
    private int currentEncoding;
    private VNCFrameBuffer frameBuffer;

    public static VNCClient connect(String address, int port, String password, boolean shareConnection) throws IOException
    {
        VNCClient client = new VNCClient(address, port, password, shareConnection);
        while (client.state() != VNCClient.RFBSTATE_NORMAL) {
            client.processMsg();
        }
        return client;
    }

    private VNCClient(String address, int port, final String password, boolean shareConnection) throws IOException
    {
        this.security = new ThreadLocalSecurityClient(new BasicUserPasswdGetter(password));

        this.currentEncoding = Encodings.encodingTight;
        this.setShared(shareConnection);

        setServerName(address);
        setServerPort(port);
        this.sock = new TcpSocket(this.getServerName(), this.getServerPort());
        this.sock.inStream().setBlockCallback(this);
        this.setStreams(this.sock.inStream(), this.sock.outStream());
        this.initialiseProtocol();
    }

    @Override
    public PixelFormat getPreferredPF()
    {
        return new PixelFormat();
    }

    @Override
    public void serverInit()
    {
        super.serverInit();

        this.serverPF = this.cp.pf();
        this.frameBuffer = new VNCFrameBuffer(this.cp.width, this.cp.height, this.serverPF);

        this.writer().writeSetEncodings(this.currentEncoding, true);
    }

    public void setDesktopSize(int var1, int var2)
    {
        super.setDesktopSize(var1, var2);
        this.resizeFramebuffer();
    }

    public void setColourMapEntries(int offset, int nbColors, int[] rgb) {
        frameBuffer.setColourMapEntries(offset, nbColors, rgb);
    }

    private void resizeFramebuffer()
    {
        if (this.frameBuffer != null) {
            if (this.cp.width != 0 || this.cp.height != 0) {
                if (this.frameBuffer.width() != this.cp.width || this.frameBuffer.height() != this.cp.height) {
                    this.frameBuffer.resize(cp.width, cp.height);
                }
            }
        }
    }

    public void refreshFramebuffer()
    {
        refreshFramebuffer(0, 0, cp.width, cp.height, false);
    }

    /**
     * Sends FramebufferUpdateRequest message to server.
     *
     * @param x           X coordinate of desired region
     * @param y           Y coordinate of desired region
     * @param w           Width of desired region
     * @param h           Height of desired region
     * @param incremental Zero sends entire desktop, One sends changes only.
     * @throws IOException If there is a socket error
     */
    public void refreshFramebuffer(int x, int y, int w, int h, boolean incremental)
    {
        writer().writeFramebufferUpdateRequest(new Rect(x, y, w, h), incremental);
    }

    @Override
    public void framebufferUpdateStart()
    {
        refreshFramebuffer(0, 0, cp.width, cp.height, true);
    }

    @Override
    public void framebufferUpdateEnd()
    {
    }

    public void fillRect(Rect r, int p)
    {
        this.frameBuffer.fillRect(r.tl.x, r.tl.y, r.width(), r.height(), p);
    }

    public void imageRect(Rect r, Object p)
    {
        this.frameBuffer.imageRect(r.tl.x, r.tl.y, r.width(), r.height(), p);
    }

    public void copyRect(Rect r, int sx, int sy)
    {
        this.frameBuffer.copyRect(r.tl.x, r.tl.y, r.width(), r.height(), sx, sy);
    }

    /**
     * Tells VNC server to depress key.
     *
     * @param key X Window System Keysym for key.
     * @throws IOException If there is a socket error.
     */
    protected void keyDown(int key) throws IOException
    {
        writer().writeKeyEvent(key, true);
    }

    /**
     * Tells VNC server to release key.
     *
     * @param key X Window System Keysym for key.
     * @throws IOException If there is a socket error.
     */
    protected void keyUp(int key) throws IOException
    {
        writer().writeKeyEvent(key, false);
    }

    /**
     * Tells VNC server to perform a mouse event. bOne through bEight are mouse
     * buttons one through eight respectively.  A zero means release that
     * button, and a one means depress that button.
     *
     * @param buttonState logical or of BUTTON_N_DOWN
     * @param x           X coordinate of action
     * @param y           Y coordinate of action
     * @throws IOException If there is a socket error.
     */
    protected void mouseEvent(int buttonState, int x, int y) throws IOException
    {
        writer().writePointerEvent(new Point(x, y), buttonState);
    }

    /**
     * Closes the connection
     *
     * @throws IOException
     */
    public void close() throws IOException
    {
        this.shuttingDown = true;

        if (this.sock != null) {
            this.sock.shutdown();
        }
    }

    /**
     * Returns the VNCClient Object as a string
     */
    public String toString()
    {
        return "VNCClient: " + getServerName() + ":" + getServerPort();
    }

    public Rectangle getBounds()
    {
        return new Rectangle(0, 0, this.cp.width, this.cp.height);
    }

    public BufferedImage getFrameBuffer(int x, int y, int w, int h)
    {
        return frameBuffer.getImage(x, y, w, h);
    }

    @Override
    public void blockCallback()
    {
        try {
            synchronized (this) {
                this.wait(1L);
            }
        } catch (InterruptedException var4) {
            throw new Exception(var4.getMessage());
        }
    }

    public void processMessages()
    {
        while (!shuttingDown) {
            processMsg();
        }
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy