Kaynağa Gözat

corrected all inconsistent eol-styles and set eol-style:native on *.java. Also set svn:ignore on *.class

git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4574 3789f03b-4d11-0410-bbf8-ca57d06f2519
tags/v1.1.90
Brian Hinz 13 yıl önce
ebeveyn
işleme
882a1d897a

+ 250
- 250
java/src/com/tigervnc/rfb/CSecurityTLS.java Dosyayı Görüntüle

@@ -1,251 +1,251 @@
/*
* Copyright (C) 2003 Sun Microsystems, Inc.
*
* 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.
*/
/*
* Copyright (C) 2003 Sun Microsystems, Inc.
*
* 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.
*/
package com.tigervnc.rfb;
import javax.net.ssl.*;
import java.security.*;
import java.security.cert.*;
import java.security.KeyStore;
import java.io.File;
import java.io.InputStream;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Collection;
import javax.swing.JOptionPane;
import com.tigervnc.vncviewer.UserPrefs;
import com.tigervnc.rdr.*;
public class CSecurityTLS extends CSecurity {
public static StringParameter x509ca
= new StringParameter("x509ca",
"X509 CA certificate", "");
public static StringParameter x509crl
= new StringParameter("x509crl",
"X509 CRL file", "");
private void initGlobal()
{
try {
SSLSocketFactory sslfactory;
SSLContext ctx = SSLContext.getInstance("TLS");
if (anon) {
ctx.init(null, null, null);
} else {
TrustManager[] myTM = new TrustManager[] {
new MyX509TrustManager()
};
ctx.init (null, myTM, null);
}
sslfactory = ctx.getSocketFactory();
try {
ssl = (SSLSocket)sslfactory.createSocket(cc.sock,
cc.sock.getInetAddress().getHostName(),
cc.sock.getPort(), true);
} catch (java.io.IOException e) {
throw new Exception(e.toString());
}
if (anon) {
String[] supported;
ArrayList enabled = new ArrayList();
supported = ssl.getSupportedCipherSuites();
for (int i = 0; i < supported.length; i++)
if (supported[i].matches("TLS_DH_anon.*"))
enabled.add(supported[i]);
ssl.setEnabledCipherSuites((String[])enabled.toArray(new String[0]));
} else {
ssl.setEnabledCipherSuites(ssl.getSupportedCipherSuites());
}
ssl.setEnabledProtocols(new String[]{"SSLv3","TLSv1"});
ssl.addHandshakeCompletedListener(new MyHandshakeListener());
}
catch (java.security.GeneralSecurityException e)
{
vlog.error ("TLS handshake failed " + e.toString ());
return;
}
}
public CSecurityTLS(boolean _anon)
{
anon = _anon;
setDefaults();
cafile = x509ca.getData();
crlfile = x509crl.getData();
}
public static void setDefaults()
{
String homeDir = null;
if ((homeDir=UserPrefs.getHomeDir()) == null) {
vlog.error("Could not obtain VNC home directory path");
return;
}
String vnchomedir = homeDir+UserPrefs.getFileSeperator()+".vnc"+
UserPrefs.getFileSeperator();
String caDefault = new String(vnchomedir+"x509_ca.pem");
String crlDefault = new String(vnchomedir+"x509_crl.pem");
if (new File(caDefault).exists())
x509ca.setDefaultStr(caDefault);
if (new File(crlDefault).exists())
x509crl.setDefaultStr(crlDefault);
}
public boolean processMsg(CConnection cc) {
is = cc.getInStream();
os = cc.getOutStream();
initGlobal();
if (!is.checkNoWait(1))
return false;
if (is.readU8() == 0) {
int result = is.readU32();
String reason;
if (result == Security.secResultFailed ||
result == Security.secResultTooMany)
reason = is.readString();
else
reason = new String("Authentication failure (protocol error)");
throw new AuthFailureException(reason);
}
// SSLSocket.getSession blocks until the handshake is complete
session = ssl.getSession();
if (!session.isValid())
throw new Exception("TLS Handshake failed!");
try {
cc.setStreams(new JavaInStream(ssl.getInputStream()),
new JavaOutStream(ssl.getOutputStream()));
} catch (java.io.IOException e) {
throw new Exception("Failed to set streams");
}
return true;
}
class MyHandshakeListener implements HandshakeCompletedListener {
public void handshakeCompleted(HandshakeCompletedEvent e) {
vlog.info("Handshake succesful!");
vlog.info("Using cipher suite: " + e.getCipherSuite());
}
}
class MyX509TrustManager implements X509TrustManager
{
X509TrustManager tm;
MyX509TrustManager() throws java.security.GeneralSecurityException
{
TrustManagerFactory tmf =
TrustManagerFactory.getInstance("PKIX");
KeyStore ks = KeyStore.getInstance("JKS");
CertificateFactory cf = CertificateFactory.getInstance("X.509");
try {
ks.load(null, null);
File cacert = new File(cafile);
if (!cacert.exists() || !cacert.canRead())
return;
InputStream caStream = new FileInputStream(cafile);
X509Certificate ca = (X509Certificate)cf.generateCertificate(caStream);
ks.setCertificateEntry("CA", ca);
PKIXBuilderParameters params = new PKIXBuilderParameters(ks, new X509CertSelector());
File crlcert = new File(crlfile);
if (!crlcert.exists() || !crlcert.canRead()) {
params.setRevocationEnabled(false);
} else {
InputStream crlStream = new FileInputStream(crlfile);
Collection<? extends CRL> crls = cf.generateCRLs(crlStream);
CertStoreParameters csp = new CollectionCertStoreParameters(crls);
CertStore store = CertStore.getInstance("Collection", csp);
params.addCertStore(store);
params.setRevocationEnabled(true);
}
tmf.init(new CertPathTrustManagerParameters(params));
} catch (java.io.FileNotFoundException e) {
vlog.error(e.toString());
} catch (java.io.IOException e) {
vlog.error(e.toString());
}
tm = (X509TrustManager)tmf.getTrustManagers()[0];
}
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException
{
tm.checkClientTrusted(chain, authType);
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException
{
try {
tm.checkServerTrusted(chain, authType);
} catch (CertificateException e) {
Object[] answer = {"Proceed", "Exit"};
int ret = JOptionPane.showOptionDialog(null,
e.getCause().getLocalizedMessage()+"\n"+
"Continue connecting to this host?",
"Confirm certificate exception?",
JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE,
null, answer, answer[0]);
if (ret == JOptionPane.NO_OPTION)
System.exit(1);
} catch (java.lang.Exception e) {
throw new Exception(e.toString());
}
}
public X509Certificate[] getAcceptedIssuers ()
{
return tm.getAcceptedIssuers();
}
}
public final int getType() { return anon ? Security.secTypeTLSNone : Security.secTypeX509None; }
public final String description()
{ return anon ? "TLS Encryption without VncAuth" : "X509 Encryption without VncAuth"; }
//protected void setParam();
//protected void checkSession();
protected CConnection cc;
private boolean anon;
private SSLSession session;
private String cafile, crlfile;
private InStream is;
private OutStream os;
private SSLSocket ssl;
static LogWriter vlog = new LogWriter("CSecurityTLS");
}
import javax.net.ssl.*;
import java.security.*;
import java.security.cert.*;
import java.security.KeyStore;
import java.io.File;
import java.io.InputStream;
import java.io.FileInputStream;
import java.util.ArrayList;
import java.util.Collection;
import javax.swing.JOptionPane;
import com.tigervnc.vncviewer.UserPrefs;
import com.tigervnc.rdr.*;
public class CSecurityTLS extends CSecurity {
public static StringParameter x509ca
= new StringParameter("x509ca",
"X509 CA certificate", "");
public static StringParameter x509crl
= new StringParameter("x509crl",
"X509 CRL file", "");
private void initGlobal()
{
try {
SSLSocketFactory sslfactory;
SSLContext ctx = SSLContext.getInstance("TLS");
if (anon) {
ctx.init(null, null, null);
} else {
TrustManager[] myTM = new TrustManager[] {
new MyX509TrustManager()
};
ctx.init (null, myTM, null);
}
sslfactory = ctx.getSocketFactory();
try {
ssl = (SSLSocket)sslfactory.createSocket(cc.sock,
cc.sock.getInetAddress().getHostName(),
cc.sock.getPort(), true);
} catch (java.io.IOException e) {
throw new Exception(e.toString());
}
if (anon) {
String[] supported;
ArrayList enabled = new ArrayList();
supported = ssl.getSupportedCipherSuites();
for (int i = 0; i < supported.length; i++)
if (supported[i].matches("TLS_DH_anon.*"))
enabled.add(supported[i]);
ssl.setEnabledCipherSuites((String[])enabled.toArray(new String[0]));
} else {
ssl.setEnabledCipherSuites(ssl.getSupportedCipherSuites());
}
ssl.setEnabledProtocols(new String[]{"SSLv3","TLSv1"});
ssl.addHandshakeCompletedListener(new MyHandshakeListener());
}
catch (java.security.GeneralSecurityException e)
{
vlog.error ("TLS handshake failed " + e.toString ());
return;
}
}
public CSecurityTLS(boolean _anon)
{
anon = _anon;
setDefaults();
cafile = x509ca.getData();
crlfile = x509crl.getData();
}
public static void setDefaults()
{
String homeDir = null;
if ((homeDir=UserPrefs.getHomeDir()) == null) {
vlog.error("Could not obtain VNC home directory path");
return;
}
String vnchomedir = homeDir+UserPrefs.getFileSeperator()+".vnc"+
UserPrefs.getFileSeperator();
String caDefault = new String(vnchomedir+"x509_ca.pem");
String crlDefault = new String(vnchomedir+"x509_crl.pem");
if (new File(caDefault).exists())
x509ca.setDefaultStr(caDefault);
if (new File(crlDefault).exists())
x509crl.setDefaultStr(crlDefault);
}
public boolean processMsg(CConnection cc) {
is = cc.getInStream();
os = cc.getOutStream();
initGlobal();
if (!is.checkNoWait(1))
return false;
if (is.readU8() == 0) {
int result = is.readU32();
String reason;
if (result == Security.secResultFailed ||
result == Security.secResultTooMany)
reason = is.readString();
else
reason = new String("Authentication failure (protocol error)");
throw new AuthFailureException(reason);
}
// SSLSocket.getSession blocks until the handshake is complete
session = ssl.getSession();
if (!session.isValid())
throw new Exception("TLS Handshake failed!");
try {
cc.setStreams(new JavaInStream(ssl.getInputStream()),
new JavaOutStream(ssl.getOutputStream()));
} catch (java.io.IOException e) {
throw new Exception("Failed to set streams");
}
return true;
}
class MyHandshakeListener implements HandshakeCompletedListener {
public void handshakeCompleted(HandshakeCompletedEvent e) {
vlog.info("Handshake succesful!");
vlog.info("Using cipher suite: " + e.getCipherSuite());
}
}
class MyX509TrustManager implements X509TrustManager
{
X509TrustManager tm;
MyX509TrustManager() throws java.security.GeneralSecurityException
{
TrustManagerFactory tmf =
TrustManagerFactory.getInstance("PKIX");
KeyStore ks = KeyStore.getInstance("JKS");
CertificateFactory cf = CertificateFactory.getInstance("X.509");
try {
ks.load(null, null);
File cacert = new File(cafile);
if (!cacert.exists() || !cacert.canRead())
return;
InputStream caStream = new FileInputStream(cafile);
X509Certificate ca = (X509Certificate)cf.generateCertificate(caStream);
ks.setCertificateEntry("CA", ca);
PKIXBuilderParameters params = new PKIXBuilderParameters(ks, new X509CertSelector());
File crlcert = new File(crlfile);
if (!crlcert.exists() || !crlcert.canRead()) {
params.setRevocationEnabled(false);
} else {
InputStream crlStream = new FileInputStream(crlfile);
Collection<? extends CRL> crls = cf.generateCRLs(crlStream);
CertStoreParameters csp = new CollectionCertStoreParameters(crls);
CertStore store = CertStore.getInstance("Collection", csp);
params.addCertStore(store);
params.setRevocationEnabled(true);
}
tmf.init(new CertPathTrustManagerParameters(params));
} catch (java.io.FileNotFoundException e) {
vlog.error(e.toString());
} catch (java.io.IOException e) {
vlog.error(e.toString());
}
tm = (X509TrustManager)tmf.getTrustManagers()[0];
}
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException
{
tm.checkClientTrusted(chain, authType);
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException
{
try {
tm.checkServerTrusted(chain, authType);
} catch (CertificateException e) {
Object[] answer = {"Proceed", "Exit"};
int ret = JOptionPane.showOptionDialog(null,
e.getCause().getLocalizedMessage()+"\n"+
"Continue connecting to this host?",
"Confirm certificate exception?",
JOptionPane.YES_NO_OPTION, JOptionPane.WARNING_MESSAGE,
null, answer, answer[0]);
if (ret == JOptionPane.NO_OPTION)
System.exit(1);
} catch (java.lang.Exception e) {
throw new Exception(e.toString());
}
}
public X509Certificate[] getAcceptedIssuers ()
{
return tm.getAcceptedIssuers();
}
}
public final int getType() { return anon ? Security.secTypeTLSNone : Security.secTypeX509None; }
public final String description()
{ return anon ? "TLS Encryption without VncAuth" : "X509 Encryption without VncAuth"; }
//protected void setParam();
//protected void checkSession();
protected CConnection cc;
private boolean anon;
private SSLSession session;
private String cafile, crlfile;
private InStream is;
private OutStream os;
private SSLSocket ssl;
static LogWriter vlog = new LogWriter("CSecurityTLS");
}

+ 58
- 58
java/src/com/tigervnc/rfb/CSecurityVncAuth.java Dosyayı Görüntüle

@@ -1,66 +1,66 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
*/
/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
*/
package com.tigervnc.rfb;
import com.tigervnc.rdr.*;
import com.tigervnc.rdr.*;
import com.tigervnc.vncviewer.*;
public class CSecurityVncAuth extends CSecurity {
public CSecurityVncAuth() { }
private static final int vncAuthChallengeSize = 16;
public boolean processMsg(CConnection cc)
{
InStream is = cc.getInStream();
OutStream os = cc.getOutStream();
// Read the challenge & obtain the user's password
byte[] challenge = new byte[vncAuthChallengeSize];
is.readBytes(challenge, 0, vncAuthChallengeSize);
StringBuffer passwd = new StringBuffer();
CConn.upg.getUserPasswd(null, passwd);
// Calculate the correct response
byte[] key = new byte[8];
int pwdLen = passwd.length();
public class CSecurityVncAuth extends CSecurity {
public CSecurityVncAuth() { }
private static final int vncAuthChallengeSize = 16;
public boolean processMsg(CConnection cc)
{
InStream is = cc.getInStream();
OutStream os = cc.getOutStream();
// Read the challenge & obtain the user's password
byte[] challenge = new byte[vncAuthChallengeSize];
is.readBytes(challenge, 0, vncAuthChallengeSize);
StringBuffer passwd = new StringBuffer();
CConn.upg.getUserPasswd(null, passwd);
// Calculate the correct response
byte[] key = new byte[8];
int pwdLen = passwd.length();
byte[] utf8str = new byte[pwdLen];
try {
utf8str = passwd.toString().getBytes("UTF8");
} catch(java.io.UnsupportedEncodingException e) {
e.printStackTrace();
}
for (int i=0; i<8; i++)
key[i] = i<pwdLen ? utf8str[i] : 0;
DesCipher des = new DesCipher(key);
for (int j = 0; j < vncAuthChallengeSize; j += 8)
des.encrypt(challenge,j,challenge,j);
// Return the response to the server
os.writeBytes(challenge, 0, vncAuthChallengeSize);
os.flush();
return true;
}
public int getType() { return Security.secTypeVncAuth; }
public String description() { return "No Encryption"; }
static LogWriter vlog = new LogWriter("VncAuth");
}
for (int i=0; i<8; i++)
key[i] = i<pwdLen ? utf8str[i] : 0;
DesCipher des = new DesCipher(key);
for (int j = 0; j < vncAuthChallengeSize; j += 8)
des.encrypt(challenge,j,challenge,j);
// Return the response to the server
os.writeBytes(challenge, 0, vncAuthChallengeSize);
os.flush();
return true;
}
public int getType() { return Security.secTypeVncAuth; }
public String description() { return "No Encryption"; }
static LogWriter vlog = new LogWriter("VncAuth");
}

+ 45
- 45
java/src/com/tigervnc/rfb/StringParameter.java Dosyayı Görüntüle

@@ -1,46 +1,46 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
*/
/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
*/
package com.tigervnc.rfb;
public class StringParameter extends VoidParameter {
public StringParameter(String name_, String desc_, String v) {
super(name_, desc_);
value = v;
defValue = v;
}
public boolean setParam(String v) {
value = v;
return value != null;
}
public boolean setDefaultStr(String v) {
value = defValue = v;
return defValue != null;
}
public String getDefaultStr() { return defValue; }
public String getValueStr() { return value; }
public String getValue() { return value; }
public String getData() { return value; }
protected String value;
protected String defValue;
}
public class StringParameter extends VoidParameter {
public StringParameter(String name_, String desc_, String v) {
super(name_, desc_);
value = v;
defValue = v;
}
public boolean setParam(String v) {
value = v;
return value != null;
}
public boolean setDefaultStr(String v) {
value = defValue = v;
return defValue != null;
}
public String getDefaultStr() { return defValue; }
public String getValueStr() { return value; }
public String getValue() { return value; }
public String getData() { return value; }
protected String value;
protected String defValue;
}

+ 1163
- 1163
java/src/com/tigervnc/vncviewer/CConn.java
Dosya farkı çok büyük olduğundan ihmal edildi
Dosyayı Görüntüle


+ 474
- 474
java/src/com/tigervnc/vncviewer/DesktopWindow.java Dosyayı Görüntüle

@@ -1,485 +1,485 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
*/
//
// DesktopWindow is an AWT Canvas representing a VNC desktop.
//
// Methods on DesktopWindow are called from both the GUI thread and the thread
// which processes incoming RFB messages ("the RFB thread"). This means we
// need to be careful with synchronization here.
//
package com.tigervnc.vncviewer;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
*/
//
// DesktopWindow is an AWT Canvas representing a VNC desktop.
//
// Methods on DesktopWindow are called from both the GUI thread and the thread
// which processes incoming RFB messages ("the RFB thread"). This means we
// need to be careful with synchronization here.
//
package com.tigervnc.vncviewer;
import java.awt.*;
import java.awt.event.*;
import java.awt.image.*;
import java.awt.datatransfer.DataFlavor;
import java.awt.datatransfer.Transferable;
import java.awt.datatransfer.Clipboard;
import javax.swing.*;
import com.tigervnc.rfb.*;
import com.tigervnc.rfb.Cursor;
import com.tigervnc.rfb.Cursor;
import com.tigervnc.rfb.Exception;
import com.tigervnc.rfb.Point;
class DesktopWindow extends JPanel implements
Runnable,
MouseListener,
MouseMotionListener,
MouseWheelListener,
KeyListener
{
////////////////////////////////////////////////////////////////////
// The following methods are all called from the RFB thread
public DesktopWindow(int width, int height, PixelFormat serverPF, CConn cc_) {
cc = cc_;
setSize(width, height);
im = new PixelBufferImage(width, height, cc, this);
cursor = new Cursor();
cursorBacking = new ManagedPixelBuffer();
addMouseListener(this);
addMouseWheelListener(this);
addMouseMotionListener(this);
addKeyListener(this);
addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent e) {
checkClipboard();
}
});
setFocusTraversalKeysEnabled(false);
setFocusable(true);
setDoubleBuffered(true);
}
public int width() {
return getWidth();
}
public int height() {
return getHeight();
}
// initGraphics() is needed because for some reason you can't call
// getGraphics() on a newly-created awt Component. It is called when the
// DesktopWindow has actually been made visible so that getGraphics() ought
// to work.
public void initGraphics() {
cc.viewport.g = cc.viewport.getGraphics();
graphics = getComponentGraphics(cc.viewport.g);
prepareImage(im.image, -1, -1, this);
}
final public PixelFormat getPF() { return im.getPF(); }
synchronized public void setPF(PixelFormat pf) {
im.setPF(pf);
}
class DesktopWindow extends JPanel implements
Runnable,
MouseListener,
MouseMotionListener,
MouseWheelListener,
KeyListener
{
////////////////////////////////////////////////////////////////////
// The following methods are all called from the RFB thread
public DesktopWindow(int width, int height, PixelFormat serverPF, CConn cc_) {
cc = cc_;
setSize(width, height);
im = new PixelBufferImage(width, height, cc, this);
cursor = new Cursor();
cursorBacking = new ManagedPixelBuffer();
addMouseListener(this);
addMouseWheelListener(this);
addMouseMotionListener(this);
addKeyListener(this);
addFocusListener(new FocusAdapter() {
public void focusGained(FocusEvent e) {
checkClipboard();
}
});
setFocusTraversalKeysEnabled(false);
setFocusable(true);
setDoubleBuffered(true);
}
public int width() {
return getWidth();
}
public int height() {
return getHeight();
}
// initGraphics() is needed because for some reason you can't call
// getGraphics() on a newly-created awt Component. It is called when the
// DesktopWindow has actually been made visible so that getGraphics() ought
// to work.
public void initGraphics() {
cc.viewport.g = cc.viewport.getGraphics();
graphics = getComponentGraphics(cc.viewport.g);
prepareImage(im.image, -1, -1, this);
}
final public PixelFormat getPF() { return im.getPF(); }
synchronized public void setPF(PixelFormat pf) {
im.setPF(pf);
}
public void setViewport(ViewportFrame viewport)
{
viewport.setChild(this);
}

// Methods called from the RFB thread - these need to be synchronized
// wherever they access data shared with the GUI thread.
public void setCursor(int w, int h, Point hotspot,
int[] data, byte[] mask) {
// strictly we should use a mutex around this test since useLocalCursor
// might be being altered by the GUI thread. However it's only a single
// boolean and it doesn't matter if we get the wrong value anyway.
synchronized(this) {
if (!cc.viewer.useLocalCursor.getValue()) return;
hideLocalCursor();
cursor.hotspot = hotspot;
Dimension bsc = tk.getBestCursorSize(w, h);
cursor.setSize(((int)bsc.getWidth() > w ? (int)bsc.getWidth() : w),
((int)bsc.getHeight() > h ? (int)bsc.getHeight() : h));
cursor.setPF(getPF());
cursorBacking.setSize(cursor.width(), cursor.height());
cursorBacking.setPF(getPF());
cursor.data = new int[cursor.width() * cursor.height()];
cursor.mask = new byte[cursor.maskLen()];
// set the masked pixels of the cursor transparent by using an extra bit in
// the colormap. We'll OR this into the data based on the values in the mask.
if (cursor.getPF().bpp == 8) {
cursor.cm = new DirectColorModel(9, 7, (7 << 3), (3 << 6), (1 << 8));
}
int maskBytesPerRow = (w + 7) / 8;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int byte_ = y * maskBytesPerRow + x / 8;
int bit = 7 - x % 8;
if ((mask[byte_] & (1 << bit)) > 0) {
cursor.data[y * cursor.width() + x] = (cursor.getPF().bpp == 8) ?
data[y * w + x] | (1 << 8) : data[y * w + x];
}
}
System.arraycopy(mask, y * maskBytesPerRow, cursor.mask,
y * ((cursor.width() + 7) / 8), maskBytesPerRow);
}
MemoryImageSource bitmap =
new MemoryImageSource(cursor.width(), cursor.height(), cursor.cm,
cursor.data, 0, cursor.width());
softCursor =
tk.createCustomCursor(tk.createImage(bitmap), new java.awt.Point(hotspot.x,hotspot.y), "Cursor");
}
if (softCursor != null) {
setCursor(softCursor);
cursorAvailable = true;
return;
}
if (!cursorAvailable) {
cursorAvailable = true;
}
showLocalCursor();
return;
}
// setColourMapEntries() changes some of the entries in the colourmap.
// Unfortunately these messages are often sent one at a time, so we delay the
// settings taking effect unless the whole colourmap has changed. This is
// because getting java to recalculate its internal translation table and
// redraw the screen is expensive.
synchronized public void setColourMapEntries(int firstColour, int nColours,
int[] rgbs) {
im.setColourMapEntries(firstColour, nColours, rgbs);
if (nColours <= 256) {
im.updateColourMap();
im.put(0, 0, im.width(), im.height(), graphics);
} else {
if (setColourMapEntriesTimerThread == null) {
setColourMapEntriesTimerThread = new Thread(this);
setColourMapEntriesTimerThread.start();
}
}
}
// Update the actual window with the changed parts of the framebuffer.
public void framebufferUpdateEnd()
{
drawInvalidRect();
}
// resize() is called when the desktop has changed size
synchronized public void resize() {
int w = cc.cp.width;
int h = cc.cp.height;
hideLocalCursor();
setSize(w, h);
im.resize(w, h);
}
final void drawInvalidRect() {
if (!invalidRect) return;
int x = invalidLeft;
int w = invalidRight - x;
int y = invalidTop;
int h = invalidBottom - y;
invalidRect = false;
synchronized (this) {
im.put(x, y, w, h, graphics);
}
}
final void invalidate(int x, int y, int w, int h) {
if (invalidRect) {
if (x < invalidLeft) invalidLeft = x;
if (x + w > invalidRight) invalidRight = x + w;
if (y < invalidTop) invalidTop = y;
if (y + h > invalidBottom) invalidBottom = y + h;
} else {
invalidLeft = x;
invalidRight = x + w;
invalidTop = y;
invalidBottom = y + h;
invalidRect = true;
}
if ((invalidRight - invalidLeft) * (invalidBottom - invalidTop) > 100000)
drawInvalidRect();
}
public void beginRect(int x, int y, int w, int h, int encoding) {
invalidRect = false;
}
public void endRect(int x, int y, int w, int h, int encoding) {
drawInvalidRect();
}
synchronized final public void fillRect(int x, int y, int w, int h, int pix)
{
if (overlapsCursor(x, y, w, h)) hideLocalCursor();
im.fillRect(x, y, w, h, pix);
invalidate(x, y, w, h);
if (softCursor == null)
showLocalCursor();
}
synchronized final public void imageRect(int x, int y, int w, int h,
int[] pix) {
if (overlapsCursor(x, y, w, h)) hideLocalCursor();
im.imageRect(x, y, w, h, pix);
invalidate(x, y, w, h);
if (softCursor == null)
showLocalCursor();
}
synchronized final public void copyRect(int x, int y, int w, int h,
int srcX, int srcY) {
if (overlapsCursor(x, y, w, h) || overlapsCursor(srcX, srcY, w, h))
hideLocalCursor();
im.copyRect(x, y, w, h, srcX, srcY);
if (!cc.viewer.fastCopyRect.getValue()) {
invalidate(x, y, w, h);
}
}
// mutex MUST be held when overlapsCursor() is called
final boolean overlapsCursor(int x, int y, int w, int h) {
return (x < cursorBackingX + cursorBacking.width() &&
y < cursorBackingY + cursorBacking.height() &&
x+w > cursorBackingX && y+h > cursorBackingY);
}
////////////////////////////////////////////////////////////////////
// The following methods are all called from the GUI thread
synchronized void resetLocalCursor() {
hideLocalCursor();
cursorAvailable = false;
}
synchronized public Dimension getPreferredSize() {
return new Dimension(im.width(), im.height());
}
synchronized public Dimension getMinimumSize() {
return new Dimension(im.width(), im.height());
}
public void update(Graphics g) {
//repaint();
}
synchronized public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(im.image, 0, 0, this);
}
String oldContents = "";
synchronized public void checkClipboard() {
// Methods called from the RFB thread - these need to be synchronized
// wherever they access data shared with the GUI thread.
public void setCursor(int w, int h, Point hotspot,
int[] data, byte[] mask) {
// strictly we should use a mutex around this test since useLocalCursor
// might be being altered by the GUI thread. However it's only a single
// boolean and it doesn't matter if we get the wrong value anyway.
synchronized(this) {
if (!cc.viewer.useLocalCursor.getValue()) return;
hideLocalCursor();
cursor.hotspot = hotspot;
Dimension bsc = tk.getBestCursorSize(w, h);
cursor.setSize(((int)bsc.getWidth() > w ? (int)bsc.getWidth() : w),
((int)bsc.getHeight() > h ? (int)bsc.getHeight() : h));
cursor.setPF(getPF());
cursorBacking.setSize(cursor.width(), cursor.height());
cursorBacking.setPF(getPF());
cursor.data = new int[cursor.width() * cursor.height()];
cursor.mask = new byte[cursor.maskLen()];
// set the masked pixels of the cursor transparent by using an extra bit in
// the colormap. We'll OR this into the data based on the values in the mask.
if (cursor.getPF().bpp == 8) {
cursor.cm = new DirectColorModel(9, 7, (7 << 3), (3 << 6), (1 << 8));
}
int maskBytesPerRow = (w + 7) / 8;
for (int y = 0; y < h; y++) {
for (int x = 0; x < w; x++) {
int byte_ = y * maskBytesPerRow + x / 8;
int bit = 7 - x % 8;
if ((mask[byte_] & (1 << bit)) > 0) {
cursor.data[y * cursor.width() + x] = (cursor.getPF().bpp == 8) ?
data[y * w + x] | (1 << 8) : data[y * w + x];
}
}
System.arraycopy(mask, y * maskBytesPerRow, cursor.mask,
y * ((cursor.width() + 7) / 8), maskBytesPerRow);
}
MemoryImageSource bitmap =
new MemoryImageSource(cursor.width(), cursor.height(), cursor.cm,
cursor.data, 0, cursor.width());
softCursor =
tk.createCustomCursor(tk.createImage(bitmap), new java.awt.Point(hotspot.x,hotspot.y), "Cursor");
}
if (softCursor != null) {
setCursor(softCursor);
cursorAvailable = true;
return;
}
if (!cursorAvailable) {
cursorAvailable = true;
}
showLocalCursor();
return;
}
// setColourMapEntries() changes some of the entries in the colourmap.
// Unfortunately these messages are often sent one at a time, so we delay the
// settings taking effect unless the whole colourmap has changed. This is
// because getting java to recalculate its internal translation table and
// redraw the screen is expensive.
synchronized public void setColourMapEntries(int firstColour, int nColours,
int[] rgbs) {
im.setColourMapEntries(firstColour, nColours, rgbs);
if (nColours <= 256) {
im.updateColourMap();
im.put(0, 0, im.width(), im.height(), graphics);
} else {
if (setColourMapEntriesTimerThread == null) {
setColourMapEntriesTimerThread = new Thread(this);
setColourMapEntriesTimerThread.start();
}
}
}
// Update the actual window with the changed parts of the framebuffer.
public void framebufferUpdateEnd()
{
drawInvalidRect();
}
// resize() is called when the desktop has changed size
synchronized public void resize() {
int w = cc.cp.width;
int h = cc.cp.height;
hideLocalCursor();
setSize(w, h);
im.resize(w, h);
}
final void drawInvalidRect() {
if (!invalidRect) return;
int x = invalidLeft;
int w = invalidRight - x;
int y = invalidTop;
int h = invalidBottom - y;
invalidRect = false;
synchronized (this) {
im.put(x, y, w, h, graphics);
}
}
final void invalidate(int x, int y, int w, int h) {
if (invalidRect) {
if (x < invalidLeft) invalidLeft = x;
if (x + w > invalidRight) invalidRight = x + w;
if (y < invalidTop) invalidTop = y;
if (y + h > invalidBottom) invalidBottom = y + h;
} else {
invalidLeft = x;
invalidRight = x + w;
invalidTop = y;
invalidBottom = y + h;
invalidRect = true;
}
if ((invalidRight - invalidLeft) * (invalidBottom - invalidTop) > 100000)
drawInvalidRect();
}
public void beginRect(int x, int y, int w, int h, int encoding) {
invalidRect = false;
}
public void endRect(int x, int y, int w, int h, int encoding) {
drawInvalidRect();
}
synchronized final public void fillRect(int x, int y, int w, int h, int pix)
{
if (overlapsCursor(x, y, w, h)) hideLocalCursor();
im.fillRect(x, y, w, h, pix);
invalidate(x, y, w, h);
if (softCursor == null)
showLocalCursor();
}
synchronized final public void imageRect(int x, int y, int w, int h,
int[] pix) {
if (overlapsCursor(x, y, w, h)) hideLocalCursor();
im.imageRect(x, y, w, h, pix);
invalidate(x, y, w, h);
if (softCursor == null)
showLocalCursor();
}
synchronized final public void copyRect(int x, int y, int w, int h,
int srcX, int srcY) {
if (overlapsCursor(x, y, w, h) || overlapsCursor(srcX, srcY, w, h))
hideLocalCursor();
im.copyRect(x, y, w, h, srcX, srcY);
if (!cc.viewer.fastCopyRect.getValue()) {
invalidate(x, y, w, h);
}
}
// mutex MUST be held when overlapsCursor() is called
final boolean overlapsCursor(int x, int y, int w, int h) {
return (x < cursorBackingX + cursorBacking.width() &&
y < cursorBackingY + cursorBacking.height() &&
x+w > cursorBackingX && y+h > cursorBackingY);
}
////////////////////////////////////////////////////////////////////
// The following methods are all called from the GUI thread
synchronized void resetLocalCursor() {
hideLocalCursor();
cursorAvailable = false;
}
synchronized public Dimension getPreferredSize() {
return new Dimension(im.width(), im.height());
}
synchronized public Dimension getMinimumSize() {
return new Dimension(im.width(), im.height());
}
public void update(Graphics g) {
//repaint();
}
synchronized public void paintComponent(Graphics g) {
Graphics2D g2 = (Graphics2D) g;
g2.drawImage(im.image, 0, 0, this);
}
String oldContents = "";
synchronized public void checkClipboard() {
Clipboard cb = Toolkit.getDefaultToolkit().getSystemClipboard();
if (cb != null && cc.viewer.sendClipboard.getValue()) {
Transferable t = cb.getContents(null);
if ((t != null) && t.isDataFlavorSupported(DataFlavor.stringFlavor)) {
try {
String newContents = (String)t.getTransferData(DataFlavor.stringFlavor);
if (newContents != null && !newContents.equals(oldContents)) {
cc.writeClientCutText(newContents, newContents.length());
oldContents = newContents;
cc.clipboardDialog.setContents(newContents);
}
} catch (java.lang.Exception e) {
System.out.println("Exception getting clipboard data: " + e.getMessage());
}
}
}
}
/** Mouse-Motion callback function */
private void mouseMotionCB(MouseEvent e) {
if (!cc.viewer.viewOnly.getValue())
cc.writePointerEvent(e);
// - If local cursor rendering is enabled then use it
synchronized(this) {
if (cursorAvailable) {
// - Render the cursor!
if (e.getX() != cursorPosX || e.getY() != cursorPosY) {
hideLocalCursor();
if (e.getX() >= 0 && e.getX() < im.width() &&
e.getY() >= 0 && e.getY() < im.height()) {
cursorPosX = e.getX();
cursorPosY = e.getY();
if (softCursor == null)
showLocalCursor();
}
}
}
}
lastX = e.getX();
lastY = e.getY();
}
public void mouseDragged(MouseEvent e) { mouseMotionCB(e);}
public void mouseMoved(MouseEvent e) { mouseMotionCB(e);}
/** Mouse callback function */
private void mouseCB(MouseEvent e) {
if (!cc.viewer.viewOnly.getValue())
cc.writePointerEvent(e);
lastX = e.getX();
lastY = e.getY();
}
public void mouseReleased(MouseEvent e){ mouseCB(e);}
public void mousePressed(MouseEvent e) { mouseCB(e);}
public void mouseClicked(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
/** MouseWheel callback function */
private void mouseWheelCB(MouseWheelEvent e) {
if (!cc.viewer.viewOnly.getValue())
cc.writeWheelEvent(e);
}
public void mouseWheelMoved(MouseWheelEvent e){
mouseWheelCB(e);
}
/** Handle the key-typed event. */
public void keyTyped(KeyEvent e) {}
/** Handle the key-released event. */
public void keyReleased(KeyEvent e) {}
/** Handle the key-pressed event. */
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() ==
(KeyEvent.VK_F1+cc.menuKey-Keysyms.F1)) {
cc.showMenu(lastX, lastY);
return;
}
if (!cc.viewer.viewOnly.getValue())
cc.writeKeyEvent(e);
}
////////////////////////////////////////////////////////////////////
// The following methods are called from both RFB and GUI threads
// Note that mutex MUST be held when hideLocalCursor() and showLocalCursor()
// are called.
private void hideLocalCursor() {
// - Blit the cursor backing store over the cursor
if (cursorVisible) {
cursorVisible = false;
im.imageRect(cursorBackingX, cursorBackingY, cursorBacking.width(),
cursorBacking.height(), cursorBacking.data);
im.put(cursorBackingX, cursorBackingY, cursorBacking.width(),
cursorBacking.height(), graphics);
}
}
private void showLocalCursor() {
if (cursorAvailable && !cursorVisible) {
if (!im.getPF().equal(cursor.getPF()) ||
cursor.width() == 0 || cursor.height() == 0) {
vlog.debug("attempting to render invalid local cursor");
cursorAvailable = false;
return;
}
cursorVisible = true;
if (softCursor != null) return;
int cursorLeft = (int)cursor.hotspot.x;
int cursorTop = (int)cursor.hotspot.y;
int cursorRight = cursorLeft + cursor.width();
int cursorBottom = cursorTop + cursor.height();
int x = (cursorLeft >= 0 ? cursorLeft : 0);
int y = (cursorTop >= 0 ? cursorTop : 0);
int w = ((cursorRight < im.width() ? cursorRight : im.width()) - x);
int h = ((cursorBottom < im.height() ? cursorBottom : im.height()) - y);
cursorBackingX = x;
cursorBackingY = y;
cursorBacking.setSize(w, h);
for (int j = 0; j < h; j++)
System.arraycopy(im.data, (y+j) * im.width() + x,
cursorBacking.data, j*w, w);
im.maskRect(cursorLeft, cursorTop, cursor.width(), cursor.height(),
cursor.data, cursor.mask);
im.put(x, y, w, h, graphics);
}
}
// run() is executed by the setColourMapEntriesTimerThread - it sleeps for
// 100ms before actually updating the colourmap.
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
synchronized (this) {
im.updateColourMap();
im.put(0, 0, im.width(), im.height(), graphics);
setColourMapEntriesTimerThread = null;
}
}
// access to cc by different threads is specified in CConn
CConn cc;
// access to the following must be synchronized:
PixelBufferImage im;
Graphics graphics;
Thread setColourMapEntriesTimerThread;
Cursor cursor;
boolean cursorVisible; // Is cursor currently rendered?
boolean cursorAvailable; // Is cursor available for rendering?
int cursorPosX, cursorPosY;
ManagedPixelBuffer cursorBacking;
int cursorBackingX, cursorBackingY;
java.awt.Cursor softCursor;
static Toolkit tk = Toolkit.getDefaultToolkit();
// the following are only ever accessed by the RFB thread:
boolean invalidRect;
int invalidLeft, invalidRight, invalidTop, invalidBottom;
// the following are only ever accessed by the GUI thread:
int lastX, lastY;
static LogWriter vlog = new LogWriter("DesktopWindow");
}
if (cb != null && cc.viewer.sendClipboard.getValue()) {
Transferable t = cb.getContents(null);
if ((t != null) && t.isDataFlavorSupported(DataFlavor.stringFlavor)) {
try {
String newContents = (String)t.getTransferData(DataFlavor.stringFlavor);
if (newContents != null && !newContents.equals(oldContents)) {
cc.writeClientCutText(newContents, newContents.length());
oldContents = newContents;
cc.clipboardDialog.setContents(newContents);
}
} catch (java.lang.Exception e) {
System.out.println("Exception getting clipboard data: " + e.getMessage());
}
}
}
}
/** Mouse-Motion callback function */
private void mouseMotionCB(MouseEvent e) {
if (!cc.viewer.viewOnly.getValue())
cc.writePointerEvent(e);
// - If local cursor rendering is enabled then use it
synchronized(this) {
if (cursorAvailable) {
// - Render the cursor!
if (e.getX() != cursorPosX || e.getY() != cursorPosY) {
hideLocalCursor();
if (e.getX() >= 0 && e.getX() < im.width() &&
e.getY() >= 0 && e.getY() < im.height()) {
cursorPosX = e.getX();
cursorPosY = e.getY();
if (softCursor == null)
showLocalCursor();
}
}
}
}
lastX = e.getX();
lastY = e.getY();
}
public void mouseDragged(MouseEvent e) { mouseMotionCB(e);}
public void mouseMoved(MouseEvent e) { mouseMotionCB(e);}
/** Mouse callback function */
private void mouseCB(MouseEvent e) {
if (!cc.viewer.viewOnly.getValue())
cc.writePointerEvent(e);
lastX = e.getX();
lastY = e.getY();
}
public void mouseReleased(MouseEvent e){ mouseCB(e);}
public void mousePressed(MouseEvent e) { mouseCB(e);}
public void mouseClicked(MouseEvent e){}
public void mouseEntered(MouseEvent e){}
public void mouseExited(MouseEvent e){}
/** MouseWheel callback function */
private void mouseWheelCB(MouseWheelEvent e) {
if (!cc.viewer.viewOnly.getValue())
cc.writeWheelEvent(e);
}
public void mouseWheelMoved(MouseWheelEvent e){
mouseWheelCB(e);
}
/** Handle the key-typed event. */
public void keyTyped(KeyEvent e) {}
/** Handle the key-released event. */
public void keyReleased(KeyEvent e) {}
/** Handle the key-pressed event. */
public void keyPressed(KeyEvent e) {
if (e.getKeyCode() ==
(KeyEvent.VK_F1+cc.menuKey-Keysyms.F1)) {
cc.showMenu(lastX, lastY);
return;
}
if (!cc.viewer.viewOnly.getValue())
cc.writeKeyEvent(e);
}
////////////////////////////////////////////////////////////////////
// The following methods are called from both RFB and GUI threads
// Note that mutex MUST be held when hideLocalCursor() and showLocalCursor()
// are called.
private void hideLocalCursor() {
// - Blit the cursor backing store over the cursor
if (cursorVisible) {
cursorVisible = false;
im.imageRect(cursorBackingX, cursorBackingY, cursorBacking.width(),
cursorBacking.height(), cursorBacking.data);
im.put(cursorBackingX, cursorBackingY, cursorBacking.width(),
cursorBacking.height(), graphics);
}
}
private void showLocalCursor() {
if (cursorAvailable && !cursorVisible) {
if (!im.getPF().equal(cursor.getPF()) ||
cursor.width() == 0 || cursor.height() == 0) {
vlog.debug("attempting to render invalid local cursor");
cursorAvailable = false;
return;
}
cursorVisible = true;
if (softCursor != null) return;
int cursorLeft = (int)cursor.hotspot.x;
int cursorTop = (int)cursor.hotspot.y;
int cursorRight = cursorLeft + cursor.width();
int cursorBottom = cursorTop + cursor.height();
int x = (cursorLeft >= 0 ? cursorLeft : 0);
int y = (cursorTop >= 0 ? cursorTop : 0);
int w = ((cursorRight < im.width() ? cursorRight : im.width()) - x);
int h = ((cursorBottom < im.height() ? cursorBottom : im.height()) - y);
cursorBackingX = x;
cursorBackingY = y;
cursorBacking.setSize(w, h);
for (int j = 0; j < h; j++)
System.arraycopy(im.data, (y+j) * im.width() + x,
cursorBacking.data, j*w, w);
im.maskRect(cursorLeft, cursorTop, cursor.width(), cursor.height(),
cursor.data, cursor.mask);
im.put(x, y, w, h, graphics);
}
}
// run() is executed by the setColourMapEntriesTimerThread - it sleeps for
// 100ms before actually updating the colourmap.
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {}
synchronized (this) {
im.updateColourMap();
im.put(0, 0, im.width(), im.height(), graphics);
setColourMapEntriesTimerThread = null;
}
}
// access to cc by different threads is specified in CConn
CConn cc;
// access to the following must be synchronized:
PixelBufferImage im;
Graphics graphics;
Thread setColourMapEntriesTimerThread;
Cursor cursor;
boolean cursorVisible; // Is cursor currently rendered?
boolean cursorAvailable; // Is cursor available for rendering?
int cursorPosX, cursorPosY;
ManagedPixelBuffer cursorBacking;
int cursorBackingX, cursorBackingY;
java.awt.Cursor softCursor;
static Toolkit tk = Toolkit.getDefaultToolkit();
// the following are only ever accessed by the RFB thread:
boolean invalidRect;
int invalidLeft, invalidRight, invalidTop, invalidBottom;
// the following are only ever accessed by the GUI thread:
int lastX, lastY;
static LogWriter vlog = new LogWriter("DesktopWindow");
}

