From: Brian Hinz Date: Fri, 30 Sep 2011 02:47:06 +0000 (+0000) Subject: initial support for client side scaling. Options dialog offers "Auto" and "FixedRatio... X-Git-Tag: v1.1.90~131 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=476a8f5e1c0c27b70c838b4bcb12ccef4dcd345c;p=tigervnc.git initial support for client side scaling. Options dialog offers "Auto" and "FixedRatio" but these haven't been implemented yet git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@4678 3789f03b-4d11-0410-bbf8-ca57d06f2519 --- diff --git a/java/src/com/tigervnc/vncviewer/CConn.java b/java/src/com/tigervnc/vncviewer/CConn.java index be6a8d81..4abcf13b 100644 --- a/java/src/com/tigervnc/vncviewer/CConn.java +++ b/java/src/com/tigervnc/vncviewer/CConn.java @@ -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"); } diff --git a/java/src/com/tigervnc/vncviewer/DesktopWindow.java b/java/src/com/tigervnc/vncviewer/DesktopWindow.java index 5e2764bc..ea57669e 100644 --- a/java/src/com/tigervnc/vncviewer/DesktopWindow.java +++ b/java/src/com/tigervnc/vncviewer/DesktopWindow.java @@ -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; diff --git a/java/src/com/tigervnc/vncviewer/OptionsDialog.java b/java/src/com/tigervnc/vncviewer/OptionsDialog.java index f64ed682..0aa148f2 100644 --- a/java/src/com/tigervnc/vncviewer/OptionsDialog.java +++ b/java/src/com/tigervnc/vncviewer/OptionsDialog.java @@ -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()); diff --git a/java/src/com/tigervnc/vncviewer/VncViewer.java b/java/src/com/tigervnc/vncviewer/VncViewer.java index c2b39bfe..d548f423 100644 --- a/java/src/com/tigervnc/vncviewer/VncViewer.java +++ b/java/src/com/tigervnc/vncviewer/VncViewer.java @@ -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 "+