Revision: 5025
          http://tigervnc.svn.sourceforge.net/tigervnc/?rev=5025&view=rev
Author:   bphinz
Date:     2013-01-12 01:17:35 +0000 (Sat, 12 Jan 2013)
Log Message:
-----------
Fixes a number of issues related to cursor handling, including "invalid 
hotspot" exception caused when cursor hotspot is outside the maximum cursor 
size supported by the toolkit on the client.  Also, local cursor was not being 
drawn properly when the display size was scaled.

Modified Paths:
--------------
    trunk/java/com/tigervnc/vncviewer/DesktopWindow.java

Modified: trunk/java/com/tigervnc/vncviewer/DesktopWindow.java
===================================================================
--- trunk/java/com/tigervnc/vncviewer/DesktopWindow.java        2013-01-07 
22:24:01 UTC (rev 5024)
+++ trunk/java/com/tigervnc/vncviewer/DesktopWindow.java        2013-01-12 
01:17:35 UTC (rev 5025)
@@ -73,6 +73,14 @@
 
     cursor = new Cursor();
     cursorBacking = new ManagedPixelBuffer();
+    Dimension bestSize = tk.getBestCursorSize(16, 16);
+    BufferedImage cursorImage;
+    cursorImage = new BufferedImage(bestSize.width, bestSize.height, 
+                                    BufferedImage.TYPE_INT_ARGB);
+    java.awt.Point hotspot = new java.awt.Point(0,0);
+    nullCursor = tk.createCustomCursor(cursorImage, hotspot, "nullCursor");
+    if (!cc.cp.supportsLocalCursor && !bestSize.equals(new Dimension(0,0)))
+      setCursor(nullCursor);
     addMouseListener(this);
     addMouseWheelListener(this);
     addMouseMotionListener(this);
@@ -104,8 +112,8 @@
   // Methods called from the RFB thread - these need to be synchronized
   // wherever they access data shared with the GUI thread.
 
-  public void setCursor(int w, int h, Point hotspot,
-                                     int[] data, byte[] mask) {
+  public void setCursor(int w, int h, Point hotspot, 
+                        int[] data, byte[] mask) {
     // strictly we should use a mutex around this test since useLocalCursor
     // might be being altered by the GUI thread.  However it's only a single
     // boolean and it doesn't matter if we get the wrong value anyway.
@@ -117,15 +125,8 @@
 
     hideLocalCursor();
 
-    if (hotspot == null)
-      hotspot = new Point(0, 0);
-
     cursor.hotspot = hotspot;
-
-    Dimension bsc = tk.getBestCursorSize(w, h);
-
-    cursor.setSize(((int)bsc.getWidth() > w ? (int)bsc.getWidth() : w),
-                   ((int)bsc.getHeight() > h ? (int)bsc.getHeight() : h));
+    cursor.setSize(w, h);
     cursor.setPF(getPF());
 
     cursorBacking.setSize(cursor.width(), cursor.height());
@@ -150,18 +151,33 @@
         y * ((cursor.width() + 7) / 8), maskBytesPerRow);
     }
 
-    MemoryImageSource bitmap = 
-      new MemoryImageSource(cursor.width(), cursor.height(), 
ColorModel.getRGBdefault(),
-                            cursor.data, 0, cursor.width());
     int cw = (int)Math.floor((float)cursor.width() * scaleWidthRatio);
     int ch = (int)Math.floor((float)cursor.height() * scaleHeightRatio);
