From d49ca935d6380ddb992a8b678cbb6ad130fbd437 Mon Sep 17 00:00:00 2001
From: syeshchenko <stanislav.yeshchenko@gmail.com>
Date: Wed, 17 Sep 2014 13:08:14 -0400
Subject: [PATCH] added resize and move cursors to make moving and resizing
 more accessible for users

---
 .../client/frame/CaptureRegionFrame.java      | 133 ++++--
 .../client/frame/WindowlessFrame.java         | 412 ++++++++++++------
 .../src/main/resources/images/move-cursor.png | Bin 0 -> 17249 bytes
 .../main/resources/images/resize-cursor.png   | Bin 0 -> 102 bytes
 4 files changed, 387 insertions(+), 158 deletions(-)
 create mode 100755 deskshare/applet/src/main/resources/images/move-cursor.png
 create mode 100755 deskshare/applet/src/main/resources/images/resize-cursor.png

diff --git a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/frame/CaptureRegionFrame.java b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/frame/CaptureRegionFrame.java
index 398278c13b..53313b6eea 100755
--- a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/frame/CaptureRegionFrame.java
+++ b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/frame/CaptureRegionFrame.java
@@ -1,29 +1,39 @@
 /**
-* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
-* 
-* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
-*
-* This program is free software; you can redistribute it and/or modify it under the
-* terms of the GNU Lesser General Public License as published by the Free Software
-* Foundation; either version 3.0 of the License, or (at your option) any later
-* version.
-* 
-* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
-* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public License along
-* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
-*
-*/
+ * BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+ * 
+ * Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+ *
+ * This program is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation; either version 3.0 of the License, or (at your option) any later
+ * version.
+ * 
+ * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
 package org.bigbluebutton.deskshare.client.frame;
 
 import java.awt.Button;
 import java.awt.Color;
+import java.awt.Dimension;
 import java.awt.FlowLayout;
+import java.awt.Graphics;
+import java.awt.GridBagLayout;
 import java.awt.Rectangle;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+
