]> source.dussan.org Git - tigervnc.git/commitdiff
Re-introduces embedded applet mode for the java viewer. On Windows and Linux, the...
authorBrian Hinz <bphinz@users.sourceforge.net>
Thu, 2 Jan 2014 01:23:56 +0000 (01:23 +0000)
committerBrian Hinz <bphinz@users.sourceforge.net>
Thu, 2 Jan 2014 01:23:56 +0000 (01:23 +0000)
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@5149 3789f03b-4d11-0410-bbf8-ca57d06f2519

java/com/tigervnc/vncviewer/CConn.java
java/com/tigervnc/vncviewer/DesktopWindow.java
java/com/tigervnc/vncviewer/F8Menu.java
java/com/tigervnc/vncviewer/OptionsDialog.java
java/com/tigervnc/vncviewer/README
java/com/tigervnc/vncviewer/Viewport.java
java/com/tigervnc/vncviewer/VncViewer.java
java/com/tigervnc/vncviewer/index.vnc
unix/xserver/hw/vnc/XserverDesktop.cc

index dd01d9dbce31732b2606a59103d23e6f06a15d82..e48e93b28d7d1ae6d894b0fb2d47f32647604915 100644 (file)
@@ -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-2013 Brian P. Hinz
+ * Copyright (C) 2011-2014 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,9 +56,9 @@ import com.tigervnc.rfb.Exception;
 import com.tigervnc.network.Socket;
 import com.tigervnc.network.TcpSocket;
 
-public class CConn extends CConnection
-  implements UserPasswdGetter, UserMsgBox, OptionsDialogCallback, FdInStreamBlockCallback
-{
+public class CConn extends CConnection implements 
+  UserPasswdGetter, UserMsgBox, OptionsDialogCallback, 
+  FdInStreamBlockCallback, ActionListener {
 
   public final PixelFormat getPreferredPF() { return fullColourPF; }
   static final PixelFormat verylowColourPF =
@@ -265,7 +265,56 @@ public class CConn extends CConnection
     cp.setPF(pendingPF);
     pendingPFChange = false;
 
-    recreateViewport();
+    if (viewer.embed.getValue()) {
+      desktop.setScaledSize();
+      setupEmbeddedFrame();
+    } else {
+      recreateViewport();
+    }
+  }
+
+  void setupEmbeddedFrame() {
+    UIManager.getDefaults().put("ScrollPane.ancestorInputMap",
+      new UIDefaults.LazyInputMap(new Object[]{}));
+    JScrollPane sp = new JScrollPane();
+    sp.setBorder(BorderFactory.createEmptyBorder(0, 0, 0, 0));
+    sp.getViewport().setBackground(Color.BLACK);
+    InputMap im = sp.getInputMap(JComponent.WHEN_IN_FOCUSED_WINDOW);
+    int ctrlAltShiftMask = Event.SHIFT_MASK | Event.CTRL_MASK | Event.ALT_MASK;
+    if (im != null) {
+      im.put(KeyStroke.getKeyStroke(KeyEvent.VK_UP, ctrlAltShiftMask),
+             "unitScrollUp");
+      im.put(KeyStroke.getKeyStroke(KeyEvent.VK_DOWN, ctrlAltShiftMask),
+             "unitScrollDown");
+      im.put(KeyStroke.getKeyStroke(KeyEvent.VK_LEFT, ctrlAltShiftMask),
+             "unitScrollLeft");
+      im.put(KeyStroke.getKeyStroke(KeyEvent.VK_RIGHT, ctrlAltShiftMask),
+             "unitScrollRight");
+      im.put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_UP, ctrlAltShiftMask),
+             "scrollUp");
+      im.put(KeyStroke.getKeyStroke(KeyEvent.VK_PAGE_DOWN, ctrlAltShiftMask),
+             "scrollDown");
+      im.put(KeyStroke.getKeyStroke(KeyEvent.VK_HOME, ctrlAltShiftMask),
+             "scrollLeft");
+      im.put(KeyStroke.getKeyStroke(KeyEvent.VK_END, ctrlAltShiftMask),
+             "scrollRight");
+    }
+    sp.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
+    sp.setVerticalScrollBarPolicy(ScrollPaneConstants.VERTICAL_SCROLLBAR_AS_NEEDED);
+    sp.getViewport().setView(desktop);
+    viewer.getContentPane().removeAll();
+    viewer.add(sp);
+    viewer.addFocusListener(new FocusAdapter() {
+      public void focusGained(FocusEvent e) {
+        if (desktop.isAncestorOf(viewer))
+          desktop.requestFocus();
+      }
+      public void focusLost(FocusEvent e) {
+        releaseModifiers();
+      }
+    });
+    viewer.validate();
+    desktop.requestFocus();
   }
 
   // setDesktopSize() is called when the desktop size changes (including when
