case Encodings.pseudoEncodingCursorWithAlpha:
readSetCursorWithAlpha(w, h, new Point(x,y));
break;
+ case Encodings.pseudoEncodingVMwareCursor:
+ readSetVMwareCursor(w, h, new Point(x,y));
+ break;
case Encodings.pseudoEncodingDesktopName:
readSetDesktopName(x, y, w, h);
break;
handler.setCursor(width, height, hotspot, buf.array());
}
+ protected void readSetVMwareCursor(int width, int height, Point hotspot)
+ {
+ // VMware cursor sends RGBA, java BufferedImage needs ARGB
+ if (width > maxCursorSize || height > maxCursorSize)
+ throw new Exception("Too big cursor");
+
+ byte type;
+
+ type = (byte)is.readU8();
+ is.skip(1);
+
+ if (type == 0) {
+ int len = width * height * (handler.server.pf().bpp/8);
+ ByteBuffer andMask = ByteBuffer.allocate(len);
+ ByteBuffer xorMask = ByteBuffer.allocate(len);
+
+ ByteBuffer data = ByteBuffer.allocate(width*height*4);
+
+ ByteBuffer andIn;
+ ByteBuffer xorIn;
+ ByteBuffer out;
+ int Bpp;
+
+ is.readBytes(andMask, len);
+ is.readBytes(xorMask, len);
+
+ andIn = ByteBuffer.wrap(andMask.array());
+ xorIn = ByteBuffer.wrap(xorMask.array());
+ out = ByteBuffer.wrap(data.array());
+ Bpp = handler.server.pf().bpp/8;
+ for (int y = 0;y < height;y++) {
+ for (int x = 0;x < width;x++) {
+ int andPixel, xorPixel;
+
+ andPixel = handler.server.pf().pixelFromBuffer(andIn.duplicate());
+ xorPixel = handler.server.pf().pixelFromBuffer(xorIn.duplicate());
+ andIn.position(andIn.position() + Bpp);
+ xorIn.position(xorIn.position() + Bpp);
+
+ if (andPixel == 0) {
+ byte r, g, b;
+
+ // Opaque pixel
+
+ r = (byte)handler.server.pf().getColorModel().getRed(xorPixel);
+ g = (byte)handler.server.pf().getColorModel().getGreen(xorPixel);
+ b = (byte)handler.server.pf().getColorModel().getBlue(xorPixel);
+ out.put((byte)0xff);
+ out.put(r);
+ out.put(g);
+ out.put(b);
+ } else if (xorPixel == 0) {
+ // Fully transparent pixel
+ out.put((byte)0);
+ out.put((byte)0);
+ out.put((byte)0);
+ out.put((byte)0);
+ } else if (andPixel == xorPixel) {
+ // Inverted pixel
+
+ // We don't really support this, so just turn the pixel black
+ // FIXME: Do an outline like WinVNC does?
+ out.put((byte)0xff);
+ out.put((byte)0);
+ out.put((byte)0);
+ out.put((byte)0);
+ } else {
+ // Partially transparent/inverted pixel
+
+ // We _really_ can't handle this, just make it black
+ out.put((byte)0xff);
+ out.put((byte)0);
+ out.put((byte)0);
+ out.put((byte)0);
+ }
+ }
+ }
+
+ handler.setCursor(width, height, hotspot, data.array());
+ } else if (type == 1) {
+ ByteBuffer data = ByteBuffer.allocate(width*height*4);
+
+ // FIXME: Is alpha premultiplied?
+ ByteBuffer buf = ByteBuffer.allocate(4);
+ for (int i=0;i < width*height*4;i+=4) {
+ is.readBytes(buf,4);
+ data.put(buf.array(),3,1);
+ data.put(buf.array(),0,3);
+ buf.clear();
+ }
+
+ handler.setCursor(width, height, hotspot, data.array());
+ } else {
+ throw new Exception("Unknown cursor type");
+ }
+ }
+
protected void readSetDesktopName(int x, int y, int w, int h)
{
String name = is.readString();
protected CMsgHandler handler;
protected InStream is;
protected int nUpdateRectsLeft;
+ protected final int maxCursorSize = 256;
protected int[] imageBuf;
protected int imageBufSize;
}