diff options
Diffstat (limited to 'unix')
-rw-r--r-- | unix/vncconfig/QueryConnectDialog.cxx | 5 | ||||
-rw-r--r-- | unix/vncconfig/QueryConnectDialog.h | 2 | ||||
-rw-r--r-- | unix/vncconfig/vncconfig.cxx | 2 | ||||
-rw-r--r-- | unix/x0vncserver/XDesktop.cxx | 10 | ||||
-rw-r--r-- | unix/x0vncserver/XDesktop.h | 3 | ||||
-rw-r--r-- | unix/x0vncserver/x0vncserver.cxx | 7 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/Makefile.am | 4 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/XserverDesktop.cc | 46 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/XserverDesktop.h | 13 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/vncExtInit.cc | 29 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/vncExtInit.h | 6 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/vncPresent.c | 93 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/vncPresent.h | 27 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/xvnc.c | 11 |
14 files changed, 225 insertions, 33 deletions
diff --git a/unix/vncconfig/QueryConnectDialog.cxx b/unix/vncconfig/QueryConnectDialog.cxx index e13af34b..e725de7d 100644 --- a/unix/vncconfig/QueryConnectDialog.cxx +++ b/unix/vncconfig/QueryConnectDialog.cxx @@ -74,14 +74,13 @@ void QueryConnectDialog::buttonActivate(TXButton* b) { callback->queryRejected(); } -bool QueryConnectDialog::handleTimeout(rfb::Timer* /*t*/) { +void QueryConnectDialog::handleTimeout(rfb::Timer* t) { if (timeUntilReject-- == 0) { unmap(); callback->queryTimedOut(); - return false; } else { refreshTimeout(); - return true; + t->repeat(); } } diff --git a/unix/vncconfig/QueryConnectDialog.h b/unix/vncconfig/QueryConnectDialog.h index f685dc34..dcf64e40 100644 --- a/unix/vncconfig/QueryConnectDialog.h +++ b/unix/vncconfig/QueryConnectDialog.h @@ -43,7 +43,7 @@ class QueryConnectDialog : public TXDialog, public TXEventHandler, void handleEvent(TXWindow*, XEvent* ) { } void deleteWindow(TXWindow*); void buttonActivate(TXButton* b); - bool handleTimeout(rfb::Timer* t); + void handleTimeout(rfb::Timer* t); private: void refreshTimeout(); TXLabel addressLbl, address, userLbl, user, timeoutLbl, timeout; diff --git a/unix/vncconfig/vncconfig.cxx b/unix/vncconfig/vncconfig.cxx index e0c9928a..30d04ca6 100644 --- a/unix/vncconfig/vncconfig.cxx +++ b/unix/vncconfig/vncconfig.cxx @@ -313,7 +313,7 @@ int main(int argc, char** argv) // Process expired timers and get the time until the next one int timeoutMs = Timer::checkTimeouts(); - if (timeoutMs) { + if (timeoutMs >= 0) { tv.tv_sec = timeoutMs / 1000; tv.tv_usec = (timeoutMs % 1000) * 1000; tvp = &tv; diff --git a/unix/x0vncserver/XDesktop.cxx b/unix/x0vncserver/XDesktop.cxx index da298d35..55ea9667 100644 --- a/unix/x0vncserver/XDesktop.cxx +++ b/unix/x0vncserver/XDesktop.cxx @@ -232,9 +232,13 @@ void XDesktop::poll() { } } +void XDesktop::init(VNCServer* vs) +{ + server = vs; +} -void XDesktop::start(VNCServer* vs) { - +void XDesktop::start() +{ // Determine actual number of buttons of the X pointer device. unsigned char btnMap[8]; int numButtons = XGetPointerMapping(dpy, btnMap, 8); @@ -249,7 +253,6 @@ void XDesktop::start(VNCServer* vs) { pb = new XPixelBuffer(dpy, factory, geometry->getRect()); vlog.info("Allocated %s", pb->getImage()->classDesc()); - server = vs; server->setPixelBuffer(pb, computeScreenLayout()); #ifdef HAVE_XDAMAGE @@ -292,7 +295,6 @@ void XDesktop::stop() { queryConnectDialog = 0; server->setPixelBuffer(0); - server = 0; delete pb; pb = 0; diff --git a/unix/x0vncserver/XDesktop.h b/unix/x0vncserver/XDesktop.h index 1cb73f43..fc230e5b 100644 --- a/unix/x0vncserver/XDesktop.h +++ b/unix/x0vncserver/XDesktop.h @@ -47,7 +47,8 @@ public: virtual ~XDesktop(); void poll(); // -=- SDesktop interface - virtual void start(rfb::VNCServer* vs); + virtual void init(rfb::VNCServer* vs); + virtual void start(); virtual void stop(); virtual void terminate(); bool isRunning(); diff --git a/unix/x0vncserver/x0vncserver.cxx b/unix/x0vncserver/x0vncserver.cxx index 8e27e62b..ffaf5788 100644 --- a/unix/x0vncserver/x0vncserver.cxx +++ b/unix/x0vncserver/x0vncserver.cxx @@ -382,7 +382,7 @@ int main(int argc, char** argv) PollingScheduler sched((int)pollingCycle, (int)maxProcessorUsage); while (!caughtSignal) { - int wait_ms; + int wait_ms, nextTimeout; struct timeval tv; fd_set rfds, wfds; std::list<Socket*> sockets; @@ -426,7 +426,10 @@ int main(int argc, char** argv) } } - soonestTimeout(&wait_ms, Timer::checkTimeouts()); + // Trigger timers and check when the next will expire + nextTimeout = Timer::checkTimeouts(); + if (nextTimeout >= 0 && nextTimeout < wait_ms) + wait_ms = nextTimeout; tv.tv_sec = wait_ms / 1000; tv.tv_usec = (wait_ms % 1000) * 1000; diff --git a/unix/xserver/hw/vnc/Makefile.am b/unix/xserver/hw/vnc/Makefile.am index 1e985966..40eba4f2 100644 --- a/unix/xserver/hw/vnc/Makefile.am +++ b/unix/xserver/hw/vnc/Makefile.am @@ -11,12 +11,12 @@ COMMON_LIBS=$(NETWORK_LIB) $(RFB_LIB) $(RDR_LIB) $(OS_LIB) $(UNIXCOMMON_LIB) noinst_LTLIBRARIES = libvnccommon.la HDRS = vncExtInit.h vncHooks.h \ - vncBlockHandler.h vncSelection.h \ + vncBlockHandler.h vncPresent.h vncSelection.h \ XorgGlue.h XserverDesktop.h xorg-version.h \ vncInput.h RFBGlue.h libvnccommon_la_SOURCES = $(HDRS) \ - vncExt.c vncExtInit.cc vncHooks.c vncSelection.c \ + vncExt.c vncExtInit.cc vncHooks.c vncPresent.c vncSelection.c \ vncBlockHandler.c XorgGlue.c RandrGlue.c RFBGlue.cc XserverDesktop.cc \ vncInput.c vncInputXKB.c qnum_to_xorgevdev.c qnum_to_xorgkbd.c diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc index 4cf37937..d4ee16b8 100644 --- a/unix/xserver/hw/vnc/XserverDesktop.cc +++ b/unix/xserver/hw/vnc/XserverDesktop.cc @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009-2019 Pierre Ossman for Cendio AB + * Copyright 2009-2024 Pierre Ossman for Cendio AB * Copyright 2014 Brian P. Hinz * * This is free software; you can redistribute it and/or modify @@ -54,6 +54,7 @@ extern "C" { void vncSetGlueContext(int screenIndex); +void vncPresentMscEvent(uint64_t id, uint64_t msc); } using namespace rfb; @@ -145,15 +146,26 @@ void XserverDesktop::refreshScreenLayout() server->setScreenLayout(::computeScreenLayout(&outputIdMap)); } -void XserverDesktop::start(rfb::VNCServer* vs) +uint64_t XserverDesktop::getMsc() { - // We already own the server object, and we always keep it in a - // ready state - assert(vs == server); + return server->getMsc(); +} + +void XserverDesktop::queueMsc(uint64_t id, uint64_t msc) +{ + pendingMsc[id] = msc; + server->queueMsc(msc); } -void XserverDesktop::stop() +void XserverDesktop::abortMsc(uint64_t id) { + pendingMsc.erase(id); +} + +void XserverDesktop::init(rfb::VNCServer* vs) +{ + // We already own the server object, and we always keep it in a + // ready state } void XserverDesktop::queryConnection(network::Socket* sock, @@ -395,7 +407,7 @@ void XserverDesktop::blockHandler(int* timeout) // Trigger timers and check when the next will expire int nextTimeout = Timer::checkTimeouts(); - if (nextTimeout > 0 && (*timeout == -1 || nextTimeout < *timeout)) + if (nextTimeout >= 0 && (*timeout == -1 || nextTimeout < *timeout)) *timeout = nextTimeout; } catch (rdr::Exception& e) { vlog.error("XserverDesktop::blockHandler: %s",e.str()); @@ -476,6 +488,22 @@ unsigned int XserverDesktop::setScreenLayout(int fb_width, int fb_height, return result; } +void XserverDesktop::frameTick(uint64_t msc) +{ + std::map<uint64_t, uint64_t>::iterator iter, next; + + for (iter = pendingMsc.begin(); iter != pendingMsc.end();) { + next = iter; next++; + + if (iter->second <= msc) { + pendingMsc.erase(iter->first); + vncPresentMscEvent(iter->first, msc); + } + + iter = next; + } +} + void XserverDesktop::handleClipboardRequest() { vncHandleClipboardRequest(); @@ -518,13 +546,11 @@ void XserverDesktop::keyEvent(uint32_t keysym, uint32_t keycode, bool down) vncKeyboardEvent(keysym, keycode, down); } -bool XserverDesktop::handleTimeout(Timer* t) +void XserverDesktop::handleTimeout(Timer* t) { if (t == &queryConnectTimer) { server->approveConnection(queryConnectSocket, false, "The attempt to prompt the user to " "accept the connection failed"); } - - return false; } diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h index 9cc5bf79..e604295b 100644 --- a/unix/xserver/hw/vnc/XserverDesktop.h +++ b/unix/xserver/hw/vnc/XserverDesktop.h @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2009-2019 Pierre Ossman for Cendio AB + * Copyright 2009-2024 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -59,6 +59,9 @@ public: void unblockUpdates(); void setFramebuffer(int w, int h, void* fbptr, int stride); void refreshScreenLayout(); + uint64_t getMsc(); + void queueMsc(uint64_t id, uint64_t msc); + void abortMsc(uint64_t id); void requestClipboard(); void announceClipboard(bool available); void sendClipboardData(const char* data); @@ -88,8 +91,7 @@ public: const char* rejectMsg=0); // rfb::SDesktop callbacks - virtual void start(rfb::VNCServer* vs); - virtual void stop(); + virtual void init(rfb::VNCServer* vs); virtual void terminate(); virtual void queryConnection(network::Socket* sock, const char* userName); @@ -97,6 +99,7 @@ public: virtual void keyEvent(uint32_t keysym, uint32_t keycode, bool down); virtual unsigned int setScreenLayout(int fb_width, int fb_height, const rfb::ScreenSet& layout); + virtual void frameTick(uint64_t msc); virtual void handleClipboardRequest(); virtual void handleClipboardAnnounce(bool available); virtual void handleClipboardData(const char* data); @@ -112,7 +115,7 @@ protected: rfb::VNCServer* sockserv, bool read, bool write); - virtual bool handleTimeout(rfb::Timer* t); + virtual void handleTimeout(rfb::Timer* t); private: @@ -129,6 +132,8 @@ private: OutputIdMap outputIdMap; + std::map<uint64_t, uint64_t> pendingMsc; + rfb::Point oldCursorPos; }; #endif diff --git a/unix/xserver/hw/vnc/vncExtInit.cc b/unix/xserver/hw/vnc/vncExtInit.cc index b260e626..4003e768 100644 --- a/unix/xserver/hw/vnc/vncExtInit.cc +++ b/unix/xserver/hw/vnc/vncExtInit.cc @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2011-2019 Pierre Ossman for Cendio AB + * Copyright 2011-2024 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -484,6 +484,33 @@ void vncRefreshScreenLayout(int scrIdx) } } +uint64_t vncGetMsc(int scrIdx) +{ + try { + return desktop[scrIdx]->getMsc(); + } catch (rdr::Exception& e) { + vncFatalError("vncGetMsc: %s\n", e.str()); + } +} + +void vncQueueMsc(int scrIdx, uint64_t id, uint64_t msc) +{ + try { + desktop[scrIdx]->queueMsc(id, msc); + } catch (rdr::Exception& e) { + vncFatalError("vncQueueMsc: %s\n", e.str()); + } +} + +void vncAbortMsc(int scrIdx, uint64_t id) +{ + try { + desktop[scrIdx]->abortMsc(id); + } catch (rdr::Exception& e) { + vncFatalError("vncAbortMsc: %s\n", e.str()); + } +} + int vncOverrideParam(const char *nameAndValue) { const char* equalSign = strchr(nameAndValue, '='); diff --git a/unix/xserver/hw/vnc/vncExtInit.h b/unix/xserver/hw/vnc/vncExtInit.h index 333e32a9..6b37fe62 100644 --- a/unix/xserver/hw/vnc/vncExtInit.h +++ b/unix/xserver/hw/vnc/vncExtInit.h @@ -1,5 +1,5 @@ /* Copyright (C) 2002-2005 RealVNC Ltd. All Rights Reserved. - * Copyright 2011-2019 Pierre Ossman for Cendio AB + * Copyright 2011-2024 Pierre Ossman for Cendio AB * * This is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -87,6 +87,10 @@ void vncPreScreenResize(int scrIdx); void vncPostScreenResize(int scrIdx, int success, int width, int height); void vncRefreshScreenLayout(int scrIdx); +uint64_t vncGetMsc(int scrIdx); +void vncQueueMsc(int scrIdx, uint64_t id, uint64_t msc); +void vncAbortMsc(int scrIdx, uint64_t id); + int vncOverrideParam(const char *nameAndValue); #ifdef __cplusplus diff --git a/unix/xserver/hw/vnc/vncPresent.c b/unix/xserver/hw/vnc/vncPresent.c new file mode 100644 index 00000000..89dcc1d0 --- /dev/null +++ b/unix/xserver/hw/vnc/vncPresent.c @@ -0,0 +1,93 @@ +/* Copyright 2024 Pierre Ossman for Cendio AB + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include <dix-config.h> +#endif + +#include "vncExtInit.h" +#include "vncPresent.h" + +#include <present.h> + +static RRCrtcPtr vncPresentGetCrtc(WindowPtr window) +{ + ScreenPtr pScreen = window->drawable.pScreen; + rrScrPrivPtr rp = rrGetScrPriv(pScreen); + + /* All output is synchronized, so just pick the first active crtc */ + for (int c = 0; c < rp->numCrtcs; c++) { + RRCrtcPtr crtc; + + crtc = rp->crtcs[c]; + if (crtc->mode == NULL) + continue; + + return crtc; + } + + return NULL; +} + +static int vncPresentGetUstMsc(RRCrtcPtr crtc, CARD64 *ust, CARD64 *msc) +{ + *ust = GetTimeInMicros(); + *msc = vncGetMsc(crtc->pScreen->myNum); + + return Success; +} + +static int vncPresentQueueVBlank(RRCrtcPtr crtc, uint64_t event_id, + uint64_t msc) +{ + vncQueueMsc(crtc->pScreen->myNum, event_id, msc); + return Success; +} + +void vncPresentMscEvent(uint64_t id, uint64_t msc) +{ + present_event_notify(id, GetTimeInMicros(), msc); +} + +static void vncPresentAbortVBlank(RRCrtcPtr crtc, uint64_t event_id, + uint64_t msc) +{ + vncAbortMsc(crtc->pScreen->myNum, event_id); +} + +static void vncPresentFlush(WindowPtr window) +{ +} + +static present_screen_info_rec vncPresentScreenInfo = { + .version = PRESENT_SCREEN_INFO_VERSION, + + .get_crtc = vncPresentGetCrtc, + .get_ust_msc = vncPresentGetUstMsc, + .queue_vblank = vncPresentQueueVBlank, + .abort_vblank = vncPresentAbortVBlank, + .flush = vncPresentFlush, + + .capabilities = PresentCapabilityNone, +}; + +Bool +vncPresentInit(ScreenPtr screen) +{ + return present_screen_init(screen, &vncPresentScreenInfo); +}
\ No newline at end of file diff --git a/unix/xserver/hw/vnc/vncPresent.h b/unix/xserver/hw/vnc/vncPresent.h new file mode 100644 index 00000000..17407402 --- /dev/null +++ b/unix/xserver/hw/vnc/vncPresent.h @@ -0,0 +1,27 @@ +/* Copyright 2024 Pierre Ossman for Cendio AB + * + * This is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This software is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this software; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, + * USA. + */ + +#ifndef __PRESENT_H__ +#define __PRESENT_H__ + +#include <dix.h> + +Bool vncPresentInit(ScreenPtr screen); +void vncPresentMscEvent(uint64_t id, uint64_t msc); + +#endif diff --git a/unix/xserver/hw/vnc/xvnc.c b/unix/xserver/hw/vnc/xvnc.c index 16a28831..706c9d5a 100644 --- a/unix/xserver/hw/vnc/xvnc.c +++ b/unix/xserver/hw/vnc/xvnc.c @@ -36,6 +36,7 @@ from the X Consortium. #include "RFBGlue.h" #include "XorgGlue.h" #include "RandrGlue.h" +#include "vncPresent.h" #include "xorg-version.h" #include <stdio.h> @@ -670,14 +671,14 @@ vncRandRScreenSetSize(ScreenPtr pScreen, ret = vncRandRCrtcSet(pScreen, crtc, NULL, crtc->x, crtc->y, crtc->rotation, 0, NULL); if (!ret) - ErrorF("Warning: Unable to disable CRTC that is outside of new screen dimensions"); + ErrorF("Warning: Unable to disable CRTC that is outside of new screen dimensions\n"); continue; } /* Just needs to be resized to a temporary mode */ mode = vncRandRModeGet(width - crtc->x, height - crtc->y); if (mode == NULL) { - ErrorF("Warning: Unable to create custom mode for %dx%d", + ErrorF("Warning: Unable to create custom mode for %dx%d\n", width - crtc->x, height - crtc->y); continue; } @@ -687,7 +688,7 @@ vncRandRScreenSetSize(ScreenPtr pScreen, crtc->numOutputs, crtc->outputs); RRModeDestroy(mode); if (!ret) - ErrorF("Warning: Unable to crop CRTC to new screen dimensions"); + ErrorF("Warning: Unable to crop CRTC to new screen dimensions\n"); } return TRUE; @@ -1085,6 +1086,10 @@ vncScreenInit(ScreenPtr pScreen, int argc, char **argv) if (!ret) return FALSE; + ret = vncPresentInit(pScreen); + if (!ret) + ErrorF("Failed to initialize Present extension\n"); + return TRUE; } /* end vncScreenInit */ |