]> source.dussan.org Git - tigervnc.git/commitdiff
initial support for client side scaling. Options dialog offers "Auto" and "FixedRatio...
authorBrian Hinz <bphinz@users.sourceforge.net>
Fri, 30 Sep 2011 02:47:06 +0000 (02:47 +0000)
committerBrian Hinz <bphinz@users.sourceforge.net>
Fri, 30 Sep 2011 02:47:06 +0000 (02:47 +0000)
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4678 3789f03b-4d11-0410-bbf8-ca57d06f2519

java/src/com/tigervnc/vncviewer/CConn.java
java/src/com/tigervnc/vncviewer/DesktopWindow.java
java/src/com/tigervnc/vncviewer/OptionsDialog.java
java/src/com/tigervnc/vncviewer/VncViewer.java

index be6a8d81dcf13f773805fbf095ac4b9c4a072521..4abcf13b80b357e87a7e0c56e50b155ca076c34b 100644 (file)
@@ -94,9 +94,12 @@ class ViewportFrame extends JFrame
     addChild(child);
   }
 
-  public void setGeometry(int x, int y, int w, int h) {
-    pack();
-    if (cc.fullScreen) setSize(w, h);
+  public void setGeometry(int x, int y, int w, int h, boolean pack) {
+    if (pack) {
+      pack();
+    } else {
+      setSize(w, h);
+    }
     setLocation(x, y);
     setBackground(Color.BLACK);
   }
@@ -127,6 +130,7 @@ public class CConn extends CConnection
     fullScreen = viewer.fullScreen.getValue();
     menuKey = Keysyms.F8;
     options = new OptionsDialog(this);
+    options.initDialog();
     clipboardDialog = new ClipboardDialog(this);
     firstUpdate = true; pendingUpdate = false;
 
@@ -465,27 +469,39 @@ public class CConn extends CConnection
 
   private void reconfigureViewport()
   {
-    //viewport->setMaxSize(cp.width, cp.height);
+    //viewport.setMaxSize(cp.width, cp.height);
+    boolean pack = true;
+    int w = cp.width;
+    int h = cp.height;
+    Dimension dpySize = viewport.getToolkit().getScreenSize();
+    desktop.setScaledSize();
+    if (!options.autoScale && !options.fixedRatioScale) {
+      w = (int)java.lang.Math.floor(cp.width*scaleFactor/100);
+      h = (int)java.lang.Math.floor(cp.height*scaleFactor/100);
+    }
     if (fullScreen) {
-      Dimension dpySize = viewport.getToolkit().getScreenSize();
       viewport.setExtendedState(JFrame.MAXIMIZED_BOTH);
-      viewport.setGeometry(0, 0, dpySize.width, dpySize.height);
+      viewport.setGeometry(0, 0, dpySize.width, dpySize.height, false);
     } 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)
+      if (w + wmDecorationWidth >= dpySize.width) {
         w = dpySize.width - wmDecorationWidth;
-      if (h + wmDecorationHeight >= dpySize.height)
+        pack = false;
+      }
+      if (h + wmDecorationHeight >= dpySize.height) {
         h = dpySize.height - wmDecorationHeight;
+        pack = false;
+      }
+
+      if (!pack)
+        viewport.setPreferredSize(new Dimension(w,h));
 
       int x = (dpySize.width - w - wmDecorationWidth) / 2;
       int y = (dpySize.height - h - wmDecorationHeight)/2;
 
       viewport.setExtendedState(JFrame.NORMAL);
-      viewport.setGeometry(x, y, w, h);
+      viewport.setGeometry(x, y, w, h, pack);
     }
   }
 
@@ -799,6 +815,25 @@ public class CConn extends CConnection
     options.useLocalCursor.setSelected(viewer.useLocalCursor.getValue());
     options.fastCopyRect.setSelected(viewer.fastCopyRect.getValue());
     options.acceptBell.setSelected(viewer.acceptBell.getValue());
