Merge pull request #190 from bphinz/master

Java viewer updates
diff --git a/java/com/tigervnc/vncviewer/CConn.java b/java/com/tigervnc/vncviewer/CConn.java
index 5ce1c2f..88b25ec 100644
--- a/java/com/tigervnc/vncviewer/CConn.java
+++ b/java/com/tigervnc/vncviewer/CConn.java
@@ -1,7 +1,7 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
  * Copyright 2009-2013 Pierre Ossman <ossman@cendio.se> for Cendio AB
  * Copyright (C) 2011-2013 D. R. Commander.  All Rights Reserved.
- * Copyright (C) 2011-2014 Brian P. Hinz
+ * Copyright (C) 2011-2015 Brian P. Hinz
  *
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -545,9 +545,13 @@
   }
   
   public void setEmbeddedFeatures(boolean s) {
+    menu.restore.setEnabled(s);
+    menu.minimize.setEnabled(s);
+    menu.maximize.setEnabled(s);
     menu.fullScreen.setEnabled(s);
     menu.newConn.setEnabled(s);
     options.fullScreen.setEnabled(s);
+    options.fullScreenAllMonitors.setEnabled(s);
     options.scalingFactor.setEnabled(s);
   }
 
@@ -569,16 +573,17 @@
   }
 
   private void reconfigureViewport() {
-    //viewport.setMaxSize(cp.width, cp.height);
     boolean pack = true;
-    Dimension dpySize = viewport.getToolkit().getScreenSize();
+    Dimension dpySize = viewport.getScreenSize();
     desktop.setScaledSize();
     int w = desktop.scaledWidth;
     int h = desktop.scaledHeight;
     if (fullScreen) {
-      viewport.setExtendedState(JFrame.MAXIMIZED_BOTH);
-      viewport.setGeometry(0, 0, dpySize.width, dpySize.height, false);
-      Viewport.setFullScreenWindow(viewport);
+      if (!viewer.fullScreenAllMonitors.getValue())
+        viewport.setExtendedState(JFrame.MAXIMIZED_BOTH);
+      viewport.setBounds(viewport.getScreenBounds());
+      if (!viewer.fullScreenAllMonitors.getValue())
+        Viewport.setFullScreenWindow(viewport);
     } else {
       int wmDecorationWidth = viewport.getInsets().left + viewport.getInsets().right;
       int wmDecorationHeight = viewport.getInsets().top + viewport.getInsets().bottom;
@@ -982,6 +987,7 @@
     }
 
     options.fullScreen.setSelected(fullScreen);
+    options.fullScreenAllMonitors.setSelected(viewer.fullScreenAllMonitors.getValue());
     options.useLocalCursor.setSelected(viewer.useLocalCursor.getValue());
     options.acceptBell.setSelected(viewer.acceptBell.getValue());
     String scaleString = viewer.scalingFactor.getValue();
@@ -1208,13 +1214,22 @@
         Security.DisableSecType(Security.secTypeX509Ident);
       }
     }
