]> source.dussan.org Git - tigervnc.git/commitdiff
Store the mouse cursor in the ConnParams object
authorPierre Ossman <ossman@cendio.se>
Thu, 13 Feb 2014 13:40:25 +0000 (14:40 +0100)
committerPierre Ossman <ossman@cendio.se>
Mon, 14 Jul 2014 14:03:35 +0000 (16:03 +0200)
Like we do for everything else. This also gets rid
of the callback, which is a bit out of place
compared to everything else.

common/rfb/ConnParams.cxx
common/rfb/ConnParams.h
common/rfb/SMsgWriter.cxx
common/rfb/SMsgWriter.h
common/rfb/VNCSConnectionST.cxx
common/rfb/VNCSConnectionST.h

index 6fd6668ead16d50029d789b3962b064f8504d31a..36f6daa66059b26f5665db6cb2681f3cfda6cac8 100644 (file)
@@ -86,6 +86,21 @@ void ConnParams::setName(const char* name)
   name_ = strDup(name);
 }
 
+void ConnParams::setCursor(const Cursor& other)
+{
+  const rdr::U8* data;
+  int stride;
+
+  cursor_.hotspot = other.hotspot;
+  cursor_.setPF(other.getPF());
+  cursor_.setSize(other.width(), other.height());
+
+  data = other.getBuffer(other.getRect(), &stride);
+  cursor_.imageRect(cursor_.getRect(), data, stride);
+
+  memcpy(cursor_.mask.buf, other.mask.buf, cursor_.maskLen());
+}
+
 void ConnParams::setEncodings(int nEncodings, const rdr::S32* encodings)
 {
   useCopyRect = false;
index 43267ffdfb18022b6194dc93cb0997fe28d37083..7a6d60ccf91d8818c50be630ac6378150df507ef 100644 (file)
@@ -24,6 +24,7 @@
 #define __RFB_CONNPARAMS_H__
 
 #include <rdr/types.h>
+#include <rfb/Cursor.h>
 #include <rfb/PixelFormat.h>
 #include <rfb/ScreenSet.h>
 
@@ -74,6 +75,9 @@ namespace rfb {
     const char* name() { return name_; }
     void setName(const char* name);
 
+    const Cursor& cursor() { return cursor_; }
+    void setCursor(const Cursor& cursor);
+
     rdr::S32 currentEncoding() { return currentEncoding_; }
 
     void setEncodings(int nEncodings, const rdr::S32* encodings);
@@ -100,6 +104,7 @@ namespace rfb {
 
     PixelFormat pf_;
     char* name_;
+    Cursor cursor_;
     int currentEncoding_;
     char verStr[13];
     int verStrPos;
index 40e6d7f692f47c5a0ceccadf7161767a5232e25c..46c41388917d9cb95b32f73badae9e87828b0181 100644 (file)
@@ -36,8 +36,8 @@ static LogWriter vlog("SMsgWriter");
 SMsgWriter::SMsgWriter(ConnParams* cp_, rdr::OutStream* os_)
   : imageBufIdealSize(0), cp(cp_), os(os_), currentEncoding(0),
     nRectsInUpdate(0), nRectsInHeader(0),
-    wsccb(0), needSetDesktopSize(false),
-    needExtendedDesktopSize(false), needSetDesktopName(false),
+    needSetDesktopSize(false), needExtendedDesktopSize(false),
+    needSetDesktopName(false), needSetCursor(false), needSetXCursor(false),
     lenBeforeRect(0), updatesSent(0), rawBytesEquivalent(0),
     imageBuf(0), imageBufSize(0)
 {
@@ -179,69 +179,46 @@ bool SMsgWriter::writeSetDesktopName() {
   return true;
 }
 
-void SMsgWriter::cursorChange(WriteSetCursorCallback* cb)
+bool SMsgWriter::writeSetCursor()
 {
-  wsccb = cb;
-}
-
-void SMsgWriter::writeSetCursor(int width, int height, const Point& hotspot,
-                                void* data, void* mask)
-{
-  if (!wsccb)
-    return;
+  if (!cp->supportsLocalCursor)
+    return false;
 
-  if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
-    throw Exception("SMsgWriter::writeSetCursor: nRects out of sync");
+  needSetCursor = true;
 
-  os->writeS16(hotspot.x);
-  os->writeS16(hotspot.y);
-  os->writeU16(width);
-  os->writeU16(height);
-  os->writeU32(pseudoEncodingCursor);
-  os->writeBytes(data, width * height * (cp->pf().bpp/8));
-  os->writeBytes(mask, (width+7)/8 * height);
+  return true;
 }
 
-void SMsgWriter::writeSetXCursor(int width, int height, int hotspotX,
-                                 int hotspotY, void* data, void* mask)
+bool SMsgWriter::writeSetXCursor()
 {
-  if (!wsccb)
-    return;
+  if (!cp->supportsLocalXCursor)
+    return false;
 
-  if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
-    throw Exception("SMsgWriter::writeSetXCursor: nRects out of sync");
+  needSetXCursor = true;
 
-  os->writeS16(hotspotX);
-  os->writeS16(hotspotY);
-  os->writeU16(width);
-  os->writeU16(height);
-  os->writeU32(pseudoEncodingXCursor);
-  // FIXME: We only support black and white cursors, currently. We
-  // could pass the correct color by using the pix0/pix1 values
-  // returned from getBitmap, in writeSetCursorCallback. However, we
-  // would then need to undo the conversion from rgb to Pixel that is
-  // done by FakeAllocColor.
-  if (width * height) {
-    os->writeU8(0);
-    os->writeU8(0);
-    os->writeU8(0);
-    os->writeU8(255);
-    os->writeU8(255);
-    os->writeU8(255);
-    os->writeBytes(data, (width+7)/8 * height);
-    os->writeBytes(mask, (width+7)/8 * height);
-  }
+  return true;
 }
 
 bool SMsgWriter::needFakeUpdate()
 {
-  return wsccb || needSetDesktopName || needNoDataUpdate();
+  if (needSetDesktopName)
+    return true;
+  if (needSetCursor || needSetXCursor)
+    return true;
+  if (needNoDataUpdate())
+    return true;
+
+  return false;
 }
 
 bool SMsgWriter::needNoDataUpdate()
 {
-  return needSetDesktopSize || needExtendedDesktopSize ||
-         !extendedDesktopSizeMsgs.empty();
+  if (needSetDesktopSize)
+    return true;
+  if (needExtendedDesktopSize || !extendedDesktopSizeMsgs.empty())
+    return true;
+
+  return false;
 }
 
 void SMsgWriter::writeNoDataUpdate()
@@ -268,10 +245,12 @@ void SMsgWriter::writeFramebufferUpdateStart(int nRects)
   os->pad(1);
 
   if (nRects != 0xFFFF) {
-    if (wsccb)
-      nRects++;
     if (needSetDesktopName)
       nRects++;
+    if (needSetCursor)
+      nRects++;
+    if (needSetXCursor)
+      nRects++;
   }
 
   os->writeU16(nRects);
@@ -369,9 +348,41 @@ void SMsgWriter::endMsg()
 
 void SMsgWriter::writePseudoRects()
 {
-  if (wsccb) {
-    wsccb->writeSetCursorCallback();
-    wsccb = 0;
+  if (needSetCursor) {
+    rdr::U8* data;
+    int stride;
+
+    const Cursor& cursor = cp->cursor();
+
+    data = new rdr::U8[cursor.area() * cp->pf().bpp/8];
+    cursor.getImage(cp->pf(), data, cursor.getRect());
+
+    writeSetCursorRect(cursor.width(), cursor.height(),
+                       cursor.hotspot.x, cursor.hotspot.y,
+                       data, cursor.mask.buf);
+    needSetCursor = false;
+
+    delete [] data;
+  }
+
+  if (needSetXCursor) {
+    const Cursor& cursor = cp->cursor();
+    Pixel pix0, pix1;
+    rdr::U8 rgb0[3], rgb1[3];
+    rdr::U8Array bitmap(cursor.getBitmap(&pix0, &pix1));
+
+    if (!bitmap.buf) {
+      // FIXME: We could reduce to two colors.
+      throw Exception("SMsgWriter::writePseudoRects: Unable to send multicolor cursor: RichCursor not supported by client");
+    }
+
+    cp->pf().rgbFromPixel(pix0, &rgb0[0], &rgb0[1], &rgb0[2]);
+    cp->pf().rgbFromPixel(pix1, &rgb1[0], &rgb1[1], &rgb1[2]);
+
+    writeSetXCursorRect(cursor.width(), cursor.height(),
+                        cursor.hotspot.x, cursor.hotspot.y,
+                        rgb0, rgb1, bitmap.buf, cursor.mask.buf);
+    needSetXCursor = false;
   }
 
   if (needSetDesktopName) {
@@ -469,3 +480,49 @@ void SMsgWriter::writeSetDesktopNameRect(const char *name)
   os->writeU32(pseudoEncodingDesktopName);
   os->writeString(name);
 }
+
+void SMsgWriter::writeSetCursorRect(int width, int height,
+                                    int hotspotX, int hotspotY,
+                                    const void* data, const void* mask)
+{
+  if (!cp->supportsLocalCursor)
+    throw Exception("Client does not support local cursors");
+  if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
+    throw Exception("SMsgWriter::writeSetCursorRect: nRects out of sync");
+
+  os->writeS16(hotspotX);
+  os->writeS16(hotspotY);
+  os->writeU16(width);
+  os->writeU16(height);
+  os->writeU32(pseudoEncodingCursor);
+  os->writeBytes(data, width * height * (cp->pf().bpp/8));
+  os->writeBytes(mask, (width+7)/8 * height);
+}
+
+void SMsgWriter::writeSetXCursorRect(int width, int height,
+                                     int hotspotX, int hotspotY,
+                                     const rdr::U8 pix0[],
+                                     const rdr::U8 pix1[],
+                                     const void* data, const void* mask)
+{
+  if (!cp->supportsLocalXCursor)
+    throw Exception("Client does not support local cursors");
+  if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
+    throw Exception("SMsgWriter::writeSetXCursorRect: nRects out of sync");
+
+  os->writeS16(hotspotX);
+  os->writeS16(hotspotY);
+  os->writeU16(width);
+  os->writeU16(height);
+  os->writeU32(pseudoEncodingXCursor);
+  if (width * height) {
+    os->writeU8(pix0[0]);
+    os->writeU8(pix0[1]);
+    os->writeU8(pix0[2]);
+    os->writeU8(pix1[0]);
+    os->writeU8(pix1[1]);
+    os->writeU8(pix1[2]);
+    os->writeBytes(data, (width+7)/8 * height);
+    os->writeBytes(mask, (width+7)/8 * height);
+  }
+}
index c3ee45771ba09a697007287abc4eca6bc7c8df22..e9fc5a47394263587ffbab832fc4fe79aca975f4 100644 (file)
@@ -34,11 +34,6 @@ namespace rfb {
   class ConnParams;
   class ScreenSet;
 
-  class WriteSetCursorCallback {
-  public:
-    virtual void writeSetCursorCallback() = 0;
-  };
-
   class SMsgWriter {
   public:
     SMsgWriter(ConnParams* cp, rdr::OutStream* os);
@@ -81,16 +76,10 @@ namespace rfb {
 
     bool writeSetDesktopName();
 
-    // Like setDesktopSize, we can't just write out a setCursor message
-    // immediately. Instead of calling writeSetCursor() directly,
-    // you must call cursorChange(), and then invoke writeSetCursor()
-    // in response to the writeSetCursorCallback() callback. This will
-    // happen when the next update is sent.
-    void cursorChange(WriteSetCursorCallback* cb);
-    void writeSetCursor(int width, int height, const Point& hotspot,
-                        void* data, void* mask);
-    void writeSetXCursor(int width, int height, int hotspotX, int hotspotY,
-                         void* data, void* mask);
+    // Like setDesktopSize, we can't just write out a cursor message
+    // immediately. 
+    bool writeSetCursor();
+    bool writeSetXCursor();
 
     // needFakeUpdate() returns true when an immediate update is needed in
     // order to flush out pseudo-rectangles to the client.
@@ -141,6 +130,13 @@ namespace rfb {
                                       int fb_width, int fb_height,
                                       const ScreenSet& layout);
     void writeSetDesktopNameRect(const char *name);
+    void writeSetCursorRect(int width, int height,
+                            int hotspotX, int hotspotY,
+                            const void* data, const void* mask);
+    void writeSetXCursorRect(int width, int height,
+                             int hotspotX, int hotspotY,
+                             const rdr::U8 pix0[], const rdr::U8 pix1[],
+                             const void* data, const void* mask);
 
     ConnParams* cp;
     rdr::OutStream* os;
@@ -150,12 +146,12 @@ namespace rfb {
     int nRectsInUpdate;
     int nRectsInHeader;
 
-    WriteSetCursorCallback* wsccb;
-
     bool needSetDesktopSize;
     bool needExtendedDesktopSize;
     bool needSetDesktopName;
     bool needLastRect;
+    bool needSetCursor;
+    bool needSetXCursor;
 
     int lenBeforeRect;
     int updatesSent;
index f8674deae20d02a9288911d87dc5fb368f58bc69..e7123000401770fd391c61cf1957b6aa1807b56f 100644 (file)
@@ -712,46 +712,6 @@ void VNCSConnectionST::supportsContinuousUpdates()
   writer()->writeEndOfContinuousUpdates();
 }
 
-void VNCSConnectionST::writeSetCursorCallback()
-{
-  if (cp.supportsLocalXCursor) {
-    Pixel pix0, pix1;
-    rdr::U8Array bitmap(server->cursor.getBitmap(&pix0, &pix1));
-    if (bitmap.buf) {
-      // The client supports XCursor and the cursor only has two
-      // colors. Use the XCursor encoding.
-      writer()->writeSetXCursor(server->cursor.width(),
-                               server->cursor.height(),
-                               server->cursor.hotspot.x,
-                               server->cursor.hotspot.y,
-                               bitmap.buf, server->cursor.mask.buf);
-      return;
-    } else {
-      // More than two colors
-      if (!cp.supportsLocalCursor) {
-       // FIXME: We could reduce to two colors. 
-       vlog.info("Unable to send multicolor cursor: RichCursor not supported by client");
-       return;
-      }
-    }
-  }
-
-  // Use RichCursor
-  rdr::U8* transBuffer;
-  int stride;
-  const rdr::U8* buffer;
-
-  transBuffer = writer()->getImageBuf(server->cursor.area());
-
-  buffer = server->cursor.getBuffer(server->cursor.getRect(), &stride);
-  image_getter.translatePixels(buffer, transBuffer, server->cursor.area());
-
-  writer()->writeSetCursor(server->cursor.width(),
-                           server->cursor.height(),
-                           server->cursor.hotspot,
-                           transBuffer, server->cursor.mask.buf);
-}
-
 
 bool VNCSConnectionST::handleTimeout(Timer* t)
 {
@@ -1166,10 +1126,16 @@ void VNCSConnectionST::setCursor()
 {
   if (state() != RFBSTATE_NORMAL)
     return;
-  if (!cp.supportsLocalCursor)
-    return;
 
-  writer()->cursorChange(this);
+  cp.setCursor(server->cursor);
+
+  if (!writer()->writeSetCursor()) {
+    if (!writer()->writeSetXCursor()) {
+      // No client support
+      return;
+    }
+  }
+
   writeFramebufferUpdate();
 }
 
index ca5c4f015b8902d9aafbd6e09e0851a0bbd2e08e..c918c599473a5975d1c828d24b54099d829bcbbd 100644 (file)
@@ -40,7 +40,6 @@ namespace rfb {
   class Encoder;
 
   class VNCSConnectionST : public SConnection,
-                           public WriteSetCursorCallback,
                            public Timer::Callback {
   public:
     VNCSConnectionST(VNCServerST* server_, network::Socket* s, bool reverse);
@@ -152,9 +151,6 @@ namespace rfb {
     // default access settings and the connection's access settings.
     virtual void setAccessRights(AccessRights ar) {accessRights=ar;}
 
-    // WriteSetCursorCallback
-    virtual void writeSetCursorCallback();
-
     // Timer callbacks
     virtual bool handleTimeout(Timer* t);