diff --git a/common/rfb/InputHandler.h b/common/rfb/InputHandler.h index 6c07284..806625f 100644 --- a/common/rfb/InputHandler.h +++ b/common/rfb/InputHandler.h @@ -36,7 +36,9 @@ namespace rfb { rdr::U32 __unused_attr keycode, bool __unused_attr down) { } virtual void pointerEvent(const Point& __unused_attr pos, - int __unused_attr buttonMask) { } + int __unused_attr buttonMask, + const bool __unused_attr skipClick, + const bool __unused_attr skipRelease) { } virtual void clientCutText(const char* __unused_attr str, int __unused_attr len) { } }; diff --git a/common/rfb/SMsgReader.cxx b/common/rfb/SMsgReader.cxx index 7fb3f2c..a71272a 100644 --- a/common/rfb/SMsgReader.cxx +++ b/common/rfb/SMsgReader.cxx @@ -217,7 +217,7 @@ void SMsgReader::readPointerEvent() int mask = is->readU8(); int x = is->readU16(); int y = is->readU16(); - handler->pointerEvent(Point(x, y), mask); + handler->pointerEvent(Point(x, y), mask, false, false); } diff --git a/common/rfb/ServerCore.cxx b/common/rfb/ServerCore.cxx index 94f1196..3b36af0 100644 --- a/common/rfb/ServerCore.cxx +++ b/common/rfb/ServerCore.cxx @@ -168,6 +168,15 @@ rfb::StringParameter rfb::Server::DLP_Region "Black out anything outside this region", ""); +rfb::BoolParameter rfb::Server::DLP_RegionAllowClick +("DLP_RegionAllowClick", + "Allow clicks inside the blacked-out region", + false); +rfb::BoolParameter rfb::Server::DLP_RegionAllowRelease +("DLP_RegionAllowRelease", + "Allow click releases inside the blacked-out region", + true); + rfb::StringParameter rfb::Server::maxVideoResolution ("MaxVideoResolution", "When in video mode, downscale the screen to max this size.", diff --git a/common/rfb/ServerCore.h b/common/rfb/ServerCore.h index 77314bd..280596f 100644 --- a/common/rfb/ServerCore.h +++ b/common/rfb/ServerCore.h @@ -50,6 +50,8 @@ namespace rfb { static IntParameter DLP_KeyRateLimit; static StringParameter DLP_ClipLog; static StringParameter DLP_Region; + static BoolParameter DLP_RegionAllowClick; + static BoolParameter DLP_RegionAllowRelease; static IntParameter jpegVideoQuality; static IntParameter webpVideoQuality; static StringParameter maxVideoResolution; diff --git a/common/rfb/VNCSConnectionST.cxx b/common/rfb/VNCSConnectionST.cxx index 467e8f9..05f9282 100644 --- a/common/rfb/VNCSConnectionST.cxx +++ b/common/rfb/VNCSConnectionST.cxx @@ -637,7 +637,7 @@ void VNCSConnectionST::setPixelFormat(const PixelFormat& pf) setCursor(); } -void VNCSConnectionST::pointerEvent(const Point& pos, int buttonMask) +void VNCSConnectionST::pointerEvent(const Point& pos, int buttonMask, const bool skipClick, const bool skipRelease) { pointerEventTime = lastEventTime = time(0); server->lastUserInputTime = lastEventTime; @@ -649,7 +649,23 @@ void VNCSConnectionST::pointerEvent(const Point& pos, int buttonMask) server->pointerClient = this; else server->pointerClient = 0; - server->desktop->pointerEvent(pointerEventPos, buttonMask); + + bool skipclick = false, skiprelease = false; + if (server->DLPRegion.enabled) { + rdr::U16 x1, y1, x2, y2; + server->translateDLPRegion(x1, y1, x2, y2); + + if (pos.x < x1 || pos.x >= x2 || + pos.y < y1 || pos.y >= y2) { + + if (!Server::DLP_RegionAllowClick) + skipclick = true; + if (!Server::DLP_RegionAllowRelease) + skiprelease = true; + } + } + + server->desktop->pointerEvent(pointerEventPos, buttonMask, skipclick, skiprelease); } } diff --git a/common/rfb/VNCSConnectionST.h b/common/rfb/VNCSConnectionST.h index 3eff9ad..d1e1267 100644 --- a/common/rfb/VNCSConnectionST.h +++ b/common/rfb/VNCSConnectionST.h @@ -168,7 +168,7 @@ namespace rfb { virtual void queryConnection(const char* userName); virtual void clientInit(bool shared); virtual void setPixelFormat(const PixelFormat& pf); - virtual void pointerEvent(const Point& pos, int buttonMask); + virtual void pointerEvent(const Point& pos, int buttonMask, const bool skipClick, const bool skipRelease); virtual void keyEvent(rdr::U32 keysym, rdr::U32 keycode, bool down); virtual void clientCutText(const char* str, int len); virtual void framebufferUpdateRequest(const Rect& r, bool incremental); diff --git a/common/rfb/VNCServerST.cxx b/common/rfb/VNCServerST.cxx index 1e2a12f..5cd317a 100644 --- a/common/rfb/VNCServerST.cxx +++ b/common/rfb/VNCServerST.cxx @@ -123,7 +123,7 @@ static void parseRegionPart(const bool percents, rdr::U16 &pcdest, int &dest, VNCServerST::VNCServerST(const char* name_, SDesktop* desktop_) : blHosts(&blacklist), desktop(desktop_), desktopStarted(false), - blockCounter(0), pb(0), ledState(ledUnknown), + blockCounter(0), pb(0), blackedpb(0), ledState(ledUnknown), name(strDup(name_)), pointerClient(0), comparer(0), cursor(new Cursor(0, 0, Point(), NULL)), renderedCursorInvalid(false), @@ -800,11 +800,8 @@ static void checkAPIMessages(network::GetAPIMessager *apimessager) pthread_mutex_unlock(&apimessager->userMutex); } -void VNCServerST::blackOut() +void VNCServerST::translateDLPRegion(rdr::U16 &x1, rdr::U16 &y1, rdr::U16 &x2, rdr::U16 &y2) const { - // Compute the region, since the resolution may have changed - rdr::U16 x1, y1, x2, y2; - if (DLPRegion.percents) { x1 = DLPRegion.pcx1 ? DLPRegion.pcx1 * pb->getRect().width() / 100 : 0; y1 = DLPRegion.pcy1 ? DLPRegion.pcy1 * pb->getRect().height() / 100 : 0; @@ -834,11 +831,25 @@ void VNCServerST::blackOut() //slog.info("DLP_Region vals %u,%u %u,%u", x1, y1, x2, y2); - ManagedPixelBuffer *mpb = (ManagedPixelBuffer *) pb; +void VNCServerST::blackOut() +{ + // Compute the region, since the resolution may have changed + rdr::U16 x1, y1, x2, y2; + + translateDLPRegion(x1, y1, x2, y2); + + if (blackedpb) + delete blackedpb; + blackedpb = new ManagedPixelBuffer(pb->getPF(), pb->getRect().width(), pb->getRect().height()); + int stride; + const rdr::U8 *src = pb->getBuffer(pb->getRect(), &stride); + rdr::U8 *data = blackedpb->getBufferRW(pb->getRect(), &stride); rdr::U8 *data = mpb->getBufferRW(mpb->getRect(), &stride); stride *= 4; + memcpy(data, src, stride * pb->getRect().height()); + rdr::U16 y; const rdr::U16 w = pb->getRect().width(); const rdr::U16 h = pb->getRect().height(); @@ -873,8 +884,10 @@ void VNCServerST::writeUpdate() assert(blockCounter == 0); assert(desktopStarted); - if (DLPRegion.enabled) + if (DLPRegion.enabled) { + comparer->enable_copyrect(false); blackOut(); + } comparer->getUpdateInfo(&ui, pb->getRect()); toCheck = ui.changed.union_(ui.copied); diff --git a/common/rfb/VNCServerST.h b/common/rfb/VNCServerST.h index b42f63c..7872141 100644 --- a/common/rfb/VNCServerST.h +++ b/common/rfb/VNCServerST.h @@ -95,7 +95,7 @@ namespace rfb { virtual void setPixelBuffer(PixelBuffer* pb, const ScreenSet& layout); virtual void setPixelBuffer(PixelBuffer* pb); virtual void setScreenLayout(const ScreenSet& layout); - virtual PixelBuffer* getPixelBuffer() const { return pb; } + virtual PixelBuffer* getPixelBuffer() const { if (DLPRegion.enabled && blackedpb) return blackedpb; else return pb; } virtual void serverCutText(const char* str, int len); virtual void add_changed(const Region ®ion); virtual void add_copied(const Region &dest, const Point &delta); @@ -209,6 +209,7 @@ namespace rfb { bool desktopStarted; int blockCounter; PixelBuffer* pb; + ManagedPixelBuffer *blackedpb; ScreenSet screenLayout; unsigned int ledState; @@ -264,6 +265,8 @@ namespace rfb { bool percents; rdr::U16 pcx1, pcy1, pcx2, pcy2; } DLPRegion; + + void translateDLPRegion(rdr::U16 &x1, rdr::U16 &y1, rdr::U16 &x2, rdr::U16 &y2) const; }; }; diff --git a/unix/xserver/hw/vnc/Input.c b/unix/xserver/hw/vnc/Input.c index 2519ad3..f8ac3fd 100644 --- a/unix/xserver/hw/vnc/Input.c +++ b/unix/xserver/hw/vnc/Input.c @@ -155,7 +155,8 @@ static void enqueueEvents(DeviceIntPtr dev, int n) } #endif /* XORG < 111 */ -void vncPointerButtonAction(int buttonMask) +void vncPointerButtonAction(int buttonMask, const unsigned char skipclick, + const unsigned char skiprelease) { int i; #if XORG < 111 @@ -169,6 +170,14 @@ void vncPointerButtonAction(int buttonMask) if ((buttonMask ^ oldButtonMask) & (1 << i)) { int action = (buttonMask & (1<