Server support for cursor with alpha
diff --git a/common/rfb/SMsgWriter.cxx b/common/rfb/SMsgWriter.cxx
index 51e1105..cf3264e 100644
--- a/common/rfb/SMsgWriter.cxx
+++ b/common/rfb/SMsgWriter.cxx
@@ -36,7 +36,8 @@
: cp(cp_), os(os_),
nRectsInUpdate(0), nRectsInHeader(0),
needSetDesktopSize(false), needExtendedDesktopSize(false),
- needSetDesktopName(false), needSetCursor(false), needSetXCursor(false)
+ needSetDesktopName(false), needSetCursor(false),
+ needSetXCursor(false), needSetCursorWithAlpha(false)
{
}
@@ -180,11 +181,21 @@
return true;
}
+bool SMsgWriter::writeSetCursorWithAlpha()
+{
+ if (!cp->supportsLocalCursorWithAlpha)
+ return false;
+
+ needSetCursorWithAlpha = true;
+
+ return true;
+}
+
bool SMsgWriter::needFakeUpdate()
{
if (needSetDesktopName)
return true;
- if (needSetCursor || needSetXCursor)
+ if (needSetCursor || needSetXCursor || needSetCursorWithAlpha)
return true;
if (needNoDataUpdate())
return true;
@@ -232,6 +243,8 @@
nRects++;
if (needSetXCursor)
nRects++;
+ if (needSetCursorWithAlpha)
+ nRects++;
}
os->writeU16(nRects);
@@ -334,6 +347,15 @@
needSetXCursor = false;
}
+ if (needSetCursorWithAlpha) {
+ const Cursor& cursor = cp->cursor();
+
+ writeSetCursorWithAlphaRect(cursor.width(), cursor.height(),
+ cursor.hotspot().x, cursor.hotspot().y,
+ cursor.getBuffer());
+ needSetCursorWithAlpha = false;
+ }
+
if (needSetDesktopName) {
writeSetDesktopNameRect(cp->name());
needSetDesktopName = false;
@@ -473,3 +495,31 @@
os->writeBytes(mask, (width+7)/8 * height);
}
}
+
+void SMsgWriter::writeSetCursorWithAlphaRect(int width, int height,
+ int hotspotX, int hotspotY,
+ const rdr::U8* data)
+{
+ if (!cp->supportsLocalCursorWithAlpha)
+ throw Exception("Client does not support local cursors");
+ if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
+ throw Exception("SMsgWriter::writeSetCursorWithAlphaRect: nRects out of sync");
+
+ os->writeS16(hotspotX);
+ os->writeS16(hotspotY);
+ os->writeU16(width);
+ os->writeU16(height);
+ os->writeU32(pseudoEncodingCursorWithAlpha);
+
+ // FIXME: Use an encoder with compression?
+ os->writeU32(encodingRaw);
+
+ // Alpha needs to be pre-multiplied
+ for (int i = 0;i < width*height;i++) {
+ os->writeU8((unsigned)data[0] * data[3] / 255);
+ os->writeU8((unsigned)data[1] * data[3] / 255);
+ os->writeU8((unsigned)data[2] * data[3] / 255);
+ os->writeU8(data[3]);
+ data += 4;
+ }
+}