aboutsummaryrefslogtreecommitdiffstats
path: root/unix
diff options
context:
space:
mode:
Diffstat (limited to 'unix')
-rw-r--r--unix/vncconfig/QueryConnectDialog.cxx5
-rw-r--r--unix/vncconfig/QueryConnectDialog.h2
-rw-r--r--unix/vncconfig/vncconfig.cxx2
-rw-r--r--unix/x0vncserver/XDesktop.cxx10
-rw-r--r--unix/x0vncserver/XDesktop.h3
-rw-r--r--unix/x0vncserver/x0vncserver.cxx7
-rw-r--r--unix/xserver/hw/vnc/Makefile.am4
-rw-r--r--unix/xserver/hw/vnc/XserverDesktop.cc46
-rw-r--r--unix/xserver/hw/vnc/XserverDesktop.h13
-rw-r--r--unix/xserver/hw/vnc/vncExtInit.cc29
-rw-r--r--unix/xserver/hw/vnc/vncExtInit.h6
-rw-r--r--unix/xserver/hw/vnc/vncPresent.c93
-rw-r--r--unix/xserver/hw/vnc/vncPresent.h27
-rw-r--r--unix/xserver/hw/vnc/xvnc.c11
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 */