Skip to content

Commit

Permalink
Convert screen layout change request to signals
Browse files Browse the repository at this point in the history
  • Loading branch information
CendioOssman committed Aug 13, 2024
1 parent 376c9db commit 83065da
Show file tree
Hide file tree
Showing 14 changed files with 83 additions and 57 deletions.
21 changes: 21 additions & 0 deletions common/rfb/SConnection.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ SConnection::SConnection(AccessRights accessRights_)
registerSignal<bool>("clipboardannounce");
registerSignal<const char*>("clipboarddata");

registerSignal<LayoutEvent>("layoutrequest");

defaultMajorVersion = 3;
defaultMinorVersion = 8;
if (rfb::Server::protocol3_3)
Expand Down Expand Up @@ -539,6 +541,25 @@ void SConnection::handleClipboardProvide(uint32_t flags,
emitSignal("clipboarddata", clientClipboard.c_str());
}

void SConnection::setDesktopSize(int fb_width, int fb_height,
const ScreenSet& layout)
{
char buffer[2048];

vlog.debug("Got request for framebuffer resize to %dx%d",
fb_width, fb_height);
layout.print(buffer, sizeof(buffer));
vlog.debug("%s", buffer);

if (!accessCheck(AccessSetDesktopSize)) {
vlog.debug("Rejecting unauthorized framebuffer resize request");
writer()->writeDesktopSize(reasonClient, resultProhibited);
} else {
emitSignal("layoutrequest",
LayoutEvent({fb_width, fb_height, layout}));
}
}

void SConnection::supportsLocalCursor()
{
}
Expand Down
11 changes: 11 additions & 0 deletions common/rfb/SConnection.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ namespace rfb {
uint8_t buttonMask;
};

struct LayoutEvent {
int width, height;
ScreenSet layout;
};

