Changes to support cursor pos and shape updates in archives.
git-svn-id: svn://svn.code.sf.net/p/tigervnc/code/trunk@2533 3789f03b-4d11-0410-bbf8-ca57d06f2519
diff --git a/java/src/com/tightvnc/rfbplayer/VncCanvas.java b/java/src/com/tightvnc/rfbplayer/VncCanvas.java
index 96e8035..cf6c2bd 100644
--- a/java/src/com/tightvnc/rfbplayer/VncCanvas.java
+++ b/java/src/com/tightvnc/rfbplayer/VncCanvas.java
@@ -106,6 +106,13 @@
synchronized(memImage) {
g.drawImage(memImage, 0, 0, null);
}
+ if (showSoftCursor) {
+ int x0 = cursorX - hotX, y0 = cursorY - hotY;
+ Rectangle r = new Rectangle(x0, y0, cursorWidth, cursorHeight);
+ if (r.intersects(g.getClipBounds())) {
+ g.drawImage(softCursor, x0, y0, null);
+ }
+ }
}
//
@@ -242,6 +249,9 @@
for (int i = 0; i < rfb.updateNRects; i++) {
rfb.readFramebufferUpdateRectHdr();
+
+ boolean cursorPosReceived = false;
+
int rx = rfb.updateRectX, ry = rfb.updateRectY;
int rw = rfb.updateRectW, rh = rfb.updateRectH;
@@ -258,8 +268,19 @@
if (rfb.updateRectEncoding == rfb.EncodingXCursor ||
rfb.updateRectEncoding == rfb.EncodingRichCursor) {
- throw new Exception("Sorry, no support for" +
- " cursor shape updates yet");
+ handleCursorShapeUpdate(rfb.updateRectEncoding, rx, ry, rw, rh);
+ continue;
+ }
+// if (rfb.updateRectEncoding == rfb.EncodingXCursor ||
+// rfb.updateRectEncoding == rfb.EncodingRichCursor) {
+// throw new Exception("Sorry, no support for" +
+// " cursor shape updates yet");
+// }
+
+ if (rfb.updateRectEncoding == rfb.EncodingPointerPos) {
+ softCursorMove(rx, ry);
+ cursorPosReceived = true;
+ continue;
}
switch (rfb.updateRectEncoding) {
@@ -286,7 +307,7 @@
break;
default:
throw new Exception("Unknown RFB rectangle encoding " +
- rfb.updateRectEncoding);
+ Integer.toString(rfb.updateRectEncoding, 16));
}
}
break;
@@ -303,7 +324,8 @@
break;
default:
- throw new Exception("Unknown RFB message type " + msgType);
+ throw new Exception("Unknown RFB message type " +
+ Integer.toString(msgType, 16));
}
player.updatePos();
@@ -814,6 +836,251 @@
memGraphics.setClip(0, 0, rfb.framebufferWidth, rfb.framebufferHeight);
}
+ //////////////////////////////////////////////////////////////////
+ //
+ // Handle cursor shape updates (XCursor and RichCursor encodings).
+ //
+ boolean showSoftCursor = false;
+
+ int[] softCursorPixels;
+ MemoryImageSource softCursorSource;
+ Image softCursor;
+
+ int cursorX = 0, cursorY = 0;
+ int cursorWidth, cursorHeight;
+ int origCursorWidth, origCursorHeight;
+ int hotX, hotY;
+ int origHotX, origHotY;
+ int deferCursorUpdates = 10;
+
+ //
+ // Handle cursor shape update (XCursor and RichCursor encodings).
+ //
+ synchronized void handleCursorShapeUpdate(int encodingType,
+ int xhot, int yhot, int width,
+ int height)
+ throws IOException {
+
+ int bytesPerRow = (width + 7) / 8;
+ int bytesMaskData = bytesPerRow * height;
+
+ softCursorFree();
+
+ if (width * height == 0)
+ return;
+
+// // Ignore cursor shape data if requested by user.
+//
+// if (viewer.options.ignoreCursorUpdates) {
+// if (encodingType == rfb.EncodingXCursor) {
+// rfb.is.skipBytes(6 + bytesMaskData * 2);
+// } else {
+// // rfb.EncodingRichCursor
+// rfb.is.skipBytes(width * height + bytesMaskData);
+// }
+// return;
+// }
+
+ // Decode cursor pixel data.
+
+ softCursorPixels = new int[width * height];
+
+ if (encodingType == rfb.EncodingXCursor) {
+ System.out.println("Reading x cursor");
+
+ // Read foreground and background colors of the cursor.
+ byte[] rgb = new byte[6];
+ rfb.is.readFully(rgb);
+ int[] colors = {(0xFF000000 | (rgb[3] & 0xFF) << 16 |
+ (rgb[4] & 0xFF) << 8 | (rgb[5] & 0xFF)),
+ (0xFF000000 | (rgb[0] & 0xFF) << 16 |
+ (rgb[1] & 0xFF) << 8 | (rgb[2] & 0xFF))
+ };
+ for (int i = 0; i < 2; i++) {
+ System.out.println("Color is " + Integer.toString(colors[i], 16));
+ }
+
+ // Read pixel and mask data.
+ byte[] pixBuf = new byte[bytesMaskData];
+ rfb.is.readFully(pixBuf);
+ byte[] maskBuf = new byte[bytesMaskData];
+ rfb.is.readFully(maskBuf);
+
+ // Decode pixel data into softCursorPixels[].
+ byte pixByte, maskByte;
+ int x, y, n, result;
+ int i = 0;
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width / 8; x++) {
+ pixByte = pixBuf[y * bytesPerRow + x];
+ maskByte = maskBuf[y * bytesPerRow + x];
+ for (n = 7; n >= 0; n--) {
+ if ((maskByte >> n & 1) != 0) {
+ result = colors[pixByte >> n & 1];
+ } else {
+ result = 0; // Transparent pixel
+ }
+ softCursorPixels[i++] = result;
+ }
+ }
+ for (n = 7; n >= 8 - width % 8; n--) {
+ if ((maskBuf[y * bytesPerRow + x] >> n & 1) != 0) {
+ result = colors[pixBuf[y * bytesPerRow + x] >> n & 1];
+ } else {
+ result = 0; // Transparent pixel
+ }
+ softCursorPixels[i++] = result;
+ }
+ }
+
+ } else {
+ // encodingType == rfb.EncodingRichCursor
+ System.out.println("Reading x cursor");
+
+ // Read pixel and mask data.
+ byte[] pixBuf = new byte[width * height * 4];
+ rfb.is.readFully(pixBuf);
+ byte[] maskBuf = new byte[bytesMaskData];
+ rfb.is.readFully(maskBuf);
+
+ // Decode pixel data into softCursorPixels[].
+ byte pixByte, maskByte;
+ int x, y, n, result;
+ int i = 0;
+ for (y = 0; y < height; y++) {
+ for (x = 0; x < width / 8; x++) {
+ maskByte = maskBuf[y * bytesPerRow + x];
+ for (n = 7; n >= 0; n--) {
+ if ((maskByte >> n & 1) != 0) {
+// if (bytesPerPixel == 1) {
+// result = cm8.getRGB(pixBuf[i]);
+// } else {
+ result = (pixBuf[i * 4] & 0xFF) << 24 |
+ (pixBuf[i * 4 + 1] & 0xFF) << 16 |
+ (pixBuf[i * 4 + 2] & 0xFF) << 8 |
+ (pixBuf[i * 4 + 3] & 0xFF);
+ //result = 0xFF000000 |
+ // (pixBuf[i * 4 + 1] & 0xFF) << 16 |
+ // (pixBuf[i * 4 + 2] & 0xFF) << 8 |
+ // (pixBuf[i * 4 + 3] & 0xFF);
+// }
+ } else {
+ result = 0; // Transparent pixel
+ }
+ softCursorPixels[i++] = result;
+ }
+ }
+
+ for (n = 7; n >= 8 - width % 8; n--) {
+ if ((maskBuf[y * bytesPerRow + x] >> n & 1) != 0) {
+// if (bytesPerPixel == 1) {
+// result = cm8.getRGB(pixBuf[i]);
+// } else {
+ result = 0xFF000000 |
+ (pixBuf[i * 4 + 1] & 0xFF) << 16 |
+ (pixBuf[i * 4 + 2] & 0xFF) << 8 |
+ (pixBuf[i * 4 + 3] & 0xFF);
+// }
+ } else {
+ result = 0; // Transparent pixel
+ }
+ softCursorPixels[i++] = result;
+ }
+ }
+
+ }
+
+ // Draw the cursor on an off-screen image.
+
+ softCursorSource =
+ new MemoryImageSource(width, height, softCursorPixels, 0, width);
+ softCursor = Toolkit.getDefaultToolkit().createImage(softCursorSource);
+// if (inputEnabled && viewer.options.scaleCursor != 0) {
+// int w = (width * viewer.options.scaleCursor) / 100;
+// int h = (height * viewer.options.scaleCursor) / 100;
+// Image newCursor = softCursor.getScaledInstance(w, h, Image.SCALE_SMOOTH);
+// softCursor = newCursor;
+// cursorWidth = w;
+// cursorHeight = h;
+// hotX = (xhot * viewer.options.scaleCursor) / 100;
+// hotY = (yhot * viewer.options.scaleCursor) / 100;
+// } else {
+ cursorWidth = width;
+ cursorHeight = height;
+ hotX = xhot;
+ hotY = yhot;
+// }
+
+ // Set data associated with cursor.
+ origCursorWidth = width;
+ origCursorHeight = height;
+ origHotX = xhot;
+ origHotY = yhot;
+
+ showSoftCursor = true;
+
+ // Show the cursor.
+
+ repaint(deferCursorUpdates,
+ cursorX - hotX, cursorY - hotY, cursorWidth, cursorHeight);
+ }
+
+ //
+ // softCursorMove(). Moves soft cursor into a particular location.
+ //
+ synchronized void softCursorMove(int x, int y) {
+ if (showSoftCursor) {
+ repaint(deferCursorUpdates,
+ cursorX - hotX, cursorY - hotY, cursorWidth, cursorHeight);
+ repaint(deferCursorUpdates,
+ x - hotX, y - hotY, cursorWidth, cursorHeight);
+
+ // Automatic viewport scrolling
+// if (viewer.desktopScrollPane != null) {
+// boolean needScroll = false;
+// Dimension d = viewer.desktopScrollPane.getSize();
+// Point topLeft = viewer.desktopScrollPane.getScrollPosition();
+// Point botRight = new Point(topLeft.x + d.width, topLeft.y + d.height);
+//
+// if (x < topLeft.x + SCROLL_MARGIN) {
+// // shift left
+// topLeft.x = x - SCROLL_MARGIN;
+// needScroll = true;
+// } else if (x > botRight.x - SCROLL_MARGIN) {
+// // shift right
+// topLeft.x = x - d.width + SCROLL_MARGIN;
+// needScroll = true;
+// }
+// if (y < topLeft.y + SCROLL_MARGIN) {
+// // shift up
+// topLeft.y = y - SCROLL_MARGIN;
+// needScroll = true;
+// } else if (y > botRight.y - SCROLL_MARGIN) {
+// // shift down
+// topLeft.y = y - d.height + SCROLL_MARGIN;
+// needScroll = true;
+// }
+// viewer.desktopScrollPane.setScrollPosition(topLeft.x, topLeft.y);
+// }
+ }
+
+ cursorX = x;
+ cursorY = y;
+ }
+ //
+ // softCursorFree(). Remove soft cursor, dispose resources.
+ //
+ synchronized void softCursorFree() {
+ if (showSoftCursor) {
+ showSoftCursor = false;
+ softCursor = null;
+ softCursorSource = null;
+ softCursorPixels = null;
+
+ repaint(deferCursorUpdates,
+ cursorX - hotX, cursorY - hotY, cursorWidth, cursorHeight);
+ }
+ }
//
// Tell JVM to repaint specified desktop area.
//