+    options.autoScale = false;
+    options.fixedRatioScale = false;
+    String scaleString = viewer.scalingFactor.getValue();
+    if (scaleString.equals("Auto")) {
+      options.autoScale = true;
+    } else if( scaleString.equals("FixedRatio")) {
+      options.fixedRatioScale = true;
+    } else { 
+      digit = Integer.parseInt(scaleString);
+      if (digit >= 1 && digit <= 1000) {
+        options.scalingFactor.setSelectedItem(digit+"%");
+      } else {
+        options.scalingFactor.setSelectedItem(Integer.parseInt(viewer.scalingFactor.getDefaultStr())+"%");
+      }
+      scaleFactor = 
+        Integer.parseInt(scaleString.substring(0, scaleString.length()));
+      if (desktop != null)
+        desktop.setScaledSize();
+    }
   }
 
   public void getOptions() {
@@ -855,6 +890,24 @@ public class CConn extends CConnection
     viewer.sendClipboard.setParam(options.sendClipboard.isSelected());
     viewer.fastCopyRect.setParam(options.fastCopyRect.isSelected());
     viewer.acceptBell.setParam(options.acceptBell.isSelected());
+    if (options.autoScale) {
+      viewer.scalingFactor.setParam("Auto");
+    } else if(options.fixedRatioScale) {
+      viewer.scalingFactor.setParam("FixedRatio");
+    } else { 
+      String scaleString =
+        options.scalingFactor.getSelectedItem().toString();
+      viewer.scalingFactor.setParam(scaleString.substring(0, scaleString.length()-1));
+      int oldScaleFactor = scaleFactor;
+      scaleFactor = 
+        Integer.parseInt(scaleString.substring(0, scaleString.length()-1));
+      if (oldScaleFactor != scaleFactor && desktop != null) {
+        //desktop.setScaledSize();
+        reconfigureViewport();
+        viewport.update(viewport.g);
+      }
+    }
+
     clipboardDialog.setSendingEnabled(viewer.sendClipboard.getValue());
     menuKey = (int)(options.menuKey.getSelectedIndex()+0xFFBE);
     F8Menu.f8.setLabel("Send F"+(menuKey-Keysyms.F1+1));
@@ -1096,14 +1149,17 @@ public class CConn extends CConnection
 
     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 (cp.width != desktop.scaledWidth || 
+        cp.height != desktop.scaledHeight) {
+      int sx = (desktop.scaleWidthRatio == -1) 
+        ? ev.getX() : (int)java.lang.Math.floor(ev.getX()/desktop.scaleWidthRatio);
+      int sy = (desktop.scaleHeightRatio == -1) 
+        ? ev.getY() : (int)java.lang.Math.floor(ev.getY()/desktop.scaleWidthRatio);
+      ev.translatePoint(sx - ev.getX(), sy - ev.getY());
+      writer().writePointerEvent(new Point(ev.getX(),ev.getY()), buttonMask);
+    } else {
+      writer().writePointerEvent(new Point(ev.getX(),ev.getY()), buttonMask);
+    }
 
     if (buttonMask == 0) writeModifiers(0);
   }
@@ -1216,5 +1272,7 @@ public class CConn extends CConnection
   boolean firstUpdate;
   boolean pendingUpdate;
   
+  int scaleFactor;
+  
   static LogWriter vlog = new LogWriter("CConn");
 }
index 5e2764bc9c25992a93d4b46d760598bbfe683df1..ea57669e6aed7f502ba35b15f3b4fb23a5f3b924 100644 (file)
@@ -86,7 +86,7 @@ class DesktopWindow extends JPanel implements
   public void initGraphics() { 
     cc.viewport.g = cc.viewport.getGraphics(); 
     graphics = getComponentGraphics(cc.viewport.g);
-    prepareImage(im.image, -1, -1, this);
+    prepareImage(im.image, scaledWidth, scaledHeight, this);
   }
 
   final public PixelFormat getPF() { return im.getPF(); }
