changeset 448:344a35b7c47f

send both frame buffer size and selected screen size in Disktop size change (INIT_DATA)
author Shinji KONO <kono@ie.u-ryukyu.ac.jp>
date Sat, 18 Jun 2016 20:09:46 +0900
parents 3996fde6f8ed
children d5bcae14c2cd
files .idea/misc.xml src/main/java/com/glavsoft/rfb/client/FramebufferUpdateRequestMessage.java src/main/java/com/glavsoft/rfb/encoding/decoder/FramebufferUpdateRectangle.java src/main/java/com/glavsoft/rfb/protocol/ReceiverTask.java src/main/java/jp/ac/u_ryukyu/treevnc/ChangeDesktopSize.java src/main/java/jp/ac/u_ryukyu/treevnc/RequestScreenThread.java src/main/java/jp/ac/u_ryukyu/treevnc/TreeRFBProto.java src/main/java/jp/ac/u_ryukyu/treevnc/TreeVncCommandChannelListener.java src/viewer_swing/java/com/glavsoft/viewer/CuiViewer.java src/viewer_swing/java/com/glavsoft/viewer/TreeViewer.java src/viewer_swing/java/com/glavsoft/viewer/Viewer.java src/viewer_swing/java/com/glavsoft/viewer/ViewerInterface.java src/viewer_swing/java/com/glavsoft/viewer/swing/SwingViewerWindow.java
diffstat 13 files changed, 122 insertions(+), 213 deletions(-) [+]
line wrap: on
line diff
--- a/.idea/misc.xml	Fri Jun 17 17:06:22 2016 +0900
+++ b/.idea/misc.xml	Sat Jun 18 20:09:46 2016 +0900
@@ -16,19 +16,4 @@
   <component name="ProjectRootManager" version="2" languageLevel="JDK_1_6" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
     <output url="file://$PROJECT_DIR$/build/classes" />
   </component>
-  <component name="masterDetails">
-    <states>
-      <state key="ProjectJDKs.UI">
-        <settings>
-          <splitter-proportions>
-            <option name="proportions">
-              <list>
-                <option value="0.2" />
-              </list>
-            </option>
-          </splitter-proportions>
-        </settings>
-      </state>
-    </states>
-  </component>
 </project>
\ No newline at end of file
--- a/src/main/java/com/glavsoft/rfb/client/FramebufferUpdateRequestMessage.java	Fri Jun 17 17:06:22 2016 +0900
+++ b/src/main/java/com/glavsoft/rfb/client/FramebufferUpdateRequestMessage.java	Sat Jun 18 20:09:46 2016 +0900
@@ -24,15 +24,14 @@
 
 package com.glavsoft.rfb.client;
 
+import com.glavsoft.exceptions.TransportException;
+import com.glavsoft.transport.Writer;
+
 import java.util.Timer;
 import java.util.TimerTask;
 