@@ -487,15 +536,28 @@ public class CConn extends CConnection
       return;
 
     desktop.resize();
-    recreateViewport();
+    if (viewer.embed.getValue()) {
+      desktop.setScaledSize();
+      setupEmbeddedFrame();
+    } else {
+      recreateViewport();
+    }
+  }
+  
+  public void setEmbeddedFeatures(boolean s) {
+    menu.fullScreen.setEnabled(s);
+    menu.newConn.setEnabled(s);
+    options.fullScreen.setEnabled(s);
+    options.scalingFactor.setEnabled(s);
   }
 
   // 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()
-  {
+  public void recreateViewport() {
+    if (viewer.embed.getValue())
+      return;
     if (viewport != null) viewport.dispose();
     viewport = new Viewport(cp.name(), this);
     viewport.setUndecorated(fullScreen);
@@ -506,8 +568,7 @@ public class CConn extends CConnection
     desktop.requestFocusInWindow();
   }
 
-  private void reconfigureViewport()
-  {
+  private void reconfigureViewport() {
     //viewport.setMaxSize(cp.width, cp.height);
     boolean pack = true;
     Dimension dpySize = viewport.getToolkit().getScreenSize();
@@ -680,6 +741,14 @@ public class CConn extends CConnection
 
   // close() shuts down the socket, thus waking up the RFB thread.
   public void close() {
+    if (closeListener != null) {
+      viewer.embed.setParam(true);
+      if (VncViewer.nViewers == 1) {
+        JFrame f = (JFrame)JOptionPane.getFrameForComponent(viewer);
+        if (f != null)
+          f.dispatchEvent(new WindowEvent(f, WindowEvent.WINDOW_CLOSING));
+      }
+    }
     deleteWindow();
     shuttingDown = true;
     try {
@@ -723,7 +792,7 @@ public class CConn extends CConnection
     JOptionPane op =
       new JOptionPane(msg, JOptionPane.INFORMATION_MESSAGE,
                       JOptionPane.DEFAULT_OPTION, VncViewer.logoIcon);
-    JDialog dlg = op.createDialog("About TigerVNC Viewer for Java");
+    JDialog dlg = op.createDialog(desktop, "About TigerVNC Viewer for Java");
     dlg.setIconImage(VncViewer.frameIcon);
     dlg.setVisible(true);
     if (fullScreenWindow != null)
@@ -758,7 +827,7 @@ public class CConn extends CConnection
                     csecurity.description());
     JOptionPane op = new JOptionPane(msg, JOptionPane.PLAIN_MESSAGE,
                                      JOptionPane.DEFAULT_OPTION);
-    JDialog dlg = op.createDialog("VNC connection info");
+    JDialog dlg = op.createDialog(desktop, "VNC connection info");
     dlg.setIconImage(VncViewer.frameIcon);
     dlg.setVisible(true);
     if (fullScreenWindow != null)
@@ -1134,6 +1203,8 @@ public class CConn extends CConnection
   }
 
   public void toggleFullScreen() {
+    if (viewer.embed.getValue())
+      return;
     fullScreen = !fullScreen;
     menu.fullScreen.setSelected(fullScreen);
     if (viewport != null) {
@@ -1319,6 +1390,13 @@ public class CConn extends CConnection
       writeKeyEvent(Keysyms.Super_R, true);
   }
 
+  // this is a special ActionListener passed in by the
+  // Java Plug-in software to control applet's close behavior
+  public void setCloseListener(ActionListener cl) {
+    closeListener = cl;
+  }
+
+  public void actionPerformed(ActionEvent e) {}
 
   ////////////////////////////////////////////////////////////////////
   // The following methods are called from both RFB and GUI threads
@@ -1401,6 +1479,7 @@ public class CConn extends CConnection
   private boolean autoSelect;
   boolean fullScreen;
   private HashMap<Integer, Integer> downKeySym;
+  public ActionListener closeListener = null;
 
   static LogWriter vlog = new LogWriter("CConn");
 }
index 3dc4c25ac95ddb37ba086db785254195c486ce1b..4749eb2a8e52ff0887f6cadd4e1b9bf4e3ccd945 100644 (file)
@@ -2,7 +2,7 @@
  * Copyright (C) 2006 Constantin Kaplinsky.  All Rights Reserved.
  * Copyright (C) 2009 Paul Donohue.  All Rights Reserved.
  * Copyright (C) 2010, 2012-2013 D. R. Commander.  All Rights Reserved.
- * Copyright (C) 2011-2013 Brian P. Hinz
+ * Copyright (C) 2011-2014 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
@@ -426,7 +426,10 @@ class DesktopWindow extends JPanel implements Runnable, MouseListener,
   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 mouseEntered(MouseEvent e) {
+    if (cc.viewer.embed.getValue())
+      requestFocus();
+  }
   public void mouseExited(MouseEvent e) {}
 
   // MouseWheel callback function
index 543f7408fb1b65fb4bb3eb331cdfcba819caf59c..5045b77f14a1ae6421b80e39054162c019e9ca38 100644 (file)
@@ -1,5 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * Copyright (C) 2011 Brian P. Hinz
+ * Copyright (C) 2011-2014 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
@@ -49,6 +49,7 @@ public class F8Menu extends JPopupMenu implements ActionListener {
     fullScreen.setMnemonic(KeyEvent.VK_F);
     fullScreen.setSelected(cc.fullScreen);
     fullScreen.addActionListener(this);
+    fullScreen.setEnabled(!cc.viewer.embed.getValue());
     add(fullScreen);
     addSeparator();
     clipboard  = addMenuItem("Clipboard...");
@@ -59,6 +60,7 @@ public class F8Menu extends JPopupMenu implements ActionListener {
     refresh    = addMenuItem("Refresh Screen", KeyEvent.VK_H);
     addSeparator();
     newConn    = addMenuItem("New connection...", KeyEvent.VK_W);
+    newConn.setEnabled(!cc.viewer.embed.getValue());
     options    = addMenuItem("Options...", KeyEvent.VK_O);
     save       = addMenuItem("Save connection info as...", KeyEvent.VK_S);
     info       = addMenuItem("Connection info...", KeyEvent.VK_I);
index 3d73d4c37c8efdccbfb382aa50802e2d995e86e7..24c7b0e0d5866d38d5fb2a07d778e55b03bd4e3d 100644 (file)
@@ -1,5 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * Copyright (C) 2011-2012 Brian P. Hinz
+ * Copyright (C) 2011-2014 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
@@ -36,7 +36,7 @@ class OptionsDialog extends Dialog implements
   // Static variables
   static LogWriter vlog = new LogWriter("OptionsDialog");
 
-  OptionsDialogCallback cb;
+  CConn cc;
   JPanel FormatPanel, InputsPanel, MiscPanel, DefaultsPanel, SecPanel;
   JCheckBox autoSelect, customCompressLevel, noJpeg;
   @SuppressWarnings({"rawtypes"})
@@ -53,9 +53,9 @@ class OptionsDialog extends Dialog implements
   JButton cfLoadButton, cfSaveAsButton, defSaveButton, defReloadButton, defClearButton;
 
   @SuppressWarnings({"rawtypes","unchecked"})
-  public OptionsDialog(OptionsDialogCallback cb_) {
+  public OptionsDialog(CConn cc_) {
     super(true);
-    cb = cb_;
+    cc = cc_;
     setResizable(false);
     setTitle("VNC Viewer Options");
 
@@ -149,6 +149,7 @@ class OptionsDialog extends Dialog implements
 
     fullScreen = new JCheckBox("Full-screen mode");
     fullScreen.addItemListener(this);
+    fullScreen.setEnabled(!cc.viewer.embed.getValue());
     shared = new JCheckBox("Shared connection (do not disconnect other viewers)");
     shared.addItemListener(this);
     useLocalCursor = new JCheckBox("Render cursor locally");
@@ -172,6 +173,7 @@ class OptionsDialog extends Dialog implements
     }
     scalingFactor.setEditable(true);
     scalingFactor.addItemListener(this);
+    scalingFactor.setEnabled(!cc.viewer.embed.getValue());
     addGBComponent(fullScreen,MiscPanel,     0, 0, 2, 1, 2, 2, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,5,0,5));
     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));
@@ -205,7 +207,6 @@ class OptionsDialog extends Dialog implements
 
     addGBComponent(configPanel,DefaultsPanel, 0, 0, 1, GridBagConstraints.REMAINDER, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(4,5,4,5));
     addGBComponent(defaultsPanel,DefaultsPanel, 1, 0, 1, GridBagConstraints.REMAINDER, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.PAGE_START, new Insets(4,0,4,5));
-    //defReloadButton.setEnabled(!applet);
 
     // security tab
     SecPanel=new JPanel(new GridBagLayout());
@@ -278,7 +279,7 @@ class OptionsDialog extends Dialog implements
   }
 
   public void initDialog() {
-    if (cb != null) cb.setOptions();
+    if (cc != null) cc.setOptions();
     zrle.setEnabled(!autoSelect.isSelected());
     hextile.setEnabled(!autoSelect.isSelected());
     tight.setEnabled(!autoSelect.isSelected());
@@ -472,7 +473,6 @@ class OptionsDialog extends Dialog implements
 
   public void endDialog() {
     super.endDialog();
-    CConn cc = (CConn)cb;
     if (cc.viewport != null && cc.viewport.isVisible()) {
       cc.viewport.toFront();
       cc.viewport.requestFocus();
@@ -482,7 +482,7 @@ class OptionsDialog extends Dialog implements
   public void actionPerformed(ActionEvent e) {
     Object s = e.getSource();
     if (s instanceof JButton && (JButton)s == okButton) {
-      if (cb != null) cb.getOptions();
+      if (cc != null) cc.getOptions();
       endDialog();
     } else if (s instanceof JButton && (JButton)s == cancelButton) {
       endDialog();
@@ -496,7 +496,7 @@ class OptionsDialog extends Dialog implements
         String filename = fc.getSelectedFile().toString();
         if (filename != null)
           Configuration.load(filename);
-        cb.setOptions();
+        cc.setOptions();
       }
     } else if (s instanceof JButton && (JButton)s == cfSaveAsButton) {
       JFileChooser fc = new JFileChooser();
@@ -516,7 +516,7 @@ class OptionsDialog extends Dialog implements
       restorePreferences();
     } else if (s instanceof JButton && (JButton)s == defClearButton) {
       UserPreferences.clear();
-      cb.setOptions();
+      cc.setOptions();
     } else if (s instanceof JButton && (JButton)s == ca) {
       JFileChooser fc = new JFileChooser(new File(CSecurityTLS.getDefaultCA()));
       fc.setDialogTitle("Path to X509 CA certificate");
index 196df40f78eaeec0fb6529cefcb5b60220d7c46a..446bbf963b886305066e2d793b56d0beeba512ef 100644 (file)
@@ -13,6 +13,7 @@ optimizations, major GUI improvements, and more.
         Copyright (C) 2005 Martin Koegler
         Copyright (C) 2009 Pierre Ossman for Cendio AB
         Copyright (C) 2009-2013 TigerVNC Team
+        Copyright (C) 2011-2014 Brian P. Hinz
         All rights reserved.
 
 This software is distributed under the GNU General Public Licence as
@@ -46,6 +47,10 @@ There are three basic ways to use the TigerVNC Java Viewer:
      Java Viewer by simply copying a new version of VncViewer.jar and/or
      index.vnc into the VNC classes directory.
 
+     On Windows and Linux, the embedded applet can be drag-undocked from the 
+     browser window and converted to a standalone application. The drag
+     gesture ALT+drag on Windows, and SHIFT+drag on Linux.
+
      In the case of the Windows TigerVNC Server, VncViewer.jar and index.vnc
      are embedded as resources in the WinVNC executable, so deploying a
      modified version of the TigerVNC Java Viewer on a Windows server requires
index f43f592db730702b21fb45be4ec02680740a454e..19c51c94e7e14332df7b83b953b5bcf059b1e26b 100644 (file)
@@ -1,5 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
- * Copyright (C) 2011-2013 Brian P. Hinz
+ * Copyright (C) 2011-2014 Brian P. Hinz
  * Copyright (C) 2012-2013 D. R. Commander.  All Rights Reserved.
  *
  * This is free software; you can redistribute it and/or modify
@@ -64,7 +64,11 @@ public class Viewport extends JFrame
     addWindowListener(new WindowAdapter() {
       public void windowClosing(WindowEvent e) {
         if (VncViewer.nViewers == 1) {
-          cc.viewer.exit(1);
+          if (cc.closeListener != null) {
+            cc.close();
+          } else {
+            cc.viewer.exit(1);
+          }
         } else {
           cc.close();
         }
@@ -163,19 +167,19 @@ public class Viewport extends JFrame
   }
 
   public static Window getFullScreenWindow() {
-      GraphicsEnvironment ge =
-        GraphicsEnvironment.getLocalGraphicsEnvironment();
-      GraphicsDevice gd = ge.getDefaultScreenDevice();
-      Window fullScreenWindow = gd.getFullScreenWindow();
-      return fullScreenWindow;
+    GraphicsEnvironment ge =
+      GraphicsEnvironment.getLocalGraphicsEnvironment();
+    GraphicsDevice gd = ge.getDefaultScreenDevice();
+    Window fullScreenWindow = gd.getFullScreenWindow();
+    return fullScreenWindow;
   }
 
   public static void setFullScreenWindow(Window fullScreenWindow) {
-      GraphicsEnvironment ge =
-        GraphicsEnvironment.getLocalGraphicsEnvironment();
-      GraphicsDevice gd = ge.getDefaultScreenDevice();
-      if (gd.isFullScreenSupported())
-        gd.setFullScreenWindow(fullScreenWindow);
+    GraphicsEnvironment ge =
+      GraphicsEnvironment.getLocalGraphicsEnvironment();
+    GraphicsDevice gd = ge.getDefaultScreenDevice();
+    if (gd.isFullScreenSupported())
+      gd.setFullScreenWindow(fullScreenWindow);
   }
 
   CConn cc;
index 8a1f930eb34f34b727370c32bdfc6dfa173905b1..e63ec3b1862789603f90446ab4477ccd075a3de6 100644 (file)
@@ -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-2013 Brian P. Hinz
+ * Copyright (C) 2011-2014 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
@@ -31,6 +31,7 @@
 package com.tigervnc.vncviewer;
 
 import java.awt.*;
+import java.awt.event.*;
 import java.awt.Color;
 import java.awt.Graphics;
 import java.awt.Image;
@@ -49,8 +50,9 @@ import com.tigervnc.rdr.*;
 import com.tigervnc.rfb.*;
 import com.tigervnc.network.*;
 
-public class VncViewer extends java.applet.Applet implements Runnable
-{
+public class VncViewer extends javax.swing.JApplet 
+  implements Runnable, ActionListener {
+
   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"+
@@ -122,7 +124,7 @@ public class VncViewer extends java.applet.Applet implements Runnable
 
 
   public VncViewer(String[] argv) {
-    applet = false;
+    embed.setParam(false);
 
     // load user preferences
     UserPreferences.load("global");
@@ -268,12 +270,12 @@ public class VncViewer extends java.applet.Applet implements Runnable
 
   public VncViewer() {
     UserPreferences.load("global");
-    applet = true;
+    embed.setParam(true);
   }
 
   public static void newViewer(VncViewer oldViewer, Socket sock, boolean close) {
     VncViewer viewer = new VncViewer();
-    viewer.applet = oldViewer.applet;
+    viewer.embed.setParam(oldViewer.embed.getValue());
     viewer.sock = sock;
     viewer.start();
     if (close)
@@ -288,8 +290,56 @@ public class VncViewer extends java.applet.Applet implements Runnable
     newViewer(oldViewer, null);
   }
 
+  public boolean isAppletDragStart(MouseEvent e) {
+    if(e.getID() == MouseEvent.MOUSE_DRAGGED) {
+      // Drag undocking on Mac works, but introduces a host of
+      // problems so disable it for now.
+      if (os.startsWith("mac os x"))
+        return false;
+      else if (os.startsWith("windows"))
+        return (e.getModifiersEx() & MouseEvent.ALT_DOWN_MASK) != 0;
+      else
+        return (e.getModifiersEx() & MouseEvent.SHIFT_DOWN_MASK) != 0;
+    } else {
+      return false;
+    }
+  }
+
+  public void appletDragStarted() {
+    embed.setParam(false);
+    cc.recreateViewport();
+    JFrame f = (JFrame)JOptionPane.getFrameForComponent(this);
+    // The default JFrame created by the drag event will be
+    // visible briefly between appletDragStarted and Finished.
+    if (f != null)
+      f.setSize(0, 0);
+  }
+
+  public void appletDragFinished() {
+    cc.setEmbeddedFeatures(true);
+    JFrame f = (JFrame)JOptionPane.getFrameForComponent(this);
+    if (f != null)
+      f.dispose();
+  }
+
+  public void setAppletCloseListener(ActionListener cl) {
+    cc.setCloseListener(cl);
+  }
+
+  public void appletRestored() {
+    cc.setEmbeddedFeatures(false);
+    cc.setCloseListener(null);
+  }
+
   public void init() {
     vlog.debug("init called");
+    Container parent = getParent();
+    while (!parent.isFocusCycleRoot()) {
+      parent = parent.getParent();
+    }
+    ((Frame)parent).setModalExclusionType(null);
+    parent.setFocusable(false);
+    parent.setFocusTraversalKeysEnabled(false);
     setLookAndFeel();
     setBackground(Color.white);
   }
@@ -310,9 +360,11 @@ public class VncViewer extends java.applet.Applet implements Runnable
   public void start() {
     vlog.debug("start called");
     getTimestamp();
-    if (applet && nViewers == 0) {
+    if (embed.getValue() && nViewers == 0) {
       alwaysShowServerDialog.setParam(true);
       Configuration.global().readAppletParams(this);
+      fullScreen.setParam(false);
+      scalingFactor.setParam("100");
       String host = getCodeBase().getHost();
       if (vncServerName.getValue() == null && vncServerPort.getValue() != 0) {
         int port = vncServerPort.getValue();
@@ -330,22 +382,48 @@ public class VncViewer extends java.applet.Applet implements Runnable
     nViewers--;
     if (nViewers > 0)
       return;
-    if (applet) {
+    if (embed.getValue())
       destroy();
-    } else {
+    else
       System.exit(n);
-    }
   }
 
-  public void paint(Graphics g) {
-    g.drawImage(logoImage, 0, 0, this);
-    int h = logoImage.getHeight(this)+20;
-    g.drawString(String.format(aboutText, version, build,
-                               buildDate, buildTime), 0, h);
+  // If "Reconnect" button is pressed
+  public void actionPerformed(ActionEvent e) {
+    getContentPane().removeAll();
+    start();
   }
 
+  void reportException(java.lang.Exception e) {
+    String title, msg = e.getMessage();
+    int msgType = JOptionPane.ERROR_MESSAGE;
+    title = "TigerVNC Viewer : Error";
+    e.printStackTrace();
+    if (embed.getValue()) {
+      getContentPane().removeAll();
+      JLabel label = new JLabel("<html><center><b>" + title + "</b><p><i>" +
+                                msg + "</i></center></html>", JLabel.CENTER);
+      label.setFont(new Font("Helvetica", Font.PLAIN, 24));
+      label.setMaximumSize(new Dimension(getSize().width, 100));
+      label.setVerticalAlignment(JLabel.CENTER);
+      label.setAlignmentX(Component.CENTER_ALIGNMENT);
+      JButton button = new JButton("Reconnect");
+      button.addActionListener(this);
+      button.setMaximumSize(new Dimension(200, 30));
+      button.setAlignmentX(Component.CENTER_ALIGNMENT);
+      setLayout(new BoxLayout(getContentPane(), BoxLayout.Y_AXIS));
+      add(label);
+      add(button);
+      validate();
+      repaint();
+    } else {
+      JOptionPane.showMessageDialog(null, msg, title, msgType);
+    }
+  }
+
+  CConn cc;
   public void run() {
-    CConn cc = null;
+    cc = null;
 
     if (listenMode.getValue()) {
       int port = 5500;
@@ -358,7 +436,7 @@ public class VncViewer extends java.applet.Applet implements Runnable
       try {
         listener = new TcpListener(null, port);
       } catch (java.lang.Exception e) {
-        System.out.println(e.toString());
+        reportException(e);
         exit(1);
       }
 
@@ -376,18 +454,14 @@ public class VncViewer extends java.applet.Applet implements Runnable
       while (!cc.shuttingDown)
         cc.processMsg();
     } catch (java.lang.Exception e) {
-      if (e instanceof EndOfStream) {
-        vlog.info(e.getMessage());
-      } else if (cc == null || !cc.shuttingDown) {
-        e.printStackTrace();
-        JOptionPane op =
-          new JOptionPane(e.getMessage(), JOptionPane.WARNING_MESSAGE);
-        JDialog dlg = op.createDialog("TigerVNC Viewer");
-        dlg.setIconImage(frameIcon);
-        dlg.setVisible(true);
+      if (cc == null || !cc.shuttingDown) {
+        reportException(e);
+        if (cc != null)
+          cc.deleteWindow();
+        exit(1);
+      } else if (embed.getValue()) {
+        reportException(new java.lang.Exception("Connection closed"));
       } else {
-        if (!cc.shuttingDown)
-          vlog.info(e.toString());
         cc = null;
       }
     }
@@ -400,6 +474,13 @@ public class VncViewer extends java.applet.Applet implements Runnable
   static BoolParameter noLionFS
   = new BoolParameter("NoLionFS", null, false);
 
+  BoolParameter embed
+  = new BoolParameter("Embed",
+  "If the viewer is being run as an applet, display its output to " +
+  "an embedded frame in the browser window rather than to a dedicated " +
+  "window.  This also has the effect of setting FullScreen=0, and Scale=100.",
+  false);
+
   BoolParameter useLocalCursor
   = new BoolParameter("UseLocalCursor",
                       "Render the mouse cursor locally",
@@ -568,7 +649,6 @@ public class VncViewer extends java.applet.Applet implements Runnable
 
   Thread thread;
   Socket sock;
-  boolean applet;
   static int nViewers;
   static LogWriter vlog = new LogWriter("main");
 }
index e88998750f0ba47c25d306263a8a813d38c41409..27bdebcb9391985a9ea531ca7da71c3020d806fa 100644 (file)
@@ -14,6 +14,8 @@ $USER's $DESKTOP desktop ($DISPLAY)
 <APPLET CODE=com.tigervnc.vncviewer.VncViewer ARCHIVE=VncViewer.jar
         WIDTH=$APPLETWIDTH HEIGHT=$APPLETHEIGHT>
 <param name=PORT value=$PORT>
+<param name="Embed" value="true">
+<param name="draggable" value="true">
 </APPLET>
 <BR>
 <A href="http://www.tigervnc.org/">TigerVNC site</A>
index b087279379592e891672f7068d01d1232bf2740b..b0d4601e347d1d00da546623650b3c50f310964e 100644 (file)
@@ -1,5 +1,6 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
  * Copyright 2009-2011 Pierre Ossman for Cendio AB
+ * Copyright 2014 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
@@ -338,7 +339,7 @@ char* XserverDesktop::substitute(const char* varName)
   }
   if (strcmp(varName, "$APPLETHEIGHT") == 0) {
     char* str = new char[10];
-    sprintf(str, "%d", height() + 32);
+    sprintf(str, "%d", height());
     return str;
   }
   if (strcmp(varName, "$DESKTOP") == 0) {