+ 376
- 376
java/src/com/tigervnc/vncviewer/OptionsDialog.java Dosyayı Görüntüle

@@ -1,380 +1,380 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
*/
/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
*/
package com.tigervnc.vncviewer;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.filechooser.*;
import javax.swing.ImageIcon;
import java.net.URL;
import java.io.IOException;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import javax.swing.filechooser.*;
import javax.swing.ImageIcon;
import java.net.URL;
import java.io.IOException;

import com.tigervnc.rfb.*;
import com.tigervnc.rfb.Exception;
class OptionsDialog extends Dialog implements
ActionListener,
ItemListener
{
// Constants
// Static variables
static LogWriter vlog = new LogWriter("OptionsDialog");
OptionsDialogCallback cb;
JPanel FormatPanel, InputsPanel, MiscPanel, DefaultsPanel, SecPanel;
JCheckBox autoSelect, customCompressLevel, noJpeg;
JComboBox menuKey, compressLevel, qualityLevel ;
ButtonGroup encodingGroup, colourGroup;
JRadioButton zrle, hextile, tight, raw;
JRadioButton fullColour, mediumColour, lowColour, veryLowColour;
JCheckBox viewOnly, acceptClipboard, sendClipboard;
JCheckBox fullScreen, shared, useLocalCursor, fastCopyRect;
JCheckBox secVeNCrypt, encNone, encTLS, encX509;
JCheckBox secNone, secVnc, secPlain, secIdent, sendLocalUsername;
JButton okButton, cancelButton;
JButton ca, crl;
JButton defSaveButton;
boolean encryption = true;
UserPrefs defaults;
public OptionsDialog(OptionsDialogCallback cb_) {
super(false);
cb = cb_;
setResizable(false);
setTitle("VNC Viewer Options");
defaults = new UserPrefs("vncviewer");
getContentPane().setLayout(
new BoxLayout(getContentPane(), BoxLayout.PAGE_AXIS));
JTabbedPane tabPane = new JTabbedPane();
ButtonGroup encodingGroup = new ButtonGroup();
ButtonGroup colourGroup = new ButtonGroup();
// Colour & Encoding tab
FormatPanel=new JPanel(new GridBagLayout());
autoSelect = new JCheckBox("Auto Select");
autoSelect.addItemListener(this);
JPanel encodingPanel = new JPanel(new GridBagLayout());
encodingPanel.setBorder(BorderFactory.createTitledBorder("Preferred encoding"));
zrle = addRadioCheckbox("ZRLE", encodingGroup, encodingPanel);
hextile = addRadioCheckbox("Hextile", encodingGroup, encodingPanel);
tight = addRadioCheckbox("Tight", encodingGroup, encodingPanel);
raw = addRadioCheckbox("Raw", encodingGroup, encodingPanel);
JPanel tightPanel = new JPanel(new GridBagLayout());
customCompressLevel = new JCheckBox("Custom Compression Level");
customCompressLevel.addItemListener(this);
Object[] compressionLevels = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
compressLevel = new JComboBox(compressionLevels);
JLabel compressionLabel = new JLabel("Level (1=fast, 9=best)");
noJpeg = new JCheckBox("Allow JPEG Compression");
noJpeg.addItemListener(this);
Object[] qualityLevels = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
qualityLevel = new JComboBox(qualityLevels);
JLabel qualityLabel = new JLabel("Level (1=poor, 9=best)");
addGBComponent(customCompressLevel, tightPanel, 0, 0, 2, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,2,0,0));
addGBComponent(compressLevel, tightPanel, 0, 1, 1, 1, 2, 2, 0, 0, GridBagConstraints.NONE, GridBagConstraints.FIRST_LINE_START, new Insets(0,20,0,0));
addGBComponent(compressionLabel, tightPanel, 1, 1, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(0,5,0,0));
addGBComponent(noJpeg, tightPanel, 0, 2, 2, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,2,0,0));
addGBComponent(qualityLevel, tightPanel, 0, 3, 1, 1, 2, 2, 0, 0, GridBagConstraints.NONE, GridBagConstraints.FIRST_LINE_START, new Insets(0,20,0,0));
addGBComponent(qualityLabel, tightPanel, 1, 3, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(0,5,0,0));
JPanel colourPanel = new JPanel(new GridBagLayout());
colourPanel.setBorder(BorderFactory.createTitledBorder("Colour level"));
fullColour = addRadioCheckbox("Full (all available colours)", colourGroup, colourPanel);
mediumColour = addRadioCheckbox("Medium (256 colours)", colourGroup, colourPanel);
lowColour = addRadioCheckbox("Low (64 colours)", colourGroup, colourPanel);
veryLowColour = addRadioCheckbox("Very low(8 colours)", colourGroup, colourPanel);
addGBComponent(autoSelect,FormatPanel, 0, 0, 2, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,2,0,0));
addGBComponent(encodingPanel,FormatPanel, 0, 1, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(0,2,0,0));
addGBComponent(colourPanel,FormatPanel, 1, 1, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_END, new Insets(0,2,0,0));
addGBComponent(tightPanel,FormatPanel, 0, 2, 2, GridBagConstraints.REMAINDER, 2, 2, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,2,0,0));
// Inputs tab
InputsPanel=new JPanel(new GridBagLayout());
viewOnly = new JCheckBox("View Only (ignore mouse & keyboard)");
viewOnly.addItemListener(this);
acceptClipboard = new JCheckBox("Accept clipboard from server");
acceptClipboard.addItemListener(this);
sendClipboard = new JCheckBox("Send clipboard to server");
sendClipboard.addItemListener(this);
JLabel menuKeyLabel = new JLabel("Menu Key");
String[] menuKeys =
{ "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12" };
menuKey = new JComboBox(menuKeys);
menuKey.addItemListener(this);
addGBComponent(viewOnly,InputsPanel, 0, 0, 2, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4));
addGBComponent(acceptClipboard,InputsPanel, 0, 1, 2, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4));
addGBComponent(sendClipboard,InputsPanel, 0, 2, 2, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4));
addGBComponent(menuKeyLabel,InputsPanel, 0, 3, 1, GridBagConstraints.REMAINDER, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(8,10,0,4));
addGBComponent(menuKey,InputsPanel, 1, 3, 1, GridBagConstraints.REMAINDER, 0, 0, 2, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(4,4,0,125));
//((javax.swing.plaf.basic.BasicComboBoxRenderer)menuKey.getRenderer()).setBorder(new EmptyBorder(0,3,0,3));
// Misc tab
MiscPanel=new JPanel(new GridBagLayout());
fullScreen = new JCheckBox("Full-screen mode");
fullScreen.addItemListener(this);
shared = new JCheckBox("Shared connection (do not disconnect other viewers)");
shared.addItemListener(this);
useLocalCursor = new JCheckBox("Render cursor locally");
useLocalCursor.addItemListener(this);
fastCopyRect = new JCheckBox("Fast CopyRect");
fastCopyRect.addItemListener(this);
addGBComponent(fullScreen,MiscPanel, 0, 0, 1, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4));
addGBComponent(shared,MiscPanel, 0, 1, 1, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4));
addGBComponent(useLocalCursor,MiscPanel, 0, 2, 1, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4));
addGBComponent(fastCopyRect,MiscPanel, 0, 3, 1, GridBagConstraints.REMAINDER, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(4,4,0,4));
// load/save tab
DefaultsPanel=new JPanel(new GridBagLayout());
JPanel configPanel = new JPanel(new GridBagLayout());
configPanel.setBorder(BorderFactory.createTitledBorder("Configuration File"));
JButton cfReloadButton = new JButton("Reload");
cfReloadButton.addActionListener(this);
addGBComponent(cfReloadButton,configPanel, 0, 0, 1, 1, 0, 0, 0, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(4,8,4,8));
JButton cfSaveButton = new JButton("Save");
cfSaveButton.addActionListener(this);
addGBComponent(cfSaveButton,configPanel, 0, 1, 1, 1, 0, 0, 0, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(4,8,4,8));
JButton cfSaveAsButton = new JButton("Save As...");
cfSaveAsButton.addActionListener(this);
addGBComponent(cfSaveAsButton,configPanel, 0, 2, 1, 1, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(4,8,4,8));
cfReloadButton.setEnabled(false);
cfSaveButton.setEnabled(false);
JPanel defaultsPanel = new JPanel(new GridBagLayout());
defaultsPanel.setBorder(BorderFactory.createTitledBorder("Defaults"));
JButton defReloadButton = new JButton("Reload");
defReloadButton.addActionListener(this);
addGBComponent(defReloadButton,defaultsPanel, 0, 0, 1, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(4,8,4,8));
defSaveButton = new JButton("Save");
defSaveButton.addActionListener(this);
addGBComponent(defSaveButton,defaultsPanel, 0, 1, 1, 1, 0, 0, 0, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(4,8,4,8));
addGBComponent(configPanel,DefaultsPanel, 0, 0, 1, GridBagConstraints.REMAINDER, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(4,4,4,4));
addGBComponent(defaultsPanel,DefaultsPanel, 1, 0, 1, GridBagConstraints.REMAINDER, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(4,4,4,4));
// security tab
SecPanel=new JPanel(new GridBagLayout());
JPanel encryptionPanel = new JPanel(new GridBagLayout());
encryptionPanel.setBorder(BorderFactory.createTitledBorder("Session Encryption"));
encNone = addCheckbox("None", null, encryptionPanel);
encTLS = addCheckbox("Anonymous TLS", null, encryptionPanel);
encX509 = addJCheckBox("TLS with X.509 certificates", null, encryptionPanel, new GridBagConstraints(0,2,1,1,1,1,GridBagConstraints.LINE_START,GridBagConstraints.REMAINDER,new Insets(0,0,0,60),0,0));
JPanel x509Panel = new JPanel(new GridBagLayout());
x509Panel.setBorder(BorderFactory.createTitledBorder("X.509 certificates"));
ca = new JButton("Load CA certificate");
ca.setPreferredSize(new Dimension(145,25));
ca.addActionListener(this);
crl = new JButton("Load CRL certificate");
crl.setPreferredSize(new Dimension(145,25));
crl.addActionListener(this);
addGBComponent(ca, x509Panel, 0, 0, 1, 1, 2, 2, 0, 1, GridBagConstraints.NONE, GridBagConstraints.LINE_START, new Insets(2,2,2,2));
addGBComponent(crl, x509Panel, 1, 0, 1, 1, 2, 2, 1, 1, GridBagConstraints.NONE, GridBagConstraints.LINE_START, new Insets(2,2,2,2));
JPanel authPanel = new JPanel(new GridBagLayout());
authPanel.setBorder(BorderFactory.createTitledBorder("Authentication"));
secNone = addCheckbox("None", null, authPanel);
secVnc = addCheckbox("Standard VNC", null, authPanel);
secPlain = addJCheckBox("Plaintext", null, authPanel, new GridBagConstraints(0,2,1,1,1,1,GridBagConstraints.LINE_START,GridBagConstraints.NONE,new Insets(0,0,0,5),0,0));
secIdent = addJCheckBox("Ident", null, authPanel, new GridBagConstraints(0,3,1,1,1,1,GridBagConstraints.LINE_START,GridBagConstraints.NONE,new Insets(0,0,0,5),0,0));
sendLocalUsername = new JCheckBox("Send Local Username");
sendLocalUsername.addItemListener(this);
addGBComponent(sendLocalUsername, authPanel, 1, 2, 1, 2, 0, 0, 2, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(0,20,0,0));
secVeNCrypt = new JCheckBox("Extended encryption and authentication methods (VeNCrypt)");
secVeNCrypt.addItemListener(this);
addGBComponent(secVeNCrypt,SecPanel, 0, 0, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,2,0,20));
addGBComponent(encryptionPanel,SecPanel, 0, 1, 1, 1, 2, 2, 1, 0, GridBagConstraints.NONE, GridBagConstraints.LINE_START, new Insets(0,4,2,4));
addGBComponent(x509Panel,SecPanel, 0, 2, 1, 1, 2, 2, 1, 0, GridBagConstraints.NONE, GridBagConstraints.LINE_START, new Insets(2,4,2,4));
addGBComponent(authPanel,SecPanel, 0, 3, 1, 1, 2, 2, 1, 1, GridBagConstraints.NONE, GridBagConstraints.FIRST_LINE_START, new Insets(2,4,2,4));
tabPane.add(FormatPanel);
tabPane.add(InputsPanel);
tabPane.add(MiscPanel);
tabPane.add(DefaultsPanel);
tabPane.add(SecPanel);
tabPane.addTab("Colour & Encoding", FormatPanel);
tabPane.addTab("Inputs", InputsPanel);
tabPane.addTab("Misc", MiscPanel);
tabPane.addTab("Load / Save", DefaultsPanel);
tabPane.addTab("Security", SecPanel);
tabPane.setBorder(BorderFactory.createEmptyBorder(4,4,0,4));
okButton = new JButton("OK");
okButton.setPreferredSize(new Dimension(90,30));
okButton.addActionListener(this);
cancelButton = new JButton("Cancel");
cancelButton.setPreferredSize(new Dimension(90,30));
cancelButton.addActionListener(this);
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
buttonPane.setBorder(BorderFactory.createEmptyBorder(4,0,0,0));
buttonPane.add(Box.createHorizontalGlue());
buttonPane.add(okButton);
buttonPane.add(Box.createRigidArea(new Dimension(4,0)));
buttonPane.add(cancelButton);
buttonPane.add(Box.createRigidArea(new Dimension(4,0)));
this.getContentPane().add(tabPane);
this.getContentPane().add(buttonPane);
pack();
}
public void initDialog() {
if (cb != null) cb.setOptions();
zrle.setEnabled(!autoSelect.isSelected());
hextile.setEnabled(!autoSelect.isSelected());
tight.setEnabled(!autoSelect.isSelected());
raw.setEnabled(!autoSelect.isSelected());
fullColour.setEnabled(!autoSelect.isSelected());
mediumColour.setEnabled(!autoSelect.isSelected());
lowColour.setEnabled(!autoSelect.isSelected());
veryLowColour.setEnabled(!autoSelect.isSelected());
compressLevel.setEnabled(customCompressLevel.isSelected());
qualityLevel.setEnabled(noJpeg.isSelected());
sendLocalUsername.setEnabled(secVeNCrypt.isEnabled()&&
(secPlain.isSelected()||secIdent.isSelected()));
}
JRadioButton addRadioCheckbox(String str, ButtonGroup group, JPanel panel) {
JRadioButton c = new JRadioButton(str);
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.weighty = 1;
panel.add(c,gbc);
group.add(c);
c.addItemListener(this);
return c;
}
JCheckBox addCheckbox(String str, ButtonGroup group, JPanel panel) {
JCheckBox c = new JCheckBox(str);
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.weighty = 1;
panel.add(c,gbc);
if (group != null)
group.add(c);
c.addItemListener(this);
return c;
}
JCheckBox addJCheckBox(String str, ButtonGroup group, JPanel panel,
GridBagConstraints gbc) {
JCheckBox c = new JCheckBox(str);
panel.add(c,gbc);
if (group != null)
group.add(c);
c.addItemListener(this);
return c;
}
public void actionPerformed(ActionEvent e) {
Object s = e.getSource();
if (s instanceof JButton && (JButton)s == okButton) {
ok = true;
if (cb != null) cb.getOptions();
endDialog();
} else if (s instanceof JButton && (JButton)s == cancelButton) {
ok = false;
endDialog();
} else if (s instanceof JButton && (JButton)s == defSaveButton) {
try {
defaults.Save();
} catch (java.lang.Exception x) { }
} else if (s instanceof JButton && (JButton)s == ca) {
JFileChooser fc = new JFileChooser();
fc.setDialogTitle("Path to X509 CA certificate");
int ret = fc.showOpenDialog(this);
if (ret == JFileChooser.APPROVE_OPTION)
CSecurityTLS.x509ca.setParam(fc.getSelectedFile().toString());
} else if (s instanceof JButton && (JButton)s == crl) {
JFileChooser fc = new JFileChooser();
fc.setDialogTitle("Path to X509 CRL file");
int ret = fc.showOpenDialog(this);
if (ret == JFileChooser.APPROVE_OPTION)
CSecurityTLS.x509crl.setParam(fc.getSelectedFile().toString());
}
}
public void itemStateChanged(ItemEvent e) {
Object s = e.getSource();
if (s instanceof JCheckBox && (JCheckBox)s == autoSelect) {
zrle.setEnabled(!autoSelect.isSelected());
hextile.setEnabled(!autoSelect.isSelected());
tight.setEnabled(!autoSelect.isSelected());
raw.setEnabled(!autoSelect.isSelected());
fullColour.setEnabled(!autoSelect.isSelected());
mediumColour.setEnabled(!autoSelect.isSelected());
lowColour.setEnabled(!autoSelect.isSelected());
veryLowColour.setEnabled(!autoSelect.isSelected());
defaults.setPref("autoSelect",(autoSelect.isSelected()) ? "on" : "off");
}
if (s instanceof JCheckBox && (JCheckBox)s == customCompressLevel) {
compressLevel.setEnabled(customCompressLevel.isSelected());
defaults.setPref("customCompressLevel",(customCompressLevel.isSelected()) ? "on" : "off");
}
if (s instanceof JCheckBox && (JCheckBox)s == noJpeg) {
qualityLevel.setEnabled(noJpeg.isSelected());
defaults.setPref("noJpeg",(noJpeg.isSelected()) ? "on" : "off");
}
if (s instanceof JCheckBox && (JCheckBox)s == sendLocalUsername) {
defaults.setPref("sendLocalUsername",(sendLocalUsername.isSelected()) ? "on" : "off");
}
if (s instanceof JCheckBox && (JCheckBox)s == secVeNCrypt) {
encNone.setEnabled(secVeNCrypt.isSelected());
encTLS.setEnabled(secVeNCrypt.isSelected());
encX509.setEnabled(secVeNCrypt.isSelected());
ca.setEnabled(secVeNCrypt.isSelected());
crl.setEnabled(secVeNCrypt.isSelected());
secIdent.setEnabled(secVeNCrypt.isSelected());
secNone.setEnabled(secVeNCrypt.isSelected());
secVnc.setEnabled(secVeNCrypt.isSelected());
secPlain.setEnabled(secVeNCrypt.isSelected());
sendLocalUsername.setEnabled(secVeNCrypt.isSelected());
}
if (s instanceof JCheckBox && (JCheckBox)s == secIdent ||
s instanceof JCheckBox && (JCheckBox)s == secPlain) {
sendLocalUsername.setEnabled(secIdent.isSelected()||secPlain.isSelected());
}
}
}
class OptionsDialog extends Dialog implements
ActionListener,
ItemListener
{
// Constants
// Static variables
static LogWriter vlog = new LogWriter("OptionsDialog");
OptionsDialogCallback cb;
JPanel FormatPanel, InputsPanel, MiscPanel, DefaultsPanel, SecPanel;
JCheckBox autoSelect, customCompressLevel, noJpeg;
JComboBox menuKey, compressLevel, qualityLevel ;
ButtonGroup encodingGroup, colourGroup;
JRadioButton zrle, hextile, tight, raw;
JRadioButton fullColour, mediumColour, lowColour, veryLowColour;
JCheckBox viewOnly, acceptClipboard, sendClipboard;
JCheckBox fullScreen, shared, useLocalCursor, fastCopyRect;
JCheckBox secVeNCrypt, encNone, encTLS, encX509;
JCheckBox secNone, secVnc, secPlain, secIdent, sendLocalUsername;
JButton okButton, cancelButton;
JButton ca, crl;
JButton defSaveButton;
boolean encryption = true;
UserPrefs defaults;
public OptionsDialog(OptionsDialogCallback cb_) {
super(false);
cb = cb_;
setResizable(false);
setTitle("VNC Viewer Options");
defaults = new UserPrefs("vncviewer");
getContentPane().setLayout(
new BoxLayout(getContentPane(), BoxLayout.PAGE_AXIS));
JTabbedPane tabPane = new JTabbedPane();
ButtonGroup encodingGroup = new ButtonGroup();
ButtonGroup colourGroup = new ButtonGroup();
// Colour & Encoding tab
FormatPanel=new JPanel(new GridBagLayout());
autoSelect = new JCheckBox("Auto Select");
autoSelect.addItemListener(this);
JPanel encodingPanel = new JPanel(new GridBagLayout());
encodingPanel.setBorder(BorderFactory.createTitledBorder("Preferred encoding"));
zrle = addRadioCheckbox("ZRLE", encodingGroup, encodingPanel);
hextile = addRadioCheckbox("Hextile", encodingGroup, encodingPanel);
tight = addRadioCheckbox("Tight", encodingGroup, encodingPanel);
raw = addRadioCheckbox("Raw", encodingGroup, encodingPanel);
JPanel tightPanel = new JPanel(new GridBagLayout());
customCompressLevel = new JCheckBox("Custom Compression Level");
customCompressLevel.addItemListener(this);
Object[] compressionLevels = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
compressLevel = new JComboBox(compressionLevels);
JLabel compressionLabel = new JLabel("Level (1=fast, 9=best)");
noJpeg = new JCheckBox("Allow JPEG Compression");
noJpeg.addItemListener(this);
Object[] qualityLevels = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
qualityLevel = new JComboBox(qualityLevels);
JLabel qualityLabel = new JLabel("Level (1=poor, 9=best)");
addGBComponent(customCompressLevel, tightPanel, 0, 0, 2, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,2,0,0));
addGBComponent(compressLevel, tightPanel, 0, 1, 1, 1, 2, 2, 0, 0, GridBagConstraints.NONE, GridBagConstraints.FIRST_LINE_START, new Insets(0,20,0,0));
addGBComponent(compressionLabel, tightPanel, 1, 1, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(0,5,0,0));
addGBComponent(noJpeg, tightPanel, 0, 2, 2, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,2,0,0));
addGBComponent(qualityLevel, tightPanel, 0, 3, 1, 1, 2, 2, 0, 0, GridBagConstraints.NONE, GridBagConstraints.FIRST_LINE_START, new Insets(0,20,0,0));
addGBComponent(qualityLabel, tightPanel, 1, 3, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(0,5,0,0));
JPanel colourPanel = new JPanel(new GridBagLayout());
colourPanel.setBorder(BorderFactory.createTitledBorder("Colour level"));
fullColour = addRadioCheckbox("Full (all available colours)", colourGroup, colourPanel);
mediumColour = addRadioCheckbox("Medium (256 colours)", colourGroup, colourPanel);
lowColour = addRadioCheckbox("Low (64 colours)", colourGroup, colourPanel);
veryLowColour = addRadioCheckbox("Very low(8 colours)", colourGroup, colourPanel);
addGBComponent(autoSelect,FormatPanel, 0, 0, 2, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,2,0,0));
addGBComponent(encodingPanel,FormatPanel, 0, 1, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(0,2,0,0));
addGBComponent(colourPanel,FormatPanel, 1, 1, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_END, new Insets(0,2,0,0));
addGBComponent(tightPanel,FormatPanel, 0, 2, 2, GridBagConstraints.REMAINDER, 2, 2, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,2,0,0));
// Inputs tab
InputsPanel=new JPanel(new GridBagLayout());
viewOnly = new JCheckBox("View Only (ignore mouse & keyboard)");
viewOnly.addItemListener(this);
acceptClipboard = new JCheckBox("Accept clipboard from server");
acceptClipboard.addItemListener(this);
sendClipboard = new JCheckBox("Send clipboard to server");
sendClipboard.addItemListener(this);
JLabel menuKeyLabel = new JLabel("Menu Key");
String[] menuKeys =
{ "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12" };
menuKey = new JComboBox(menuKeys);
menuKey.addItemListener(this);
addGBComponent(viewOnly,InputsPanel, 0, 0, 2, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4));
addGBComponent(acceptClipboard,InputsPanel, 0, 1, 2, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4));
addGBComponent(sendClipboard,InputsPanel, 0, 2, 2, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4));
addGBComponent(menuKeyLabel,InputsPanel, 0, 3, 1, GridBagConstraints.REMAINDER, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(8,10,0,4));
addGBComponent(menuKey,InputsPanel, 1, 3, 1, GridBagConstraints.REMAINDER, 0, 0, 2, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(4,4,0,125));
//((javax.swing.plaf.basic.BasicComboBoxRenderer)menuKey.getRenderer()).setBorder(new EmptyBorder(0,3,0,3));
// Misc tab
MiscPanel=new JPanel(new GridBagLayout());
fullScreen = new JCheckBox("Full-screen mode");
fullScreen.addItemListener(this);
shared = new JCheckBox("Shared connection (do not disconnect other viewers)");
shared.addItemListener(this);
useLocalCursor = new JCheckBox("Render cursor locally");
useLocalCursor.addItemListener(this);
fastCopyRect = new JCheckBox("Fast CopyRect");
fastCopyRect.addItemListener(this);
addGBComponent(fullScreen,MiscPanel, 0, 0, 1, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4));
addGBComponent(shared,MiscPanel, 0, 1, 1, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4));
addGBComponent(useLocalCursor,MiscPanel, 0, 2, 1, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4));
addGBComponent(fastCopyRect,MiscPanel, 0, 3, 1, GridBagConstraints.REMAINDER, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(4,4,0,4));
// load/save tab
DefaultsPanel=new JPanel(new GridBagLayout());
JPanel configPanel = new JPanel(new GridBagLayout());
configPanel.setBorder(BorderFactory.createTitledBorder("Configuration File"));
JButton cfReloadButton = new JButton("Reload");
cfReloadButton.addActionListener(this);
addGBComponent(cfReloadButton,configPanel, 0, 0, 1, 1, 0, 0, 0, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(4,8,4,8));
JButton cfSaveButton = new JButton("Save");
cfSaveButton.addActionListener(this);
addGBComponent(cfSaveButton,configPanel, 0, 1, 1, 1, 0, 0, 0, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(4,8,4,8));
JButton cfSaveAsButton = new JButton("Save As...");
cfSaveAsButton.addActionListener(this);
addGBComponent(cfSaveAsButton,configPanel, 0, 2, 1, 1, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(4,8,4,8));
cfReloadButton.setEnabled(false);
cfSaveButton.setEnabled(false);
JPanel defaultsPanel = new JPanel(new GridBagLayout());
defaultsPanel.setBorder(BorderFactory.createTitledBorder("Defaults"));
JButton defReloadButton = new JButton("Reload");
defReloadButton.addActionListener(this);
addGBComponent(defReloadButton,defaultsPanel, 0, 0, 1, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(4,8,4,8));
defSaveButton = new JButton("Save");
defSaveButton.addActionListener(this);
addGBComponent(defSaveButton,defaultsPanel, 0, 1, 1, 1, 0, 0, 0, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(4,8,4,8));
addGBComponent(configPanel,DefaultsPanel, 0, 0, 1, GridBagConstraints.REMAINDER, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(4,4,4,4));
addGBComponent(defaultsPanel,DefaultsPanel, 1, 0, 1, GridBagConstraints.REMAINDER, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(4,4,4,4));
// security tab
SecPanel=new JPanel(new GridBagLayout());
JPanel encryptionPanel = new JPanel(new GridBagLayout());
encryptionPanel.setBorder(BorderFactory.createTitledBorder("Session Encryption"));
encNone = addCheckbox("None", null, encryptionPanel);
encTLS = addCheckbox("Anonymous TLS", null, encryptionPanel);
encX509 = addJCheckBox("TLS with X.509 certificates", null, encryptionPanel, new GridBagConstraints(0,2,1,1,1,1,GridBagConstraints.LINE_START,GridBagConstraints.REMAINDER,new Insets(0,0,0,60),0,0));
JPanel x509Panel = new JPanel(new GridBagLayout());
x509Panel.setBorder(BorderFactory.createTitledBorder("X.509 certificates"));
ca = new JButton("Load CA certificate");
ca.setPreferredSize(new Dimension(145,25));
ca.addActionListener(this);
crl = new JButton("Load CRL certificate");
crl.setPreferredSize(new Dimension(145,25));
crl.addActionListener(this);
addGBComponent(ca, x509Panel, 0, 0, 1, 1, 2, 2, 0, 1, GridBagConstraints.NONE, GridBagConstraints.LINE_START, new Insets(2,2,2,2));
addGBComponent(crl, x509Panel, 1, 0, 1, 1, 2, 2, 1, 1, GridBagConstraints.NONE, GridBagConstraints.LINE_START, new Insets(2,2,2,2));
JPanel authPanel = new JPanel(new GridBagLayout());
authPanel.setBorder(BorderFactory.createTitledBorder("Authentication"));
secNone = addCheckbox("None", null, authPanel);
secVnc = addCheckbox("Standard VNC", null, authPanel);
secPlain = addJCheckBox("Plaintext", null, authPanel, new GridBagConstraints(0,2,1,1,1,1,GridBagConstraints.LINE_START,GridBagConstraints.NONE,new Insets(0,0,0,5),0,0));
secIdent = addJCheckBox("Ident", null, authPanel, new GridBagConstraints(0,3,1,1,1,1,GridBagConstraints.LINE_START,GridBagConstraints.NONE,new Insets(0,0,0,5),0,0));
sendLocalUsername = new JCheckBox("Send Local Username");
sendLocalUsername.addItemListener(this);
addGBComponent(sendLocalUsername, authPanel, 1, 2, 1, 2, 0, 0, 2, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(0,20,0,0));
secVeNCrypt = new JCheckBox("Extended encryption and authentication methods (VeNCrypt)");
secVeNCrypt.addItemListener(this);
addGBComponent(secVeNCrypt,SecPanel, 0, 0, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(0,2,0,20));
addGBComponent(encryptionPanel,SecPanel, 0, 1, 1, 1, 2, 2, 1, 0, GridBagConstraints.NONE, GridBagConstraints.LINE_START, new Insets(0,4,2,4));
addGBComponent(x509Panel,SecPanel, 0, 2, 1, 1, 2, 2, 1, 0, GridBagConstraints.NONE, GridBagConstraints.LINE_START, new Insets(2,4,2,4));
addGBComponent(authPanel,SecPanel, 0, 3, 1, 1, 2, 2, 1, 1, GridBagConstraints.NONE, GridBagConstraints.FIRST_LINE_START, new Insets(2,4,2,4));
tabPane.add(FormatPanel);
tabPane.add(InputsPanel);
tabPane.add(MiscPanel);
tabPane.add(DefaultsPanel);
tabPane.add(SecPanel);
tabPane.addTab("Colour & Encoding", FormatPanel);
tabPane.addTab("Inputs", InputsPanel);
tabPane.addTab("Misc", MiscPanel);
tabPane.addTab("Load / Save", DefaultsPanel);
tabPane.addTab("Security", SecPanel);
tabPane.setBorder(BorderFactory.createEmptyBorder(4,4,0,4));
okButton = new JButton("OK");
okButton.setPreferredSize(new Dimension(90,30));
okButton.addActionListener(this);
cancelButton = new JButton("Cancel");
cancelButton.setPreferredSize(new Dimension(90,30));
cancelButton.addActionListener(this);
JPanel buttonPane = new JPanel();
buttonPane.setLayout(new BoxLayout(buttonPane, BoxLayout.LINE_AXIS));
buttonPane.setBorder(BorderFactory.createEmptyBorder(4,0,0,0));
buttonPane.add(Box.createHorizontalGlue());
buttonPane.add(okButton);
buttonPane.add(Box.createRigidArea(new Dimension(4,0)));
buttonPane.add(cancelButton);
buttonPane.add(Box.createRigidArea(new Dimension(4,0)));
this.getContentPane().add(tabPane);
this.getContentPane().add(buttonPane);
pack();
}
public void initDialog() {
if (cb != null) cb.setOptions();
zrle.setEnabled(!autoSelect.isSelected());
hextile.setEnabled(!autoSelect.isSelected());
tight.setEnabled(!autoSelect.isSelected());
raw.setEnabled(!autoSelect.isSelected());
fullColour.setEnabled(!autoSelect.isSelected());
mediumColour.setEnabled(!autoSelect.isSelected());
lowColour.setEnabled(!autoSelect.isSelected());
veryLowColour.setEnabled(!autoSelect.isSelected());
compressLevel.setEnabled(customCompressLevel.isSelected());
qualityLevel.setEnabled(noJpeg.isSelected());
sendLocalUsername.setEnabled(secVeNCrypt.isEnabled()&&
(secPlain.isSelected()||secIdent.isSelected()));
}
JRadioButton addRadioCheckbox(String str, ButtonGroup group, JPanel panel) {
JRadioButton c = new JRadioButton(str);
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.weighty = 1;
panel.add(c,gbc);
group.add(c);
c.addItemListener(this);
return c;
}
JCheckBox addCheckbox(String str, ButtonGroup group, JPanel panel) {
JCheckBox c = new JCheckBox(str);
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.weightx = 1;
gbc.weighty = 1;
panel.add(c,gbc);
if (group != null)
group.add(c);
c.addItemListener(this);
return c;
}
JCheckBox addJCheckBox(String str, ButtonGroup group, JPanel panel,
GridBagConstraints gbc) {
JCheckBox c = new JCheckBox(str);
panel.add(c,gbc);
if (group != null)
group.add(c);
c.addItemListener(this);
return c;
}
public void actionPerformed(ActionEvent e) {
Object s = e.getSource();
if (s instanceof JButton && (JButton)s == okButton) {
ok = true;
if (cb != null) cb.getOptions();
endDialog();
} else if (s instanceof JButton && (JButton)s == cancelButton) {
ok = false;
endDialog();
} else if (s instanceof JButton && (JButton)s == defSaveButton) {
try {
defaults.Save();
} catch (java.lang.Exception x) { }
} else if (s instanceof JButton && (JButton)s == ca) {
JFileChooser fc = new JFileChooser();
fc.setDialogTitle("Path to X509 CA certificate");
int ret = fc.showOpenDialog(this);
if (ret == JFileChooser.APPROVE_OPTION)
CSecurityTLS.x509ca.setParam(fc.getSelectedFile().toString());
} else if (s instanceof JButton && (JButton)s == crl) {
JFileChooser fc = new JFileChooser();
fc.setDialogTitle("Path to X509 CRL file");
int ret = fc.showOpenDialog(this);
if (ret == JFileChooser.APPROVE_OPTION)
CSecurityTLS.x509crl.setParam(fc.getSelectedFile().toString());
}
}
public void itemStateChanged(ItemEvent e) {
Object s = e.getSource();
if (s instanceof JCheckBox && (JCheckBox)s == autoSelect) {
zrle.setEnabled(!autoSelect.isSelected());
hextile.setEnabled(!autoSelect.isSelected());
tight.setEnabled(!autoSelect.isSelected());
raw.setEnabled(!autoSelect.isSelected());
fullColour.setEnabled(!autoSelect.isSelected());
mediumColour.setEnabled(!autoSelect.isSelected());
lowColour.setEnabled(!autoSelect.isSelected());
veryLowColour.setEnabled(!autoSelect.isSelected());
defaults.setPref("autoSelect",(autoSelect.isSelected()) ? "on" : "off");
}
if (s instanceof JCheckBox && (JCheckBox)s == customCompressLevel) {
compressLevel.setEnabled(customCompressLevel.isSelected());
defaults.setPref("customCompressLevel",(customCompressLevel.isSelected()) ? "on" : "off");
}
if (s instanceof JCheckBox && (JCheckBox)s == noJpeg) {
qualityLevel.setEnabled(noJpeg.isSelected());
defaults.setPref("noJpeg",(noJpeg.isSelected()) ? "on" : "off");
}
if (s instanceof JCheckBox && (JCheckBox)s == sendLocalUsername) {
defaults.setPref("sendLocalUsername",(sendLocalUsername.isSelected()) ? "on" : "off");
}
if (s instanceof JCheckBox && (JCheckBox)s == secVeNCrypt) {
encNone.setEnabled(secVeNCrypt.isSelected());
encTLS.setEnabled(secVeNCrypt.isSelected());
encX509.setEnabled(secVeNCrypt.isSelected());
ca.setEnabled(secVeNCrypt.isSelected());
crl.setEnabled(secVeNCrypt.isSelected());
secIdent.setEnabled(secVeNCrypt.isSelected());
secNone.setEnabled(secVeNCrypt.isSelected());
secVnc.setEnabled(secVeNCrypt.isSelected());
secPlain.setEnabled(secVeNCrypt.isSelected());
sendLocalUsername.setEnabled(secVeNCrypt.isSelected());
}
if (s instanceof JCheckBox && (JCheckBox)s == secIdent ||
s instanceof JCheckBox && (JCheckBox)s == secPlain) {
sendLocalUsername.setEnabled(secIdent.isSelected()||secPlain.isSelected());
}
}
}