-import com.glavsoft.exceptions.TransportException;
-import com.glavsoft.transport.Writer;
-
 
 public class FramebufferUpdateRequestMessage implements ClientToServerMessage {
-	private final boolean incremental;
 	private final int height;
 	private final int width;
 	private final int y;
@@ -41,12 +40,12 @@
 	private boolean sendFullScreenFlag;
 	
 	public FramebufferUpdateRequestMessage(int x, int y, int width,
-			int height, boolean incremental) {
+			int height, boolean fullScreen) {
 		this.x = x;
 		this.y = y;
 		this.width = width;
 		this.height = height;
-		this.incremental = incremental;
+		this.sendFullScreenFlag = fullScreen;
 //		sendFullScreenRequest();
 	}
 
@@ -70,9 +69,14 @@
 	public String toString() {
 		return "FramebufferUpdateRequestMessage: [x: " + x + " y: " + y
 		+ " width: " + width + " height: " + height +
-		" incremental: " + incremental + "]";
+		" fullScreen: " + sendFullScreenFlag + "]";
 	}
-	
+
+    /**
+     * start send full screen request timer
+     *    it is periodically executed
+     *    there is no way to stop this
+     */
 	public void sendFullScreenRequest() {
 		int sendFullScreenTimer = 5 * 1000;
 		TimerTask tt = new TimerTask() {
--- a/src/main/java/com/glavsoft/rfb/encoding/decoder/FramebufferUpdateRectangle.java	Fri Jun 17 17:06:22 2016 +0900
+++ b/src/main/java/com/glavsoft/rfb/encoding/decoder/FramebufferUpdateRectangle.java	Sat Jun 18 20:09:46 2016 +0900
@@ -24,12 +24,12 @@
 
 package com.glavsoft.rfb.encoding.decoder;
 
-import java.io.UnsupportedEncodingException;
-
 import com.glavsoft.exceptions.TransportException;
 import com.glavsoft.rfb.encoding.EncodingType;
 import com.glavsoft.transport.Reader;
 
+import java.io.UnsupportedEncodingException;
+
 /**
  * Header for framebuffer-update-rectangle header server message
  * 2 - U16 - x-position
@@ -58,8 +58,8 @@
     }
 
     public void fill(Reader reader) throws TransportException, UnsupportedEncodingException {
-        x = reader.readUInt16();
-        y = reader.readUInt16();
+        x = reader.readInt16();
+        y = reader.readInt16();
         width = reader.readUInt16();
         height = reader.readUInt16();
         int encoding = reader.readInt32();
--- a/src/main/java/com/glavsoft/rfb/protocol/ReceiverTask.java	Fri Jun 17 17:06:22 2016 +0900
+++ b/src/main/java/com/glavsoft/rfb/protocol/ReceiverTask.java	Sat Jun 18 20:09:46 2016 +0900
@@ -46,7 +46,6 @@
 import java.io.UnsupportedEncodingException;
 import java.util.LinkedList;
 import java.util.Timer;
-import java.util.TimerTask;
 import java.util.logging.Logger;
 
 
@@ -88,30 +87,17 @@
         decoders.setDecoderByType(EncodingType.ZLIB, decoder);
         decoders.setDecoderByType(EncodingType.ZRLE, decoder);
         decoders.setDecoderByType(EncodingType.ZRLEE, decoder);
-
+        if(rfb.fixingSize) {
+            context.setFbWidth(rfb.fixingSizeWidth);
+            context.setFbHeight(rfb.fixingSizeHeight);
+        }
         if(!rfb.getCuiVersion()) {
-            if (rfb.filterSingleDisplay) {
-                renderer = repaintController.createRenderer(reader, context.getFbWidth(), context.getFbHeight(), context.getPixelFormat());
-                fullscreenFbUpdateIncrementalRequest = new FramebufferUpdateRequestMessage(0, 0, rfb.getSingleWidth(), rfb.getSingleHeight(), false);
-            } else {
-                renderer = repaintController.createRenderer(reader, context.getFbWidth(), context.getFbHeight(), context.getPixelFormat());
-                fullscreenFbUpdateIncrementalRequest = new FramebufferUpdateRequestMessage(rfb.getX(), rfb.getY(), rfb.frameSizeWidth * rfb.getRetinaScale(), rfb.frameSizeHeight * rfb.getRetinaScale(), false);
-            }
+            renderer = repaintController.createRenderer(reader, context.getFbWidth(), context.getFbHeight(), context.getPixelFormat());
+            fullscreenFbUpdateIncrementalRequest = new FramebufferUpdateRequestMessage(rfb.getX(), rfb.getY(), rfb.frameSizeWidth, rfb.frameSizeHeight, false);
         }
         if(rfb.isTreeManager()) {
             fullscreenFbUpdateIncrementalRequest.sendFullScreenRequest();
             connectionFinished();
-            if(rfb.fixingSize) {
-                timer = new Timer("framebufferUpdate-request-timer", true);
-                timer.schedule(new TimerTask() {
-                    @Override
-                    public void run() { 
-                        context.setFbWidth(rfb.fixingSizeWidth);
-                        context.setFbHeight(rfb.fixingSizeHeight);
-                        context.sendMessage(new FramebufferUpdateRequestMessage(rfb.getX(), rfb.getY(), rfb.frameSizeWidth * rfb.getRetinaScale(), rfb.frameSizeHeight * rfb.getRetinaScale(), true));
-                    }
-                }, 0, 100);
-            }
         }
     }
 
@@ -289,14 +275,16 @@
                     rfb.setCuiVersion(false);
                     renderer = repaintController.createRenderer(reader, rect.width, rect.height, context.getPixelFormat());
                     if (rfb.hasViewer()){
-                        setScreenParameter();
+                        setScreenParameter(rect,rect.width,rect.height);
                     }
                 } else if (rect.getEncodingType() == EncodingType.INIT_DATA) {
                     fullscreenFbUpdateIncrementalRequest = new FramebufferUpdateRequestMessage(rect.x, rect.y, rect.width, rect.height, false);
                     rfb.setCuiVersion(false);
                     // VNCServer is changed, initiarize new screen.
-                    int length = reader.readInt32() - 2;
+                    int length = reader.readInt32() - 6;
                     short id = reader.readInt16();
+                    int singleWidth = reader.readUInt16();
+                    int singleHeight = reader.readUInt16();
                     byte[] initData = new byte[length];
                     reader.read(initData);
                     String name = new String(initData, 24, length - 24, "UTF-8");
@@ -310,13 +298,13 @@
                     reader.reset();
                     // All children multicastqueue should be discarded here.
                     //                        rfb.clearChildrenTransmission();
-                    rfb.readSendData(length + 20 + 2, reader, null, rect); // size of UpdateRectangleMessage with initData.
+                    rfb.readSendData(length + 16 + 10, reader, null, rect); // size of UpdateRectangleMessage with initData.
                     if (!(rfb.getCuiVersion())) {
                         renderer = repaintController.createRenderer(reader, rect.width, rect.height, context.getPixelFormat());
                     }
                     repaintController.setVisible(id != rfb.getId());
                     if (rfb.hasViewer()){
-                        setScreenParameter();
+                        setScreenParameter(rect,singleWidth,singleHeight);
                     }
                 } else if (rect.getEncodingType() == EncodingType.CHECK_DELAY) {
                         int checkDelaySize = 24;
@@ -358,13 +346,14 @@
         }
     }
 
-    private void setScreenParameter() {
+    private void setScreenParameter(FramebufferUpdateRectangle rect,int singleWidth ,int singleHeight) {
         ViewerInterface v = rfb.getViewer();
+        rfb.setSingleDisplaySize(singleWidth,singleHeight);
         ConnectionPresenter cp = v.getConnectionPresenter();
-        cp.setX(rfb.getX());
-        cp.setY(rfb.getY());
-        cp.setFrameSizeWidth(rfb.frameSizeWidth);
-        cp.setFrameSizeHeight(rfb.frameSizeHeight);
+        cp.setX(rect.x);
+        cp.setY(rect.y);
+        cp.setFrameSizeWidth(rect.width);
+        cp.setFrameSizeHeight(rect.height);
         v.setFitScreen();
     }
 
--- a/src/main/java/jp/ac/u_ryukyu/treevnc/ChangeDesktopSize.java	Fri Jun 17 17:06:22 2016 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/treevnc/ChangeDesktopSize.java	Sat Jun 18 20:09:46 2016 +0900
@@ -1,27 +1,29 @@
 package jp.ac.u_ryukyu.treevnc;
 
+import com.glavsoft.rfb.encoding.EncodingType;
+
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 
-import com.glavsoft.rfb.encoding.EncodingType;
-
 public class ChangeDesktopSize {
 
     private ByteBuffer msg;
 
-    public ChangeDesktopSize(int width, int height,
+    public ChangeDesktopSize(int fbwidth, int fbheight,int width, int height,
                              int x, int y, EncodingType desktopSize, byte[] initData, short id) {
-        msg = ByteBuffer.allocate(16+4+initData.length+2).order(ByteOrder.BIG_ENDIAN);
+        msg = ByteBuffer.allocate(16+10+initData.length).order(ByteOrder.BIG_ENDIAN);
         msg.put((byte) 0); // FrameBufferUpdate
         msg.put((byte) 0); // padding
         msg.putShort((short) 1); // number of rectangle
         msg.putShort((short) x);
         msg.putShort((short) y);
-        msg.putShort((short) width);
-        msg.putShort((short) height);
+        msg.putShort((short) fbwidth);
+        msg.putShort((short) fbheight);
         msg.putInt(desktopSize.getId());
-        msg.putInt(initData.length+2);
+        msg.putInt(initData.length+6);
         msg.putShort(id);
+        msg.putShort((short) width);
+        msg.putShort((short)height);
         msg.put(initData);
         msg.flip();
 
--- a/src/main/java/jp/ac/u_ryukyu/treevnc/RequestScreenThread.java	Fri Jun 17 17:06:22 2016 +0900
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,48 +0,0 @@
-package jp.ac.u_ryukyu.treevnc;
-
-import com.glavsoft.exceptions.TransportException;
-import com.glavsoft.rfb.protocol.Protocol;
-
-public class RequestScreenThread implements Runnable {
-	public TreeRFBProto rfb;
-	Protocol protocol;
-
-	public RequestScreenThread(TreeRFBProto _rfb) {
-		rfb = _rfb;
-	}
-
-	
-
-	/* (non-Javadoc)
-	 * @see java.lang.Runnable#run()
-	 * 
-	 * request full screen update every 3 second.
-	 * restart send this immediately.
-	 * nobody call this.
-	 * 
-	 */
-	public void run() {
-		while (true) {
-			try {
-				synchronized(this) {
-					wait();
-				}
-				Thread.sleep(3000);
-				rfb.writeFramebufferUpdateRequest(0, 0, protocol.getFbWidth(), protocol.getFbHeight(), false);
-			} catch (InterruptedException e) {
-				e.printStackTrace();
-                System.out.println("any thread has interrupted the current thread");
-				break;
-            }
-        }
-	}
-	
-
-    /**
-     * do nothing.
-     */
-    public synchronized void reStart() {
-    	notify();
-    }
-    
-}
--- a/src/main/java/jp/ac/u_ryukyu/treevnc/TreeRFBProto.java	Fri Jun 17 17:06:22 2016 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/treevnc/TreeRFBProto.java	Sat Jun 18 20:09:46 2016 +0900
@@ -29,13 +29,11 @@
 
 public class TreeRFBProto {
 
-    final static int FramebufferUpdateRequest = 3;
     final static int CheckDelay = 11;
     protected final static int FramebufferUpdate = 0;
     protected ProtocolContext context;
     private int clients = 0;
     public MulticastQueue<LinkedList<ByteBuffer>> multicastqueue = new MulticastQueue<LinkedList<ByteBuffer>>();
-    private RequestScreenThread rThread;
     public int acceptPort = 0;
     private String myAddress;
     private long counter = 0; // packet serial number
@@ -66,23 +64,21 @@
     public boolean checkDelay = false;
     public boolean addSerialNum = false;
     public boolean fixingSize = false;
-    public boolean filterSingleDisplay = false;
-    public int frameSizeWidth;
+    public int frameSizeWidth;     // contains all screens
     public int frameSizeHeight;
     public int fixingSizeWidth;
     public int fixingSizeHeight;
-    private int singleWidth = 0;
+    private int singleWidth = 0;     //  only one screen
     private int singleHeight = 0;
+    private int x;
+    private int y;
     private DatagramSocket socket = null;
     private byte[] originalInitData = null;
     private boolean childrenMulticast = true;
     private int retinaScale = 1;
-    private int x;
-    private int y;
 
 
     public TreeRFBProto(boolean isTreeManager, ViewerInterface viewer) {
-        rThread = new RequestScreenThread(this);
         nets.setMyRfb(this);
         this.isTreeManager = isTreeManager;
         this.viewer = viewer;
@@ -215,12 +211,12 @@
                                     String newHostName = new String(byteAddress, "UTF-8");
                                     int x = buf.getInt();
                                     int y = buf.getInt();
-                                    int frameSizeWidth = buf.getInt();
-                                    int frameSizeHeight = buf.getInt();
+                                    singleWidth = buf.getInt();
+                                    singleHeight = buf.getInt();
                                     int port = buf.getInt();
                                     int scale = buf.getInt();
                                     System.out.println("Root server change request :" + newHostName + " : " + port);
-                                    changeVNCServer(viewer, newHostName, port, x, y, frameSizeWidth, frameSizeHeight, scale, id, is, os);
+                                    changeVNCServer(viewer, newHostName, port, x, y, singleWidth, singleHeight, scale, id, is, os);
                                 } else {
                                     continue;
                                 }
@@ -369,7 +365,7 @@
     }
 
     public void requestThreadNotify() {
-        rThread.reStart();
+        // send full screen update
     }
 
 
@@ -401,22 +397,6 @@
         return port;
     }
 
-
-    public void writeFramebufferUpdateRequest(int x, int y, int w, int h, boolean incremental) {
-        byte[] b = new byte[10];
-
-        b[0] = (byte) FramebufferUpdateRequest; // 3 is FrameBufferUpdateRequest
-        b[1] = (byte) (incremental ? 1 : 0);
-        b[2] = (byte) ((x >> 8) & 0xff);
-        b[3] = (byte) (x & 0xff);
-        b[4] = (byte) ((y >> 8) & 0xff);
-        b[5] = (byte) (y & 0xff);
-        b[6] = (byte) ((w >> 8) & 0xff);
-        b[7] = (byte) (w & 0xff);
-        b[8] = (byte) ((h >> 8) & 0xff);
-        b[9] = (byte) (h & 0xff);
-    }
-
     public void setViewer(ViewerInterface v) {
         viewer = v;
     }
@@ -505,14 +485,7 @@
 
     public void sendDesktopSizeChange(short id) {
         LinkedList<ByteBuffer> desktopSize = new LinkedList<ByteBuffer>();
-        int width = context.getFbWidth();
-        int height = context.getFbHeight();
-        if (filterSingleDisplay) {
-            originalInitData = createOriginalInitData(singleWidth, singleHeight, context.getRemoteDesktopName());
-            desktopSize.add(new ChangeDesktopSize(width, height, x, y, EncodingType.INIT_DATA, context.getInitData(), id).getMessage());
-        } else {
-            desktopSize.add(new ChangeDesktopSize(width, height, x, y, EncodingType.INIT_DATA, context.getInitData(), id).getMessage());
-        }
+        desktopSize.add(new ChangeDesktopSize(context.getFbWidth(), context.getFbHeight(), singleWidth,singleHeight, x, y, EncodingType.INIT_DATA, context.getInitData(), id).getMessage());
         if (addSerialNum) {
             addSerialNumber(desktopSize);
         }
@@ -712,13 +685,7 @@
                     if (addSerialNum) {
                         addSerialNumber(bufs);
                     }
-                    if (filterSingleDisplay) {
-                        if (rect.x < singleWidth) {
-                            multicastqueue.put(bufs);
-                        }
-                    } else {
-                        multicastqueue.put(bufs);
-                    }
+                    multicastqueue.put(bufs);
                 } catch (IOException e) {
                     throw new TransportException(e);
                 } catch (DataFormatException e) {
@@ -813,6 +780,11 @@
             return;
         }
         // serverChangeの処理
+        // keep requested screen size ( not frame buffer size )
+        singleWidth = width;
+        singleHeight = height;
+        this.x = x;
+        this.y = y;
         vncProxyService.inhelitClients(hostName, newVNCServerId, x, y, width, height, scale);
         // after connecting VNC server, rfb send SEND_INIT_DATA command and wakes me up if necessary
         // stop reader stop
@@ -878,10 +850,6 @@
         this.fixingSize = fixingSize;
     }
 
