@@ -90,6 +90,30 @@ public: | |||
XserverDesktop* desktop; | |||
}; | |||
#if XORG >= 119 | |||
extern "C" { | |||
/* | |||
* xserver NotifyFd callbacks. Note we also expect write notifies to work, | |||
* which only works with xserver >= 1.19. | |||
*/ | |||
#include "os.h" | |||
static void HandleListenFd(int fd, int xevents, void *data) | |||
{ | |||
XserverDesktop *desktop = (XserverDesktop *)data; | |||
desktop->handleListenFd(fd); | |||
} | |||
static void HandleSocketFd(int fd, int xevents, void *data) | |||
{ | |||
XserverDesktop *desktop = (XserverDesktop *)data; | |||
desktop->handleSocketFd(fd, xevents); | |||
} | |||
} | |||
#endif | |||
XserverDesktop::XserverDesktop(int screenIndex_, | |||
std::list<network::TcpListener*> listeners_, | |||
@@ -111,15 +135,35 @@ XserverDesktop::XserverDesktop(int screenIndex_, | |||
if (!httpListeners.empty ()) | |||
httpServer = new FileHTTPServer(this); | |||
#if XORG >= 119 | |||
for (std::list<TcpListener*>::iterator i = listeners.begin(); | |||
i != listeners.end(); | |||
i++) { | |||
SetNotifyFd((*i)->getFd(), HandleListenFd, X_NOTIFY_READ, this); | |||
} | |||
for (std::list<TcpListener*>::iterator i = httpListeners.begin(); | |||
i != httpListeners.end(); | |||
i++) { | |||
SetNotifyFd((*i)->getFd(), HandleListenFd, X_NOTIFY_READ, this); | |||
} | |||
#endif | |||
} | |||
XserverDesktop::~XserverDesktop() | |||
{ | |||
while (!listeners.empty()) { | |||
#if XORG >= 119 | |||
RemoveNotifyFd(listeners.back()->getFd()); | |||
#endif | |||
delete listeners.back(); | |||
listeners.pop_back(); | |||
} | |||
while (!httpListeners.empty()) { | |||
#if XORG >= 119 | |||
RemoveNotifyFd(listeners.back()->getFd()); | |||
#endif | |||
delete httpListeners.back(); | |||
httpListeners.pop_back(); | |||
} | |||
@@ -389,6 +433,140 @@ void XserverDesktop::add_copied(const rfb::Region &dest, const rfb::Point &delta | |||
} | |||
} | |||
#if XORG >= 119 | |||
void XserverDesktop::handleListenFd(int fd) | |||
{ | |||
std::list<TcpListener*>::iterator i; | |||
SocketServer *fd_server = NULL; | |||
bool is_http = false; | |||
for (i = listeners.begin(); i != listeners.end(); i++) { | |||
if ((*i)->getFd() == fd) { | |||
fd_server = server; | |||
break; | |||
} | |||
} | |||
if (httpServer && !fd_server) { | |||
for (i = httpListeners.begin(); i != httpListeners.end(); i++) { | |||
if ((*i)->getFd() == fd) { | |||
fd_server = httpServer; | |||
is_http = true; | |||
break; | |||
} | |||
} | |||
} | |||
if (!fd_server) { | |||
vlog.error("XserverDesktop::handleListenFd: Error cannot find fd"); | |||
return; | |||
} | |||
Socket* sock = (*i)->accept(); | |||
sock->outStream().setBlocking(false); | |||
vlog.debug("new %sclient, sock %d", is_http ? "http " : "", sock->getFd()); | |||
fd_server->addSocket(sock); | |||
SetNotifyFd(sock->getFd(), HandleSocketFd, X_NOTIFY_READ, this); | |||
} | |||
void XserverDesktop::handleSocketFd(int fd, int xevents) | |||
{ | |||
std::list<Socket*> sockets; | |||
std::list<Socket*>::iterator i; | |||
SocketServer *fd_server = NULL; | |||
bool is_http = false; | |||
server->getSockets(&sockets); | |||
for (i = sockets.begin(); i != sockets.end(); i++) { | |||
if ((*i)->getFd() == fd) { | |||
fd_server = server; | |||
break; | |||
} | |||
} | |||
if (httpServer && !fd_server) { | |||
httpServer->getSockets(&sockets); | |||
for (i = sockets.begin(); i != sockets.end(); i++) { | |||
if ((*i)->getFd() == fd) { | |||
fd_server = httpServer; | |||
is_http = true; | |||
break; | |||
} | |||
} | |||
} | |||
if (!fd_server) { | |||
vlog.error("XserverDesktop::handleSocketFd: Error cannot find fd"); | |||
return; | |||
} | |||
if (xevents & X_NOTIFY_READ) | |||
fd_server->processSocketReadEvent(*i); | |||
if (xevents & X_NOTIFY_WRITE) | |||
fd_server->processSocketWriteEvent(*i); | |||
if ((*i)->isShutdown()) { | |||
vlog.debug("%sclient gone, sock %d", is_http ? "http " : "", fd); | |||
RemoveNotifyFd(fd); | |||
fd_server->removeSocket(*i); | |||
if (!is_http) | |||
vncClientGone(fd); | |||
delete (*i); | |||
} | |||
} | |||
void XserverDesktop::blockHandler(int* timeout) | |||
{ | |||
// We don't have a good callback for when we can init input devices[1], | |||
// so we abuse the fact that this routine will be called first thing | |||
// once the dix is done initialising. | |||
// [1] Technically Xvnc has InitInput(), but libvnc.so has nothing. | |||
vncInitInputDevice(); | |||
try { | |||
std::list<Socket*> sockets; | |||
std::list<Socket*>::iterator i; | |||
server->getSockets(&sockets); | |||
for (i = sockets.begin(); i != sockets.end(); i++) { | |||
int fd = (*i)->getFd(); | |||
if ((*i)->isShutdown()) { | |||
vlog.debug("client gone, sock %d",fd); | |||
server->removeSocket(*i); | |||
vncClientGone(fd); | |||
delete (*i); | |||
} else { | |||
/* Update existing NotifyFD to listen for write (or not) */ | |||
if ((*i)->outStream().bufferUsage() > 0) | |||
SetNotifyFd(fd, HandleSocketFd, X_NOTIFY_READ | X_NOTIFY_WRITE, this); | |||
else | |||
SetNotifyFd(fd, HandleSocketFd, X_NOTIFY_READ, this); | |||
} | |||
} | |||
if (httpServer) { | |||
httpServer->getSockets(&sockets); | |||
for (i = sockets.begin(); i != sockets.end(); i++) { | |||
int fd = (*i)->getFd(); | |||
if ((*i)->isShutdown()) { | |||
vlog.debug("http client gone, sock %d",fd); | |||
httpServer->removeSocket(*i); | |||
delete (*i); | |||
} else { | |||
/* Update existing NotifyFD to listen for write (or not) */ | |||
if ((*i)->outStream().bufferUsage() > 0) | |||
SetNotifyFd(fd, HandleSocketFd, X_NOTIFY_READ | X_NOTIFY_WRITE, this); | |||
else | |||
SetNotifyFd(fd, HandleSocketFd, X_NOTIFY_READ, this); | |||
} | |||
} | |||
} | |||
int nextTimeout = server->checkTimeouts(); | |||
if (nextTimeout > 0 && (*timeout == -1 || nextTimeout < *timeout)) | |||
*timeout = nextTimeout; | |||
} catch (rdr::Exception& e) { | |||
vlog.error("XserverDesktop::blockHandler: %s",e.str()); | |||
} | |||
} | |||
#else | |||
void XserverDesktop::readBlockHandler(fd_set* fds, struct timeval ** timeout) | |||
{ | |||
// We don't have a good callback for when we can init input devices[1], | |||
@@ -603,10 +781,15 @@ void XserverDesktop::writeWakeupHandler(fd_set* fds, int nfds) | |||
} | |||
} | |||
#endif | |||
void XserverDesktop::addClient(Socket* sock, bool reverse) | |||
{ | |||
vlog.debug("new client, sock %d reverse %d",sock->getFd(),reverse); | |||
server->addSocket(sock, reverse); | |||
#if XORG >= 119 | |||
SetNotifyFd(sock->getFd(), HandleSocketFd, X_NOTIFY_READ, this); | |||
#endif | |||
} | |||
void XserverDesktop::disconnectClients() |
@@ -38,6 +38,7 @@ | |||
#include <rfb/VNCServerST.h> | |||
#include <rdr/SubstitutingInStream.h> | |||
#include "Input.h" | |||
#include "xorg-version.h" | |||
namespace rfb { | |||
class VNCServerST; | |||
@@ -69,10 +70,16 @@ public: | |||
const unsigned char *rgbaData); | |||
void add_changed(const rfb::Region ®ion); | |||
void add_copied(const rfb::Region &dest, const rfb::Point &delta); | |||
#if XORG >= 119 | |||
void handleListenFd(int fd); | |||
void handleSocketFd(int fd, int xevents); | |||
void blockHandler(int* timeout); | |||
#else | |||
void readBlockHandler(fd_set* fds, struct timeval ** timeout); | |||
void readWakeupHandler(fd_set* fds, int nfds); | |||
void writeBlockHandler(fd_set* fds, struct timeval ** timeout); | |||
void writeWakeupHandler(fd_set* fds, int nfds); | |||
#endif | |||
void addClient(network::Socket* sock, bool reverse); | |||
void disconnectClients(); | |||
@@ -30,6 +30,23 @@ | |||
#include "vncExtInit.h" | |||
#include "vncBlockHandler.h" | |||
#include "xorg-version.h" | |||
#if XORG >= 119 | |||
static void vncBlockHandler(void* data, void* timeout) | |||
{ | |||
vncCallBlockHandlers(timeout); | |||
} | |||
void vncRegisterBlockHandlers(void) | |||
{ | |||
if (!RegisterBlockAndWakeupHandlers(vncBlockHandler, | |||
(ServerWakeupHandlerProcPtr)NoopDDA, 0)) | |||
FatalError("RegisterBlockAndWakeupHandlers() failed\n"); | |||
} | |||
#else | |||
static void vncBlockHandler(void * data, OSTimePtr t, void * readmask); | |||
static void vncWakeupHandler(void * data, int nfds, void * readmask); | |||
@@ -144,3 +161,5 @@ static void vncWriteWakeupHandlerFallback(void) | |||
vncWriteWakeupHandler(ret, &fallbackFds); | |||
} | |||
#endif |
@@ -249,6 +249,17 @@ int vncExtensionIsActive(int scrIdx) | |||
return (desktop[scrIdx] != NULL); | |||
} | |||
#if XORG >= 119 | |||
void vncCallBlockHandlers(int* timeout) | |||
{ | |||
for (int scr = 0; scr < vncGetScreenCount(); scr++) | |||
if (desktop[scr]) | |||
desktop[scr]->blockHandler(timeout); | |||
} | |||
#else | |||
void vncCallReadBlockHandlers(fd_set * fds, struct timeval ** timeout) | |||
{ | |||
for (int scr = 0; scr < vncGetScreenCount(); scr++) | |||
@@ -277,6 +288,8 @@ void vncCallWriteWakeupHandlers(fd_set * fds, int nfds) | |||
desktop[scr]->writeWakeupHandler(fds, nfds); | |||
} | |||
#endif | |||
int vncGetAvoidShiftNumLock(void) | |||
{ | |||
return (bool)avoidShiftNumLock; |
@@ -22,6 +22,7 @@ | |||
#include <stdint.h> | |||
#include <stddef.h> | |||
#include <sys/select.h> | |||
#include "xorg-version.h" | |||
// Only from C++ | |||
#ifdef __cplusplus | |||
@@ -50,10 +51,14 @@ extern int vncInetdSock; | |||
void vncExtensionInit(void); | |||
int vncExtensionIsActive(int scrIdx); | |||
#if XORG >= 119 | |||
void vncCallBlockHandlers(int* timeout); | |||
#else | |||
void vncCallReadBlockHandlers(fd_set * fds, struct timeval ** timeout); | |||
void vncCallReadWakeupHandlers(fd_set * fds, int nfds); | |||
void vncCallWriteBlockHandlers(fd_set * fds, struct timeval ** timeout); | |||
void vncCallWriteWakeupHandlers(fd_set * fds, int nfds); | |||
#endif | |||
int vncGetAvoidShiftNumLock(void); | |||
@@ -128,9 +128,11 @@ static Bool vncHooksDisplayCursor(DeviceIntPtr pDev, | |||
#if XORG <= 112 | |||
static void vncHooksBlockHandler(int i, pointer blockData, pointer pTimeout, | |||
pointer pReadmask); | |||
#else | |||
#elif XORG <= 118 | |||
static void vncHooksBlockHandler(ScreenPtr pScreen, void * pTimeout, | |||
void * pReadmask); | |||
#else | |||
static void vncHooksBlockHandler(ScreenPtr pScreen, void * pTimeout); | |||
#endif | |||
#ifdef RENDER | |||
static void vncHooksComposite(CARD8 op, PicturePtr pSrc, PicturePtr pMask, | |||
@@ -716,9 +718,11 @@ out: | |||
#if XORG <= 112 | |||
static void vncHooksBlockHandler(int i, pointer blockData, pointer pTimeout, | |||
pointer pReadmask) | |||
#else | |||
#elif XORG <= 118 | |||
static void vncHooksBlockHandler(ScreenPtr pScreen_, void * pTimeout, | |||
void * pReadmask) | |||
#else | |||
static void vncHooksBlockHandler(ScreenPtr pScreen_, void * pTimeout) | |||
#endif | |||
{ | |||
#if XORG <= 112 | |||
@@ -731,8 +735,10 @@ static void vncHooksBlockHandler(ScreenPtr pScreen_, void * pTimeout, | |||
#if XORG <= 112 | |||
(*pScreen->BlockHandler) (i, blockData, pTimeout, pReadmask); | |||
#else | |||
#elif XORG <= 118 | |||
(*pScreen->BlockHandler) (pScreen, pTimeout, pReadmask); | |||
#else | |||
(*pScreen->BlockHandler) (pScreen, pTimeout); | |||
#endif | |||
vncHooksScreen->ignoreHooks--; | |||
@@ -1033,12 +1039,21 @@ static void vncHooksCopyClip(GCPtr dst, GCPtr src) { | |||
// Unwrap and rewrap helpers | |||
#if XORG >= 116 | |||
#define GC_OP_PROLOGUE(pGC, name)\ | |||
vncHooksGCPtr pGCPriv = vncHooksGCPrivate(pGC);\ | |||
const GCFuncs *oldFuncs = pGC->funcs;\ | |||
pGC->funcs = pGCPriv->wrappedFuncs;\ | |||
pGC->ops = pGCPriv->wrappedOps; \ | |||
DBGPRINT((stderr,"vncHooks" #name " called\n")) | |||
#else | |||
#define GC_OP_PROLOGUE(pGC, name)\ | |||
vncHooksGCPtr pGCPriv = vncHooksGCPrivate(pGC);\ | |||
GCFuncs *oldFuncs = pGC->funcs;\ | |||
pGC->funcs = pGCPriv->wrappedFuncs;\ | |||
pGC->ops = pGCPriv->wrappedOps; \ | |||
DBGPRINT((stderr,"vncHooks" #name " called\n")) | |||
#endif | |||
#define GC_OP_EPILOGUE(pGC)\ | |||
pGCPriv->wrappedOps = pGC->ops;\ |
@@ -50,8 +50,10 @@ | |||
#define XORG 117 | |||
#elif XORG_VERSION_CURRENT < ((1 * 10000000) + (18 * 100000) + (99 * 1000)) | |||
#define XORG 118 | |||
#elif XORG_VERSION_CURRENT < ((1 * 10000000) + (19 * 100000) + (99 * 1000)) | |||
#define XORG 119 | |||
#else | |||
#error "X.Org newer than 1.18 is not supported" | |||
#error "X.Org newer than 1.19 is not supported" | |||
#endif | |||
#endif |
@@ -0,0 +1,95 @@ | |||
diff -up xserver/configure.ac.xserver116-rebased xserver/configure.ac | |||
--- xserver/configure.ac.xserver116-rebased 2016-09-29 13:14:45.595441590 +0200 | |||
+++ xserver/configure.ac 2016-09-29 13:14:45.631442006 +0200 | |||
@@ -74,6 +74,7 @@ dnl forcing an entire recompile.x | |||
AC_CONFIG_HEADERS(include/version-config.h) | |||
AM_PROG_AS | |||
+AC_PROG_CXX | |||
AC_PROG_LN_S | |||
LT_PREREQ([2.2]) | |||
LT_INIT([disable-static win32-dll]) | |||
@@ -1863,6 +1864,10 @@ if test "x$XVFB" = xyes; then | |||
AC_SUBST([XVFB_SYS_LIBS]) | |||
fi | |||
+dnl Xvnc DDX | |||
+AC_SUBST([XVNC_CPPFLAGS], ["-DHAVE_DIX_CONFIG_H $XSERVER_CFLAGS"]) | |||
+AC_SUBST([XVNC_LIBS], ["$FB_LIB $FIXES_LIB $XEXT_LIB $CONFIG_LIB $DBE_LIB $RECORD_LIB $GLX_LIBS $RANDR_LIB $RENDER_LIB $DAMAGE_LIB $DRI3_LIB $PRESENT_LIB $MIEXT_SYNC_LIB $MIEXT_DAMAGE_LIB $MIEXT_SHADOW_LIB $XI_LIB $XKB_LIB $XKB_STUB_LIB $COMPOSITE_LIB $MAIN_LIB"]) | |||
+AC_SUBST([XVNC_SYS_LIBS], ["$GLX_SYS_LIBS"]) | |||
dnl Xnest DDX | |||
@@ -1898,6 +1903,8 @@ if test "x$XORG" = xauto; then | |||
fi | |||
AC_MSG_RESULT([$XORG]) | |||
+AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version]) | |||
+ | |||
if test "x$XORG" = xyes; then | |||
XORG_DDXINCS='-I$(top_srcdir)/hw/xfree86 -I$(top_srcdir)/hw/xfree86/include -I$(top_srcdir)/hw/xfree86/common' | |||
XORG_OSINCS='-I$(top_srcdir)/hw/xfree86/os-support -I$(top_srcdir)/hw/xfree86/os-support/bus -I$(top_srcdir)/os' | |||
@@ -2116,7 +2123,6 @@ if test "x$XORG" = xyes; then | |||
AC_DEFINE(XORG_SERVER, 1, [Building Xorg server]) | |||
AC_DEFINE(XORGSERVER, 1, [Building Xorg server]) | |||
AC_DEFINE(XFree86Server, 1, [Building XFree86 server]) | |||
- AC_DEFINE_UNQUOTED(XORG_VERSION_CURRENT, [$VENDOR_RELEASE], [Current Xorg version]) | |||
AC_DEFINE(NEED_XF86_TYPES, 1, [Need XFree86 typedefs]) | |||
AC_DEFINE(NEED_XF86_PROTOTYPES, 1, [Need XFree86 helper functions]) | |||
AC_DEFINE(__XSERVERNAME__, "Xorg", [Name of X server]) | |||
@@ -2691,6 +2697,7 @@ hw/dmx/Makefile | |||
hw/dmx/man/Makefile | |||
hw/vfb/Makefile | |||
hw/vfb/man/Makefile | |||
+hw/vnc/Makefile | |||
hw/xnest/Makefile | |||
hw/xnest/man/Makefile | |||
hw/xwin/Makefile | |||
diff -up xserver/hw/Makefile.am.xserver116-rebased xserver/hw/Makefile.am | |||
--- xserver/hw/Makefile.am.xserver116-rebased 2016-09-29 13:14:45.601441659 +0200 | |||
+++ xserver/hw/Makefile.am 2016-09-29 13:14:45.631442006 +0200 | |||
@@ -38,7 +38,8 @@ SUBDIRS = \ | |||
$(DMX_SUBDIRS) \ | |||
$(KDRIVE_SUBDIRS) \ | |||
$(XQUARTZ_SUBDIRS) \ | |||
- $(XWAYLAND_SUBDIRS) | |||
+ $(XWAYLAND_SUBDIRS) \ | |||
+ vnc | |||
DIST_SUBDIRS = dmx xfree86 vfb xnest xwin xquartz kdrive xwayland | |||
diff -up xserver/mi/miinitext.c.xserver116-rebased xserver/mi/miinitext.c | |||
--- xserver/mi/miinitext.c.xserver116-rebased 2016-09-29 13:14:45.618441855 +0200 | |||
+++ xserver/mi/miinitext.c 2016-09-29 13:14:45.631442006 +0200 | |||
@@ -114,6 +114,10 @@ SOFTWARE. | |||
#include "micmap.h" | |||
#include "globals.h" | |||
+#ifdef TIGERVNC | |||
+extern void vncExtensionInit(INITARGS); | |||
+#endif | |||
+ | |||
/* The following is only a small first step towards run-time | |||
* configurable extensions. | |||
*/ | |||
@@ -238,6 +242,9 @@ EnableDisableExtensionError(const char * | |||
/* List of built-in (statically linked) extensions */ | |||
static const ExtensionModule staticExtensions[] = { | |||
+#ifdef TIGERVNC | |||
+ {vncExtensionInit, "VNC-EXTENSION", NULL}, | |||
+#endif | |||
{GEExtensionInit, "Generic Event Extension", &noGEExtension}, | |||
{ShapeExtensionInit, "SHAPE", NULL}, | |||
#ifdef MITSHM | |||
--- xserver/include/os.h~ 2016-10-03 09:07:29.000000000 +0200 | |||
+++ xserver/include/os.h 2016-10-03 14:13:00.013654506 +0200 | |||
@@ -621,7 +621,7 @@ | |||
extern _X_EXPORT void | |||
LogClose(enum ExitCode error); | |||
extern _X_EXPORT Bool | |||
-LogSetParameter(LogParameter param, int value); | |||
+LogSetParameter(enum _LogParameter param, int value); | |||
extern _X_EXPORT void | |||
LogVWrite(int verb, const char *f, va_list args) | |||
_X_ATTRIBUTE_PRINTF(2, 0); |