Skip to content

Commit

Permalink
Xvnc: support ExtendedMouseButtons pseudo-encoding
Browse files Browse the repository at this point in the history
This commit contains work originally done by manny33:
  * #1711

This commit adds support for the pseudo-encoding ExtendedMouseButtons in
Xvnc, which makes it possible to use to use the back/forward mouse
buttons.

The back/forward buttons are mapped to the X11 button labels
BTN_LABEL_PROP_BTN_SIDE and BTN_LABEL_PROP_BTN_EXTRA respectively. These
seems to be used more widely both by mice with extra side buttons, as
well as X applications to incidate a back/forward navigation.

There are two other labels:
  BTN_LABEL_PROP_BTN_BACK,
  BTN_LABEL_PROP_BTN_EXTRA,
which some applications listen to as well. But from what I've seen, the
applications that listen to these two labels also listen to SIDE/EXTRA
as well.
  • Loading branch information
CendioHalim committed Sep 24, 2024
1 parent 2fe9dca commit 34ef409
Show file tree
Hide file tree
Showing 22 changed files with 123 additions and 19 deletions.
2 changes: 1 addition & 1 deletion common/rfb/CMsgWriter.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ 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)
{
Point p(pos);
if (p.x < 0) p.x = 0;
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 & 0x180 ) {
int highBits;
int lowBits;

if (!is->hasDataOrRestore(1))
return false;

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/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
2 changes: 1 addition & 1 deletion common/rfb/VNCServerST.h
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ namespace rfb {

// Event handlers
void keyEvent(uint32_t keysym, uint32_t keycode, bool down);
void pointerEvent(VNCSConnectionST* client, const Point& pos, uint8_t buttonMask);
void pointerEvent(VNCSConnectionST* client, const Point& pos, uint16_t buttonMask);

void handleClipboardRequest(VNCSConnectionST* client);
void handleClipboardAnnounce(VNCSConnectionST* client, bool available);
Expand Down
1 change: 1 addition & 0 deletions common/rfb/encodings.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ namespace rfb {

const int pseudoEncodingXCursor = -240;
const int pseudoEncodingCursor = -239;
const int pseudoEncodingExtendedMouseButtons = -316;
const int pseudoEncodingDesktopSize = -223;
const int pseudoEncodingLEDState = -261;
const int pseudoEncodingExtendedDesktopSize = -308;
Expand Down
2 changes: 1 addition & 1 deletion unix/x0vncserver/XDesktop.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ void XDesktop::queryConnection(network::Socket* sock,
queryConnectDialog->map();
}

void XDesktop::pointerEvent(const Point& pos, uint8_t buttonMask) {
void XDesktop::pointerEvent(const Point& pos, uint16_t buttonMask) {
#ifdef HAVE_XTEST
if (!haveXtest) return;
XTestFakeMotionEvent(dpy, DefaultScreen(dpy),
Expand Down
2 changes: 1 addition & 1 deletion unix/x0vncserver/XDesktop.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ class XDesktop : public rfb::SDesktop,
bool isRunning();
void queryConnection(network::Socket* sock,
const char* userName) override;
void pointerEvent(const rfb::Point& pos, uint8_t buttonMask) override;
void pointerEvent(const rfb::Point& pos, uint16_t buttonMask) override;
void keyEvent(uint32_t keysym, uint32_t xtcode, bool down) override;
unsigned int setScreenLayout(int fb_width, int fb_height,
const rfb::ScreenSet& layout) override;
Expand Down
2 changes: 1 addition & 1 deletion unix/xserver/hw/vnc/XserverDesktop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ void XserverDesktop::terminate()
kill(getpid(), SIGTERM);
}

void XserverDesktop::pointerEvent(const Point& pos, uint8_t buttonMask)
void XserverDesktop::pointerEvent(const Point& pos, uint16_t buttonMask)
{
vncPointerMove(pos.x + vncGetScreenX(screenIndex),
pos.y + vncGetScreenY(screenIndex));
Expand Down
2 changes: 1 addition & 1 deletion unix/xserver/hw/vnc/XserverDesktop.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ class XserverDesktop : public rfb::SDesktop, public rfb::FullFramePixelBuffer,
void terminate() override;
void queryConnection(network::Socket* sock,
const char* userName) override;
void pointerEvent(const rfb::Point& pos, uint8_t buttonMask) override;
void pointerEvent(const rfb::Point& pos, uint16_t buttonMask) override;
void keyEvent(uint32_t keysym, uint32_t keycode, bool down) override;
unsigned int setScreenLayout(int fb_width, int fb_height,
const rfb::ScreenSet& layout) override;
Expand Down
21 changes: 20 additions & 1 deletion unix/xserver/hw/vnc/vncInput.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ extern const unsigned int code_map_qnum_to_xorgevdev_len;
extern const unsigned short code_map_qnum_to_xorgkbd[];
extern const unsigned int code_map_qnum_to_xorgkbd_len;

#define BUTTONS 7
#define BUTTONS 9

DeviceIntPtr vncKeyboardDev;
DeviceIntPtr vncPointerDev;
Expand Down Expand Up @@ -207,6 +207,25 @@ static int vncPointerProc(DeviceIntPtr pDevice, int onoff)
btn_labels[5] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_LEFT);
btn_labels[6] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_HWHEEL_RIGHT);

/*
* The labels BTN_LABEL_PROP_BTN_SIDE and BTN_LABEL_PROP_BTN_EXTRA
* represent the side buttons on mice that are typically used to
* navigate back/forward respectively in web browsers (and other
* applications).
*
* There are also two similar labels:
* BTN_LABEL_PROP_BTN_BACK and BTN_LABEL_PROP_BTN_FORWARD,
* which are also used by *some* X applications to indicate
* back/forward navigation. The SIDE/EXTRA labels seem to be more
* widely spread by X applications, and some applications even
* detect both labels.
*
* Most modern mice seem to label the side buttons
* (back / forward) with SIDE/EXTRA.
*/
btn_labels[7] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_SIDE);
btn_labels[8] = XIGetKnownProperty(BTN_LABEL_PROP_BTN_EXTRA);

axes_labels[0] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_X);
axes_labels[1] = XIGetKnownProperty(AXIS_LABEL_PROP_REL_Y);

Expand Down

0 comments on commit 34ef409

Please sign in to comment.