class SConnection : public core::Object, public SMsgHandler {
public:

Expand Down Expand Up @@ -180,6 +185,9 @@ namespace rfb {
// client received the request. A const char* string is included
// that contains the actual clipboard contents.

// "layoutrequest" is emitted whenever the client requests the to
// reconfigure the framebuffer and/or the layout of screens.

protected:

// Overridden from SMsgHandler
Expand All @@ -201,6 +209,9 @@ namespace rfb {
void handleClipboardProvide(uint32_t flags, const size_t* lengths,
const uint8_t* const* data) override;

void setDesktopSize(int fb_width, int fb_height,
const ScreenSet& layout) override;

// Methods to be overridden in a derived class

// supportsLocalCursor() is called whenever the status of
Expand Down
5 changes: 0 additions & 5 deletions common/rfb/SDesktop.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,11 +61,6 @@ namespace rfb {
virtual void queryConnection(network::Socket* sock,
const char* userName) = 0;

// setScreenLayout() requests to reconfigure the framebuffer and/or
// the layout of screens.
virtual void setScreenLayout(int fb_width, int fb_height,
const ScreenSet& layout) = 0;

protected:
virtual ~SDesktop() {}
};
Expand Down
18 changes: 0 additions & 18 deletions common/rfb/VNCSConnectionST.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -671,24 +671,6 @@ void VNCSConnectionST::framebufferUpdateRequest(const core::Rect& r,bool increme
}
}

void VNCSConnectionST::setDesktopSize(int fb_width, int fb_height,
const ScreenSet& layout)
{
char buffer[2048];

vlog.debug("Got request for framebuffer resize to %dx%d",
fb_width, fb_height);
layout.print(buffer, sizeof(buffer));
vlog.debug("%s", buffer);

if (!accessCheck(AccessSetDesktopSize)) {
vlog.debug("Rejecting unauthorized framebuffer resize request");
setDesktopSizeFailure(resultProhibited);
} else {
server->setDesktopSize(this, fb_width, fb_height, layout);
}
}

void VNCSConnectionST::fence(uint32_t flags, unsigned len, const uint8_t data[])
{
uint8_t type;
Expand Down
2 changes: 0 additions & 2 deletions common/rfb/VNCSConnectionST.h
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,6 @@ namespace rfb {
bool down) override;
void framebufferUpdateRequest(const core::Rect& r,
bool incremental) override;
void setDesktopSize(int fb_width, int fb_height,
const ScreenSet& layout) override;
void fence(uint32_t flags, unsigned len,
const uint8_t data[]) override;
void enableContinuousUpdates(bool enable,
Expand Down
3 changes: 3 additions & 0 deletions common/rfb/VNCServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -198,6 +198,9 @@ namespace rfb {
// client received the request. A const char* string is included
// that contains the actual clipboard contents.

// "layoutrequest" is emitted whenever the client requests the to
// reconfigure the framebuffer and/or the layout of screens.

// "frame" is emitted whenever a frame update has been processed,
// signalling that a good time to render new data
};
Expand Down
17 changes: 11 additions & 6 deletions common/rfb/VNCServerST.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,8 @@ VNCServerST::VNCServerST(const char* name_, SDesktop* desktop_)
registerSignal<bool>("clipboardannounce");
registerSignal<const char*>("clipboarddata");

registerSignal<LayoutEvent>("layoutrequest");

registerSignal("frame");

idleTimer.connectSignal("timer", this,
Expand Down Expand Up @@ -206,6 +208,9 @@ void VNCServerST::addSocket(network::Socket* sock, bool outgoing, AccessRights a
client->connectSignal("clipboarddata", this,
&VNCServerST::handleClipboardData);

client->connectSignal("layoutrequest", this,
&VNCServerST::handleLayoutRequest);

client->init();
}

Expand Down Expand Up @@ -622,9 +627,9 @@ void VNCServerST::pointerEvent(VNCSConnectionST* client,
emitSignal(evname, event);
}

void VNCServerST::setDesktopSize(VNCSConnectionST* requester,
int fb_width, int fb_height,
const ScreenSet& layout)
void VNCServerST::handleLayoutRequest(VNCSConnectionST* requester,
const char* evname,
LayoutEvent event)
{
std::list<VNCSConnectionST*>::iterator ci;

Expand All @@ -635,14 +640,14 @@ void VNCServerST::setDesktopSize(VNCSConnectionST* requester,

// We can't handle a framebuffer larger than this, so don't let a
// client set one (see PixelBuffer.cxx)
if ((fb_width > 16384) || (fb_height > 16384)) {
if ((event.width > 16384) || (event.height > 16384)) {
slog.error("Rejecting too large framebuffer resize request");
requester->setDesktopSizeFailureOrClose(resultProhibited);
return;
}

// Don't bother the desktop with an invalid configuration
if (!layout.validate(fb_width, fb_height)) {
if (!event.layout.validate(event.width, event.height)) {
slog.error("Invalid screen layout requested by client");
requester->setDesktopSizeFailureOrClose(resultInvalid);
return;
Expand All @@ -661,7 +666,7 @@ void VNCServerST::setDesktopSize(VNCSConnectionST* requester,
// FIXME: the desktop will call back to VNCServerST and an extra set
// of ExtendedDesktopSize messages will be sent. This is okay
// protocol-wise, but unnecessary.
desktop->setScreenLayout(fb_width, fb_height, layout);
emitSignal(evname, event);
}

// Other public methods
Expand Down
9 changes: 4 additions & 5 deletions common/rfb/VNCServerST.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,11 +118,6 @@ namespace rfb {
const char* getName() const { return name.c_str(); }
unsigned getLEDState() const { return ledState; }

// Event handlers
void setDesktopSize(VNCSConnectionST* requester,
int fb_width, int fb_height,
const ScreenSet& layout);

// closeClients() closes all RFB sessions, except the specified one (if
// any), and logs the specified reason for closure.
void closeClients(const char* reason, network::Socket* sock);
Expand Down Expand Up @@ -162,6 +157,10 @@ namespace rfb {
void handleClipboardData(VNCSConnectionST* client,
const char*, const char* data);

void handleLayoutRequest(VNCSConnectionST* client,
const char* name,
LayoutEvent event);

// Timer callbacks
void frameTimeout(core::Timer*, const char*);
void idleTimeout(core::Timer*, const char*);
Expand Down
22 changes: 13 additions & 9 deletions unix/x0vncserver/XDesktop.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -249,6 +249,9 @@ void XDesktop::init(VNCServer* vs)
server->connectSignal("keydown", this, &XDesktop::keyEvent);
server->connectSignal("keyup", this, &XDesktop::keyEvent);
server->connectSignal("pointer", this, &XDesktop::pointerEvent);

server->connectSignal("layoutrequest", this,
&XDesktop::layoutRequest);
}

void XDesktop::start(VNCServer*, const char*)
Expand Down Expand Up @@ -685,8 +688,8 @@ static void GetSmallerMode(XRRScreenResources *res,
}
#endif /* HAVE_XRANDR */

void XDesktop::setScreenLayout(int fb_width, int fb_height,
const rfb::ScreenSet& layout)
void XDesktop::layoutRequest(rfb::VNCServer*, const char*,
rfb::LayoutEvent event)
{
#ifdef HAVE_XRANDR
unsigned int ret;
Expand All @@ -707,15 +710,16 @@ void XDesktop::setScreenLayout(int fb_width, int fb_height,
cases, we first call tryScreenLayout. If this fails, we try to
adjust the request to one screen with a smaller mode. */
vlog.debug("Testing screen layout");
ret = ::tryScreenLayout(fb_width, fb_height, layout, &outputIdMap);
ret = ::tryScreenLayout(event.width, event.height,
event.layout, &outputIdMap);
if (ret == rfb::resultSuccess) {
adjustedWidth = fb_width;
adjustedHeight = fb_height;
adjustedLayout = layout;
adjustedWidth = event.width;
adjustedHeight = event.height;
adjustedLayout = event.layout;
} else {
vlog.debug("Impossible layout - trying to adjust");

ScreenSet::const_iterator firstscreen = layout.begin();
ScreenSet::const_iterator firstscreen = event.layout.begin();
adjustedLayout.add_screen(*firstscreen);
ScreenSet::iterator iter = adjustedLayout.begin();
RROutput outputId = None;
Expand Down Expand Up @@ -837,7 +841,7 @@ void XDesktop::setScreenLayout(int fb_width, int fb_height,
VNCSConnectionST::setDesktopSize. Another ExtendedDesktopSize
with reason=0 will be sent in response to the changes seen by the
event handler. */
if (adjustedLayout != layout) {
if (adjustedLayout != event.layout) {
server->rejectScreenLayout(rfb::resultInvalid);
return;
}
Expand All @@ -847,7 +851,7 @@ void XDesktop::setScreenLayout(int fb_width, int fb_height,
server->setScreenLayout(computeScreenLayout());

if (ret == rfb::resultSuccess)
server->acceptScreenLayout(fb_width, fb_height, layout);
server->acceptScreenLayout(event.width, event.height, event.layout);
else
server->rejectScreenLayout(rfb::resultInvalid);

Expand Down
4 changes: 2 additions & 2 deletions unix/x0vncserver/XDesktop.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,6 @@ class XDesktop : public rfb::SDesktop,
bool isRunning();
void queryConnection(network::Socket* sock,
const char* userName) override;
void setScreenLayout(int fb_width, int fb_height,
const rfb::ScreenSet& layout) override;

// -=- TXGlobalEventHandler interface
bool handleGlobalEvent(XEvent* ev) override;
Expand All @@ -75,6 +73,8 @@ class XDesktop : public rfb::SDesktop,
rfb::PointerEvent event);
void keyEvent(rfb::VNCServer*, const char* name,
rfb::KeyEvent event);
void layoutRequest(rfb::VNCServer*, const char*,
rfb::LayoutEvent event);

protected:
Display* dpy;
Expand Down
13 changes: 9 additions & 4 deletions unix/xserver/hw/vnc/XserverDesktop.cc
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,9 @@ XserverDesktop::XserverDesktop(int screenIndex_,
server->connectSignal("clipboarddata", this,
&XserverDesktop::handleClipboardData);

server->connectSignal("layoutrequest", this,
&XserverDesktop::layoutRequest);

setFramebuffer(width, height, fbptr, stride_);

queryConnectTimer.connectSignal("timer", this,
Expand Down Expand Up @@ -481,20 +484,22 @@ void XserverDesktop::pointerEvent(rfb::VNCServerST*, const char*,
vncPointerButtonAction(event.buttonMask);
}

void XserverDesktop::setScreenLayout(int fb_width, int fb_height,
const rfb::ScreenSet& layout)
void XserverDesktop::layoutRequest(rfb::VNCServerST*, const char*,
rfb::LayoutEvent event)
{
unsigned int result;

vncSetGlueContext(screenIndex);
result = ::setScreenLayout(fb_width, fb_height, layout, &outputIdMap);
result = ::setScreenLayout(event.width, event.height,
event.layout, &outputIdMap);

// Explicitly update the server state with the result as there
// can be corner cases where we don't get feedback from the X core
refreshScreenLayout();

if (result == rfb::resultSuccess)
server->acceptScreenLayout(fb_width, fb_height, layout);
server->acceptScreenLayout(event.width, event.height,
event.layout);
else
server->rejectScreenLayout(result);
}
Expand Down
5 changes: 3 additions & 2 deletions unix/xserver/hw/vnc/XserverDesktop.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,6 @@ class XserverDesktop : public rfb::SDesktop,
void init(rfb::VNCServer* vs) override;
void queryConnection(network::Socket* sock,
const char* userName) override;
void setScreenLayout(int fb_width, int fb_height,
const rfb::ScreenSet& layout) override;

// rfb::PixelBuffer callbacks
void grabRegion(const core::Region& r) override;
Expand All @@ -113,6 +111,9 @@ class XserverDesktop : public rfb::SDesktop,
void handleClipboardData(rfb::VNCServerST*, const char*,
const char* data);

void layoutRequest(rfb::VNCServerST*, const char*,
rfb::LayoutEvent event) ;

void frameTick(rfb::VNCServerST*, const char*);

bool handleListenerEvent(int fd,
Expand Down
6 changes: 4 additions & 2 deletions win/rfb_win32/SDisplay.cxx
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,9 @@ void SDisplay::init(VNCServer* vs)
&SDisplay::handleClipboardAnnounce);
server->connectSignal("clipboarddata", this,
&SDisplay::handleClipboardData);

server->connectSignal("layoutrequest", this,
&SDisplay::layoutRequest);
}

void SDisplay::start(VNCServer*, const char*)
Expand Down Expand Up @@ -180,8 +183,7 @@ void SDisplay::queryConnection(network::Socket* sock,
}


void SDisplay::setScreenLayout(int /*fb_width*/, int /*fb_height*/,
const ScreenSet& /*layout*/)
void SDisplay::layoutRequest(VNCServer*, const char*, LayoutEvent)
{
assert(server != nullptr);
server->rejectScreenLayout(rfb::resultProhibited);
Expand Down
4 changes: 2 additions & 2 deletions win/rfb_win32/SDisplay.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,8 +74,6 @@ namespace rfb {
void init(VNCServer* vs) override;
void queryConnection(network::Socket* sock,
const char* userName) override;
void setScreenLayout(int fb_width, int fb_height,
const ScreenSet& layout) override;

// -=- Clipboard events

Expand Down Expand Up @@ -132,6 +130,8 @@ namespace rfb {
void handleClipboardData(VNCServer*, const char*,
const char* data);

void layoutRequest(VNCServer*, const char*, LayoutEvent);

VNCServer* server;

// -=- Display pixel buffer
Expand Down

0 comments on commit 83065da

Please sign in to comment.