@@ -289,21 +289,46 @@ class DesktopWindow extends JPanel implements
     cursorAvailable = false;
   }
 
-  synchronized public Dimension getPreferredSize() {
-    return new Dimension(im.width(), im.height());
+  //
+  // Callback methods to determine geometry of our Component.
+  //
+
+  public Dimension getPreferredSize() {
+    return new Dimension(scaledWidth, scaledHeight);
+  }
+
+  public Dimension getMinimumSize() {
+    return new Dimension(scaledWidth, scaledHeight);
   }
 
-  synchronized public Dimension getMinimumSize() {
-    return new Dimension(im.width(), im.height());
+  public Dimension getMaximumSize() {
+    return new Dimension(scaledWidth, scaledHeight);
   }
 
   public void update(Graphics g) {
     //repaint();
   }
 
+  public void setScaledSize() {
+    int w = (int)java.lang.Math.floor(cc.cp.width*cc.scaleFactor/100);
+    int h = (int)java.lang.Math.floor(cc.cp.height*cc.scaleFactor/100);
+    scaledWidth = w;
+    scaledHeight = h;
+    scaleWidthRatio = ((float)w/(float)cc.cp.width);
+    scaleHeightRatio = ((float)h/(float)cc.cp.height);
+  }
+
   synchronized public void paintComponent(Graphics g) {
     Graphics2D g2 = (Graphics2D) g;
-    g2.drawImage(im.image, 0, 0, this);
+    g2.setRenderingHint(RenderingHints.KEY_INTERPOLATION, 
+                        RenderingHints.VALUE_INTERPOLATION_BILINEAR);  
+    g2.setRenderingHint(RenderingHints.KEY_RENDERING, 
+                        RenderingHints.VALUE_RENDER_QUALITY);
+    if (cc.cp.width == scaledWidth && cc.cp.height == scaledHeight) {
+      g2.drawImage(im.image, 0, 0, null);
+    } else {
+      g2.drawImage(im.image, 0, 0, scaledWidth, scaledHeight, null);  
+    }
   }
 
 
@@ -474,6 +499,9 @@ class DesktopWindow extends JPanel implements
   java.awt.Cursor softCursor;
   static Toolkit tk = Toolkit.getDefaultToolkit();
 
+  public int scaledWidth = 0, scaledHeight = 0;
+  float scaleWidthRatio, scaleHeightRatio;
+
   // the following are only ever accessed by the RFB thread:
   boolean invalidRect;
   int invalidLeft, invalidRight, invalidTop, invalidBottom;
index f64ed68290dd70f9c25cc05ccdf0cac2e4d50dc1..0aa148f20835ef41624be2961c980be0ab6eb3ca 100644 (file)
@@ -42,7 +42,7 @@ class OptionsDialog extends Dialog implements
   OptionsDialogCallback cb;
   JPanel FormatPanel, InputsPanel, MiscPanel, DefaultsPanel, SecPanel;
   JCheckBox autoSelect, customCompressLevel, noJpeg;
-  JComboBox menuKey, compressLevel, qualityLevel ;
+  JComboBox menuKey, compressLevel, qualityLevel, scalingFactor;
   ButtonGroup encodingGroup, colourGroup;
   JRadioButton zrle, hextile, tight, raw;
   JRadioButton fullColour, mediumColour, lowColour, veryLowColour;
@@ -55,6 +55,9 @@ class OptionsDialog extends Dialog implements
   JButton defSaveButton;
   UserPrefs defaults;
 
+  boolean autoScale = false;
+  boolean fixedRatioScale = false;
+
   public OptionsDialog(OptionsDialogCallback cb_) { 
     super(false);
     cb = cb_;
@@ -142,9 +145,8 @@ class OptionsDialog extends Dialog implements
     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));
+    addGBComponent(menuKeyLabel,InputsPanel,    0, 3, 1, GridBagConstraints.REMAINDER, 0, 0, 1, 1, GridBagConstraints.NONE, GridBagConstraints.FIRST_LINE_START, new Insets(8,8,0,4));
+    addGBComponent(menuKey,InputsPanel,         1, 3, 1, GridBagConstraints.REMAINDER, 0, 0, 25, 1, GridBagConstraints.NONE, GridBagConstraints.FIRST_LINE_START, new Insets(4,4,0,4));
 
     // Misc tab
     MiscPanel=new JPanel(new GridBagLayout());
@@ -159,11 +161,21 @@ class OptionsDialog extends Dialog implements
     fastCopyRect.addItemListener(this);
     acceptBell = new JCheckBox("Beep when requested by the server");
     acceptBell.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, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4));