-    public void setFilterSingleDisplay(boolean filterSingleDisplay) {
-        this.filterSingleDisplay = filterSingleDisplay;
-    }
-
     private DatagramSocket createSocket() {
 
         try {
@@ -969,8 +937,6 @@
         this.y = connectionPresenter.getY();
         this.frameSizeWidth = connectionPresenter.getFrameSizeWidth();
         this.frameSizeHeight = connectionPresenter.getFrameSizeHeight();
-        this.singleWidth = frameSizeWidth;
-        this.singleHeight = frameSizeHeight;
         this.retinaScale = connectionPresenter.getRetinaScale();
         if (previousContext != null && isTreeManager() && hasParent()) {
             Reader previousReader = previousContext.getReader();
--- a/src/main/java/jp/ac/u_ryukyu/treevnc/TreeVncCommandChannelListener.java	Fri Jun 17 17:06:22 2016 +0900
+++ b/src/main/java/jp/ac/u_ryukyu/treevnc/TreeVncCommandChannelListener.java	Sat Jun 18 20:09:46 2016 +0900
@@ -1,4 +1,14 @@
 package jp.ac.u_ryukyu.treevnc;
+import com.glavsoft.exceptions.TransportException;
+import com.glavsoft.rfb.protocol.ProtocolContext;
+import com.glavsoft.rfb.protocol.ProtocolContext.TreeCommand;
+import com.glavsoft.rfb.protocol.state.HandshakeState;
+import com.glavsoft.transport.Reader;
+import com.glavsoft.transport.Writer;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
 import java.net.InetAddress;
 import java.net.NetworkInterface;
@@ -7,16 +17,6 @@
 import java.nio.ByteOrder;
 import java.util.concurrent.LinkedBlockingQueue;
 import java.util.concurrent.TimeUnit;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-
-import com.glavsoft.exceptions.TransportException;
-import com.glavsoft.rfb.protocol.ProtocolContext;
-import com.glavsoft.rfb.protocol.ProtocolContext.TreeCommand;
-import com.glavsoft.rfb.protocol.state.HandshakeState;
-import com.glavsoft.transport.Reader;
-import com.glavsoft.transport.Writer;
 
 
 public class TreeVncCommandChannelListener implements Runnable {
@@ -228,15 +228,7 @@
     void sendInitData(Writer os) throws TransportException {
         ProtocolContext context = rfb.context;
         if (context != null) {
-            if (rfb.filterSingleDisplay) {
-                int width = rfb.getSingleWidth();
-                int height = rfb.getSingleHeight();
-                byte[] initData = createOriginalInitData(width, height, context.getRemoteDesktopName());
-//                os.write(initData);
-                os.write(context.getInitData());
-            } else {
-                os.write(context.getInitData());
-            }
+            os.write(context.getInitData());
         } else {
             // In case of "-d" we have no context
             // Send dummy data
--- a/src/viewer_swing/java/com/glavsoft/viewer/CuiViewer.java	Fri Jun 17 17:06:22 2016 +0900
+++ b/src/viewer_swing/java/com/glavsoft/viewer/CuiViewer.java	Sat Jun 18 20:09:46 2016 +0900
@@ -7,21 +7,23 @@
 import com.glavsoft.viewer.swing.ConnectionParams;
 import com.glavsoft.viewer.swing.ParametersHandler;
 import com.glavsoft.viewer.swing.SwingConnectionWorkerFactory;
+import jp.ac.u_ryukyu.treevnc.CreateConnectionParam;
+import jp.ac.u_ryukyu.treevnc.TreeRFBProto;
 
 import javax.swing.*;
-
 import java.awt.*;
 import java.awt.event.WindowEvent;
 import java.awt.event.WindowListener;
 import java.io.IOException;
 import java.io.InputStream;
 import java.net.Socket;
+import java.util.ArrayList;
 import java.util.jar.Attributes;
 import java.util.jar.Manifest;
-import java.util.logging.*;
-
-import jp.ac.u_ryukyu.treevnc.CreateConnectionParam;
-import jp.ac.u_ryukyu.treevnc.TreeRFBProto;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 public class CuiViewer implements Runnable, WindowListener, ViewerInterface {
 
@@ -302,8 +304,11 @@
     }
 
     @Override
+    public Point getScreenOffset(ArrayList<Rectangle> rectangles) {
+        return null;
+    }
+
+    @Override
     public void setFitScreen() {
-        // TODO Auto-generated method stub
-        
     }
 }
--- a/src/viewer_swing/java/com/glavsoft/viewer/TreeViewer.java	Fri Jun 17 17:06:22 2016 +0900
+++ b/src/viewer_swing/java/com/glavsoft/viewer/TreeViewer.java	Sat Jun 18 20:09:46 2016 +0900
@@ -129,10 +129,6 @@
                 fixingSizeWidth = Integer.parseInt(args[++i]);
                 fixingSizeHeight = Integer.parseInt(args[++i]);
                 fixingSizeDisplay = true;
-            } else if ("--filterSingleDisplay".equals(args[i])) {
-                // retina display too large for TreeVNC.
-                // restrict display size.
-                filterSingleDisplay = true;
             } else if ("--width".equals(args[i])) {
                 width = Integer.parseInt(args[i+1]);
                 i++;
@@ -189,7 +185,6 @@
                         + "--showTree:              Show connected tree node.\n"
                         + "--checkDelay:            Check speed flow of data each node.\n"
                         + "--logFile logFileName:   Set log file name.\n"
-                        + "--filterSingleDisplay:   Share single display (case of use multi display).\n"
                         + "--fixingSize w h:        Fix share screen size.\n"
                         + "--addSerialNum:          Check lost data.\n");
                 System.exit(0);
--- a/src/viewer_swing/java/com/glavsoft/viewer/Viewer.java	Fri Jun 17 17:06:22 2016 +0900
+++ b/src/viewer_swing/java/com/glavsoft/viewer/Viewer.java	Sat Jun 18 20:09:46 2016 +0900
@@ -28,10 +28,13 @@
 import com.glavsoft.transport.Reader;
 import com.glavsoft.transport.Writer;
 import com.glavsoft.viewer.cli.Parser;
-import com.glavsoft.viewer.swing.*;
+import com.glavsoft.viewer.swing.ConnectionParams;
+import com.glavsoft.viewer.swing.ParametersHandler;
+import com.glavsoft.viewer.swing.SwingViewerWindow;
+import jp.ac.u_ryukyu.treevnc.CreateConnectionParam;
+import jp.ac.u_ryukyu.treevnc.TreeRFBProto;
 
 import javax.swing.*;
-
 import java.awt.*;
 import java.awt.event.WindowEvent;
 import java.awt.event.WindowListener;
@@ -41,10 +44,10 @@
 import java.util.ArrayList;
 import java.util.jar.Attributes;
 import java.util.jar.Manifest;
-import java.util.logging.*;
-
-import jp.ac.u_ryukyu.treevnc.CreateConnectionParam;
-import jp.ac.u_ryukyu.treevnc.TreeRFBProto;
+import java.util.logging.ConsoleHandler;
+import java.util.logging.Handler;
+import java.util.logging.Level;
+import java.util.logging.Logger;
 
 @SuppressWarnings("serial")
 public class Viewer extends JApplet implements Runnable, WindowListener , ViewerInterface {
@@ -417,7 +420,6 @@
             myRfb.fixingSizeWidth = fixingSizeWidth;
             myRfb.fixingSizeHeight = fixingSizeHeight;
         }
-        myRfb.setFilterSingleDisplay(filterSingleDisplay);
         myRfb.setCuiVersion(false);
         myRfb.setHasViewer(true); // this flag will be overwrited after this method. Do we have to set here?
         if (myRfb.getAcceptThread() == null) {
@@ -498,12 +500,25 @@
 
         for (GraphicsDevice gd : gs) {
             for (GraphicsConfiguration r : gd.getConfigurations()) {
-                rectangles.add(r.getBounds());
+                Rectangle rect = r.getBounds();
+                rectangles.add(rect);
             }
         }
         return rectangles;
     }
 
+    public Point getScreenOffset(ArrayList<Rectangle> rectangles) {
+        // position of screen may negavie, but RFBscreen position is always positive
+        // compute offset to make them positive
+        int offsetx = 0;
+        int offsety = 0;
+        for (Rectangle rect : rectangles) {
+            if (rect.x < offsetx) offsetx = rect.x;
+            if (rect.y < offsety) offsety = rect.y;
+        }
+        return new Point(-offsetx,-offsety);
+    }
+
 
     @Override
     public void setFitScreen() {
--- a/src/viewer_swing/java/com/glavsoft/viewer/ViewerInterface.java	Fri Jun 17 17:06:22 2016 +0900
+++ b/src/viewer_swing/java/com/glavsoft/viewer/ViewerInterface.java	Sat Jun 18 20:09:46 2016 +0900
@@ -1,14 +1,14 @@
 package com.glavsoft.viewer;
 
+import com.glavsoft.transport.Reader;
+import com.glavsoft.transport.Writer;
+import jp.ac.u_ryukyu.treevnc.TreeRFBProto;
+
 import java.awt.*;
 import java.io.IOException;
 import java.net.Socket;
 import java.util.ArrayList;
 
-import com.glavsoft.transport.Reader;
-import com.glavsoft.transport.Writer;
-import jp.ac.u_ryukyu.treevnc.TreeRFBProto;
-
 public interface ViewerInterface extends Runnable {
 
     public boolean getCuiVersion();
@@ -23,7 +23,7 @@
 
 	public void setTerminationType(boolean b);
 
-	public void setCuiVersion(boolean flag);
+    void setCuiVersion(boolean flag);
 
     public void startTreeViewer(String hostName, boolean b, boolean addSerialNum);
 
@@ -51,9 +51,13 @@
 
     public ArrayList<Rectangle> getScreenRectangles();
 
+    public Point getScreenOffset(ArrayList<Rectangle> rectangles);
+
     public ConnectionPresenter getConnectionPresenter();
 
     public void setConnectionPresenter(ConnectionPresenter connectionPresenter);
 
     void changeToDirectConnectedServer(String hostName, Reader is, Writer os, int x, int y, int width, int height, int scale);
+
+
 }
--- a/src/viewer_swing/java/com/glavsoft/viewer/swing/SwingViewerWindow.java	Fri Jun 17 17:06:22 2016 +0900
+++ b/src/viewer_swing/java/com/glavsoft/viewer/swing/SwingViewerWindow.java	Sat Jun 18 20:09:46 2016 +0900
@@ -917,19 +917,19 @@
 
     public void screenChangeRequest(ProtocolContext context, int shareScreenNumber) {
         ArrayList<Rectangle> rectangles =  viewer.getScreenRectangles();
+        Point offset = viewer.getScreenOffset(rectangles);
         Rectangle rectangle1 = rectangles.get(shareScreenNumber);
         int singleWidth = (int) (rectangle1.getWidth());
         int singleHeight = (int) (rectangle1.getHeight());
-        int x = (int) (rectangle1.getX()); // convert double to int
-        int y = (int) (rectangle1.getY());
+        int x = (int) (rectangle1.getX())+offset.x; // convert double to int
+        int y = (int) (rectangle1.getY())+offset.y;
         int scale = retinaScale(shareScreenNumber);
         viewer.getRfb().setSingleDisplaySize(singleWidth, singleHeight);
+        showScreenInfo("request screen change",0, x,y,singleWidth,singleHeight,scale);
 
         if (viewer.getRfb().isTreeManager()) {
             changeVncServer(viewer, x, y, singleWidth, singleHeight, scale, viewer.getRfb().getId());
-            // treeeManager may have its parent
-        }
-        if (viewer.getRfb().hasParent()) {
+        } else if (viewer.getRfb().hasParent()) {
             String adr = viewer.getRfb().getMyAddress();
                 if (scanPort(adr, ConnectionParams.DEFAULT_RFB_PORT)) {
                     // -1 means request to reverse direct connection socket
@@ -995,14 +995,14 @@
         final int thatScreenX = presenter.getX();
         final int thatScreenY = presenter.getY();
         // int thatRetinaScale = presenter.getRetinaScale();
-        final int thatScreenWidth = presenter.getFrameSizeWidth();
-        final int thatScreenHeight = presenter.getFrameSizeHeight();
-        // showScreenInfo("that", 0, thatScreenX, thatScreenY, thatScreenWidth, thatScreenHeight, thatRetinaScale);
+        final int thatScreenWidth = viewer.getRfb().getSingleWidth();
+        final int thatScreenHeight = viewer.getRfb().getSingleHeight();
+        showScreenInfo("that", 0, thatScreenX, thatScreenY, thatScreenWidth, thatScreenHeight, 1);
 
         frame.setSize(thisScreenWidth, thisScreenHeight);
         final double scale = uiSettings.fitScreen(thisScreenWidth, thisScreenHeight, thatScreenWidth, thatScreenHeight);
         // final Rectangle visible = new Rectangle(thatScreenX,thatScreenY,thatScreenWidth,thatScreenHeight);
-        // showScreenInfo("this", thisScreenNumber, 0, 0,thisScreenWidth, thisScreenHeight, thisRetinaScale);
+        showScreenInfo("this", thisScreenNumber, 0, 0,thisScreenWidth, thisScreenHeight, 1);
         System.out.println("thisScrollScale: " + scale);
         SwingUtilities.invokeLater(new Runnable() {
             public void run() {