Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for forward and back mouse buttons #1826

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions common/rfb/CConnection.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -835,6 +835,7 @@ void CConnection::updateEncodings()
encodings.push_back(pseudoEncodingContinuousUpdates);
encodings.push_back(pseudoEncodingFence);
encodings.push_back(pseudoEncodingQEMUKeyEvent);
encodings.push_back(pseudoEncodingExtendedMouseButtons);

if (Decoder::supported(preferredEncoding)) {
encodings.push_back(preferredEncoding);
Expand Down
5 changes: 5 additions & 0 deletions common/rfb/CMsgHandler.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ void CMsgHandler::endOfContinuousUpdates()
server.supportsContinuousUpdates = true;
}

void CMsgHandler::supportsExtendedMouseButtons()
{
server.supportsExtendedMouseButtons = true;
}

void CMsgHandler::supportsQEMUKeyEvent()
{
server.supportsQEMUKeyEvent = true;
Expand Down
1 change: 1 addition & 0 deletions common/rfb/CMsgHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ namespace rfb {
virtual void fence(uint32_t flags, unsigned len, const uint8_t data[]);
virtual void endOfContinuousUpdates();
virtual void supportsQEMUKeyEvent();
virtual void supportsExtendedMouseButtons();
virtual void serverInit(int width, int height,
const PixelFormat& pf,
const char* name) = 0;
Expand Down
4 changes: 4 additions & 0 deletions common/rfb/CMsgReader.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,10 @@ bool CMsgReader::readMsg()
handler->supportsQEMUKeyEvent();
ret = true;
break;
case pseudoEncodingExtendedMouseButtons:
handler->supportsExtendedMouseButtons();
ret = true;
break;
default:
ret = readRect(dataRect, rectEncoding);
break;
Expand Down
38 changes: 34 additions & 4 deletions common/rfb/CMsgWriter.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#endif

#include <stdio.h>
#include <assert.h>

#include <rdr/OutStream.h>
#include <rdr/MemOutStream.h>
Expand Down Expand Up @@ -173,18 +174,47 @@ void CMsgWriter::writeKeyEvent(uint32_t keysym, uint32_t keycode, bool down)
}


void CMsgWriter::writePointerEvent(const Point& pos, uint8_t buttonMask)
void CMsgWriter::writePointerEvent(const Point& pos, uint16_t buttonMask)
CendioHalim marked this conversation as resolved.
Show resolved Hide resolved
{
Point p(pos);
bool extendedMouseButtons;

if (p.x < 0) p.x = 0;
if (p.y < 0) p.y = 0;
if (p.x >= server->width()) p.x = server->width() - 1;
if (p.y >= server->height()) p.y = server->height() - 1;

/* The highest bit in buttonMask is never sent to the server */
assert(!(buttonMask & 0x8000));

/* Only send extended pointerEvent message when needed */
extendedMouseButtons = buttonMask & 0x7f80;

startMsg(msgTypePointerEvent);
os->writeU8(buttonMask);
os->writeU16(p.x);
os->writeU16(p.y);
if (server->supportsExtendedMouseButtons && extendedMouseButtons) {
int higherBits;
int lowerBits;

higherBits = (buttonMask >> 7) & 0xff;
assert(!(higherBits & 0xfc)); /* Bits 2-7 are reserved */

lowerBits = buttonMask & 0x7f;
lowerBits |= 0x80; /* Set marker bit to 1 */

os->writeU8(lowerBits);
os->writeU16(p.x);
os->writeU16(p.y);
os->writeU8(higherBits);
} else {
/* Marker bit must be set to 0, otherwise the server might confuse
* the marker bit with the highest bit in a normal PointerEvent
* message.
*/
buttonMask &= 0x7f;
os->writeU8(buttonMask);
os->writeU16(p.x);
os->writeU16(p.y);
}
endMsg();
}

Expand Down
2 changes: 1 addition & 1 deletion common/rfb/CMsgWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ namespace rfb {
void writeFence(uint32_t flags, unsigned len, const uint8_t data[]);

void writeKeyEvent(uint32_t keysym, uint32_t keycode, bool down);
void writePointerEvent(const Point& pos, uint8_t buttonMask);
void writePointerEvent(const Point& pos, uint16_t buttonMask);

void writeClientCutText(const char* str);

Expand Down
7 changes: 7 additions & 0 deletions common/rfb/ClientParams.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -228,3 +228,10 @@ bool ClientParams::supportsContinuousUpdates() const
return true;
return false;
}

bool ClientParams::supportsExtendedMouseButtons() const
{
if (supportsEncoding(pseudoEncodingExtendedMouseButtons))
return true;
return false;
}
1 change: 1 addition & 0 deletions common/rfb/ClientParams.h
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,7 @@ namespace rfb {
bool supportsLEDState() const;
bool supportsFence() const;
bool supportsContinuousUpdates() const;
bool supportsExtendedMouseButtons() const;

int compressLevel;
int qualityLevel;
Expand Down
5 changes: 5 additions & 0 deletions common/rfb/SConnection.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,11 @@ void SConnection::supportsQEMUKeyEvent()
writer()->writeQEMUKeyEvent();
}

void SConnection::supportsExtendedMouseButtons()
{
writer()->writeExtendedMouseButtonsSupport();
}

void SConnection::versionReceived()
{
}
Expand Down
2 changes: 2 additions & 0 deletions common/rfb/SConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,8 @@ namespace rfb {

void supportsQEMUKeyEvent() override;

virtual void supportsExtendedMouseButtons() override;


// Methods to be overridden in a derived class

Expand Down
2 changes: 1 addition & 1 deletion common/rfb/SDesktop.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ namespace rfb {
// pointerEvent() is called whenever a client sends an event that
// the pointer moved, or a button was pressed or released.
virtual void pointerEvent(const Point& /*pos*/,
uint8_t /*buttonMask*/) {};
uint16_t /*buttonMask*/) {};

// handleClipboardRequest() is called whenever a client requests
// the server to send over its clipboard data. It will only be
Expand Down
11 changes: 9 additions & 2 deletions common/rfb/SMsgHandler.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,13 @@ void SMsgHandler::setPixelFormat(const PixelFormat& pf)
void SMsgHandler::setEncodings(int nEncodings, const int32_t* encodings)
{
bool firstFence, firstContinuousUpdates, firstLEDState,
firstQEMUKeyEvent;
firstQEMUKeyEvent, firstExtMouseButtonsEvent;

firstFence = !client.supportsFence();
firstContinuousUpdates = !client.supportsContinuousUpdates();
firstLEDState = !client.supportsLEDState();
firstQEMUKeyEvent = !client.supportsEncoding(pseudoEncodingQEMUKeyEvent);
firstExtMouseButtonsEvent = !client.supportsEncoding(pseudoEncodingExtendedMouseButtons);

client.setEncodings(nEncodings, encodings);

Expand All @@ -72,6 +73,8 @@ void SMsgHandler::setEncodings(int nEncodings, const int32_t* encodings)
supportsLEDState();
if (client.supportsEncoding(pseudoEncodingQEMUKeyEvent) && firstQEMUKeyEvent)
supportsQEMUKeyEvent();
if (client.supportsEncoding(pseudoEncodingExtendedMouseButtons) && firstExtMouseButtonsEvent)
supportsExtendedMouseButtons();
}

void SMsgHandler::keyEvent(uint32_t /*keysym*/, uint32_t /*keycode*/,
Expand All @@ -80,7 +83,7 @@ void SMsgHandler::keyEvent(uint32_t /*keysym*/, uint32_t /*keycode*/,
}

void SMsgHandler::pointerEvent(const Point& /*pos*/,
uint8_t /*buttonMask*/)
uint16_t /*buttonMask*/)
{
}

Expand Down Expand Up @@ -167,3 +170,7 @@ void SMsgHandler::supportsLEDState()
void SMsgHandler::supportsQEMUKeyEvent()
{
}

void SMsgHandler::supportsExtendedMouseButtons()
{
}
7 changes: 6 additions & 1 deletion common/rfb/SMsgHandler.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ namespace rfb {
virtual void keyEvent(uint32_t keysym, uint32_t keycode,
bool down);
virtual void pointerEvent(const Point& pos,
uint8_t buttonMask);
uint16_t buttonMask);

virtual void clientCutText(const char* str);

Expand Down Expand Up @@ -98,6 +98,11 @@ namespace rfb {
// handler will send a pseudo-rect back, signalling server support.
virtual void supportsQEMUKeyEvent();

// supportsExtendedMouseButtons() is called the first time we detect that the
// client supports sending 16 bit mouse button state. This lets us pass more button
// states between server and client.
virtual void supportsExtendedMouseButtons();

ClientParams client;
};
}
Expand Down
27 changes: 24 additions & 3 deletions common/rfb/SMsgReader.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -272,11 +272,32 @@ bool SMsgReader::readKeyEvent()

bool SMsgReader::readPointerEvent()
{
int mask;
int x;
int y;

if (!is->hasData(1 + 2 + 2))
return false;
int mask = is->readU8();
int x = is->readU16();
int y = is->readU16();

is->setRestorePoint();

mask = is->readU8();
x = is->readU16();
y = is->readU16();

if (handler->client.supportsExtendedMouseButtons() && mask & 0x80 ) {
int highBits;
int lowBits;

if (!is->hasDataOrRestore(1))
return false;
CendioHalim marked this conversation as resolved.
Show resolved Hide resolved

highBits = is->readU8();
lowBits = mask & 0x7f; /* Clear marker bit */
mask = (highBits << 7) | lowBits;
}

is->clearRestorePoint();
handler->pointerEvent(Point(x, y), mask);
return true;
}
Expand Down
33 changes: 32 additions & 1 deletion common/rfb/SMsgWriter.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ SMsgWriter::SMsgWriter(ClientParams* client_, rdr::OutStream* os_)
nRectsInUpdate(0), nRectsInHeader(0),
needSetDesktopName(false), needCursor(false),
needCursorPos(false), needLEDState(false),
needQEMUKeyEvent(false)
needQEMUKeyEvent(false), needExtMouseButtonsEvent(false)
{
}

Expand Down Expand Up @@ -303,6 +303,14 @@ void SMsgWriter::writeQEMUKeyEvent()
needQEMUKeyEvent = true;
}