+import javax.imageio.ImageIO;
+import javax.swing.BorderFactory;
+import javax.swing.ImageIcon;
+import javax.swing.JLabel;
 import javax.swing.JPanel;
 
 public class CaptureRegionFrame {
@@ -31,38 +41,89 @@ public class CaptureRegionFrame {
 	private CaptureRegionListener client;
 	private boolean capturing = false;
 	private WindowlessFrame frame;
-	
+	private static final int RESIZE_BAR_SIZE = 40;
+	private static final int MOVE_BAR_SIZE = 60;
+
 	public CaptureRegionFrame(CaptureRegionListener client, int borderWidth) {
 		frame = new WindowlessFrame(borderWidth);
 		this.client = client;
 		frame.setCaptureRegionListener(client);
-				
 	}
-	
+
 	public void setHeight(int h) {
 		frame.setHeight(h);
 	}
-	
+
 	public void setWidth(int w) {
 		frame.setWidth(w);
 	}
-	
+
 	public void setLocation(int x, int y) {
 		frame.setLocation(x, y);
 	}
-	
+
 	public void setVisible(boolean visible) {
 		frame.setVisible(visible);	
 	}
-	
+
 	public void start(boolean autoStart) {
 		frame.setToolbar(createToolbar());
+		frame.setResizeBar(createResizeBar());
+		frame.setMoveBar(createMoveBar());
 		setVisible(true);
 		if (autoStart) {
 			startCapture();	
 		} 
 	}
-	
+
+	private JPanel createResizeBar(){
+		final JPanel resizePanel = new JPanel();
+		resizePanel.setPreferredSize(new Dimension(RESIZE_BAR_SIZE,RESIZE_BAR_SIZE));
+		resizePanel.setBorder(BorderFactory.createLineBorder(Color.RED));
+		resizePanel.setLayout(new GridBagLayout());
+		BufferedImage resizeCursorImage = null;
+
+		try {
+			// Image was taken from http://4.bp.blogspot.com/_fhb-4UuRH50/R1ZLryoIvJI/AAAAAAAAA6U/G3S-XYabULk/s1600/se-resize.gif
+			resizeCursorImage = ImageIO.read(getClass().getResourceAsStream("/images/resize-cursor.png"));
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+
+		JLabel resizePicLabel = new JLabel(new ImageIcon(resizeCursorImage));
+		resizePanel.add(resizePicLabel);
+		return resizePanel;
+	}
+
+	private JPanel createMoveBar() {
+		final CirclePanel movePanel = new CirclePanel();
+		movePanel.setPreferredSize(new Dimension(MOVE_BAR_SIZE,MOVE_BAR_SIZE));
+		movePanel.setLayout(new GridBagLayout());
+		movePanel.setOpaque(false);
+		BufferedImage moveCursorImage = null;
+
+		try {
+			// Image was taken from http://www.iconarchive.com/show/oxygen-icons-by-oxygen-icons.org/Actions-transform-move-icon.html
+			moveCursorImage = ImageIO.read(getClass().getResourceAsStream("/images/move-cursor.png"));
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+
+		JLabel movePicLabel = new JLabel(new ImageIcon(moveCursorImage));
+		movePanel.add(movePicLabel);
+		return movePanel;
+	}
+
+	// Wrap move panel in a circle
+	public class CirclePanel extends JPanel {
+		static final long serialVersionUID = 1L;
+
+		@Override
+		protected void paintComponent(Graphics g) {
+			g.drawOval(0, 0, g.getClipBounds().width, g.getClipBounds().height);
+		}
+	}
+
 	private JPanel createToolbar() {
 		final JPanel panel = new JPanel();
 		panel.setBackground(Color.RED); 
@@ -72,28 +133,28 @@ public class CaptureRegionFrame {
 		btnStartStop.addActionListener(new ActionListener() {
 			@Override
 			public void actionPerformed(ActionEvent e) {
-//				if (capturing) {
-//					capturing = false;
-//					btnStartStop.setLabel("Start Capture");
-//					stopCapture();
-//				} else {
-//					capturing = true;
-//					btnStartStop.setLabel("Stop Capture");
-					startCapture();
-//				}					
+				//				if (capturing) {
+				//					capturing = false;
+				//					btnStartStop.setLabel("Start Capture");
+				//					stopCapture();
+				//				} else {
+				//					capturing = true;
+				//					btnStartStop.setLabel("Stop Capture");
+				startCapture();
+				//				}
 			}
 		});
 		panel.add(btnStartStop);
 		return panel;
 	}
-	
+
 	private void startCapture() {
 		frame.changeBorderToBlue();
 		frame.removeResizeListeners();
 		Rectangle rect = frame.getFramedRectangle();
 		client.onStartCapture(rect.x, rect.y, frame.getWidth(), frame.getHeight());
 	}
-	
+
 	private void stopCapture() {		
 		frame.changeBorderToRed();
 		client.onStopCapture();
diff --git a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/frame/WindowlessFrame.java b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/frame/WindowlessFrame.java
index f16c3f6465..548b5804f0 100755
--- a/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/frame/WindowlessFrame.java
+++ b/deskshare/applet/src/main/java/org/bigbluebutton/deskshare/client/frame/WindowlessFrame.java
@@ -1,21 +1,21 @@
 /**
-* BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
-* 
-* Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
-*
-* This program is free software; you can redistribute it and/or modify it under the
-* terms of the GNU Lesser General Public License as published by the Free Software
-* Foundation; either version 3.0 of the License, or (at your option) any later
-* version.
-* 
-* BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
-* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
-* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
-*
-* You should have received a copy of the GNU Lesser General Public License along
-* with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
-*
-*/
+ * BigBlueButton open source conferencing system - http://www.bigbluebutton.org/
+ * 
+ * Copyright (c) 2012 BigBlueButton Inc. and by respective authors (see below).
+ *
+ * This program is free software; you can redistribute it and/or modify it under the
+ * terms of the GNU Lesser General Public License as published by the Free Software
+ * Foundation; either version 3.0 of the License, or (at your option) any later
+ * version.
+ * 
+ * BigBlueButton is distributed in the hope that it will be useful, but WITHOUT ANY
+ * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+ * PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along
+ * with BigBlueButton; if not, see <http://www.gnu.org/licenses/>.
+ *
+ */
 package org.bigbluebutton.deskshare.client.frame;
 
 import java.awt.BasicStroke;
@@ -49,15 +49,15 @@ class WindowlessFrame implements Serializable {
 	private CaptureRegionListener captureRegionListener;
 	private MouseAdapter resizingAdapter;
 	private MouseAdapter movingAdapter;
-	
+
 	private static interface PropertyChanger {
 		void changeOn(Component component);
 	}
-	
+
 	private static interface LocationAndSizeUpdateable {
 		void updateLocationAndSize();
 	}
-	
+
 	private static interface OffsetLocator {
 		int getLeftOffset();
 		int getTopOffset();
@@ -92,7 +92,7 @@ class WindowlessFrame implements Serializable {
 			component.repaint();
 		}
 	};
-	
+
 
 	// properties that change during use
 	private Point mTopLeft = new Point();
@@ -101,11 +101,11 @@ class WindowlessFrame implements Serializable {
 	// properties initialized during construction
 	private BasicStroke mBorderStroke = new BasicStroke(5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 0, new float[] { 12, 12 }, 0);
 	private final BasicStroke borderSolidStroke = new BasicStroke(5, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND, 0);
-	
+
 	private GradientPaint mGradient = new GradientPaint(0.0f, 0.0f, Color.red, 1.0f, 1.0f, Color.white, true);
 	private final GradientPaint blueGradient = new GradientPaint(0.0f, 0.0f, Color.blue, 1.0f, 1.0f, Color.blue, true);
 	private final GradientPaint redGradient = new GradientPaint(0.0f, 0.0f, Color.red, 1.0f, 1.0f, Color.white, true);
-	
+
 	private final int mBorderWidth;
 	private final JFrame mWindowFrame;
 	private final BarFrame mTopBorder;
@@ -113,15 +113,19 @@ class WindowlessFrame implements Serializable {
 	private final BarFrame mBottomBorder;
 	private final BarFrame mLeftBorder;
 	private ToolbarFrame mToolbarFrame;
+	private ResizeBarFrame mResizeBarFrame;
+	private MoveBarFrame mMoveBarFrame;
 	
+	private static final int MIN_WINDOW_SIZE = 200;
+
 	private MultiScreen mScreen = new MultiScreen();
-	
+
 	/*****************************************************************************
     ;  Class MultiScreen
     ;----------------------------------------------------------------------------
 	; DESCRIPTION
 	;   This class is used to detect if the system has more than one screen.
-	******************************************************************************/
+	 ******************************************************************************/
 	private class MultiScreen {
 		private int                 minX=0 ;              //minimum of x position
 		private int                 totalWidth=0 ;        // total screen resolution
@@ -129,7 +133,7 @@ class WindowlessFrame implements Serializable {
 		private GraphicsEnvironment ge ;
 		private GraphicsDevice[]    screenDevice ;
 		private boolean             ismultiscreen=false ;
-		
+
 		/*****************************************************************************
 	    ;  MultiScreen
 	    ;----------------------------------------------------------------------------
@@ -150,41 +154,41 @@ class WindowlessFrame implements Serializable {
 		; __date__ :        PTS:  
 		; 2010.11.16		problem 644 and 647
 		;
-		******************************************************************************/
+		 ******************************************************************************/
 		private MultiScreen(){
 			int i ;
-			
+
 			ge = GraphicsEnvironment.getLocalGraphicsEnvironment() ;
 			screenDevice = ge.getScreenDevices() ;
-			
+
 			if ( 1 < screenDevice.length ){
 				// this is the case for multiple devices.
 				// set the flag to indicate multiple devices on the system.
 				ismultiscreen=true ;
 				for ( i=0; i<screenDevice.length; i++){
 					GraphicsConfiguration[] gc = screenDevice[i].getConfigurations() ;
-					
+
 					// determine the minimum x position for the main screen
 					if ( gc[0].getBounds().x <= minX ){
 						minX = gc[0].getBounds().x;
 					}
-					
+
 					// determine the total screen size
 					if ( gc[0].getBounds().x >= 0){
 						totalWidth = totalWidth + gc[0].getBounds().width;
 					}	
-					
+
 				}
 			}else{
 				// this is the case for one screen only.
 				ismultiscreen = false ;
 			}
-			
+
 			// set the main screen width
 			curWidth = screenDevice[0].getConfigurations()[0].getBounds().width ;
-			
+
 		} // END FUNCTION MultiScreen
-		
+
 		/*****************************************************************************
 	    ;  isMultiScreen
 	    ;----------------------------------------------------------------------------
@@ -204,19 +208,19 @@ class WindowlessFrame implements Serializable {
 		; __date__ :        PTS:  
 		; 2010.11.16		problem 644 and 647
 		;
-		******************************************************************************/
+		 ******************************************************************************/
 		public boolean isMultiScreen(){
-			
+
 			return ismultiscreen ;
 		} // END FUNCTION isMultiScreen 
-		
+
 	} // END CLASS MultiScreen 
-	
+
 	private class ToolbarFrame extends Window implements LocationAndSizeUpdateable {
 		private static final long serialVersionUID = 1L;
 
 		private final OffsetLocator mOffsetLocator;
-		
+
 		public ToolbarFrame(JFrame frame, OffsetLocator ol, JPanel content) {
 			super(frame);
 			super.setAlwaysOnTop(true);
@@ -230,18 +234,111 @@ class WindowlessFrame implements Serializable {
 		public void updateLocationAndSize() {
 			setLocation(getLocation());
 		}
-		
+
 		@Override
 		public Point getLocation() {
 			return new Point(mTopLeft.x + mOffsetLocator.getLeftOffset(), mTopLeft.y + mOffsetLocator.getTopOffset());
 		}
 	}
-	
-	private class WindowlessFrameMovingMouseListener extends MouseAdapter {
-		
+
+	private class MoveBarFrame extends Window implements LocationAndSizeUpdateable {
+		private static final long serialVersionUID = 1L;
+
+		private final OffsetLocator mOffsetLocator;
+		private MouseAdapter moveMouseAdapter = null;
+
+		public MoveBarFrame(JFrame frame, OffsetLocator ol, JPanel content) {
+			super(frame);
+			super.setAlwaysOnTop(true);
+			frame.setAlwaysOnTop(true);
+			setBackground(new Color(0, 255, 0, 0));
+			mOffsetLocator = ol;
+			add(content);
+			pack();
+
+			moveMouseAdapter = createMoveBarMovingMouseListener();
+
+			changeMovingBarFrame(new PropertyChanger() {
+				@Override
+				public void changeOn(Component component) {
+					component.addMouseListener(moveMouseAdapter);
+					component.addMouseMotionListener(moveMouseAdapter);
+				}
+			});
+		}
+
+		private void changeMovingBarFrame(PropertyChanger pc) {
+			pc.changeOn(this);
+		}
+
+		private MouseAdapter createMoveBarMovingMouseListener() {
+			return new FrameMovingMouseListener(false);
+		}
+
+		@Override
+		public void updateLocationAndSize() {
+			setLocation(getLocation());
+		}
+
+		@Override
+		public Point getLocation() {
+			return new Point(mTopLeft.x + mOffsetLocator.getLeftOffset(), mTopLeft.y + mOffsetLocator.getTopOffset());
+		}
+	}
+
+	private class ResizeBarFrame extends Window implements LocationAndSizeUpdateable {
+
+		private static final long serialVersionUID = 1L;
+		private final OffsetLocator mOffsetLocator;
+		private MouseAdapter resizeMouseAdapter = null;
+
+		public ResizeBarFrame(JFrame frame, OffsetLocator ol, JPanel content) {
+			super(frame);
+			super.setAlwaysOnTop(true);
+			frame.setAlwaysOnTop(true);
+			setBackground(new Color(0, 255, 0, 0));
+			mOffsetLocator = ol;
+			add(content);
+			pack();
+
+			resizeMouseAdapter = createResizeBarResizingMouseListener();
+
+			changeResizeBarFrame(new PropertyChanger() {
+				@Override
+				public void changeOn(Component component) {
+					component.addMouseListener(resizeMouseAdapter);
+					component.addMouseMotionListener(resizeMouseAdapter);
+				}
+			});
+		}
+
+		private MouseAdapter createResizeBarResizingMouseListener() {
+			return new FrameResizingMouseListener(false);
+		}
+
+		public void updateLocationAndSize() {
+			setLocation(getLocation());
+		}
+
+		@Override
+		public Point getLocation() {
+			return new Point(mTopLeft.x + mOffsetLocator.getLeftOffset(), mTopLeft.y + mOffsetLocator.getTopOffset());
+		}
+
+		private void changeResizeBarFrame(PropertyChanger pc) {
+			pc.changeOn(this);
+		}
+	}
+
+	private class FrameMovingMouseListener extends MouseAdapter {
+
 		private AtomicBoolean mMoving = new AtomicBoolean(false);
-		
 		private Point mActionOffset = null;
+		private Boolean isBorder = false;
+
+		public FrameMovingMouseListener(Boolean isBorder) {
+			this.isBorder = isBorder;
+		}
 
 		@Override
 		public void mouseDragged(MouseEvent e) {
@@ -249,7 +346,7 @@ class WindowlessFrame implements Serializable {
 			int changeInY = e.getLocationOnScreen().y - mActionOffset.y - mTopLeft.y;
 			Toolkit tk 	= Toolkit.getDefaultToolkit();
 			Dimension d = tk.getScreenSize();
-			
+
 			// check if multiscreen
 			if ( false == mScreen.isMultiScreen() ){
 				// case one screen only
@@ -264,7 +361,7 @@ class WindowlessFrame implements Serializable {
 				if (mTopLeft.x + mOverallSize.width > (d.width-6) && changeInX > 0) {
 					mTopLeft.x = d.width - mOverallSize.width-5;
 					changeInX = 0;
-					
+
 				}
 				if (mTopLeft.y + mOverallSize.height > (d.height-6) && changeInY > 0) {
 					mTopLeft.y = d.height - mOverallSize.height-5;
@@ -280,7 +377,7 @@ class WindowlessFrame implements Serializable {
 					mTopLeft.y = 0;
 					changeInY = 0;
 				}
-			
+
 				if (mTopLeft.x + mOverallSize.width > (mScreen.totalWidth-6) && changeInX > 0) {
 					mTopLeft.x = mScreen.totalWidth - mOverallSize.width-5;
 					changeInX = 0;
@@ -294,7 +391,7 @@ class WindowlessFrame implements Serializable {
 				WindowlessFrame.this.setLocation(changeInX + mTopLeft.x, changeInY + mTopLeft.y);
 			}
 		}
-		
+
 		@Override
 		public void mousePressed(MouseEvent e) {
 			final Point mouse = e.getLocationOnScreen();
@@ -302,39 +399,51 @@ class WindowlessFrame implements Serializable {
 			mMoving.set(true);
 			e.getComponent().setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
 		}
-		
+
 		@Override
 		public void mouseReleased(MouseEvent e) {
 			mMoving.set(false);
 			mActionOffset = null;
 			e.getComponent().setCursor(Cursor.getDefaultCursor());
 		}
-
-	}
-	
-	private class WindowlessFrameResizingMouseListener extends MouseAdapter {
 		
+		@Override
+		public void mouseMoved(MouseEvent e) {
+			if (!isBorder) {
+				e.getComponent().setCursor(Cursor.getPredefinedCursor(Cursor.MOVE_CURSOR));
+			}
+		}
+	}
+
+	private class FrameResizingMouseListener extends MouseAdapter {
+
 		private static final int CORNER_SIZE = 150;
 
 		private AtomicBoolean mResizing = new AtomicBoolean(false);
-		
+
 		private Point mActionOffset = null;
 		private Dimension mOriginalSize = null;
 		private Corner mCorner;
+		private Boolean isBorder = false;
+
+		public FrameResizingMouseListener(Boolean isBorder) {
+			this.isBorder = isBorder;
+		}
 
 		@Override
 		public void mouseDragged(MouseEvent e) {
-		    int changeInX = e.getLocationOnScreen().x - mActionOffset.x - mTopLeft.x;
+			int changeInX = e.getLocationOnScreen().x - mActionOffset.x - mTopLeft.x;
 			final int changeInY = e.getLocationOnScreen().y - mActionOffset.y - mTopLeft.y;
-			
+
 			Toolkit tk = Toolkit.getDefaultToolkit();
 			Dimension d = tk.getScreenSize();
 
 			if (mResizing.get()) {
 				int newH = mOriginalSize.height;
 				int newW = mOriginalSize.width;
-				if (Corner.SOUTHEAST == mCorner) {
-
+				if (isBorder && Corner.SOUTHEAST != mCorner) {
+					// doing nothing
+				} else {
 					if (e.getLocationOnScreen().x < mTopLeft.x+5) {
 						newW = 5;
 					} else {
@@ -345,7 +454,8 @@ class WindowlessFrame implements Serializable {
 					} else {
 						newH += changeInY;
 					}
-				} /*else if (mCorner == Corner.NORTHEAST) {
+				}
+				/*else if (mCorner == Corner.NORTHEAST) {
 					mTopLeft.y = mTopLeft.y + changeInY;
 					newH = mOverallSize.height + -changeInY;
 					newW += changeInX;
@@ -381,26 +491,40 @@ class WindowlessFrame implements Serializable {
 					if (newW + mTopLeft.x > mWidth-5 && mTopLeft.x >= 0){
 						newW = mWidth - mTopLeft.x-5;
 					}else if (mTopLeft.x<0 && mTopLeft.x + newW > -5){
-						 newW = - mTopLeft.x-5;
+						newW = - mTopLeft.x-5;
 					}
 				}
-				
+
+				// set minimum window size
+				if (newH < MIN_WINDOW_SIZE) {
+					newH = MIN_WINDOW_SIZE;
+				}
+				if (newW < MIN_WINDOW_SIZE) {
+					newW =  MIN_WINDOW_SIZE;
+				}
+
 				WindowlessFrame.this.setSize(newH, newW);
 				e.consume();
 			}
 		}
-		
+
 		@Override
 		public void mousePressed(MouseEvent e) {
 			final Point mouse = e.getLocationOnScreen();
 			mActionOffset = new Point(mouse.x - mTopLeft.x, mouse.y - mTopLeft.y);
 			mOriginalSize = new Dimension(mOverallSize);
-			mCorner = nearCorner(mouse);
-			if (mCorner != null) {
+
+			if (isBorder) {
+				mCorner = nearCorner(mouse);
+				if (mCorner != null ) {
+					mResizing.set(true);
+				}
+			}
+			else {
 				mResizing.set(true);
 			}
 		}
-		
+
 		@Override
 		public void mouseReleased(MouseEvent e) {
 			mResizing.set(false);
@@ -419,14 +543,14 @@ class WindowlessFrame implements Serializable {
 			} else if (isNearBottomLeftCorner(mouse)) {
 				return Corner.SOUTHWEST;
 			}
-			*/
+			 */
 			return null;
 		}
 
 		private boolean isNearBottomRightCorner(Point mouse) {
 			int xToBotLeft = Math.abs(mTopLeft.x + (int) mOverallSize.getWidth() - mouse.x);
-			int yToBotLeft = Math.abs(mTopLeft.y + (int) mOverallSize.getHeight() - mouse.y);
-			return xToBotLeft < CORNER_SIZE && yToBotLeft < CORNER_SIZE;
+			int yToBotLeft = Math.abs(mTopLeft.y + (int) mOverallSize.getHeight() - mouse.y);;
+			return (xToBotLeft < CORNER_SIZE && yToBotLeft < CORNER_SIZE);
 		}
 
 		/* private boolean isNearTopRightCorner(Point mouse) {
@@ -446,12 +570,12 @@ class WindowlessFrame implements Serializable {
 			int yToTopLeft = Math.abs(mTopLeft.y - mouse.y);
 			return xToTopLeft < CORNER_SIZE && yToTopLeft < CORNER_SIZE;
 		}
-		*/
+		 */
 
 		@Override
 		public void mouseMoved(MouseEvent e) {
 			final Point mouse = e.getLocationOnScreen();
-			
+
 			/*
 			if (isNearTopLeftCorner(mouse)) {
 				e.getComponent().setCursor(Cursor.getPredefinedCursor(Cursor.NW_RESIZE_CURSOR));
@@ -460,20 +584,24 @@ class WindowlessFrame implements Serializable {
 			} else if (isNearTopRightCorner(mouse)) {
 				e.getComponent().setCursor(Cursor.getPredefinedCursor(Cursor.NE_RESIZE_CURSOR));
 			} else 
-			*/
-			if (isNearBottomRightCorner(mouse)) {
-				e.getComponent().setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
+			 */
+			if (isBorder) {
+				if (isNearBottomRightCorner(mouse)) {
+					e.getComponent().setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
+				} else {
+					e.getComponent().setCursor(Cursor.getDefaultCursor());
+				}
 			} else {
-				e.getComponent().setCursor(Cursor.getDefaultCursor());
+				e.getComponent().setCursor(Cursor.getPredefinedCursor(Cursor.SE_RESIZE_CURSOR));
 			}
 		}
 	}
-	
+
 	private class BarFrame extends Window implements LocationAndSizeUpdateable {
 		private static final long serialVersionUID = 1L;
 
 		private final OffsetLocator mOffsetLocator;
-		
+
 		public BarFrame(Frame frame, OffsetLocator offsetLocator) {
 			super(frame);
 			mOffsetLocator = offsetLocator;
@@ -500,85 +628,85 @@ class WindowlessFrame implements Serializable {
 			setSize(getWidth(), getHeight());
 			setLocation(getLocation());
 		}
-		
+
 		@Override
 		public Point getLocation() {
 			return new Point(mTopLeft.x + mOffsetLocator.getLeftOffset(), mTopLeft.y + mOffsetLocator.getTopOffset());
 		}
-		
+
 		@Override
 		public int getHeight() {
 			return mBorderWidth;
 		}
-		
+
 		@Override
 		public int getWidth() {
 			return mOverallSize.width;
 		}
 	}
-	
+
 	private class HorizontalBarFrame extends BarFrame {
 		private static final long serialVersionUID = 1L;
-		
+
 		public HorizontalBarFrame(JFrame frame, OffsetLocator offsetLocator) {
 			super(frame, offsetLocator);
 			super.setAlwaysOnTop(true);
 		}
 	}
-	
+
 	private class VerticalBarFrame extends BarFrame {
 		private static final long serialVersionUID = 1L;
-		
+
 		public VerticalBarFrame(JFrame frame, OffsetLocator offsetLocator) {
 			super(frame, offsetLocator);
 			super.setAlwaysOnTop(true);
 		}
-		
+
 		@Override
 		public int getWidth() {
 			return mBorderWidth;
 		}
-		
+
 		@Override
 		public int getHeight() {
 			return mOverallSize.height;
 		}
 	}
-	
+
 	public WindowlessFrame(int borderWidth) {
 		mBorderWidth = borderWidth;
 
 		mWindowFrame = new JFrame("Windowless Frame");
 		//mWindowFrame.setAlwaysOnTop(true);
-		
+
 		mTopBorder = new HorizontalBarFrame(mWindowFrame, new StaticOffsetLocator(0, 0));
 		mBottomBorder = new HorizontalBarFrame(mWindowFrame, new OffsetLocator() {
-			
+
 			@Override
 			public int getTopOffset() {
 				return mOverallSize.height;
 			}
-			
+
 			@Override
 			public int getLeftOffset() {
 				return 0;
 			}
 		});
-		
+
 		mRightBorder = new VerticalBarFrame(mWindowFrame, new OffsetLocator() {
-			
+
 			@Override
 			public int getTopOffset() {
 				return 0;
 			}
-			
+
 			@Override
 			public int getLeftOffset() {
 				return mOverallSize.width;
 			}
 		});
 		mLeftBorder = new VerticalBarFrame(mWindowFrame, new StaticOffsetLocator(0, 0));
-		
+
 		movingAdapter = createMovingMouseListener();
 		resizingAdapter = createResizingMouseListener();
 		changeBarFrames(new PropertyChanger() {
@@ -591,13 +719,13 @@ class WindowlessFrame implements Serializable {
 			}
 		}, false);	
 	}
-		
+
 	public final MouseAdapter createMovingMouseListener() {
-		return new WindowlessFrameMovingMouseListener();
+		return new FrameMovingMouseListener(true);
 	}
 
 	public final MouseAdapter createResizingMouseListener() {
-		return new WindowlessFrameResizingMouseListener();
+		return new FrameResizingMouseListener(true);
 	}
 
 	public void setToolbar(final JPanel toolbar) {
@@ -606,7 +734,7 @@ class WindowlessFrame implements Serializable {
 			public int getTopOffset() {
 				return (mOverallSize.height + mBorderWidth - toolbar.getHeight()) / 2;
 			}
-			
+
 			@Override
 			public int getLeftOffset() {
 				return (mOverallSize.width + mBorderWidth - toolbar.getWidth()) / 2;
@@ -615,6 +743,38 @@ class WindowlessFrame implements Serializable {
 		mToolbarFrame = new ToolbarFrame(mWindowFrame, toolbarOffsetLocator, toolbar);
 	}
 	
+	public void setResizeBar(final JPanel resizeBar) {
+
+		final OffsetLocator resizeBarOffsetLocator = new OffsetLocator() {
+			@Override
+			public int getTopOffset() {
+				return (mOverallSize.height + mBorderWidth - resizeBar.getHeight());
+			}
+
+			@Override
+			public int getLeftOffset() {
+				return (mOverallSize.width + mBorderWidth - resizeBar.getWidth());
+			}
+		};
+
+		mResizeBarFrame = new ResizeBarFrame(mWindowFrame, resizeBarOffsetLocator, resizeBar);
+	}
+
+	public void setMoveBar(final JPanel moveBar) {
+		final OffsetLocator moveBarOffsetLocator = new OffsetLocator() {
+			@Override
+			public int getTopOffset() {
+				return (mOverallSize.height + mBorderWidth - (moveBar.getHeight()/2) - moveBar.getHeight())/2 - 50;
+			}
+
+			@Override
+			public int getLeftOffset() {
+				return (mOverallSize.width + mBorderWidth - (moveBar.getWidth()))/2;
+			}
+		};
+		mMoveBarFrame = new MoveBarFrame(mWindowFrame, moveBarOffsetLocator, moveBar);
+	}
+
 	public final void setSize(int height, int width) {
 		setHeight(height);
 		setWidth(width);
@@ -624,50 +784,50 @@ class WindowlessFrame implements Serializable {
 	public final void setWidth(int width) {
 		mOverallSize.width = width;
 	}
-	
+
 	public final void setHeight(int height) {
 		mOverallSize.height = height;
 	}
-	
+
 	public final void setLocation(int x, int y) {
 		mTopLeft.x = x;
 		mTopLeft.y = y;
 		repaint();
-		
+
 		if (captureRegionListener != null) {
 			Rectangle rect  = getFramedRectangle();
 			captureRegionListener.onCaptureRegionMoved(rect.x, rect.y);
 		}
 	}
-	
+
 	public final int getX(){
 		return mTopLeft.x;
 	}
-	
+
 	public final int getY(){
 		return mTopLeft.y;
 	}
-	
+
 	public final int getWidth(){
 		return mOverallSize.width - mBorderWidth;
 	}
-	
+
 	public final int getHeight(){
 		return mOverallSize.height - mBorderWidth;
 	}
-	
+
 	public final void centerOnScreen() {
-        Toolkit kit = mLeftBorder.getToolkit();
-        GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
-        GraphicsDevice[] gs = ge.getScreenDevices();
-        Insets in = kit.getScreenInsets(gs[0].getDefaultConfiguration());
-        
-        Dimension d = kit.getScreenSize();
-        int maxWidth = (d.width - in.left - in.right);
-        int maxHeight = (d.height - in.top - in.bottom);
-        setLocation((int) (maxWidth - mOverallSize.width) / 2, (int) (maxHeight - mOverallSize.height) / 2);
+		Toolkit kit = mLeftBorder.getToolkit();
+		GraphicsEnvironment ge = GraphicsEnvironment.getLocalGraphicsEnvironment();
+		GraphicsDevice[] gs = ge.getScreenDevices();
+		Insets in = kit.getScreenInsets(gs[0].getDefaultConfiguration());
+
+		Dimension d = kit.getScreenSize();
+		int maxWidth = (d.width - in.left - in.right);
+		int maxHeight = (d.height - in.top - in.bottom);
+		setLocation((int) (maxWidth - mOverallSize.width) / 2, (int) (maxHeight - mOverallSize.height) / 2);
 	}
-	
+
 	public final Rectangle getFramedRectangle() {
 		return new Rectangle(mTopLeft.x + mBorderWidth, mTopLeft.y + mBorderWidth, mOverallSize.width - mBorderWidth, mOverallSize.height - mBorderWidth);
 	}
@@ -680,7 +840,7 @@ class WindowlessFrame implements Serializable {
 			}
 		}, true);
 	}
-	
+
 	private void changeBarFrames(PropertyChanger pc, boolean repaint) {
 		pc.changeOn(mTopBorder);
 		pc.changeOn(mRightBorder);
@@ -693,6 +853,8 @@ class WindowlessFrame implements Serializable {
 
 	private void changeAll(PropertyChanger pc, boolean repaint) {
 		if (mToolbarFrame != null) pc.changeOn(mToolbarFrame);
+		if (mResizeBarFrame != null) pc.changeOn(mResizeBarFrame);
+		if (mMoveBarFrame != null) pc.changeOn(mMoveBarFrame);
 		changeBarFrames(pc, repaint);
 	}
 
@@ -705,12 +867,12 @@ class WindowlessFrame implements Serializable {
 		mGradient = blueGradient;
 		repaint();
 	}
-	
+
 	public void changeBorderToRed() {
 		mGradient = redGradient;
 		repaint();
 	}
-	
+
 	public static void main(String[] args) {
 		final WindowlessFrame wf = new WindowlessFrame(5);
 		wf.setHeight(300);
@@ -718,11 +880,11 @@ class WindowlessFrame implements Serializable {
 		wf.setLocation(100, 200);
 		wf.setVisible(true);
 	}
-	
+
 	public void setCaptureRegionListener(CaptureRegionListener listener){
 		this.captureRegionListener = listener;
 	}
-	
+
 	public void removeResizeListeners() {
 		mRightBorder.removeMouseListener(resizingAdapter);
 		mRightBorder.removeMouseMotionListener(resizingAdapter);
@@ -732,10 +894,16 @@ class WindowlessFrame implements Serializable {
 		mTopBorder.removeMouseMotionListener(resizingAdapter);
 		mBottomBorder.removeMouseListener(resizingAdapter);
 		mBottomBorder.removeMouseMotionListener(resizingAdapter);
+		mResizeBarFrame.removeMouseListener(resizingAdapter);
+		mResizeBarFrame.removeMouseMotionListener(resizingAdapter);
+		mMoveBarFrame.removeMouseListener(movingAdapter);
+		mMoveBarFrame.removeMouseMotionListener(movingAdapter);
 		repaint();
-		
+
 		System.out.println("Removing listeners......................");
 		mToolbarFrame.setVisible(false);
+		mResizeBarFrame.setVisible(false);
+		mMoveBarFrame.setVisible(false);
 	}
 
 	public void addResizeListeners() {
diff --git a/deskshare/applet/src/main/resources/images/move-cursor.png b/deskshare/applet/src/main/resources/images/move-cursor.png
new file mode 100755
index 0000000000000000000000000000000000000000..4e64fc6e4ae7f6653495dd9bf22f5d09435343d0
GIT binary patch
literal 17249
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

literal 0
HcmV?d00001

diff --git a/deskshare/applet/src/main/resources/images/resize-cursor.png b/deskshare/applet/src/main/resources/images/resize-cursor.png
new file mode 100755
index 0000000000000000000000000000000000000000..50d5f933c6eaf6a6470a16935d5ece83e74182c2
GIT binary patch
literal 102
zcmZ?wbhEHb)L_tHXkcLY|NlP&1B2pE7Djd;tpmhBaSa9rCfk<&m8akGFP^jIR`=$6
zdw%n`J@S|q*sw@#0-N^geXDj~deePlhu-7%v(h`0Op{iI`uv=BX4z-XUa#d>UM*%|
Gum%7fUn*k&

literal 0
HcmV?d00001

-- 
GitLab