]> source.dussan.org Git - tigervnc.git/commitdiff
Client support for cursors with full alpha
authorPierre Ossman <ossman@cendio.se>
Sun, 19 Feb 2017 14:50:29 +0000 (15:50 +0100)
committerPierre Ossman <ossman@cendio.se>
Wed, 22 Feb 2017 16:00:37 +0000 (17:00 +0100)
common/rfb/CConnection.cxx
common/rfb/CConnection.h
common/rfb/CMsgHandler.h
common/rfb/CMsgReader.cxx
common/rfb/CMsgReader.h
common/rfb/CMsgWriter.cxx
common/rfb/encodings.h

index 35be9468f2b9e42eb6fafdc578d83766de2e21c4..2020418163bfe0f02de0e0df3e60652d27eee631 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyright 2011-2017 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -320,6 +321,13 @@ void CConnection::setExtendedDesktopSize(unsigned reason,
   CMsgHandler::setExtendedDesktopSize(reason, result, w, h, layout);
 }
 
+void CConnection::readAndDecodeRect(const Rect& r, int encoding,
+                                    ModifiablePixelBuffer* pb)
+{
+  decoder.decodeRect(r, encoding, pb);
+  decoder.flush();
+}
+
 void CConnection::framebufferUpdateStart()
 {
   CMsgHandler::framebufferUpdateStart();
index 6bc7a389083e4979dafc6c852acb22a410336437..799a9c21cafcb6e177fe2932ff8cf6c475732b57 100644 (file)
@@ -1,4 +1,5 @@
 /* Copyright (C) 2002-2005 RealVNC Ltd.  All Rights Reserved.
+ * Copyright 2011-2017 Pierre Ossman for Cendio AB
  * 
  * This is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
@@ -99,6 +100,9 @@ namespace rfb {
                                         int w, int h,
                                         const ScreenSet& layout);
 
+    virtual void readAndDecodeRect(const Rect& r, int encoding,
+                                   ModifiablePixelBuffer* pb);
+
     virtual void framebufferUpdateStart();
     virtual void framebufferUpdateEnd();
     virtual void dataRect(const Rect& r, int encoding);
index 2686712e368d709db59710502b2db01d917dcaf9..993276ed343c4447094ee2f474a671c987a0dd15 100644 (file)
@@ -57,6 +57,9 @@ namespace rfb {
     virtual void endOfContinuousUpdates();
     virtual void serverInit() = 0;
 
+    virtual void readAndDecodeRect(const Rect& r, int encoding,
+                                   ModifiablePixelBuffer* pb) = 0;
+
     virtual void framebufferUpdateStart();
     virtual void framebufferUpdateEnd();
     virtual void dataRect(const Rect& r, int encoding) = 0;
index 152c2c85701e214cb14ffd7357dfa08d2ae6c08e..7233fbd76c9cd0f714ca0e740a8e48382ccb006e 100644 (file)
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,
  * USA.
  */
+
+#include <assert.h>
 #include <stdio.h>
+
 #include <rfb/msgTypes.h>
 #include <rdr/InStream.h>
 #include <rfb/Exception.h>
@@ -94,6 +97,9 @@ void CMsgReader::readMsg()
     case pseudoEncodingCursor:
       readSetCursor(w, h, Point(x,y));
       break;
+    case pseudoEncodingCursorWithAlpha:
+      readSetCursorWithAlpha(w, h, Point(x,y));
+      break;
     case pseudoEncodingDesktopName:
       readSetDesktopName(x, y, w, h);
       break;
@@ -287,6 +293,50 @@ void CMsgReader::readSetCursor(int width, int height, const Point& hotspot)
   handler->setCursor(width, height, hotspot, buf);
 }
 
+void CMsgReader::readSetCursorWithAlpha(int width, int height, const Point& hotspot)
+{
+  int encoding;
+
+  const PixelFormat rgbaPF(32, 32, false, true, 255, 255, 255, 16, 8, 0);
+  ManagedPixelBuffer pb(rgbaPF, width, height);
+  PixelFormat origPF;
+
+  rdr::U8* buf;
+  int stride;
+
+  encoding = is->readS32();
+
+  origPF = handler->cp.pf();
+  handler->cp.setPF(rgbaPF);
+  handler->readAndDecodeRect(pb.getRect(), encoding, &pb);
+  handler->cp.setPF(origPF);
+
+  // On-wire data has pre-multiplied alpha, but we store it
+  // non-pre-multiplied
+  buf = pb.getBufferRW(pb.getRect(), &stride);
+  assert(stride == width);
+
+  for (int i = 0;i < pb.area();i++) {
+    rdr::U8 alpha;
+
+    alpha = buf[3];
+    if (alpha == 0)
+      alpha = 1; // Avoid division by zero
+
+    buf[0] = (unsigned)buf[0] * 255/alpha;
+    buf[1] = (unsigned)buf[1] * 255/alpha;
+    buf[2] = (unsigned)buf[2] * 255/alpha;
+    buf[3] = alpha;
+
+    buf += 4;
+  }
+
+  pb.commitBufferRW(pb.getRect());
+
+  handler->setCursor(width, height, hotspot,
+                     pb.getBuffer(pb.getRect(), &stride));
+}
+
 void CMsgReader::readSetDesktopName(int x, int y, int w, int h)
 {
   char* name = is->readString();
index 296d99f02177e744329143b5285bd0c752159e4e..ff73414ef2f07063d8a6eb18579453072167de9b 100644 (file)
@@ -62,6 +62,7 @@ namespace rfb {
 
     void readSetXCursor(int width, int height, const Point& hotspot);
     void readSetCursor(int width, int height, const Point& hotspot);
+    void readSetCursorWithAlpha(int width, int height, const Point& hotspot);
     void readSetDesktopName(int x, int y, int w, int h);
     void readExtendedDesktopSize(int x, int y, int w, int h);
 
index 2ad3a79a96b85542d020faca0c399ffc6a7930fa..8576d8f1245750a740ff78910c203164a17cd985 100644 (file)
@@ -74,6 +74,7 @@ void CMsgWriter::writeSetEncodings(int preferredEncoding, bool useCopyRect)
   if (cp->supportsLocalCursor) {
     encodings[nEncodings++] = pseudoEncodingXCursor;
     encodings[nEncodings++] = pseudoEncodingCursor;
+    encodings[nEncodings++] = pseudoEncodingCursorWithAlpha;
   }
   if (cp->supportsDesktopResize)
     encodings[nEncodings++] = pseudoEncodingDesktopSize;
index 5c6c5eab98c1c96df14f0cbd5f824f405cbc8a09..a65d863ba131638d8a279beb393aa02f6e4be994 100644 (file)
@@ -38,6 +38,7 @@ namespace rfb {
   const int pseudoEncodingDesktopName = -307;
   const int pseudoEncodingFence = -312;
   const int pseudoEncodingContinuousUpdates = -313;
+  const int pseudoEncodingCursorWithAlpha = -314;
 
   // TightVNC-specific
   const int pseudoEncodingLastRect = -224;