diff options
author | Brian Hinz <bphinz@users.sourceforge.net> | 2011-06-30 13:24:24 +0000 |
---|---|---|
committer | Brian Hinz <bphinz@users.sourceforge.net> | 2011-06-30 13:24:24 +0000 |
commit | 882a1d897aaf1f964f733fdcc39146b519626aa7 (patch) | |
tree | 7f75282dfa7c3b4066bd5e9b3eb2dbaaa217caa3 /java | |
parent | 5f75df117f188870ae670a6f0f7f544c46cce01b (diff) | |
download | tigervnc-882a1d897aaf1f964f733fdcc39146b519626aa7.tar.gz tigervnc-882a1d897aaf1f964f733fdcc39146b519626aa7.zip |
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
Diffstat (limited to 'java')
-rw-r--r-- | java/src/com/tigervnc/rfb/CSecurityTLS.java | 500 | ||||
-rw-r--r-- | java/src/com/tigervnc/rfb/CSecurityVncAuth.java | 116 | ||||
-rw-r--r-- | java/src/com/tigervnc/rfb/StringParameter.java | 90 | ||||
-rw-r--r-- | java/src/com/tigervnc/vncviewer/CConn.java | 2326 | ||||
-rw-r--r-- | java/src/com/tigervnc/vncviewer/DesktopWindow.java | 948 | ||||
-rw-r--r-- | java/src/com/tigervnc/vncviewer/OptionsDialog.java | 752 | ||||
-rw-r--r-- | java/src/com/tigervnc/vncviewer/ServerDialog.java | 348 |
7 files changed, 2540 insertions, 2540 deletions
diff --git a/java/src/com/tigervnc/rfb/CSecurityTLS.java b/java/src/com/tigervnc/rfb/CSecurityTLS.java index 977987ea..355d08f4 100644 --- a/java/src/com/tigervnc/rfb/CSecurityTLS.java +++ b/java/src/com/tigervnc/rfb/CSecurityTLS.java @@ -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"); +} diff --git a/java/src/com/tigervnc/rfb/CSecurityVncAuth.java b/java/src/com/tigervnc/rfb/CSecurityVncAuth.java index 75673d51..405e79fa 100644 --- a/java/src/com/tigervnc/rfb/CSecurityVncAuth.java +++ b/java/src/com/tigervnc/rfb/CSecurityVncAuth.java @@ -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"); +} diff --git a/java/src/com/tigervnc/rfb/StringParameter.java b/java/src/com/tigervnc/rfb/StringParameter.java index 4f704d9b..d7fd1a51 100644 --- a/java/src/com/tigervnc/rfb/StringParameter.java +++ b/java/src/com/tigervnc/rfb/StringParameter.java @@ -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; +} diff --git a/java/src/com/tigervnc/vncviewer/CConn.java b/java/src/com/tigervnc/vncviewer/CConn.java index 9224aa17..9ce75fc6 100644 --- a/java/src/com/tigervnc/vncviewer/CConn.java +++ b/java/src/com/tigervnc/vncviewer/CConn.java @@ -1,287 +1,287 @@ -/* 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.
- */
- -//
-// CConn
-//
-// Methods on CConn 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.
-//
-// Any access to writer() must not only be synchronized, but we must also make
-// sure that the connection is in RFBSTATE_NORMAL. We are guaranteed this for
-// any code called after serverInit() has been called. Since the DesktopWindow
-// isn't created until then, any methods called only from DesktopWindow can
-// assume that we are in RFBSTATE_NORMAL.
-
-package com.tigervnc.vncviewer;
-
+/* 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. + */ + +// +// CConn +// +// Methods on CConn 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. +// +// Any access to writer() must not only be synchronized, but we must also make +// sure that the connection is in RFBSTATE_NORMAL. We are guaranteed this for +// any code called after serverInit() has been called. Since the DesktopWindow +// isn't created until then, any methods called only from DesktopWindow can +// assume that we are in RFBSTATE_NORMAL. + +package com.tigervnc.vncviewer; + import java.awt.Color; import java.awt.Graphics; -import java.awt.event.*;
-import java.awt.Component;
-import java.awt.Dimension;
-import java.awt.Event;
-import java.awt.Frame;
-import java.awt.ScrollPane;
-
-import java.io.*;
-import javax.net.ssl.*;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.io.File;
-import java.util.jar.Attributes;
-import java.util.jar.Manifest;
-import javax.swing.*;
-import javax.swing.filechooser.*;
-import javax.swing.ImageIcon;
-import java.net.URL;
-import java.net.ServerSocket;
-import javax.swing.border.*;
-import java.util.*;
+import java.awt.event.*; +import java.awt.Component; +import java.awt.Dimension; +import java.awt.Event; +import java.awt.Frame; +import java.awt.ScrollPane; + +import java.io.*; +import javax.net.ssl.*; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.File; +import java.util.jar.Attributes; +import java.util.jar.Manifest; +import javax.swing.*; +import javax.swing.filechooser.*; +import javax.swing.ImageIcon; +import java.net.URL; +import java.net.ServerSocket; +import javax.swing.border.*; +import java.util.*; import com.tigervnc.rdr.*; import com.tigervnc.rfb.*; import com.tigervnc.rfb.Exception; import com.tigervnc.rfb.Point; import com.tigervnc.rfb.Rect; -
-class ViewportFrame extends JFrame
-{
- public ViewportFrame(String name, CConn cc_) {
- cc = cc_;
- setTitle("TigerVNC: "+name);
- setFocusable(false);
- setFocusTraversalKeysEnabled(false);
- addWindowFocusListener(new WindowAdapter() {
- public void windowGainedFocus(WindowEvent e) {
- sp.getViewport().getView().requestFocusInWindow();
- }
- });
- addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent e) {
- cc.close();
- }
- });
- }
-
- public void addChild(DesktopWindow child) {
- sp = new JScrollPane(child);
- child.setBackground(Color.BLACK);
- child.setOpaque(true);
- sp.setBorder(BorderFactory.createEmptyBorder(0,0,0,0));
- getContentPane().add(sp);
- }
-
- public void setChild(DesktopWindow child) {
+ +class ViewportFrame extends JFrame +{ + public ViewportFrame(String name, CConn cc_) { + cc = cc_; + setTitle("TigerVNC: "+name); + setFocusable(false); + setFocusTraversalKeysEnabled(false); + addWindowFocusListener(new WindowAdapter() { + public void windowGainedFocus(WindowEvent e) { + sp.getViewport().getView().requestFocusInWindow(); + } + }); + addWindowListener(new WindowAdapter() { + public void windowClosing(WindowEvent e) { + cc.close(); + } + }); + } + + public void addChild(DesktopWindow child) { + sp = new JScrollPane(child); + child.setBackground(Color.BLACK); + child.setOpaque(true); + sp.setBorder(BorderFactory.createEmptyBorder(0,0,0,0)); + getContentPane().add(sp); + } + + public void setChild(DesktopWindow child) { getContentPane().removeAll(); addChild(child); - }
-
- public void setGeometry(int x, int y, int w, int h) {
- pack();
- if (cc.fullScreen) setSize(w, h);
- setLocation(x, y);
- setBackground(Color.BLACK);
- }
-
-
- CConn cc;
- Graphics g;
- JScrollPane sp;
- static LogWriter vlog = new LogWriter("ViewportFrame");
-}
-
-public class CConn extends CConnection
- implements UserPasswdGetter, UserMsgBox, OptionsDialogCallback
-{
- ////////////////////////////////////////////////////////////////////
- // The following methods are all called from the RFB thread
-
- public CConn(VncViewer viewer_, java.net.Socket sock_,
- String vncServerName, boolean reverse)
- {
- serverHost = null; serverPort = 0; sock = sock_; viewer = viewer_;
- currentEncoding = Encodings.encodingTight; lastServerEncoding = -1;
- fullColour = viewer.fullColour.getValue();
- lowColourLevel = 2;
- autoSelect = viewer.autoSelect.getValue();
- shared = viewer.shared.getValue(); formatChange = false;
- encodingChange = false; sameMachine = false;
- fullScreen = viewer.fullScreen.getValue();
- menuKey = Keysyms.F8;
- options = new OptionsDialog(this);
- clipboardDialog = new ClipboardDialog(this);
- firstUpdate = true; pendingUpdate = false;
-
- setShared(shared);
- upg = this;
- msg = this;
-
- String encStr = viewer.preferredEncoding.getValue();
- int encNum = Encodings.encodingNum(encStr);
- if (encNum != -1) {
- currentEncoding = encNum;
- }
- cp.supportsDesktopResize = true;
- cp.supportsExtendedDesktopSize = true;
- cp.supportsDesktopRename = true;
- cp.supportsLocalCursor = viewer.useLocalCursor.getValue();
- cp.customCompressLevel = viewer.customCompressLevel.getValue();
- cp.compressLevel = viewer.compressLevel.getValue();
- cp.noJpeg = viewer.noJpeg.getValue();
- cp.qualityLevel = viewer.qualityLevel.getValue();
- initMenu();
-
- if (sock != null) {
- String name = sock.getRemoteSocketAddress()+"::"+sock.getPort();
- vlog.info("Accepted connection from "+name);
- } else {
- if (vncServerName != null) {
- serverHost = Hostname.getHost(vncServerName);
- serverPort = Hostname.getPort(vncServerName);
- } else {
- ServerDialog dlg = new ServerDialog(options, vncServerName, this);
- if (!dlg.showDialog() || dlg.server.getSelectedItem().equals("")) {
- System.exit(1);
- }
- vncServerName = (String)dlg.server.getSelectedItem();
- serverHost = Hostname.getHost(vncServerName);
- serverPort = Hostname.getPort(vncServerName);
- }
-
- try {
- sock = new java.net.Socket(serverHost, serverPort);
- } catch (java.io.IOException e) {
- throw new Exception(e.toString());
- }
- vlog.info("connected to host "+serverHost+" port "+serverPort);
- }
-
- sameMachine = (sock.getLocalSocketAddress() == sock.getRemoteSocketAddress());
- try {
- sock.setTcpNoDelay(true);
- sock.setTrafficClass(0x10);
- setServerName(serverHost);
- jis = new JavaInStream(sock.getInputStream());
- jos = new JavaOutStream(sock.getOutputStream());
- } catch (java.net.SocketException e) {
- throw new Exception(e.toString());
- } catch (java.io.IOException e) {
- throw new Exception(e.toString());
- }
- setStreams(jis, jos);
- initialiseProtocol();
- }
-
- public boolean showMsgBox(int flags, String title, String text)
- {
- StringBuffer titleText = new StringBuffer("VNC Viewer: "+title);
-
- return true;
- }
-
- // deleteWindow() is called when the user closes the desktop or menu windows.
-
- void deleteWindow() {
- if (viewport != null)
- viewport.dispose();
- viewport = null;
- }
-
- // getUserPasswd() is called by the CSecurity object when it needs us to read
- // a password from the user.
-
- public final boolean getUserPasswd(StringBuffer user, StringBuffer passwd) {
- String title = ("VNC Authentication ["
- +csecurity.description() + "]");
- PasswdDialog dlg;
- if (user == null) {
- dlg = new PasswdDialog(title, (user == null), (passwd == null));
- } else {
- if ((passwd == null) && viewer.sendLocalUsername.getValue()) {
- user.append((String)System.getProperties().get("user.name"));
- return true;
- }
- dlg = new PasswdDialog(title, viewer.sendLocalUsername.getValue(),
- (passwd == null));
- }
- if (!dlg.showDialog()) return false;
- if (user != null) {
- if (viewer.sendLocalUsername.getValue()) {
- user.append((String)System.getProperties().get("user.name"));
- } else {
- user.append(dlg.userEntry.getText());
- }
- }
- if (passwd != null)
- passwd.append(dlg.passwdEntry.getText());
- return true;
- }
-
- // CConnection callback methods
-
- // serverInit() is called when the serverInit message has been received. At
- // this point we create the desktop window and display it. We also tell the
- // server the pixel format and encodings to use and request the first update.
- public void serverInit() {
- super.serverInit();
-
- // If using AutoSelect with old servers, start in FullColor
- // mode. See comment in autoSelectFormatAndEncoding.
- if (cp.beforeVersion(3, 8) && autoSelect) {
- fullColour = true;
- }
-
- serverPF = cp.pf();
- desktop = new DesktopWindow(cp.width, cp.height, serverPF, this);
- //desktopEventHandler = desktop.setEventHandler(this);
- //desktop.addEventMask(KeyPressMask | KeyReleaseMask);
- fullColourPF = desktop.getPF();
- if (!serverPF.trueColour)
- fullColour = true;
- recreateViewport();
- formatChange = true; encodingChange = true;
- requestNewUpdate();
- }
-
- // setDesktopSize() is called when the desktop size changes (including when
- // it is set initially).
- public void setDesktopSize(int w, int h) {
- super.setDesktopSize(w,h);
- resizeFramebuffer();
- }
-
- // setExtendedDesktopSize() is a more advanced version of setDesktopSize()
- public void setExtendedDesktopSize(int reason, int result, int w, int h,
- ScreenSet layout) {
- super.setExtendedDesktopSize(reason, result, w, h, layout);
- - if ((reason == screenTypes.reasonClient) &&
- (result != screenTypes.resultSuccess)) {
- vlog.error("SetDesktopSize failed: "+result);
- return;
- }
-
+ } + + public void setGeometry(int x, int y, int w, int h) { + pack(); + if (cc.fullScreen) setSize(w, h); + setLocation(x, y); + setBackground(Color.BLACK); + } + + + CConn cc; + Graphics g; + JScrollPane sp; + static LogWriter vlog = new LogWriter("ViewportFrame"); +} + +public class CConn extends CConnection + implements UserPasswdGetter, UserMsgBox, OptionsDialogCallback +{ + //////////////////////////////////////////////////////////////////// + // The following methods are all called from the RFB thread + + public CConn(VncViewer viewer_, java.net.Socket sock_, + String vncServerName, boolean reverse) + { + serverHost = null; serverPort = 0; sock = sock_; viewer = viewer_; + currentEncoding = Encodings.encodingTight; lastServerEncoding = -1; + fullColour = viewer.fullColour.getValue(); + lowColourLevel = 2; + autoSelect = viewer.autoSelect.getValue(); + shared = viewer.shared.getValue(); formatChange = false; + encodingChange = false; sameMachine = false; + fullScreen = viewer.fullScreen.getValue(); + menuKey = Keysyms.F8; + options = new OptionsDialog(this); + clipboardDialog = new ClipboardDialog(this); + firstUpdate = true; pendingUpdate = false; + + setShared(shared); + upg = this; + msg = this; + + String encStr = viewer.preferredEncoding.getValue(); + int encNum = Encodings.encodingNum(encStr); + if (encNum != -1) { + currentEncoding = encNum; + } + cp.supportsDesktopResize = true; + cp.supportsExtendedDesktopSize = true; + cp.supportsDesktopRename = true; + cp.supportsLocalCursor = viewer.useLocalCursor.getValue(); + cp.customCompressLevel = viewer.customCompressLevel.getValue(); + cp.compressLevel = viewer.compressLevel.getValue(); + cp.noJpeg = viewer.noJpeg.getValue(); + cp.qualityLevel = viewer.qualityLevel.getValue(); + initMenu(); + + if (sock != null) { + String name = sock.getRemoteSocketAddress()+"::"+sock.getPort(); + vlog.info("Accepted connection from "+name); + } else { + if (vncServerName != null) { + serverHost = Hostname.getHost(vncServerName); + serverPort = Hostname.getPort(vncServerName); + } else { + ServerDialog dlg = new ServerDialog(options, vncServerName, this); + if (!dlg.showDialog() || dlg.server.getSelectedItem().equals("")) { + System.exit(1); + } + vncServerName = (String)dlg.server.getSelectedItem(); + serverHost = Hostname.getHost(vncServerName); + serverPort = Hostname.getPort(vncServerName); + } + + try { + sock = new java.net.Socket(serverHost, serverPort); + } catch (java.io.IOException e) { + throw new Exception(e.toString()); + } + vlog.info("connected to host "+serverHost+" port "+serverPort); + } + + sameMachine = (sock.getLocalSocketAddress() == sock.getRemoteSocketAddress()); + try { + sock.setTcpNoDelay(true); + sock.setTrafficClass(0x10); + setServerName(serverHost); + jis = new JavaInStream(sock.getInputStream()); + jos = new JavaOutStream(sock.getOutputStream()); + } catch (java.net.SocketException e) { + throw new Exception(e.toString()); + } catch (java.io.IOException e) { + throw new Exception(e.toString()); + } + setStreams(jis, jos); + initialiseProtocol(); + } + + public boolean showMsgBox(int flags, String title, String text) + { + StringBuffer titleText = new StringBuffer("VNC Viewer: "+title); + + return true; + } + + // deleteWindow() is called when the user closes the desktop or menu windows. + + void deleteWindow() { + if (viewport != null) + viewport.dispose(); + viewport = null; + } + + // getUserPasswd() is called by the CSecurity object when it needs us to read + // a password from the user. + + public final boolean getUserPasswd(StringBuffer user, StringBuffer passwd) { + String title = ("VNC Authentication [" + +csecurity.description() + "]"); + PasswdDialog dlg; + if (user == null) { + dlg = new PasswdDialog(title, (user == null), (passwd == null)); + } else { + if ((passwd == null) && viewer.sendLocalUsername.getValue()) { + user.append((String)System.getProperties().get("user.name")); + return true; + } + dlg = new PasswdDialog(title, viewer.sendLocalUsername.getValue(), + (passwd == null)); + } + if (!dlg.showDialog()) return false; + if (user != null) { + if (viewer.sendLocalUsername.getValue()) { + user.append((String)System.getProperties().get("user.name")); + } else { + user.append(dlg.userEntry.getText()); + } + } + if (passwd != null) + passwd.append(dlg.passwdEntry.getText()); + return true; + } + + // CConnection callback methods + + // serverInit() is called when the serverInit message has been received. At + // this point we create the desktop window and display it. We also tell the + // server the pixel format and encodings to use and request the first update. + public void serverInit() { + super.serverInit(); + + // If using AutoSelect with old servers, start in FullColor + // mode. See comment in autoSelectFormatAndEncoding. + if (cp.beforeVersion(3, 8) && autoSelect) { + fullColour = true; + } + + serverPF = cp.pf(); + desktop = new DesktopWindow(cp.width, cp.height, serverPF, this); + //desktopEventHandler = desktop.setEventHandler(this); + //desktop.addEventMask(KeyPressMask | KeyReleaseMask); + fullColourPF = desktop.getPF(); + if (!serverPF.trueColour) + fullColour = true; + recreateViewport(); + formatChange = true; encodingChange = true; + requestNewUpdate(); + } + + // setDesktopSize() is called when the desktop size changes (including when + // it is set initially). + public void setDesktopSize(int w, int h) { + super.setDesktopSize(w,h); resizeFramebuffer(); - }
-
+ } + + // setExtendedDesktopSize() is a more advanced version of setDesktopSize() + public void setExtendedDesktopSize(int reason, int result, int w, int h, + ScreenSet layout) { + super.setExtendedDesktopSize(reason, result, w, h, layout); + + if ((reason == screenTypes.reasonClient) && + (result != screenTypes.resultSuccess)) { + vlog.error("SetDesktopSize failed: "+result); + return; + } + + resizeFramebuffer(); + } + // clientRedirect() migrates the client to another host/port public void clientRedirect(int port, String host, String x509subject) { @@ -301,899 +301,899 @@ public class CConn extends CConnection } } - // setName() is called when the desktop name changes
- public void setName(String name) {
- super.setName(name);
-
- if (viewport != null) {
- viewport.setTitle("TigerVNC: "+name);
- }
- }
-
- // framebufferUpdateStart() is called at the beginning of an update.
- // Here we try to send out a new framebuffer update request so that the
- // next update can be sent out in parallel with us decoding the current
- // one. We cannot do this if we're in the middle of a format change
- // though.
- public void framebufferUpdateStart() {
- if (!formatChange) {
- pendingUpdate = true;
- requestNewUpdate();
- } else
- pendingUpdate = false;
- }
-
- // framebufferUpdateEnd() is called at the end of an update.
- // For each rectangle, the FdInStream will have timed the speed
- // of the connection, allowing us to select format and encoding
- // appropriately, and then request another incremental update.
- public void framebufferUpdateEnd() {
- desktop.framebufferUpdateEnd();
-
- if (firstUpdate) {
- int width, height;
-
- if (cp.supportsSetDesktopSize &&
- viewer.desktopSize.getValue() != null &&
- viewer.desktopSize.getValue().split("x").length == 2) {
- width = Integer.parseInt(viewer.desktopSize.getValue().split("x")[0]);
- height = Integer.parseInt(viewer.desktopSize.getValue().split("x")[1]);
- ScreenSet layout;
-
- layout = cp.screenLayout;
-
- if (layout.num_screens() == 0)
- layout.add_screen(new Screen());
- else if (layout.num_screens() != 1) {
-
- while (true) {
- Iterator iter = layout.screens.iterator();
- Screen screen = (Screen)iter.next();
-
- if (!iter.hasNext())
- break;
-
- layout.remove_screen(screen.id);
- }
- }
-
- Screen screen0 = (Screen)layout.screens.iterator().next();
- screen0.dimensions.tl.x = 0;
- screen0.dimensions.tl.y = 0;
- screen0.dimensions.br.x = width;
- screen0.dimensions.br.y = height;
-
- writer().writeSetDesktopSize(width, height, layout);
- }
-
- firstUpdate = false;
- }
-
- // A format change prevented us from sending this before the update,
- // so make sure to send it now.
- if (formatChange && !pendingUpdate)
- requestNewUpdate();
-
- // Compute new settings based on updated bandwidth values
- if (autoSelect)
- autoSelectFormatAndEncoding();
- }
-
- // The rest of the callbacks are fairly self-explanatory...
-
- public void setColourMapEntries(int firstColour, int nColours, int[] rgbs) {
- desktop.setColourMapEntries(firstColour, nColours, rgbs);
- }
-
- public void bell() { desktop.getToolkit().beep(); }
-
- public void serverCutText(String str, int len) {
- if (viewer.acceptClipboard.getValue())
- clipboardDialog.serverCutText(str, len);
- }
-
- // We start timing on beginRect and stop timing on endRect, to
- // avoid skewing the bandwidth estimation as a result of the server
- // being slow or the network having high latency
- public void beginRect(Rect r, int encoding) {
- ((JavaInStream)getInStream()).startTiming();
- if (encoding != Encodings.encodingCopyRect) {
- lastServerEncoding = encoding;
- }
- }
-
- public void endRect(Rect r, int encoding) {
- ((JavaInStream)getInStream()).stopTiming();
- }
-
- public void fillRect(Rect r, int p) {
- desktop.fillRect(r.tl.x, r.tl.y, r.width(), r.height(), p);
- }
- public void imageRect(Rect r, int[] p) {
- desktop.imageRect(r.tl.x, r.tl.y, r.width(), r.height(), p);
- }
- public void copyRect(Rect r, int sx, int sy) {
- desktop.copyRect(r.tl.x, r.tl.y, r.width(), r.height(), sx, sy);
- }
-
- public void setCursor(int width, int height, Point hotspot,
- int[] data, byte[] mask) {
- desktop.setCursor(width, height, hotspot, data, mask);
- }
-
- private void resizeFramebuffer()
- {
- if ((cp.width == 0) && (cp.height == 0))
- return;
- if (desktop == null)
- return;
- if ((desktop.width() == cp.width) && (desktop.height() == cp.height))
- return;
-
- desktop.resize();
- recreateViewport();
- }
-
- // recreateViewport() recreates our top-level window. This seems to be
- // better than attempting to resize the existing window, at least with
- // various X window managers.
-
- private void recreateViewport()
- {
- if (viewport != null) viewport.dispose();
- viewport = new ViewportFrame(cp.name(), this);
- viewport.setUndecorated(fullScreen);
+ // setName() is called when the desktop name changes + public void setName(String name) { + super.setName(name); + + if (viewport != null) { + viewport.setTitle("TigerVNC: "+name); + } + } + + // framebufferUpdateStart() is called at the beginning of an update. + // Here we try to send out a new framebuffer update request so that the + // next update can be sent out in parallel with us decoding the current + // one. We cannot do this if we're in the middle of a format change + // though. + public void framebufferUpdateStart() { + if (!formatChange) { + pendingUpdate = true; + requestNewUpdate(); + } else + pendingUpdate = false; + } + + // framebufferUpdateEnd() is called at the end of an update. + // For each rectangle, the FdInStream will have timed the speed + // of the connection, allowing us to select format and encoding + // appropriately, and then request another incremental update. + public void framebufferUpdateEnd() { + desktop.framebufferUpdateEnd(); + + if (firstUpdate) { + int width, height; + + if (cp.supportsSetDesktopSize && + viewer.desktopSize.getValue() != null && + viewer.desktopSize.getValue().split("x").length == 2) { + width = Integer.parseInt(viewer.desktopSize.getValue().split("x")[0]); + height = Integer.parseInt(viewer.desktopSize.getValue().split("x")[1]); + ScreenSet layout; + + layout = cp.screenLayout; + + if (layout.num_screens() == 0) + layout.add_screen(new Screen()); + else if (layout.num_screens() != 1) { + + while (true) { + Iterator iter = layout.screens.iterator(); + Screen screen = (Screen)iter.next(); + + if (!iter.hasNext()) + break; + + layout.remove_screen(screen.id); + } + } + + Screen screen0 = (Screen)layout.screens.iterator().next(); + screen0.dimensions.tl.x = 0; + screen0.dimensions.tl.y = 0; + screen0.dimensions.br.x = width; + screen0.dimensions.br.y = height; + + writer().writeSetDesktopSize(width, height, layout); + } + + firstUpdate = false; + } + + // A format change prevented us from sending this before the update, + // so make sure to send it now. + if (formatChange && !pendingUpdate) + requestNewUpdate(); + + // Compute new settings based on updated bandwidth values + if (autoSelect) + autoSelectFormatAndEncoding(); + } + + // The rest of the callbacks are fairly self-explanatory... + + public void setColourMapEntries(int firstColour, int nColours, int[] rgbs) { + desktop.setColourMapEntries(firstColour, nColours, rgbs); + } + + public void bell() { desktop.getToolkit().beep(); } + + public void serverCutText(String str, int len) { + if (viewer.acceptClipboard.getValue()) + clipboardDialog.serverCutText(str, len); + } + + // We start timing on beginRect and stop timing on endRect, to + // avoid skewing the bandwidth estimation as a result of the server + // being slow or the network having high latency + public void beginRect(Rect r, int encoding) { + ((JavaInStream)getInStream()).startTiming(); + if (encoding != Encodings.encodingCopyRect) { + lastServerEncoding = encoding; + } + } + + public void endRect(Rect r, int encoding) { + ((JavaInStream)getInStream()).stopTiming(); + } + + public void fillRect(Rect r, int p) { + desktop.fillRect(r.tl.x, r.tl.y, r.width(), r.height(), p); + } + public void imageRect(Rect r, int[] p) { + desktop.imageRect(r.tl.x, r.tl.y, r.width(), r.height(), p); + } + public void copyRect(Rect r, int sx, int sy) { + desktop.copyRect(r.tl.x, r.tl.y, r.width(), r.height(), sx, sy); + } + + public void setCursor(int width, int height, Point hotspot, + int[] data, byte[] mask) { + desktop.setCursor(width, height, hotspot, data, mask); + } + + private void resizeFramebuffer() + { + if ((cp.width == 0) && (cp.height == 0)) + return; + if (desktop == null) + return; + if ((desktop.width() == cp.width) && (desktop.height() == cp.height)) + return; + + desktop.resize(); + recreateViewport(); + } + + // recreateViewport() recreates our top-level window. This seems to be + // better than attempting to resize the existing window, at least with + // various X window managers. + + private void recreateViewport() + { + if (viewport != null) viewport.dispose(); + viewport = new ViewportFrame(cp.name(), this); + viewport.setUndecorated(fullScreen); desktop.setViewport(viewport); - ClassLoader loader = this.getClass().getClassLoader();
- URL url = loader.getResource("com/tigervnc/vncviewer/tigervnc.ico");
- ImageIcon icon = null;
- if (url != null) {
- icon = new ImageIcon(url);
- viewport.setIconImage(icon.getImage());
- }
- viewport.addChild(desktop);
- reconfigureViewport();
- viewport.setVisible(true);
- desktop.initGraphics();
- desktop.requestFocusInWindow();
- }
-
- private void reconfigureViewport()
- {
- //viewport->setMaxSize(cp.width, cp.height);
- if (fullScreen) {
- Dimension dpySize = viewport.getToolkit().getScreenSize();
- viewport.setExtendedState(JFrame.MAXIMIZED_BOTH);
- viewport.setGeometry(0, 0, dpySize.width, dpySize.height);
- } else {
- int w = cp.width;
- int h = cp.height;
- Dimension dpySize = viewport.getToolkit().getScreenSize();
- int wmDecorationWidth = 0;
- int wmDecorationHeight = 24;
- if (w + wmDecorationWidth >= dpySize.width)
- w = dpySize.width - wmDecorationWidth;
- if (h + wmDecorationHeight >= dpySize.height)
- h = dpySize.height - wmDecorationHeight;
-
- int x = (dpySize.width - w - wmDecorationWidth) / 2;
- int y = (dpySize.height - h - wmDecorationHeight)/2;
-
- viewport.setExtendedState(JFrame.NORMAL);
- viewport.setGeometry(x, y, w, h);
- }
- }
-
- // autoSelectFormatAndEncoding() chooses the format and encoding appropriate
- // to the connection speed:
- //
- // First we wait for at least one second of bandwidth measurement.
- //
- // Above 16Mbps (i.e. LAN), we choose the second highest JPEG quality,
- // which should be perceptually lossless.
- //
- // If the bandwidth is below that, we choose a more lossy JPEG quality.
- //
- // If the bandwidth drops below 256 Kbps, we switch to palette mode.
- //
- // Note: The system here is fairly arbitrary and should be replaced
- // with something more intelligent at the server end.
- //
- private void autoSelectFormatAndEncoding() {
- long kbitsPerSecond = ((JavaInStream)getInStream()).kbitsPerSecond();
- long timeWaited = ((JavaInStream)getInStream()).timeWaited();
- boolean newFullColour = fullColour;
- int newQualityLevel = cp.qualityLevel;
-
- // Always use Tight
- if (currentEncoding != Encodings.encodingTight) {
- currentEncoding = Encodings.encodingTight;
- encodingChange = true;
- }
-
- // Check that we have a decent bandwidth measurement
- if ((kbitsPerSecond == 0) || (timeWaited < 10000))
- return;
-
- // Select appropriate quality level
- if (!cp.noJpeg) {
- if (kbitsPerSecond > 16000)
- newQualityLevel = 8;
- else
- newQualityLevel = 6;
-
- if (newQualityLevel != cp.qualityLevel) {
- vlog.info("Throughput "+kbitsPerSecond+
- " kbit/s - changing to quality "+newQualityLevel);
- cp.qualityLevel = newQualityLevel;
- viewer.qualityLevel.setParam(Integer.toString(newQualityLevel));
- encodingChange = true;
- }
- }
-
- if (cp.beforeVersion(3, 8)) {
- // Xvnc from TightVNC 1.2.9 sends out FramebufferUpdates with
- // cursors "asynchronously". If this happens in the middle of a
- // pixel format change, the server will encode the cursor with
- // the old format, but the client will try to decode it
- // according to the new format. This will lead to a
- // crash. Therefore, we do not allow automatic format change for
- // old servers.
- return;
- }
-
- // Select best color level
- newFullColour = (kbitsPerSecond > 256);
- if (newFullColour != fullColour) {
- vlog.info("Throughput "+kbitsPerSecond+
- " kbit/s - full color is now "+
- (newFullColour ? "enabled" : "disabled"));
- fullColour = newFullColour;
- formatChange = true;
- }
- }
-
- // requestNewUpdate() requests an update from the server, having set the
- // format and encoding appropriately.
- private void requestNewUpdate()
- {
- if (formatChange) {
+ ClassLoader loader = this.getClass().getClassLoader(); + URL url = loader.getResource("com/tigervnc/vncviewer/tigervnc.ico"); + ImageIcon icon = null; + if (url != null) { + icon = new ImageIcon(url); + viewport.setIconImage(icon.getImage()); + } + viewport.addChild(desktop); + reconfigureViewport(); + viewport.setVisible(true); + desktop.initGraphics(); + desktop.requestFocusInWindow(); + } + + private void reconfigureViewport() + { + //viewport->setMaxSize(cp.width, cp.height); + if (fullScreen) { + Dimension dpySize = viewport.getToolkit().getScreenSize(); + viewport.setExtendedState(JFrame.MAXIMIZED_BOTH); + viewport.setGeometry(0, 0, dpySize.width, dpySize.height); + } else { + int w = cp.width; + int h = cp.height; + Dimension dpySize = viewport.getToolkit().getScreenSize(); + int wmDecorationWidth = 0; + int wmDecorationHeight = 24; + if (w + wmDecorationWidth >= dpySize.width) + w = dpySize.width - wmDecorationWidth; + if (h + wmDecorationHeight >= dpySize.height) + h = dpySize.height - wmDecorationHeight; + + int x = (dpySize.width - w - wmDecorationWidth) / 2; + int y = (dpySize.height - h - wmDecorationHeight)/2; + + viewport.setExtendedState(JFrame.NORMAL); + viewport.setGeometry(x, y, w, h); + } + } + + // autoSelectFormatAndEncoding() chooses the format and encoding appropriate + // to the connection speed: + // + // First we wait for at least one second of bandwidth measurement. + // + // Above 16Mbps (i.e. LAN), we choose the second highest JPEG quality, + // which should be perceptually lossless. + // + // If the bandwidth is below that, we choose a more lossy JPEG quality. + // + // If the bandwidth drops below 256 Kbps, we switch to palette mode. + // + // Note: The system here is fairly arbitrary and should be replaced + // with something more intelligent at the server end. + // + private void autoSelectFormatAndEncoding() { + long kbitsPerSecond = ((JavaInStream)getInStream()).kbitsPerSecond(); + long timeWaited = ((JavaInStream)getInStream()).timeWaited(); + boolean newFullColour = fullColour; + int newQualityLevel = cp.qualityLevel; + + // Always use Tight + if (currentEncoding != Encodings.encodingTight) { + currentEncoding = Encodings.encodingTight; + encodingChange = true; + } + + // Check that we have a decent bandwidth measurement + if ((kbitsPerSecond == 0) || (timeWaited < 10000)) + return; + + // Select appropriate quality level + if (!cp.noJpeg) { + if (kbitsPerSecond > 16000) + newQualityLevel = 8; + else + newQualityLevel = 6; + + if (newQualityLevel != cp.qualityLevel) { + vlog.info("Throughput "+kbitsPerSecond+ + " kbit/s - changing to quality "+newQualityLevel); + cp.qualityLevel = newQualityLevel; + viewer.qualityLevel.setParam(Integer.toString(newQualityLevel)); + encodingChange = true; + } + } + + if (cp.beforeVersion(3, 8)) { + // Xvnc from TightVNC 1.2.9 sends out FramebufferUpdates with + // cursors "asynchronously". If this happens in the middle of a + // pixel format change, the server will encode the cursor with + // the old format, but the client will try to decode it + // according to the new format. This will lead to a + // crash. Therefore, we do not allow automatic format change for + // old servers. + return; + } + + // Select best color level + newFullColour = (kbitsPerSecond > 256); + if (newFullColour != fullColour) { + vlog.info("Throughput "+kbitsPerSecond+ + " kbit/s - full color is now "+ + (newFullColour ? "enabled" : "disabled")); + fullColour = newFullColour; + formatChange = true; + } + } + + // requestNewUpdate() requests an update from the server, having set the + // format and encoding appropriately. + private void requestNewUpdate() + { + if (formatChange) { /* Catch incorrect requestNewUpdate calls */ assert(pendingUpdate == false); - if (fullColour) {
- desktop.setPF(fullColourPF);
- } else {
- if (lowColourLevel == 0) {
- desktop.setPF(new PixelFormat(8,3,false,true,1,1,1,2,1,0));
- } else if (lowColourLevel == 1) {
- desktop.setPF(new PixelFormat(8,6,false,true,3,3,3,4,2,0));
- } else {
- desktop.setPF(new PixelFormat(8,8,false,true,7,7,3,0,3,6));
- }
- }
- String str = desktop.getPF().print();
- vlog.info("Using pixel format "+str);
- cp.setPF(desktop.getPF());
- synchronized (this) {
- writer().writeSetPixelFormat(cp.pf());
- }
- }
- checkEncodings();
- synchronized (this) {
- writer().writeFramebufferUpdateRequest(new Rect(0,0,cp.width,cp.height),
- !formatChange);
- }
- formatChange = false;
- }
-
-
- ////////////////////////////////////////////////////////////////////
- // The following methods are all called from the GUI thread
-
- // close() closes the socket, thus waking up the RFB thread.
- public void close() {
- try {
- shuttingDown = true;
- sock.close();
- } catch (java.io.IOException e) {
- e.printStackTrace();
- }
- }
-
- // Menu callbacks. These are guaranteed only to be called after serverInit()
- // has been called, since the menu is only accessible from the DesktopWindow
-
- private void initMenu() {
- menu = new F8Menu(this);
- }
-
- void showMenu(int x, int y) {
- String os = System.getProperty("os.name");
- if (os.startsWith("Windows"))
- com.sun.java.swing.plaf.windows.WindowsLookAndFeel.setMnemonicHidden(false);
- menu.show(desktop, x, y);
- }
-
- void showAbout() {
- InputStream stream = cl.getResourceAsStream("com/tigervnc/vncviewer/timestamp");
- String pkgDate = "";
- String pkgTime = "";
- try {
- Manifest manifest = new Manifest(stream);
- Attributes attributes = manifest.getMainAttributes();
- pkgDate = attributes.getValue("Package-Date");
- pkgTime = attributes.getValue("Package-Time");
- } catch (IOException e) { }
- JOptionPane.showMessageDialog((viewport != null ? viewport : null),
- VncViewer.about1+"\n"
- +"Built on "+pkgDate+" at "+pkgTime+"\n"
- +VncViewer.about2+"\n"
- +VncViewer.about3,
- "About TigerVNC Viewer for Java",
- JOptionPane.INFORMATION_MESSAGE,
- logo);
- }
-
- void showInfo() {
- JOptionPane.showMessageDialog(viewport,
- "Desktop name: "+cp.name()+"\n"
- +"Host: "+serverHost+":"+sock.getPort()+"\n"
- +"Size: "+cp.width+"x"+cp.height+"\n"
- +"Pixel format: "+desktop.getPF().print()+"\n"
- +"(server default "+serverPF.print()+")\n"
- +"Requested encoding: "+Encodings.encodingName(currentEncoding)+"\n"
- +"Last used encoding: "+Encodings.encodingName(lastServerEncoding)+"\n"
- +"Line speed estimate: "+((JavaInStream)getInStream()).kbitsPerSecond()+" kbit/s"+"\n"
- +"Protocol version: "+cp.majorVersion+"."+cp.minorVersion+"\n"
- +"Security method: "+Security.secTypeName(csecurity.getType())
- +" ["+csecurity.description()+"]",
- "VNC connection info",
- JOptionPane.PLAIN_MESSAGE);
- }
-
- synchronized public void refresh() {
- writer().writeFramebufferUpdateRequest(new Rect(0,0,cp.width,cp.height), false);
+ if (fullColour) { + desktop.setPF(fullColourPF); + } else { + if (lowColourLevel == 0) { + desktop.setPF(new PixelFormat(8,3,false,true,1,1,1,2,1,0)); + } else if (lowColourLevel == 1) { + desktop.setPF(new PixelFormat(8,6,false,true,3,3,3,4,2,0)); + } else { + desktop.setPF(new PixelFormat(8,8,false,true,7,7,3,0,3,6)); + } + } + String str = desktop.getPF().print(); + vlog.info("Using pixel format "+str); + cp.setPF(desktop.getPF()); + synchronized (this) { + writer().writeSetPixelFormat(cp.pf()); + } + } + checkEncodings(); + synchronized (this) { + writer().writeFramebufferUpdateRequest(new Rect(0,0,cp.width,cp.height), + !formatChange); + } + formatChange = false; + } + + + //////////////////////////////////////////////////////////////////// + // The following methods are all called from the GUI thread + + // close() closes the socket, thus waking up the RFB thread. + public void close() { + try { + shuttingDown = true; + sock.close(); + } catch (java.io.IOException e) { + e.printStackTrace(); + } + } + + // Menu callbacks. These are guaranteed only to be called after serverInit() + // has been called, since the menu is only accessible from the DesktopWindow + + private void initMenu() { + menu = new F8Menu(this); + } + + void showMenu(int x, int y) { + String os = System.getProperty("os.name"); + if (os.startsWith("Windows")) + com.sun.java.swing.plaf.windows.WindowsLookAndFeel.setMnemonicHidden(false); + menu.show(desktop, x, y); + } + + void showAbout() { + InputStream stream = cl.getResourceAsStream("com/tigervnc/vncviewer/timestamp"); + String pkgDate = ""; + String pkgTime = ""; + try { + Manifest manifest = new Manifest(stream); + Attributes attributes = manifest.getMainAttributes(); + pkgDate = attributes.getValue("Package-Date"); + pkgTime = attributes.getValue("Package-Time"); + } catch (IOException e) { } + JOptionPane.showMessageDialog((viewport != null ? viewport : null), + VncViewer.about1+"\n" + +"Built on "+pkgDate+" at "+pkgTime+"\n" + +VncViewer.about2+"\n" + +VncViewer.about3, + "About TigerVNC Viewer for Java", + JOptionPane.INFORMATION_MESSAGE, + logo); + } + + void showInfo() { + JOptionPane.showMessageDialog(viewport, + "Desktop name: "+cp.name()+"\n" + +"Host: "+serverHost+":"+sock.getPort()+"\n" + +"Size: "+cp.width+"x"+cp.height+"\n" + +"Pixel format: "+desktop.getPF().print()+"\n" + +"(server default "+serverPF.print()+")\n" + +"Requested encoding: "+Encodings.encodingName(currentEncoding)+"\n" + +"Last used encoding: "+Encodings.encodingName(lastServerEncoding)+"\n" + +"Line speed estimate: "+((JavaInStream)getInStream()).kbitsPerSecond()+" kbit/s"+"\n" + +"Protocol version: "+cp.majorVersion+"."+cp.minorVersion+"\n" + +"Security method: "+Security.secTypeName(csecurity.getType()) + +" ["+csecurity.description()+"]", + "VNC connection info", + JOptionPane.PLAIN_MESSAGE); + } + + synchronized public void refresh() { + writer().writeFramebufferUpdateRequest(new Rect(0,0,cp.width,cp.height), false); pendingUpdate = true; - }
-
-
- // OptionsDialogCallback. setOptions() sets the options dialog's checkboxes
- // etc to reflect our flags. getOptions() sets our flags according to the
- // options dialog's checkboxes. They are both called from the GUI thread.
- // Some of the flags are also accessed by the RFB thread. I believe that
- // reading and writing boolean and int values in java is atomic, so there is
- // no need for synchronization.
-
- public void setOptions() {
- int digit;
- options.autoSelect.setSelected(autoSelect);
- options.fullColour.setSelected(fullColour);
- options.veryLowColour.setSelected(!fullColour && lowColourLevel == 0);
- options.lowColour.setSelected(!fullColour && lowColourLevel == 1);
- options.mediumColour.setSelected(!fullColour && lowColourLevel == 2);
- options.tight.setSelected(currentEncoding == Encodings.encodingTight);
- options.zrle.setSelected(currentEncoding == Encodings.encodingZRLE);
- options.hextile.setSelected(currentEncoding == Encodings.encodingHextile);
- options.raw.setSelected(currentEncoding == Encodings.encodingRaw);
-
- options.customCompressLevel.setSelected(viewer.customCompressLevel.getValue());
- digit = 0 + viewer.compressLevel.getValue();
- options.compressLevel.setSelectedItem(digit);
- options.noJpeg.setSelected(!viewer.noJpeg.getValue());
- digit = 0 + viewer.qualityLevel.getValue();
- options.qualityLevel.setSelectedItem(digit);
-
- options.viewOnly.setSelected(viewer.viewOnly.getValue());
- options.acceptClipboard.setSelected(viewer.acceptClipboard.getValue());
- options.sendClipboard.setSelected(viewer.sendClipboard.getValue());
- options.menuKey.setSelectedIndex(menuKey-0xFFBE);
-
- if (state() == RFBSTATE_NORMAL) {
- options.shared.setEnabled(false);
- options.secVeNCrypt.setEnabled(false);
- options.encNone.setEnabled(false);
- options.encTLS.setEnabled(false);
- options.encX509.setEnabled(false);
- options.ca.setEnabled(false);
- options.crl.setEnabled(false);
- options.secIdent.setEnabled(false);
- options.secNone.setEnabled(false);
- options.secVnc.setEnabled(false);
- options.secPlain.setEnabled(false);
- options.sendLocalUsername.setEnabled(false);
- } else {
- options.shared.setSelected(shared);
-
- /* Process non-VeNCrypt sectypes */
- java.util.List<Integer> secTypes = new ArrayList<Integer>();
- secTypes = security.GetEnabledSecTypes();
- for (Iterator i = secTypes.iterator(); i.hasNext();) {
- switch ((Integer)i.next()) {
- case Security.secTypeVeNCrypt:
- options.secVeNCrypt.setSelected(true);
- break;
- case Security.secTypeNone:
- options.encNone.setSelected(true);
- options.secNone.setSelected(true);
- break;
- case Security.secTypeVncAuth:
- options.encNone.setSelected(true);
- options.secVnc.setSelected(true);
- break;
- }
- }
-
- /* Process VeNCrypt subtypes */
- if (options.secVeNCrypt.isSelected()) {
- java.util.List<Integer> secTypesExt = new ArrayList<Integer>();
- secTypesExt = security.GetEnabledExtSecTypes();
- for (Iterator iext = secTypesExt.iterator(); iext.hasNext();) {
- switch ((Integer)iext.next()) {
- case Security.secTypePlain:
- options.secPlain.setSelected(true);
- options.sendLocalUsername.setSelected(true);
- break;
- case Security.secTypeIdent:
- options.secIdent.setSelected(true);
- options.sendLocalUsername.setSelected(true);
- break;
- case Security.secTypeTLSNone:
- options.encTLS.setSelected(true);
- options.secNone.setSelected(true);
- break;
- case Security.secTypeTLSVnc:
- options.encTLS.setSelected(true);
- options.secVnc.setSelected(true);
- break;
- case Security.secTypeTLSPlain:
- options.encTLS.setSelected(true);
- options.secPlain.setSelected(true);
- options.sendLocalUsername.setSelected(true);
- break;
- case Security.secTypeTLSIdent:
- options.encTLS.setSelected(true);
- options.secIdent.setSelected(true);
- options.sendLocalUsername.setSelected(true);
- break;
- case Security.secTypeX509None:
- options.encX509.setSelected(true);
- options.secNone.setSelected(true);
- break;
- case Security.secTypeX509Vnc:
- options.encX509.setSelected(true);
- options.secVnc.setSelected(true);
- break;
- case Security.secTypeX509Plain:
- options.encX509.setSelected(true);
- options.secPlain.setSelected(true);
- options.sendLocalUsername.setSelected(true);
- break;
- case Security.secTypeX509Ident:
- options.encX509.setSelected(true);
- options.secIdent.setSelected(true);
- options.sendLocalUsername.setSelected(true);
- break;
- }
- }
- }
- options.sendLocalUsername.setEnabled(options.secPlain.isSelected()||
- options.secIdent.isSelected());
- }
-
- options.fullScreen.setSelected(fullScreen);
- options.useLocalCursor.setSelected(viewer.useLocalCursor.getValue());
- options.fastCopyRect.setSelected(viewer.fastCopyRect.getValue());
- }
-
- public void getOptions() {
- autoSelect = options.autoSelect.isSelected();
- if (fullColour != options.fullColour.isSelected())
- formatChange = true;
- fullColour = options.fullColour.isSelected();
- if (!fullColour) {
- int newLowColourLevel = (options.veryLowColour.isSelected() ? 0 :
- options.lowColour.isSelected() ? 1 : 2);
- if (newLowColourLevel != lowColourLevel) {
- lowColourLevel = newLowColourLevel;
- formatChange = true;
- }
- }
- int newEncoding = (options.zrle.isSelected() ? Encodings.encodingZRLE :
- options.hextile.isSelected() ? Encodings.encodingHextile :
- options.tight.isSelected() ? Encodings.encodingTight :
- Encodings.encodingRaw);
- if (newEncoding != currentEncoding) {
- currentEncoding = newEncoding;
- encodingChange = true;
- }
-
- viewer.customCompressLevel.setParam(options.customCompressLevel.isSelected());
- if (cp.customCompressLevel != viewer.customCompressLevel.getValue()) {
- cp.customCompressLevel = viewer.customCompressLevel.getValue();
- encodingChange = true;
- }
- viewer.compressLevel.setParam(options.compressLevel.getSelectedItem().toString());
- if (cp.compressLevel != viewer.compressLevel.getValue()) {
- cp.compressLevel = viewer.compressLevel.getValue();
- encodingChange = true;
- }
- viewer.noJpeg.setParam(!options.noJpeg.isSelected());
- if (cp.noJpeg != viewer.noJpeg.getValue()) {
- cp.noJpeg = viewer.noJpeg.getValue();
- encodingChange = true;
- }
- viewer.qualityLevel.setParam(options.qualityLevel.getSelectedItem().toString());
- if (cp.qualityLevel != viewer.qualityLevel.getValue()) {
- cp.qualityLevel = viewer.qualityLevel.getValue();
- encodingChange = true;
- }
- viewer.sendLocalUsername.setParam(options.sendLocalUsername.isSelected());
-
- viewer.viewOnly.setParam(options.viewOnly.isSelected());
- viewer.acceptClipboard.setParam(options.acceptClipboard.isSelected());
- viewer.sendClipboard.setParam(options.sendClipboard.isSelected());
- clipboardDialog.setSendingEnabled(viewer.sendClipboard.getValue());
- menuKey = (int)(options.menuKey.getSelectedIndex()+0xFFBE);
- F8Menu.f8.setLabel("Send F"+(menuKey-Keysyms.F1+1));
-
- shared = options.shared.isSelected();
- setShared(shared);
- viewer.useLocalCursor.setParam(options.useLocalCursor.isSelected());
- if (cp.supportsLocalCursor != viewer.useLocalCursor.getValue()) {
- cp.supportsLocalCursor = viewer.useLocalCursor.getValue();
- encodingChange = true;
- if (desktop != null)
- desktop.resetLocalCursor();
- }
-
- checkEncodings();
-
- if (state() != RFBSTATE_NORMAL) {
- /* Process security types which don't use encryption */
- if (options.encNone.isSelected()) {
- if (options.secNone.isSelected())
- Security.EnableSecType(Security.secTypeNone);
- if (options.secVnc.isSelected())
- Security.EnableSecType(Security.secTypeVncAuth);
- if (options.secPlain.isSelected())
- Security.EnableSecType(Security.secTypePlain);
- if (options.secIdent.isSelected())
- Security.EnableSecType(Security.secTypeIdent);
- } else {
- Security.DisableSecType(Security.secTypeNone);
- Security.DisableSecType(Security.secTypeVncAuth);
- Security.DisableSecType(Security.secTypePlain);
- Security.DisableSecType(Security.secTypeIdent);
- }
-
- /* Process security types which use TLS encryption */
- if (options.encTLS.isSelected()) {
- if (options.secNone.isSelected())
- Security.EnableSecType(Security.secTypeTLSNone);
- if (options.secVnc.isSelected())
- Security.EnableSecType(Security.secTypeTLSVnc);
- if (options.secPlain.isSelected())
- Security.EnableSecType(Security.secTypeTLSPlain);
- if (options.secIdent.isSelected())
- Security.EnableSecType(Security.secTypeTLSIdent);
- } else {
- Security.DisableSecType(Security.secTypeTLSNone);
- Security.DisableSecType(Security.secTypeTLSVnc);
- Security.DisableSecType(Security.secTypeTLSPlain);
- Security.DisableSecType(Security.secTypeTLSIdent);
- }
-
- /* Process security types which use X509 encryption */
- if (options.encX509.isSelected()) {
- if (options.secNone.isSelected())
- Security.EnableSecType(Security.secTypeX509None);
- if (options.secVnc.isSelected())
- Security.EnableSecType(Security.secTypeX509Vnc);
- if (options.secPlain.isSelected())
- Security.EnableSecType(Security.secTypeX509Plain);
- if (options.secIdent.isSelected())
- Security.EnableSecType(Security.secTypeX509Ident);
- } else {
- Security.DisableSecType(Security.secTypeX509None);
- Security.DisableSecType(Security.secTypeX509Vnc);
- Security.DisableSecType(Security.secTypeX509Plain);
- Security.DisableSecType(Security.secTypeX509Ident);
- }
-
- /* Process *None security types */
- if (options.secNone.isSelected()) {
- if (options.encNone.isSelected())
- Security.EnableSecType(Security.secTypeNone);
- if (options.encTLS.isSelected())
- Security.EnableSecType(Security.secTypeTLSNone);
- if (options.encX509.isSelected())
- Security.EnableSecType(Security.secTypeX509None);
- } else {
- Security.DisableSecType(Security.secTypeNone);
- Security.DisableSecType(Security.secTypeTLSNone);
- Security.DisableSecType(Security.secTypeX509None);
- }
-
- /* Process *Vnc security types */
- if (options.secVnc.isSelected()) {
- if (options.encNone.isSelected())
- Security.EnableSecType(Security.secTypeVncAuth);
- if (options.encTLS.isSelected())
- Security.EnableSecType(Security.secTypeTLSVnc);
- if (options.encX509.isSelected())
- Security.EnableSecType(Security.secTypeX509Vnc);
- } else {
- Security.DisableSecType(Security.secTypeVncAuth);
- Security.DisableSecType(Security.secTypeTLSVnc);
- Security.DisableSecType(Security.secTypeX509Vnc);
- }
-
- /* Process *Plain security types */
- if (options.secPlain.isSelected()) {
- if (options.encNone.isSelected())
- Security.EnableSecType(Security.secTypePlain);
- if (options.encTLS.isSelected())
- Security.EnableSecType(Security.secTypeTLSPlain);
- if (options.encX509.isSelected())
- Security.EnableSecType(Security.secTypeX509Plain);
- } else {
- Security.DisableSecType(Security.secTypePlain);
- Security.DisableSecType(Security.secTypeTLSPlain);
- Security.DisableSecType(Security.secTypeX509Plain);
- }
-
- /* Process *Ident security types */
- if (options.secIdent.isSelected()) {
- if (options.encNone.isSelected())
- Security.EnableSecType(Security.secTypeIdent);
- if (options.encTLS.isSelected())
- Security.EnableSecType(Security.secTypeTLSIdent);
- if (options.encX509.isSelected())
- Security.EnableSecType(Security.secTypeX509Ident);
- } else {
- Security.DisableSecType(Security.secTypeIdent);
- Security.DisableSecType(Security.secTypeTLSIdent);
- Security.DisableSecType(Security.secTypeX509Ident);
- }
-
- CSecurityTLS.x509ca.setParam(options.ca.getText());
- CSecurityTLS.x509crl.setParam(options.crl.getText());
- }
- }
-
- public void toggleFullScreen() {
- fullScreen = !fullScreen;
- if (!fullScreen) menu.fullScreen.setSelected(false);
- recreateViewport();
- }
-
- // writeClientCutText() is called from the clipboard dialog
- synchronized public void writeClientCutText(String str, int len) {
- if (state() != RFBSTATE_NORMAL) return;
- writer().writeClientCutText(str,len);
- }
-
- synchronized public void writeKeyEvent(int keysym, boolean down) {
- if (state() != RFBSTATE_NORMAL) return;
- writer().writeKeyEvent(keysym, down);
- }
-
- synchronized public void writeKeyEvent(KeyEvent ev) {
- if (ev.getID() != KeyEvent.KEY_PRESSED && !ev.isActionKey())
- return;
-
- int keysym;
-
- if (!ev.isActionKey()) {
- vlog.debug("key press "+ev.getKeyChar());
- if (ev.getKeyChar() < 32) {
- // if the ctrl modifier key is down, send the equivalent ASCII since we
- // will send the ctrl modifier anyway
-
- if ((ev.getModifiers() & KeyEvent.CTRL_MASK) != 0) {
- if ((ev.getModifiers() & KeyEvent.SHIFT_MASK) != 0) {
- keysym = ev.getKeyChar() + 64;
- if (keysym == -1)
- return;
- } else {
- keysym = ev.getKeyChar() + 96;
- if (keysym == 127) keysym = 95;
- }
- } else {
- switch (ev.getKeyCode()) {
- case KeyEvent.VK_BACK_SPACE: keysym = Keysyms.BackSpace; break;
- case KeyEvent.VK_TAB: keysym = Keysyms.Tab; break;
- case KeyEvent.VK_ENTER: keysym = Keysyms.Return; break;
- case KeyEvent.VK_ESCAPE: keysym = Keysyms.Escape; break;
- default: return;
- }
- }
-
- } else if (ev.getKeyChar() == 127) {
- keysym = Keysyms.Delete;
-
- } else {
- keysym = UnicodeToKeysym.translate(ev.getKeyChar());
- if (keysym == -1)
- return;
- }
-
- } else {
- // KEY_ACTION
- vlog.debug("key action "+ev.getKeyCode());
- switch (ev.getKeyCode()) {
- case KeyEvent.VK_HOME: keysym = Keysyms.Home; break;
- case KeyEvent.VK_END: keysym = Keysyms.End; break;
- case KeyEvent.VK_PAGE_UP: keysym = Keysyms.Page_Up; break;
- case KeyEvent.VK_PAGE_DOWN: keysym = Keysyms.Page_Down; break;
- case KeyEvent.VK_UP: keysym = Keysyms.Up; break;
- case KeyEvent.VK_DOWN: keysym = Keysyms.Down; break;
- case KeyEvent.VK_LEFT: keysym = Keysyms.Left; break;
- case KeyEvent.VK_RIGHT: keysym = Keysyms.Right; break;
- case KeyEvent.VK_F1: keysym = Keysyms.F1; break;
- case KeyEvent.VK_F2: keysym = Keysyms.F2; break;
- case KeyEvent.VK_F3: keysym = Keysyms.F3; break;
- case KeyEvent.VK_F4: keysym = Keysyms.F4; break;
- case KeyEvent.VK_F5: keysym = Keysyms.F5; break;
- case KeyEvent.VK_F6: keysym = Keysyms.F6; break;
- case KeyEvent.VK_F7: keysym = Keysyms.F7; break;
- case KeyEvent.VK_F8: keysym = Keysyms.F8; break;
- case KeyEvent.VK_F9: keysym = Keysyms.F9; break;
- case KeyEvent.VK_F10: keysym = Keysyms.F10; break;
- case KeyEvent.VK_F11: keysym = Keysyms.F11; break;
- case KeyEvent.VK_F12: keysym = Keysyms.F12; break;
- case KeyEvent.VK_PRINTSCREEN: keysym = Keysyms.Print; break;
- case KeyEvent.VK_PAUSE: keysym = Keysyms.Pause; break;
- case KeyEvent.VK_INSERT: keysym = Keysyms.Insert; break;
- default: return;
- }
- }
-
- writeModifiers(ev.getModifiers());
- writeKeyEvent(keysym, true);
- writeKeyEvent(keysym, false);
- writeModifiers(0);
- }
-
-
- synchronized public void writePointerEvent(MouseEvent ev) {
- if (state() != RFBSTATE_NORMAL) return;
- int x, y;
-
- switch (ev.getID()) {
- case MouseEvent.MOUSE_PRESSED:
- buttonMask = 1;
- if ((ev.getModifiers() & KeyEvent.ALT_MASK) != 0) buttonMask = 2;
- if ((ev.getModifiers() & KeyEvent.META_MASK) != 0) buttonMask = 4;
- break;
- case MouseEvent.MOUSE_RELEASED:
- buttonMask = 0;
- break;
- }
-
- writeModifiers(ev.getModifiers() & ~KeyEvent.ALT_MASK & ~KeyEvent.META_MASK);
-
- x = ev.getX();
- y = ev.getY();
- if (x < 0) x = 0;
- if (x > cp.width-1) x = cp.width-1;
- if (y < 0) y = 0;
- if (y > cp.height-1) y = cp.height-1;
-
- writer().writePointerEvent(new Point(x, y), buttonMask);
-
- if (buttonMask == 0) writeModifiers(0);
- }
-
-
- synchronized public void writeWheelEvent(MouseWheelEvent ev) {
- if (state() != RFBSTATE_NORMAL) return;
- int x, y;
- int clicks = ev.getWheelRotation();
- if (clicks < 0) {
- buttonMask = 8;
- } else {
- buttonMask = 16;
- }
- writeModifiers(ev.getModifiers() & ~KeyEvent.ALT_MASK & ~KeyEvent.META_MASK);
- for (int i=0;i<java.lang.Math.abs(clicks);i++) {
- x = ev.getX();
- y = ev.getY();
- writer().writePointerEvent(new Point(x, y), buttonMask);
- buttonMask = 0;
- writer().writePointerEvent(new Point(x, y), buttonMask);
- }
- writeModifiers(0);
-
- }
-
-
- void writeModifiers(int m) {
- if ((m & Event.SHIFT_MASK) != (pressedModifiers & Event.SHIFT_MASK))
- writeKeyEvent(Keysyms.Shift_L, (m & Event.SHIFT_MASK) != 0);
- if ((m & Event.CTRL_MASK) != (pressedModifiers & Event.CTRL_MASK))
- writeKeyEvent(Keysyms.Control_L, (m & Event.CTRL_MASK) != 0);
- if ((m & Event.ALT_MASK) != (pressedModifiers & Event.ALT_MASK))
- writeKeyEvent(Keysyms.Alt_L, (m & Event.ALT_MASK) != 0);
- if ((m & Event.META_MASK) != (pressedModifiers & Event.META_MASK))
- writeKeyEvent(Keysyms.Meta_L, (m & Event.META_MASK) != 0);
- pressedModifiers = m;
- }
-
-
- ////////////////////////////////////////////////////////////////////
- // The following methods are called from both RFB and GUI threads
-
- // checkEncodings() sends a setEncodings message if one is needed.
- synchronized private void checkEncodings() {
- if (encodingChange && state() == RFBSTATE_NORMAL) {
- vlog.info("Using "+Encodings.encodingName(currentEncoding)+" encoding");
- writer().writeSetEncodings(currentEncoding, true);
- encodingChange = false;
- }
- }
-
- // the following never change so need no synchronization:
- JavaInStream jis;
- JavaOutStream jos;
-
-
- // viewer object is only ever accessed by the GUI thread so needs no
- // synchronization (except for one test in DesktopWindow - see comment
- // there).
- VncViewer viewer;
-
- // access to desktop by different threads is specified in DesktopWindow
-
- // the following need no synchronization:
-
- ClassLoader cl = this.getClass().getClassLoader();
- ImageIcon logo = new ImageIcon(cl.getResource("com/tigervnc/vncviewer/tigervnc.png"));
- public static UserPasswdGetter upg;
- public UserMsgBox msg;
-
- // shuttingDown is set by the GUI thread and only ever tested by the RFB
- // thread after the window has been destroyed.
- boolean shuttingDown;
-
- // reading and writing int and boolean is atomic in java, so no
- // synchronization of the following flags is needed:
- int currentEncoding, lastServerEncoding;
-
- int lowColourLevel;
-
-
- // All menu, options, about and info stuff is done in the GUI thread (apart
- // from when constructed).
- F8Menu menu;
- OptionsDialog options;
-
- // clipboard sync issues?
- ClipboardDialog clipboardDialog;
-
- // the following are only ever accessed by the GUI thread:
- int buttonMask;
- int pressedModifiers;
-
- public String serverHost;
- public int serverPort;
- public int menuKey;
- PixelFormat serverPF;
- ViewportFrame viewport;
- DesktopWindow desktop;
- PixelFormat fullColourPF;
- boolean fullColour;
- boolean autoSelect;
- boolean shared;
- boolean formatChange;
- boolean encodingChange;
- boolean sameMachine;
- boolean fullScreen;
- boolean reverseConnection;
- boolean firstUpdate;
- boolean pendingUpdate;
-
- static LogWriter vlog = new LogWriter("CConn");
-}
+ } + + + // OptionsDialogCallback. setOptions() sets the options dialog's checkboxes + // etc to reflect our flags. getOptions() sets our flags according to the + // options dialog's checkboxes. They are both called from the GUI thread. + // Some of the flags are also accessed by the RFB thread. I believe that + // reading and writing boolean and int values in java is atomic, so there is + // no need for synchronization. + + public void setOptions() { + int digit; + options.autoSelect.setSelected(autoSelect); + options.fullColour.setSelected(fullColour); + options.veryLowColour.setSelected(!fullColour && lowColourLevel == 0); + options.lowColour.setSelected(!fullColour && lowColourLevel == 1); + options.mediumColour.setSelected(!fullColour && lowColourLevel == 2); + options.tight.setSelected(currentEncoding == Encodings.encodingTight); + options.zrle.setSelected(currentEncoding == Encodings.encodingZRLE); + options.hextile.setSelected(currentEncoding == Encodings.encodingHextile); + options.raw.setSelected(currentEncoding == Encodings.encodingRaw); + + options.customCompressLevel.setSelected(viewer.customCompressLevel.getValue()); + digit = 0 + viewer.compressLevel.getValue(); + options.compressLevel.setSelectedItem(digit); + options.noJpeg.setSelected(!viewer.noJpeg.getValue()); + digit = 0 + viewer.qualityLevel.getValue(); + options.qualityLevel.setSelectedItem(digit); + + options.viewOnly.setSelected(viewer.viewOnly.getValue()); + options.acceptClipboard.setSelected(viewer.acceptClipboard.getValue()); + options.sendClipboard.setSelected(viewer.sendClipboard.getValue()); + options.menuKey.setSelectedIndex(menuKey-0xFFBE); + + if (state() == RFBSTATE_NORMAL) { + options.shared.setEnabled(false); + options.secVeNCrypt.setEnabled(false); + options.encNone.setEnabled(false); + options.encTLS.setEnabled(false); + options.encX509.setEnabled(false); + options.ca.setEnabled(false); + options.crl.setEnabled(false); + options.secIdent.setEnabled(false); + options.secNone.setEnabled(false); + options.secVnc.setEnabled(false); + options.secPlain.setEnabled(false); + options.sendLocalUsername.setEnabled(false); + } else { + options.shared.setSelected(shared); + + /* Process non-VeNCrypt sectypes */ + java.util.List<Integer> secTypes = new ArrayList<Integer>(); + secTypes = security.GetEnabledSecTypes(); + for (Iterator i = secTypes.iterator(); i.hasNext();) { + switch ((Integer)i.next()) { + case Security.secTypeVeNCrypt: + options.secVeNCrypt.setSelected(true); + break; + case Security.secTypeNone: + options.encNone.setSelected(true); + options.secNone.setSelected(true); + break; + case Security.secTypeVncAuth: + options.encNone.setSelected(true); + options.secVnc.setSelected(true); + break; + } + } + + /* Process VeNCrypt subtypes */ + if (options.secVeNCrypt.isSelected()) { + java.util.List<Integer> secTypesExt = new ArrayList<Integer>(); + secTypesExt = security.GetEnabledExtSecTypes(); + for (Iterator iext = secTypesExt.iterator(); iext.hasNext();) { + switch ((Integer)iext.next()) { + case Security.secTypePlain: + options.secPlain.setSelected(true); + options.sendLocalUsername.setSelected(true); + break; + case Security.secTypeIdent: + options.secIdent.setSelected(true); + options.sendLocalUsername.setSelected(true); + break; + case Security.secTypeTLSNone: + options.encTLS.setSelected(true); + options.secNone.setSelected(true); + break; + case Security.secTypeTLSVnc: + options.encTLS.setSelected(true); + options.secVnc.setSelected(true); + break; + case Security.secTypeTLSPlain: + options.encTLS.setSelected(true); + options.secPlain.setSelected(true); + options.sendLocalUsername.setSelected(true); + break; + case Security.secTypeTLSIdent: + options.encTLS.setSelected(true); + options.secIdent.setSelected(true); + options.sendLocalUsername.setSelected(true); + break; + case Security.secTypeX509None: + options.encX509.setSelected(true); + options.secNone.setSelected(true); + break; + case Security.secTypeX509Vnc: + options.encX509.setSelected(true); + options.secVnc.setSelected(true); + break; + case Security.secTypeX509Plain: + options.encX509.setSelected(true); + options.secPlain.setSelected(true); + options.sendLocalUsername.setSelected(true); + break; + case Security.secTypeX509Ident: + options.encX509.setSelected(true); + options.secIdent.setSelected(true); + options.sendLocalUsername.setSelected(true); + break; + } + } + } + options.sendLocalUsername.setEnabled(options.secPlain.isSelected()|| + options.secIdent.isSelected()); + } + + options.fullScreen.setSelected(fullScreen); + options.useLocalCursor.setSelected(viewer.useLocalCursor.getValue()); + options.fastCopyRect.setSelected(viewer.fastCopyRect.getValue()); + } + + public void getOptions() { + autoSelect = options.autoSelect.isSelected(); + if (fullColour != options.fullColour.isSelected()) + formatChange = true; + fullColour = options.fullColour.isSelected(); + if (!fullColour) { + int newLowColourLevel = (options.veryLowColour.isSelected() ? 0 : + options.lowColour.isSelected() ? 1 : 2); + if (newLowColourLevel != lowColourLevel) { + lowColourLevel = newLowColourLevel; + formatChange = true; + } + } + int newEncoding = (options.zrle.isSelected() ? Encodings.encodingZRLE : + options.hextile.isSelected() ? Encodings.encodingHextile : + options.tight.isSelected() ? Encodings.encodingTight : + Encodings.encodingRaw); + if (newEncoding != currentEncoding) { + currentEncoding = newEncoding; + encodingChange = true; + } + + viewer.customCompressLevel.setParam(options.customCompressLevel.isSelected()); + if (cp.customCompressLevel != viewer.customCompressLevel.getValue()) { + cp.customCompressLevel = viewer.customCompressLevel.getValue(); + encodingChange = true; + } + viewer.compressLevel.setParam(options.compressLevel.getSelectedItem().toString()); + if (cp.compressLevel != viewer.compressLevel.getValue()) { + cp.compressLevel = viewer.compressLevel.getValue(); + encodingChange = true; + } + viewer.noJpeg.setParam(!options.noJpeg.isSelected()); + if (cp.noJpeg != viewer.noJpeg.getValue()) { + cp.noJpeg = viewer.noJpeg.getValue(); + encodingChange = true; + } + viewer.qualityLevel.setParam(options.qualityLevel.getSelectedItem().toString()); + if (cp.qualityLevel != viewer.qualityLevel.getValue()) { + cp.qualityLevel = viewer.qualityLevel.getValue(); + encodingChange = true; + } + viewer.sendLocalUsername.setParam(options.sendLocalUsername.isSelected()); + + viewer.viewOnly.setParam(options.viewOnly.isSelected()); + viewer.acceptClipboard.setParam(options.acceptClipboard.isSelected()); + viewer.sendClipboard.setParam(options.sendClipboard.isSelected()); + clipboardDialog.setSendingEnabled(viewer.sendClipboard.getValue()); + menuKey = (int)(options.menuKey.getSelectedIndex()+0xFFBE); + F8Menu.f8.setLabel("Send F"+(menuKey-Keysyms.F1+1)); + + shared = options.shared.isSelected(); + setShared(shared); + viewer.useLocalCursor.setParam(options.useLocalCursor.isSelected()); + if (cp.supportsLocalCursor != viewer.useLocalCursor.getValue()) { + cp.supportsLocalCursor = viewer.useLocalCursor.getValue(); + encodingChange = true; + if (desktop != null) + desktop.resetLocalCursor(); + } + + checkEncodings(); + + if (state() != RFBSTATE_NORMAL) { + /* Process security types which don't use encryption */ + if (options.encNone.isSelected()) { + if (options.secNone.isSelected()) + Security.EnableSecType(Security.secTypeNone); + if (options.secVnc.isSelected()) + Security.EnableSecType(Security.secTypeVncAuth); + if (options.secPlain.isSelected()) + Security.EnableSecType(Security.secTypePlain); + if (options.secIdent.isSelected()) + Security.EnableSecType(Security.secTypeIdent); + } else { + Security.DisableSecType(Security.secTypeNone); + Security.DisableSecType(Security.secTypeVncAuth); + Security.DisableSecType(Security.secTypePlain); + Security.DisableSecType(Security.secTypeIdent); + } + + /* Process security types which use TLS encryption */ + if (options.encTLS.isSelected()) { + if (options.secNone.isSelected()) + Security.EnableSecType(Security.secTypeTLSNone); + if (options.secVnc.isSelected()) + Security.EnableSecType(Security.secTypeTLSVnc); + if (options.secPlain.isSelected()) + Security.EnableSecType(Security.secTypeTLSPlain); + if (options.secIdent.isSelected()) + Security.EnableSecType(Security.secTypeTLSIdent); + } else { + Security.DisableSecType(Security.secTypeTLSNone); + Security.DisableSecType(Security.secTypeTLSVnc); + Security.DisableSecType(Security.secTypeTLSPlain); + Security.DisableSecType(Security.secTypeTLSIdent); + } + + /* Process security types which use X509 encryption */ + if (options.encX509.isSelected()) { + if (options.secNone.isSelected()) + Security.EnableSecType(Security.secTypeX509None); + if (options.secVnc.isSelected()) + Security.EnableSecType(Security.secTypeX509Vnc); + if (options.secPlain.isSelected()) + Security.EnableSecType(Security.secTypeX509Plain); + if (options.secIdent.isSelected()) + Security.EnableSecType(Security.secTypeX509Ident); + } else { + Security.DisableSecType(Security.secTypeX509None); + Security.DisableSecType(Security.secTypeX509Vnc); + Security.DisableSecType(Security.secTypeX509Plain); + Security.DisableSecType(Security.secTypeX509Ident); + } + + /* Process *None security types */ + if (options.secNone.isSelected()) { + if (options.encNone.isSelected()) + Security.EnableSecType(Security.secTypeNone); + if (options.encTLS.isSelected()) + Security.EnableSecType(Security.secTypeTLSNone); + if (options.encX509.isSelected()) + Security.EnableSecType(Security.secTypeX509None); + } else { + Security.DisableSecType(Security.secTypeNone); + Security.DisableSecType(Security.secTypeTLSNone); + Security.DisableSecType(Security.secTypeX509None); + } + + /* Process *Vnc security types */ + if (options.secVnc.isSelected()) { + if (options.encNone.isSelected()) + Security.EnableSecType(Security.secTypeVncAuth); + if (options.encTLS.isSelected()) + Security.EnableSecType(Security.secTypeTLSVnc); + if (options.encX509.isSelected()) + Security.EnableSecType(Security.secTypeX509Vnc); + } else { + Security.DisableSecType(Security.secTypeVncAuth); + Security.DisableSecType(Security.secTypeTLSVnc); + Security.DisableSecType(Security.secTypeX509Vnc); + } + + /* Process *Plain security types */ + if (options.secPlain.isSelected()) { + if (options.encNone.isSelected()) + Security.EnableSecType(Security.secTypePlain); + if (options.encTLS.isSelected()) + Security.EnableSecType(Security.secTypeTLSPlain); + if (options.encX509.isSelected()) + Security.EnableSecType(Security.secTypeX509Plain); + } else { + Security.DisableSecType(Security.secTypePlain); + Security.DisableSecType(Security.secTypeTLSPlain); + Security.DisableSecType(Security.secTypeX509Plain); + } + + /* Process *Ident security types */ + if (options.secIdent.isSelected()) { + if (options.encNone.isSelected()) + Security.EnableSecType(Security.secTypeIdent); + if (options.encTLS.isSelected()) + Security.EnableSecType(Security.secTypeTLSIdent); + if (options.encX509.isSelected()) + Security.EnableSecType(Security.secTypeX509Ident); + } else { + Security.DisableSecType(Security.secTypeIdent); + Security.DisableSecType(Security.secTypeTLSIdent); + Security.DisableSecType(Security.secTypeX509Ident); + } + + CSecurityTLS.x509ca.setParam(options.ca.getText()); + CSecurityTLS.x509crl.setParam(options.crl.getText()); + } + } + + public void toggleFullScreen() { + fullScreen = !fullScreen; + if (!fullScreen) menu.fullScreen.setSelected(false); + recreateViewport(); + } + + // writeClientCutText() is called from the clipboard dialog + synchronized public void writeClientCutText(String str, int len) { + if (state() != RFBSTATE_NORMAL) return; + writer().writeClientCutText(str,len); + } + + synchronized public void writeKeyEvent(int keysym, boolean down) { + if (state() != RFBSTATE_NORMAL) return; + writer().writeKeyEvent(keysym, down); + } + + synchronized public void writeKeyEvent(KeyEvent ev) { + if (ev.getID() != KeyEvent.KEY_PRESSED && !ev.isActionKey()) + return; + + int keysym; + + if (!ev.isActionKey()) { + vlog.debug("key press "+ev.getKeyChar()); + if (ev.getKeyChar() < 32) { + // if the ctrl modifier key is down, send the equivalent ASCII since we + // will send the ctrl modifier anyway + + if ((ev.getModifiers() & KeyEvent.CTRL_MASK) != 0) { + if ((ev.getModifiers() & KeyEvent.SHIFT_MASK) != 0) { + keysym = ev.getKeyChar() + 64; + if (keysym == -1) + return; + } else { + keysym = ev.getKeyChar() + 96; + if (keysym == 127) keysym = 95; + } + } else { + switch (ev.getKeyCode()) { + case KeyEvent.VK_BACK_SPACE: keysym = Keysyms.BackSpace; break; + case KeyEvent.VK_TAB: keysym = Keysyms.Tab; break; + case KeyEvent.VK_ENTER: keysym = Keysyms.Return; break; + case KeyEvent.VK_ESCAPE: keysym = Keysyms.Escape; break; + default: return; + } + } + + } else if (ev.getKeyChar() == 127) { + keysym = Keysyms.Delete; + + } else { + keysym = UnicodeToKeysym.translate(ev.getKeyChar()); + if (keysym == -1) + return; + } + + } else { + // KEY_ACTION + vlog.debug("key action "+ev.getKeyCode()); + switch (ev.getKeyCode()) { + case KeyEvent.VK_HOME: keysym = Keysyms.Home; break; + case KeyEvent.VK_END: keysym = Keysyms.End; break; + case KeyEvent.VK_PAGE_UP: keysym = Keysyms.Page_Up; break; + case KeyEvent.VK_PAGE_DOWN: keysym = Keysyms.Page_Down; break; + case KeyEvent.VK_UP: keysym = Keysyms.Up; break; + case KeyEvent.VK_DOWN: keysym = Keysyms.Down; break; + case KeyEvent.VK_LEFT: keysym = Keysyms.Left; break; + case KeyEvent.VK_RIGHT: keysym = Keysyms.Right; break; + case KeyEvent.VK_F1: keysym = Keysyms.F1; break; + case KeyEvent.VK_F2: keysym = Keysyms.F2; break; + case KeyEvent.VK_F3: keysym = Keysyms.F3; break; + case KeyEvent.VK_F4: keysym = Keysyms.F4; break; + case KeyEvent.VK_F5: keysym = Keysyms.F5; break; + case KeyEvent.VK_F6: keysym = Keysyms.F6; break; + case KeyEvent.VK_F7: keysym = Keysyms.F7; break; + case KeyEvent.VK_F8: keysym = Keysyms.F8; break; + case KeyEvent.VK_F9: keysym = Keysyms.F9; break; + case KeyEvent.VK_F10: keysym = Keysyms.F10; break; + case KeyEvent.VK_F11: keysym = Keysyms.F11; break; + case KeyEvent.VK_F12: keysym = Keysyms.F12; break; + case KeyEvent.VK_PRINTSCREEN: keysym = Keysyms.Print; break; + case KeyEvent.VK_PAUSE: keysym = Keysyms.Pause; break; + case KeyEvent.VK_INSERT: keysym = Keysyms.Insert; break; + default: return; + } + } + + writeModifiers(ev.getModifiers()); + writeKeyEvent(keysym, true); + writeKeyEvent(keysym, false); + writeModifiers(0); + } + + + synchronized public void writePointerEvent(MouseEvent ev) { + if (state() != RFBSTATE_NORMAL) return; + int x, y; + + switch (ev.getID()) { + case MouseEvent.MOUSE_PRESSED: + buttonMask = 1; + if ((ev.getModifiers() & KeyEvent.ALT_MASK) != 0) buttonMask = 2; + if ((ev.getModifiers() & KeyEvent.META_MASK) != 0) buttonMask = 4; + break; + case MouseEvent.MOUSE_RELEASED: + buttonMask = 0; + break; + } + + writeModifiers(ev.getModifiers() & ~KeyEvent.ALT_MASK & ~KeyEvent.META_MASK); + + x = ev.getX(); + y = ev.getY(); + if (x < 0) x = 0; + if (x > cp.width-1) x = cp.width-1; + if (y < 0) y = 0; + if (y > cp.height-1) y = cp.height-1; + + writer().writePointerEvent(new Point(x, y), buttonMask); + + if (buttonMask == 0) writeModifiers(0); + } + + + synchronized public void writeWheelEvent(MouseWheelEvent ev) { + if (state() != RFBSTATE_NORMAL) return; + int x, y; + int clicks = ev.getWheelRotation(); + if (clicks < 0) { + buttonMask = 8; + } else { + buttonMask = 16; + } + writeModifiers(ev.getModifiers() & ~KeyEvent.ALT_MASK & ~KeyEvent.META_MASK); + for (int i=0;i<java.lang.Math.abs(clicks);i++) { + x = ev.getX(); + y = ev.getY(); + writer().writePointerEvent(new Point(x, y), buttonMask); + buttonMask = 0; + writer().writePointerEvent(new Point(x, y), buttonMask); + } + writeModifiers(0); + + } + + + void writeModifiers(int m) { + if ((m & Event.SHIFT_MASK) != (pressedModifiers & Event.SHIFT_MASK)) + writeKeyEvent(Keysyms.Shift_L, (m & Event.SHIFT_MASK) != 0); + if ((m & Event.CTRL_MASK) != (pressedModifiers & Event.CTRL_MASK)) + writeKeyEvent(Keysyms.Control_L, (m & Event.CTRL_MASK) != 0); + if ((m & Event.ALT_MASK) != (pressedModifiers & Event.ALT_MASK)) + writeKeyEvent(Keysyms.Alt_L, (m & Event.ALT_MASK) != 0); + if ((m & Event.META_MASK) != (pressedModifiers & Event.META_MASK)) + writeKeyEvent(Keysyms.Meta_L, (m & Event.META_MASK) != 0); + pressedModifiers = m; + } + + + //////////////////////////////////////////////////////////////////// + // The following methods are called from both RFB and GUI threads + + // checkEncodings() sends a setEncodings message if one is needed. + synchronized private void checkEncodings() { + if (encodingChange && state() == RFBSTATE_NORMAL) { + vlog.info("Using "+Encodings.encodingName(currentEncoding)+" encoding"); + writer().writeSetEncodings(currentEncoding, true); + encodingChange = false; + } + } + + // the following never change so need no synchronization: + JavaInStream jis; + JavaOutStream jos; + + + // viewer object is only ever accessed by the GUI thread so needs no + // synchronization (except for one test in DesktopWindow - see comment + // there). + VncViewer viewer; + + // access to desktop by different threads is specified in DesktopWindow + + // the following need no synchronization: + + ClassLoader cl = this.getClass().getClassLoader(); + ImageIcon logo = new ImageIcon(cl.getResource("com/tigervnc/vncviewer/tigervnc.png")); + public static UserPasswdGetter upg; + public UserMsgBox msg; + + // shuttingDown is set by the GUI thread and only ever tested by the RFB + // thread after the window has been destroyed. + boolean shuttingDown; + + // reading and writing int and boolean is atomic in java, so no + // synchronization of the following flags is needed: + int currentEncoding, lastServerEncoding; + + int lowColourLevel; + + + // All menu, options, about and info stuff is done in the GUI thread (apart + // from when constructed). + F8Menu menu; + OptionsDialog options; + + // clipboard sync issues? + ClipboardDialog clipboardDialog; + + // the following are only ever accessed by the GUI thread: + int buttonMask; + int pressedModifiers; + + public String serverHost; + public int serverPort; + public int menuKey; + PixelFormat serverPF; + ViewportFrame viewport; + DesktopWindow desktop; + PixelFormat fullColourPF; + boolean fullColour; + boolean autoSelect; + boolean shared; + boolean formatChange; + boolean encodingChange; + boolean sameMachine; + boolean fullScreen; + boolean reverseConnection; + boolean firstUpdate; + boolean pendingUpdate; + + static LogWriter vlog = new LogWriter("CConn"); +} diff --git a/java/src/com/tigervnc/vncviewer/DesktopWindow.java b/java/src/com/tigervnc/vncviewer/DesktopWindow.java index 7a8cda84..5e2764bc 100644 --- a/java/src/com/tigervnc/vncviewer/DesktopWindow.java +++ b/java/src/com/tigervnc/vncviewer/DesktopWindow.java @@ -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"); +} diff --git a/java/src/com/tigervnc/vncviewer/OptionsDialog.java b/java/src/com/tigervnc/vncviewer/OptionsDialog.java index 98198158..f38a1e65 100644 --- a/java/src/com/tigervnc/vncviewer/OptionsDialog.java +++ b/java/src/com/tigervnc/vncviewer/OptionsDialog.java @@ -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()); + } + } + +} diff --git a/java/src/com/tigervnc/vncviewer/ServerDialog.java b/java/src/com/tigervnc/vncviewer/ServerDialog.java index 86160f80..e38085a1 100644 --- a/java/src/com/tigervnc/vncviewer/ServerDialog.java +++ b/java/src/com/tigervnc/vncviewer/ServerDialog.java @@ -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"); + +} |