-    addGBComponent(acceptBell,MiscPanel,     0, 4, 1, GridBagConstraints.REMAINDER, 0, 0, 1, 1, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(4,4,0,4));
+    JLabel scalingFactorLabel = new JLabel("Scaling Factor");
+    Object[] scalingFactors = { 
+      //"50%", "75%", "95%", "100%", "105%", 
+      "Auto", "Fixed Aspect Ratio", "50%", "75%", "95%", "100%", "105%", 
+      "125%", "150%", "175%", "200%", "250%", "300%", "350%", "400%" };
+    scalingFactor  = new JComboBox(scalingFactors);
+    scalingFactor.setEditable(true);
+    scalingFactor.addItemListener(this);
+    addGBComponent(fullScreen,MiscPanel,     0, 0, 2, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4));
+    addGBComponent(shared,MiscPanel,         0, 1, 2, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4));
+    addGBComponent(useLocalCursor,MiscPanel, 0, 2, 2, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4));
+    addGBComponent(fastCopyRect,MiscPanel,   0, 3, 2, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.LINE_START, new Insets(4,4,0,4));
+    addGBComponent(acceptBell,MiscPanel,     0, 4, 2, 1, 0, 0, 1, 0, GridBagConstraints.HORIZONTAL, GridBagConstraints.FIRST_LINE_START, new Insets(4,4,0,4));
+    addGBComponent(scalingFactorLabel,MiscPanel, 0, 5, 1, GridBagConstraints.REMAINDER, 0, 0, 1, 1, GridBagConstraints.NONE, GridBagConstraints.FIRST_LINE_START, new Insets(8,8,0,4));
+    addGBComponent(scalingFactor,MiscPanel, 1, 5, 1, GridBagConstraints.REMAINDER, 0, 0, 25, 1, GridBagConstraints.NONE, GridBagConstraints.FIRST_LINE_START, new Insets(4,4,0,4));
 
     // load/save tab
     DefaultsPanel=new JPanel(new GridBagLayout());
index c2b39bfeedc6bf3f3f2316ce07dc3ae66d1a2b36..d548f4238e1ff1587dce7dca80ee7b40a30a9ef5 100644 (file)
@@ -233,6 +233,18 @@ public class VncViewer extends java.applet.Applet implements Runnable
   = new StringParameter("DesktopSize",
                         "Reconfigure desktop size on the server on "+
                         "connect (if possible)", "");
+  StringParameter scalingFactor
+  = new StringParameter("ScalingFactor",
+                        "Reduce or enlarge the remote desktop image. "+
+                        "The value is interpreted as a scaling factor "+
+                        "in percent.  If the parameter is set to "+
+                        "\"Auto\", then automatic scaling is "+
+                        "performed.  Auto-scaling tries to choose a "+
+                        "scaling factor in such a way that the whole "+
+                        "remote desktop will fit on the local screen.  "+
+                        "If the parameter is set to \"FixedRatio\", "+
+                        "then automatic scaling is performed, but the "+
+                        "original aspect ratio is preserved.", "100");
   BoolParameter alwaysShowServerDialog
   = new BoolParameter("AlwaysShowServerDialog",
                           "Always show the server dialog even if a server "+