void SMsgWriter::writeExtendedMouseButtonsSupport()
{
if (!client->supportsEncoding(pseudoEncodingExtendedMouseButtons))
throw Exception("Client does not support Extended Mouse Buttons");

needExtMouseButtonsEvent = true;
}

bool SMsgWriter::needFakeUpdate()
{
if (needSetDesktopName)
Expand All @@ -315,6 +323,8 @@ bool SMsgWriter::needFakeUpdate()
return true;
if (needQEMUKeyEvent)
return true;
if (needExtMouseButtonsEvent)
return true;
if (needNoDataUpdate())
return true;

Expand Down Expand Up @@ -363,6 +373,8 @@ void SMsgWriter::writeFramebufferUpdateStart(int nRects)
nRects++;
if (needQEMUKeyEvent)
nRects++;
if (needExtMouseButtonsEvent)
nRects++;
}

os->writeU16(nRects);
Expand Down Expand Up @@ -502,6 +514,11 @@ void SMsgWriter::writePseudoRects()
writeQEMUKeyEventRect();
needQEMUKeyEvent = false;
}

if (needExtMouseButtonsEvent) {
writeExtendedMouseButtonsRect();
needExtMouseButtonsEvent = false;
}
}

void SMsgWriter::writeNoDataRects()
Expand Down Expand Up @@ -734,3 +751,17 @@ void SMsgWriter::writeQEMUKeyEventRect()
os->writeU16(0);
os->writeU32(pseudoEncodingQEMUKeyEvent);
}