-    if (options.desktopSize.isSelected()) {
-      String desktopSize =
-        options.desktopWidth.getText() + "x" + options.desktopHeight.getText();
-      viewer.desktopSize.setParam(desktopSize);
-    }
-    if (options.fullScreen.isSelected() ^ fullScreen)
+    String desktopSize = (options.desktopSize.isSelected()) ?
+        options.desktopWidth.getText() + "x" + options.desktopHeight.getText() : "";
+    viewer.desktopSize.setParam(desktopSize);
+    if (options.fullScreen.isSelected() ^ fullScreen) {
+      viewer.fullScreenAllMonitors.setParam(options.fullScreenAllMonitors.isSelected());
       toggleFullScreen();
+    } else {
+      if (viewer.fullScreenAllMonitors.getValue() !=
+          options.fullScreenAllMonitors.isSelected()) {
+        viewer.fullScreenAllMonitors.setParam(options.fullScreenAllMonitors.isSelected());
+        if (desktop != null)
+          recreateViewport();
+      } else {
+        viewer.fullScreenAllMonitors.setParam(options.fullScreenAllMonitors.isSelected());
+      }
+    }
   }
 
   public void toggleFullScreen() {
diff --git a/java/com/tigervnc/vncviewer/F8Menu.java b/java/com/tigervnc/vncviewer/F8Menu.java
index 5045b77..472f11f 100644
--- a/java/com/tigervnc/vncviewer/F8Menu.java
+++ b/java/com/tigervnc/vncviewer/F8Menu.java
@@ -36,12 +36,15 @@
     setLightWeightPopupEnabled(false);
     cc = cc_;
     restore    = addMenuItem("Restore",KeyEvent.VK_R);
+    restore.setEnabled(!cc.viewer.embed.getValue());
     move       = addMenuItem("Move");
     move.setEnabled(false);
     size       = addMenuItem("Size");
     size.setEnabled(false);
     minimize   = addMenuItem("Minimize", KeyEvent.VK_N);
+    minimize.setEnabled(!cc.viewer.embed.getValue());
     maximize   = addMenuItem("Maximize", KeyEvent.VK_X);
+    maximize.setEnabled(!cc.viewer.embed.getValue());
     addSeparator();
     exit       = addMenuItem("Close Viewer", KeyEvent.VK_C);
     addSeparator();
diff --git a/java/com/tigervnc/vncviewer/OptionsDialog.java b/java/com/tigervnc/vncviewer/OptionsDialog.java
index a47ec39..e2cd7c8 100644
--- a/java/com/tigervnc/vncviewer/OptionsDialog.java
+++ b/java/com/tigervnc/vncviewer/OptionsDialog.java
@@ -1,5 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * Copyright (C) 2011-2014 Brian P. Hinz
+ * Copyright (C) 2011-2015 Brian P. Hinz
  *
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -62,7 +62,7 @@
   JRadioButton zrle, hextile, tight, raw;
   JRadioButton fullColour, mediumColour, lowColour, veryLowColour;
   JCheckBox viewOnly, acceptClipboard, sendClipboard, acceptBell;
-  JCheckBox desktopSize, fullScreen, shared, useLocalCursor;
+  JCheckBox desktopSize, fullScreen, fullScreenAllMonitors, shared, useLocalCursor;
   JCheckBox secVeNCrypt, encNone, encTLS, encX509;
   JCheckBox secNone, secVnc, secPlain, secIdent, sendLocalUsername;
   JButton okButton, cancelButton;
@@ -81,6 +81,7 @@
       new BoxLayout(getContentPane(), BoxLayout.PAGE_AXIS));
 
     JTabbedPane tabPane = new JTabbedPane();
+    tabPane.setTabLayoutPolicy(JTabbedPane.SCROLL_TAB_LAYOUT);
 
     ButtonGroup encodingGroup = new ButtonGroup();
     ButtonGroup colourGroup = new ButtonGroup();
@@ -166,7 +167,8 @@
     ScreenPanel=new JPanel(new GridBagLayout());
     desktopSize = new JCheckBox("Resize remote session on connect");
     desktopSize.addItemListener(this);
-    desktopSize.setEnabled(cc.viewer.desktopSize.getValue() != null);
+    desktopSize.setEnabled(!cc.viewer.embed.getValue() &&
+                           (cc.viewer.desktopSize.getValue() != null));
     NumberFormat format = NumberFormat.getIntegerInstance();
     format.setMaximumIntegerDigits(5);
     format.setMinimumIntegerDigits(0);
@@ -184,6 +186,9 @@
     fullScreen = new JCheckBox("Full-screen mode");
     fullScreen.addItemListener(this);
     fullScreen.setEnabled(!cc.viewer.embed.getValue());
+    fullScreenAllMonitors = new JCheckBox("Enable full-screen mode over all monitors");
+    fullScreenAllMonitors.addItemListener(this);
+    fullScreenAllMonitors.setEnabled(!cc.viewer.embed.getValue());
     JLabel scalingFactorLabel = new JLabel("Scaling Factor");
     Object[] scalingFactors = {
       "Auto", "Fixed Aspect Ratio", "50%", "75%", "95%", "100%", "105%",
@@ -202,9 +207,10 @@
     scalingFactor.setEditable(true);
     scalingFactor.addItemListener(this);
     scalingFactor.setEnabled(!cc.viewer.embed.getValue());
-    addGBComponent(desktopSize,ScreenPanel, 0, 1, 2, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,5,0,5));
-    addGBComponent(desktopSizePanel,ScreenPanel, 0, 2, 2, 1, 2, 2, 1, 0, GridBagConstraints.REMAINDER, GridBagConstraints.LINE_START, new Insets(0,20,0,0));
-    addGBComponent(fullScreen,ScreenPanel, 0, 3, 2, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(0,5,0,5));
+    addGBComponent(desktopSize,ScreenPanel, 0, 0, 2, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,5,0,5));
+    addGBComponent(desktopSizePanel,ScreenPanel, 0, 1, 2, 1, 2, 2, 1, 0, GridBagConstraints.REMAINDER, GridBagConstraints.LINE_START, new Insets(0,20,0,0));
+    addGBComponent(fullScreen,ScreenPanel, 0, 2, 2, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(0,5,0,5));
+    addGBComponent(fullScreenAllMonitors,ScreenPanel, 0, 3, 4, 1, 2, 2, 1, 0, GridBagConstraints.REMAINDER, GridBagConstraints.LINE_START, new Insets(4,25,0,5));
     addGBComponent(scalingFactorLabel,ScreenPanel, 0, 4, 1, GridBagConstraints.REMAINDER, 2, 2, 1, 1, GridBagConstraints.NONE, GridBagConstraints.FIRST_LINE_START, new Insets(8,8,0,5));
     addGBComponent(scalingFactor,ScreenPanel, 1, 4, 1, GridBagConstraints.REMAINDER, 2, 2, 25, 1, GridBagConstraints.NONE, GridBagConstraints.FIRST_LINE_START, new Insets(4,5,0,5));
 