-    int hint = java.awt.Image.SCALE_DEFAULT;
-    hotspot = new Point((int)Math.floor((float)hotspot.x * scaleWidthRatio),
-                        (int)Math.floor((float)hotspot.y * scaleHeightRatio));
-    Image cursorImage = (cw <= 0 || ch <= 0) ? tk.createImage(bitmap) :
-      tk.createImage(bitmap).getScaledInstance(cw,ch,hint);
-    softCursor = tk.createCustomCursor(cursorImage,
-                  new java.awt.Point(hotspot.x,hotspot.y), "Cursor");
+    Dimension bestSize = tk.getBestCursorSize(cw, ch);
+    MemoryImageSource cursorSrc;
+    cursorSrc = new MemoryImageSource(cursor.width(), cursor.height(), 
+                                      ColorModel.getRGBdefault(),
+                                      cursor.data, 0, cursor.width());
+    Image srcImage = tk.createImage(cursorSrc);
+    BufferedImage cursorImage; 
+    cursorImage = new BufferedImage(bestSize.width, bestSize.height, 
+                                    BufferedImage.TYPE_INT_ARGB);
+    Graphics2D g2 = cursorImage.createGraphics();
+    g2.setRenderingHint(RenderingHints.KEY_RENDERING,
+                        RenderingHints.VALUE_RENDER_SPEED);
+    g2.drawImage(srcImage, 0, 0, (int)Math.min(cw, bestSize.width),
+                 (int)Math.min(ch, bestSize.height), 0, 0, cursor.width(),
+                 cursor.height(), this) ;
+    g2.dispose();
+    srcImage.flush();
+
+    int x = (int)Math.floor((float)hotspot.x * scaleWidthRatio);
+    int y = (int)Math.floor((float)hotspot.y * scaleHeightRatio);
+    x = (int)Math.min(x, Math.max(bestSize.width-1, 0));
+    y = (int)Math.min(y, Math.max(bestSize.height-1, 0));
+    java.awt.Point hs = new java.awt.Point(x, y);
+    if (!bestSize.equals(new Dimension(0,0)))
+      softCursor = tk.createCustomCursor(cursorImage, hs, "softCursor");
     cursorImage.flush();
 
     if (softCursor != null) {
@@ -210,7 +226,16 @@
   {
     Rect r = damage;
     if (!r.is_empty()) {
-      paintImmediately(r.tl.x, r.tl.y, r.width(), r.height());
+      if (cc.cp.width != scaledWidth || cc.cp.height != scaledHeight) {
+        int x = (int)Math.floor(r.tl.x * scaleWidthRatio);
+        int y = (int)Math.floor(r.tl.y * scaleHeightRatio);
+        // Need one extra pixel to account for rounding.
+        int width = (int)Math.ceil(r.width() * scaleWidthRatio) + 1;
+        int height = (int)Math.ceil(r.height() * scaleHeightRatio) + 1;
+        paintImmediately(x, y, width, height);
+      } else {
+        paintImmediately(r.tl.x, r.tl.y, r.width(), r.height());
+      }
       damage.clear();
     }
   }
@@ -229,7 +254,7 @@
     if (overlapsCursor(x, y, w, h)) hideLocalCursor();
     im.fillRect(x, y, w, h, pix);
     damageRect(new Rect(x, y, x+w, y+h));
-    if (softCursor == null)
+    if (!cc.cp.supportsLocalCursor)
       showLocalCursor();
   }
 
@@ -238,7 +263,7 @@
     if (overlapsCursor(x, y, w, h)) hideLocalCursor();
     im.imageRect(x, y, w, h, pix);
     damageRect(new Rect(x, y, x+w, y+h));
-    if (softCursor == null)
+    if (!cc.cp.supportsLocalCursor)
       showLocalCursor();
   }
 
@@ -263,6 +288,12 @@
   // The following methods are all called from the GUI thread
 
   void resetLocalCursor() {
+    if (cc.cp.supportsLocalCursor) {
+      if (softCursor != null)
+        setCursor(softCursor);
+    } else {
+      setCursor(nullCursor);
+    }
     hideLocalCursor();
     cursorAvailable = false;
   }
@@ -323,6 +354,8 @@
   public void paintComponent(Graphics g) {
     Graphics2D g2 = (Graphics2D) g;
     if (cc.cp.width != scaledWidth || cc.cp.height != scaledHeight) {
+      g2.setRenderingHint(RenderingHints.KEY_RENDERING,
+                          RenderingHints.VALUE_RENDER_QUALITY);
       g2.drawImage(im.getImage(), 0, 0, scaledWidth, scaledHeight, null);  
     } else {
       g2.drawImage(im.getImage(), 0, 0, null);
@@ -370,7 +403,7 @@
             e.getY() >= 0 && e.getY() < im.height()) {
           cursorPosX = e.getX();
           cursorPosY = e.getY();
-          if (softCursor == null)
+          if (!cc.cp.supportsLocalCursor)
             showLocalCursor();
         }
       }
@@ -447,7 +480,7 @@
         return;
       }
       cursorVisible = true;
-      if (softCursor != null) return;
+      if (cc.cp.supportsLocalCursor) return;
 
       int cursorLeft = cursor.hotspot.x;
       int cursorTop = cursor.hotspot.y;
@@ -504,7 +537,7 @@
   int cursorPosX, cursorPosY;
   ManagedPixelBuffer cursorBacking;
   int cursorBackingX, cursorBackingY;
-  java.awt.Cursor softCursor;
+  java.awt.Cursor softCursor, nullCursor;
   static Toolkit tk = Toolkit.getDefaultToolkit();
 
   public int scaledWidth = 0, scaledHeight = 0;

This was sent by the SourceForge.net collaborative development platform, the 
world's largest Open Source development site.


------------------------------------------------------------------------------
Master Visual Studio, SharePoint, SQL, ASP.NET, C# 2012, HTML5, CSS,
MVC, Windows 8 Apps, JavaScript and much more. Keep your skills current
with LearnDevNow - 3,200 step-by-step video tutorials by Microsoft
MVPs and experts. SALE $99.99 this month only -- learn more at:
http://p.sf.net/sfu/learnmore_122912
_______________________________________________
Tigervnc-commits mailing list
Tigervnc-commits@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/tigervnc-commits

Reply via email to