void SMsgWriter::writeExtendedMouseButtonsRect()
{
if (!client->supportsEncoding(pseudoEncodingExtendedMouseButtons))
throw Exception("Client does not support extended mouse button events");
if (++nRectsInUpdate > nRectsInHeader && nRectsInHeader)
throw Exception("SMsgWriter::writeExtendedMouseButtonsRect: nRects out of sync");

os->writeS16(0);
os->writeS16(0);
os->writeU16(0);
os->writeU16(0);
os->writeU32(pseudoEncodingExtendedMouseButtons);
}
5 changes: 5 additions & 0 deletions common/rfb/SMsgWriter.h
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ namespace rfb {
// And QEMU keyboard event handshake
void writeQEMUKeyEvent();

// let the client know we support extended mouse button support
void writeExtendedMouseButtonsSupport();

// needFakeUpdate() returns true when an immediate update is needed in
// order to flush out pseudo-rectangles to the client.
bool needFakeUpdate();
Expand Down Expand Up @@ -148,6 +151,7 @@ namespace rfb {
void writeSetVMwareCursorPositionRect(int hotspotX, int hotspotY);
void writeLEDStateRect(uint8_t state);
void writeQEMUKeyEventRect();
void writeExtendedMouseButtonsRect();

ClientParams* client;
rdr::OutStream* os;
Expand All @@ -160,6 +164,7 @@ namespace rfb {
bool needCursorPos;
bool needLEDState;
bool needQEMUKeyEvent;
bool needExtMouseButtonsEvent;

typedef struct {
uint16_t reason, result;
Expand Down
2 changes: 1 addition & 1 deletion common/rfb/ServerParams.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ ServerParams::ServerParams()
: majorVersion(0), minorVersion(0),
supportsQEMUKeyEvent(false),
supportsSetDesktopSize(false), supportsFence(false),
supportsContinuousUpdates(false),
supportsContinuousUpdates(false), supportsExtendedMouseButtons(false),
width_(0), height_(0),
ledState_(ledUnknown)
{
Expand Down
1 change: 1 addition & 0 deletions common/rfb/ServerParams.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,7 @@ namespace rfb {
bool supportsSetDesktopSize;
bool supportsFence;
bool supportsContinuousUpdates;
bool supportsExtendedMouseButtons;

private:

Expand Down
2 changes: 1 addition & 1 deletion common/rfb/VNCSConnectionST.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -477,7 +477,7 @@ void VNCSConnectionST::setPixelFormat(const PixelFormat& pf)
setCursor();
}

void VNCSConnectionST::pointerEvent(const Point& pos, uint8_t buttonMask)
void VNCSConnectionST::pointerEvent(const Point& pos, uint16_t buttonMask)
{
if (rfb::Server::idleTimeout)
idleTimer.start(secsToMillis(rfb::Server::idleTimeout));
Expand Down
2 changes: 1 addition & 1 deletion common/rfb/VNCSConnectionST.h
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ namespace rfb {
void queryConnection(const char* userName) override;
void clientInit(bool shared) override;
void setPixelFormat(const PixelFormat& pf) override;
void pointerEvent(const Point& pos, uint8_t buttonMask) override;
void pointerEvent(const Point& pos, uint16_t buttonMask) override;
void keyEvent(uint32_t keysym, uint32_t keycode,
bool down) override;
void framebufferUpdateRequest(const Rect& r,
Expand Down
2 changes: 1 addition & 1 deletion common/rfb/VNCServerST.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ void VNCServerST::keyEvent(uint32_t keysym, uint32_t keycode, bool down)
}

void VNCServerST::pointerEvent(VNCSConnectionST* client,
const Point& pos, uint8_t buttonMask)
const Point& pos, uint16_t buttonMask)
{
time_t now = time(nullptr);
if (rfb::Server::maxIdleTime)
Expand Down
Loading