@@ -217,9 +223,9 @@
     useLocalCursor.addItemListener(this);
     acceptBell = new JCheckBox("Beep when requested by the server");
     acceptBell.addItemListener(this);
-    addGBComponent(shared,MiscPanel,         0, 1, 2, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,5,0,5));
-    addGBComponent(useLocalCursor,MiscPanel, 0, 2, 2, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,5,0,5));
-    addGBComponent(acceptBell,MiscPanel,     0, 3, 2, 1, 2, 2, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(4,5,0,5));
+    addGBComponent(shared,MiscPanel,         0, 0, 2, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,5,0,5));
+    addGBComponent(useLocalCursor,MiscPanel, 0, 1, 2, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,5,0,5));
+    addGBComponent(acceptBell,MiscPanel,     0, 2, 2, 1, 2, 2, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(4,5,0,5));
 
     // load/save tab
     DefaultsPanel=new JPanel(new GridBagLayout());
@@ -252,19 +258,17 @@
     SecPanel=new JPanel(new GridBagLayout());
 
     JPanel encryptionPanel = new JPanel(new GridBagLayout());
-    encryptionPanel.setBorder(BorderFactory.createTitledBorder("Session Encryption"));
+    encryptionPanel.setBorder(BorderFactory.createTitledBorder("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));
+    encX509 = addJCheckBox("TLS with X.509 certificates", null, encryptionPanel, new GridBagConstraints(0,2,3,1,1,1,GridBagConstraints.LINE_START,GridBagConstraints.REMAINDER,new Insets(0,0,0,0),0,0));
 
-    JPanel x509Panel = new JPanel(new GridBagLayout());
-    x509Panel.setBorder(BorderFactory.createTitledBorder("X.509 certificates"));
     ca = new JButton("Load CA certificate");
     ca.addActionListener(this);
     crl = new JButton("Load CRL certificate");
     crl.addActionListener(this);
-    addGBComponent(ca, x509Panel,  0, 0, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(2,2,2,2));
-    addGBComponent(crl, x509Panel, 1, 0, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(2,2,2,2));
+    addGBComponent(ca, encryptionPanel,  0, 3, 1, 1, 2, 2, 1, 0, GridBagConstraints.NONE, GridBagConstraints.LINE_START, new Insets(2,20,2,2));
+    addGBComponent(crl, encryptionPanel, 1, 3, 1, 1, 2, 2, 1, 0, GridBagConstraints.NONE, GridBagConstraints.LINE_START, new Insets(2,2,2,2));
 
     JPanel authPanel = new JPanel(new GridBagLayout());
     authPanel.setBorder(BorderFactory.createTitledBorder("Authentication"));
@@ -280,7 +284,6 @@
     secVeNCrypt.addItemListener(this);
     addGBComponent(secVeNCrypt,SecPanel,     0, 0, 1, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(4,5,0,30));
     addGBComponent(encryptionPanel,SecPanel, 0, 1, 1, 1, 2, 2, 1, 0, GridBagConstraints.NONE, GridBagConstraints.LINE_START, new Insets(0,10,2,5));
-    addGBComponent(x509Panel,SecPanel,       0, 2, 1, 1, 2, 2, 1, 0, GridBagConstraints.NONE, GridBagConstraints.LINE_START, new Insets(2,10,2,5));
     addGBComponent(authPanel,SecPanel,       0, 3, 1, 1, 2, 2, 1, 1, GridBagConstraints.NONE, GridBagConstraints.FIRST_LINE_START, new Insets(2,10,2,5));
 
     tabPane.add(FormatPanel);
@@ -376,6 +379,7 @@
       desktopSize.isSelected() ? desktopWidth.getText() + "x" + desktopHeight.getText() : "";
     UserPreferences.set("global", "DesktopSize", desktopSizeString);
     UserPreferences.set("global", "FullScreen", fullScreen.isSelected());
+    UserPreferences.set("global", "FullScreenAllMonitors", fullScreenAllMonitors.isSelected());
     UserPreferences.set("global", "Shared", shared.isSelected());
     UserPreferences.set("global", "UseLocalCursor", useLocalCursor.isSelected());
     UserPreferences.set("global", "AcceptBell", acceptBell.isSelected());
@@ -453,6 +457,7 @@
       desktopHeight.setText(desktopSizeString.split("x")[1]);
     }
     fullScreen.setSelected(UserPreferences.getBool("global", "FullScreen"));
+    fullScreenAllMonitors.setSelected(UserPreferences.getBool("global", "FullScreenAllMonitors"));
     if (shared.isEnabled())
       shared.setSelected(UserPreferences.getBool("global", "Shared"));
     useLocalCursor.setSelected(UserPreferences.getBool("global", "UseLocalCursor"));
diff --git a/java/com/tigervnc/vncviewer/Viewport.java b/java/com/tigervnc/vncviewer/Viewport.java
index 8cb87b6..acc6bfd 100644
--- a/java/com/tigervnc/vncviewer/Viewport.java
+++ b/java/com/tigervnc/vncviewer/Viewport.java
@@ -1,5 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * Copyright (C) 2011-2014 Brian P. Hinz
+ * Copyright (C) 2011-2015 Brian P. Hinz
  * Copyright (C) 2012-2013 D. R. Commander.  All Rights Reserved.
  *
  * This is free software; you can redistribute it and/or modify
@@ -28,12 +28,14 @@
 import java.awt.GraphicsDevice;
 import java.awt.GraphicsEnvironment;
 import java.awt.Image;
+import java.awt.Insets;
 import java.awt.Window;
 import java.lang.reflect.*;
 import javax.swing.*;
 
 import com.tigervnc.rfb.*;
 import java.lang.Exception;
+import java.awt.Rectangle;
 
 public class Viewport extends JFrame
 {
@@ -167,6 +169,32 @@
       setLocation(x, y);
   }
 
+  public Dimension getScreenSize() {
+    return getScreenBounds().getSize();
+  }
+
+  public Rectangle getScreenBounds() {
+    GraphicsEnvironment ge =
+      GraphicsEnvironment.getLocalGraphicsEnvironment();
+    Rectangle r = new Rectangle();
+    setMaximizedBounds(null);
+    if (cc.viewer.fullScreenAllMonitors.getValue()) {
+      for (GraphicsDevice gd : ge.getScreenDevices())
+        for (GraphicsConfiguration gc : gd.getConfigurations())
+          r = r.union(gc.getBounds());
+      if (!cc.fullScreen)
+        pack();
+      Rectangle mb = new Rectangle(r);
+      mb.grow(getInsets().left, getInsets().bottom);
+      setMaximizedBounds(mb);
+    } else {
+      GraphicsDevice gd = ge.getDefaultScreenDevice();
+      GraphicsConfiguration gc = gd.getDefaultConfiguration();
+      r = gc.getBounds();
+    }
+    return r;
+  }
+
   public static Window getFullScreenWindow() {
     GraphicsEnvironment ge =
       GraphicsEnvironment.getLocalGraphicsEnvironment();
diff --git a/java/com/tigervnc/vncviewer/VncViewer.java b/java/com/tigervnc/vncviewer/VncViewer.java
index cc21c2e..0f7ce8e 100644
--- a/java/com/tigervnc/vncviewer/VncViewer.java
+++ b/java/com/tigervnc/vncviewer/VncViewer.java
@@ -1,7 +1,7 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
  * Copyright 2011 Pierre Ossman <ossman@cendio.se> for Cendio AB
  * Copyright (C) 2011-2013 D. R. Commander.  All Rights Reserved.
- * Copyright (C) 2011-2014 Brian P. Hinz
+ * Copyright (C) 2011-2015 Brian P. Hinz
  *
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -56,7 +56,7 @@
 
   public static final String aboutText = new String("TigerVNC Java Viewer v%s (%s)%n"+
                                                     "Built on %s at %s%n"+
-                                                    "Copyright (C) 1999-2013 TigerVNC Team and many others (see README.txt)%n"+
+                                                    "Copyright (C) 1999-2015 TigerVNC Team and many others (see README.txt)%n"+
                                                     "See http://www.tigervnc.org for information on TigerVNC.");
 
   public static String version = null;
@@ -100,7 +100,6 @@
           UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
       }
       UIManager.setLookAndFeel(laf);
-      UIManager.put("TitledBorder.titleColor",Color.blue);
       if (UIManager.getLookAndFeel().getName().equals("Metal")) {
         UIManager.put("swing.boldMetal", Boolean.FALSE);
         Enumeration<Object> keys = UIManager.getDefaults().keys();
@@ -554,6 +553,10 @@
   = new BoolParameter("FullScreen",
                       "Full Screen Mode",
                       false);
+  BoolParameter fullScreenAllMonitors
+  = new BoolParameter("FullScreenAllMonitors",
+                      "Enable full screen over all monitors",
+                      true);
   BoolParameter acceptClipboard
   = new BoolParameter("AcceptClipboard",
                       "Accept clipboard changes from the server",