+ 174
- 174
java/src/com/tigervnc/vncviewer/ServerDialog.java Dosyayı Görüntüle

@@ -1,178 +1,178 @@
/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
*/
/* Copyright (C) 2002-2005 RealVNC Ltd. 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.
*/
package com.tigervnc.vncviewer;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.net.URL;
import java.io.File;
import java.util.*;
import java.awt.*;
import java.awt.image.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
import java.net.URL;
import java.io.File;
import java.util.*;

import com.tigervnc.rfb.*;
import com.tigervnc.rfb.Exception;
class ServerDialog extends Dialog implements
ActionListener,
ItemListener
{
public ServerDialog(OptionsDialog options_,
String defaultServerName, CConn cc_) {
super(true);
cc = cc_;
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setResizable(false);
setSize(new Dimension(340, 135));
setTitle("VNC Viewer : Connection Details");
options = options_;
getContentPane().setLayout(new GridBagLayout());
JLabel serverLabel = new JLabel("Server:", JLabel.RIGHT);
if (options.defaults.getString("server") != null) {
server = new JComboBox(options.defaults.getString("server").split(","));
} else {
server = new JComboBox();
}
// Hack to set the left inset on editable JComboBox
if (UIManager.getLookAndFeel().getID() == "Windows") {
server.setBorder(BorderFactory.createCompoundBorder(server.getBorder(),
BorderFactory.createEmptyBorder(0,2,0,0)));
} else {
ComboBoxEditor editor = server.getEditor();
JTextField jtf = (JTextField)editor.getEditorComponent();
jtf.setBorder(new CompoundBorder(jtf.getBorder(), new EmptyBorder(0,2,0,0)));
}
server.setEditable(true);
editor = server.getEditor();
JLabel encryptionLabel = new JLabel("Encryption:");
encryption = new JComboBox();
serverLabel.setPreferredSize(encryptionLabel.getPreferredSize());
JPanel topPanel = new JPanel(new GridBagLayout());
addGBComponent(new JLabel(cc.logo),topPanel, 0, 0, 1, 1, 0, 0, 0, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(5,5,5,15));
addGBComponent(serverLabel,topPanel, 1, 0, 1, 1, 0, 0, 0, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_END, new Insets(10,0,5,5));
addGBComponent(server,topPanel, 2, 0, 1, 1, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(10,0,5,40));
optionsButton = new JButton("Options...");
aboutButton = new JButton("About...");
okButton = new JButton("OK");
cancelButton = new JButton("Cancel");
JPanel buttonPanel = new JPanel(new GridBagLayout());
buttonPanel.setPreferredSize(new Dimension(340, 40));
addGBComponent(aboutButton,buttonPanel, 0, 3, 1, 1, 0, 0, 0.2, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(0,5,0,5));
addGBComponent(optionsButton,buttonPanel, 1, 3, 1, 1, 0, 0, 0, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(0,5,0,5));
addGBComponent(okButton,buttonPanel, 2, 3, 1, 1, 0, 0, 0.8, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(0,5,0,5));
addGBComponent(cancelButton,buttonPanel, 3, 3, 1, 1, 0, 0, 0.5, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(0,5,0,5));
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.fill = GridBagConstraints.BOTH;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.gridheight = 1;
gbc.insets = new Insets(0,0,0,0);
gbc.ipadx = 0;
gbc.ipady = 0;
gbc.weightx = 1;
gbc.weighty = 1;
getContentPane().add(topPanel,gbc);
getContentPane().add(buttonPanel);
server.addActionListener(this);
optionsButton.addActionListener(this);
aboutButton.addActionListener(this);
okButton.addActionListener(this);
cancelButton.addActionListener(this);
pack();
}
public void itemStateChanged(ItemEvent e) {
Object s = e.getSource();
if (s instanceof JComboBox && (JComboBox)s == encryption) {
options.encryption=(encryption.getSelectedIndex()==1) ? false : true;
}
}
public void actionPerformed(ActionEvent e) {
Object s = e.getSource();
if (s instanceof JButton && (JButton)s == okButton) {
ok = true;
endDialog();
} else if (s instanceof JButton && (JButton)s == cancelButton) {
ok = false;
endDialog();
} else if (s instanceof JButton && (JButton)s == optionsButton) {
options.showDialog();
} else if (s instanceof JButton && (JButton)s == aboutButton) {
cc.showAbout();
} else if (s instanceof JComboBox && (JComboBox)s == server) {
if (e.getActionCommand().equals("comboBoxEdited")) {
server.insertItemAt(editor.getItem(), 0);
server.setSelectedIndex(0);
ok = true;
endDialog();
}
}
}
public void endDialog() {
if (ok) {
options.defaults.setPref("encryption",(encryption.getSelectedIndex()==1) ? "off" : "on");
if (!server.getSelectedItem().toString().equals("")) {
String t = (options.defaults.getString("server")==null) ? "" : options.defaults.getString("server");
StringTokenizer st = new StringTokenizer(t, ",");
StringBuffer sb = new StringBuffer().append((String)server.getSelectedItem());
while (st.hasMoreTokens()) {
String s = st.nextToken();
if (!s.equals((String)server.getSelectedItem()) && !s.equals("")) {
sb.append(',');
sb.append(s);
}
}
options.defaults.setPref("server", sb.toString());
}
try {
options.defaults.Save();
} catch (java.lang.Exception x) { }
}
done = true;
if (modal) {
synchronized (this) {
notify();
}
}
this.dispose();
}
CConn cc;
JComboBox encryption, server;
ComboBoxEditor editor;
JButton aboutButton, optionsButton, okButton, cancelButton;
OptionsDialog options;
static LogWriter vlog = new LogWriter("ServerDialog");
}
class ServerDialog extends Dialog implements
ActionListener,
ItemListener
{
public ServerDialog(OptionsDialog options_,
String defaultServerName, CConn cc_) {
super(true);
cc = cc_;
setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE);
setResizable(false);
setSize(new Dimension(340, 135));
setTitle("VNC Viewer : Connection Details");
options = options_;
getContentPane().setLayout(new GridBagLayout());
JLabel serverLabel = new JLabel("Server:", JLabel.RIGHT);
if (options.defaults.getString("server") != null) {
server = new JComboBox(options.defaults.getString("server").split(","));
} else {
server = new JComboBox();
}
// Hack to set the left inset on editable JComboBox
if (UIManager.getLookAndFeel().getID() == "Windows") {
server.setBorder(BorderFactory.createCompoundBorder(server.getBorder(),
BorderFactory.createEmptyBorder(0,2,0,0)));
} else {
ComboBoxEditor editor = server.getEditor();
JTextField jtf = (JTextField)editor.getEditorComponent();
jtf.setBorder(new CompoundBorder(jtf.getBorder(), new EmptyBorder(0,2,0,0)));
}
server.setEditable(true);
editor = server.getEditor();
JLabel encryptionLabel = new JLabel("Encryption:");
encryption = new JComboBox();
serverLabel.setPreferredSize(encryptionLabel.getPreferredSize());
JPanel topPanel = new JPanel(new GridBagLayout());
addGBComponent(new JLabel(cc.logo),topPanel, 0, 0, 1, 1, 0, 0, 0, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(5,5,5,15));
addGBComponent(serverLabel,topPanel, 1, 0, 1, 1, 0, 0, 0, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_END, new Insets(10,0,5,5));
addGBComponent(server,topPanel, 2, 0, 1, 1, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(10,0,5,40));
optionsButton = new JButton("Options...");
aboutButton = new JButton("About...");
okButton = new JButton("OK");
cancelButton = new JButton("Cancel");
JPanel buttonPanel = new JPanel(new GridBagLayout());
buttonPanel.setPreferredSize(new Dimension(340, 40));
addGBComponent(aboutButton,buttonPanel, 0, 3, 1, 1, 0, 0, 0.2, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(0,5,0,5));
addGBComponent(optionsButton,buttonPanel, 1, 3, 1, 1, 0, 0, 0, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(0,5,0,5));
addGBComponent(okButton,buttonPanel, 2, 3, 1, 1, 0, 0, 0.8, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(0,5,0,5));
addGBComponent(cancelButton,buttonPanel, 3, 3, 1, 1, 0, 0, 0.5, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.CENTER, new Insets(0,5,0,5));
GridBagConstraints gbc = new GridBagConstraints();
gbc.anchor = GridBagConstraints.LINE_START;
gbc.fill = GridBagConstraints.BOTH;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.gridheight = 1;
gbc.insets = new Insets(0,0,0,0);
gbc.ipadx = 0;
gbc.ipady = 0;
gbc.weightx = 1;
gbc.weighty = 1;
getContentPane().add(topPanel,gbc);
getContentPane().add(buttonPanel);
server.addActionListener(this);
optionsButton.addActionListener(this);
aboutButton.addActionListener(this);
okButton.addActionListener(this);
cancelButton.addActionListener(this);
pack();
}
public void itemStateChanged(ItemEvent e) {
Object s = e.getSource();
if (s instanceof JComboBox && (JComboBox)s == encryption) {
options.encryption=(encryption.getSelectedIndex()==1) ? false : true;
}
}
public void actionPerformed(ActionEvent e) {
Object s = e.getSource();
if (s instanceof JButton && (JButton)s == okButton) {
ok = true;
endDialog();
} else if (s instanceof JButton && (JButton)s == cancelButton) {
ok = false;
endDialog();
} else if (s instanceof JButton && (JButton)s == optionsButton) {
options.showDialog();
} else if (s instanceof JButton && (JButton)s == aboutButton) {
cc.showAbout();
} else if (s instanceof JComboBox && (JComboBox)s == server) {
if (e.getActionCommand().equals("comboBoxEdited")) {
server.insertItemAt(editor.getItem(), 0);
server.setSelectedIndex(0);
ok = true;
endDialog();
}
}
}
public void endDialog() {
if (ok) {
options.defaults.setPref("encryption",(encryption.getSelectedIndex()==1) ? "off" : "on");
if (!server.getSelectedItem().toString().equals("")) {
String t = (options.defaults.getString("server")==null) ? "" : options.defaults.getString("server");
StringTokenizer st = new StringTokenizer(t, ",");
StringBuffer sb = new StringBuffer().append((String)server.getSelectedItem());
while (st.hasMoreTokens()) {
String s = st.nextToken();
if (!s.equals((String)server.getSelectedItem()) && !s.equals("")) {
sb.append(',');
sb.append(s);
}
}
options.defaults.setPref("server", sb.toString());
}
try {
options.defaults.Save();
} catch (java.lang.Exception x) { }
}
done = true;
if (modal) {
synchronized (this) {
notify();
}
}
this.dispose();
}
CConn cc;
JComboBox encryption, server;
ComboBoxEditor editor;
JButton aboutButton, optionsButton, okButton, cancelButton;
OptionsDialog options;
static LogWriter vlog = new LogWriter("ServerDialog");
}

Loading…
İptal
Kaydet