diff options
author | Pierre Ossman <ossman@cendio.se> | 2016-10-05 13:46:01 +0200 |
---|---|---|
committer | Pierre Ossman <ossman@cendio.se> | 2016-10-05 13:46:01 +0200 |
commit | b192107b302098864358cd54b6323129c23e271e (patch) | |
tree | e93fd818a053a595b9c814238811bda043331b21 | |
parent | 574dc64dfe1e2c8b52348f95619a845172282238 (diff) | |
download | tigervnc-b192107b302098864358cd54b6323129c23e271e.tar.gz tigervnc-b192107b302098864358cd54b6323129c23e271e.zip |
Merge X server block handling code paths
Use the new X server API as the reference system and emulate it on
the older API. Avoids a lot of code duplication.
-rw-r--r-- | unix/xserver/hw/vnc/XserverDesktop.cc | 388 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/XserverDesktop.h | 22 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/vncBlockHandler.c | 185 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/vncBlockHandler.h | 3 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/vncExtInit.cc | 38 | ||||
-rw-r--r-- | unix/xserver/hw/vnc/vncExtInit.h | 9 |
6 files changed, 242 insertions, 403 deletions
diff --git a/unix/xserver/hw/vnc/XserverDesktop.cc b/unix/xserver/hw/vnc/XserverDesktop.cc index 8cc0b0b7..f6e6a7fe 100644 --- a/unix/xserver/hw/vnc/XserverDesktop.cc +++ b/unix/xserver/hw/vnc/XserverDesktop.cc @@ -41,6 +41,7 @@ #include <rfb/ServerCore.h> #include "XserverDesktop.h" +#include "vncBlockHandler.h" #include "vncExtInit.h" #include "vncHooks.h" #include "vncSelection.h" @@ -90,30 +91,6 @@ 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_, @@ -136,34 +113,28 @@ 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); + vncSetNotifyFd((*i)->getFd(), screenIndex, true, false); } for (std::list<TcpListener*>::iterator i = httpListeners.begin(); i != httpListeners.end(); i++) { - SetNotifyFd((*i)->getFd(), HandleListenFd, X_NOTIFY_READ, this); + vncSetNotifyFd((*i)->getFd(), screenIndex, true, false); } -#endif } XserverDesktop::~XserverDesktop() { while (!listeners.empty()) { -#if XORG >= 119 - RemoveNotifyFd(listeners.back()->getFd()); -#endif + vncRemoveNotifyFd(listeners.back()->getFd()); delete listeners.back(); listeners.pop_back(); } while (!httpListeners.empty()) { -#if XORG >= 119 - RemoveNotifyFd(listeners.back()->getFd()); -#endif + vncRemoveNotifyFd(listeners.back()->getFd()); delete httpListeners.back(); httpListeners.pop_back(); } @@ -433,83 +404,72 @@ void XserverDesktop::add_copied(const rfb::Region &dest, const rfb::Point &delta } } -#if XORG >= 119 -void XserverDesktop::handleListenFd(int fd) +void XserverDesktop::handleSocketEvent(int fd, bool read, bool write) +{ + try { + if (read) { + if (handleListenerEvent(fd, &listeners, server)) + return; + if (handleListenerEvent(fd, &httpListeners, httpServer)) + return; + } + + if (handleSocketEvent(fd, server, read, write)) + return; + if (handleSocketEvent(fd, httpServer, read, write)) + return; + + vlog.error("Cannot find file descriptor for socket event"); + } catch (rdr::Exception& e) { + vlog.error("XserverDesktop::handleSocketEvent: %s",e.str()); + } +} + +bool XserverDesktop::handleListenerEvent(int fd, + std::list<TcpListener*>* sockets, + SocketServer* sockserv) { 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; + for (i = sockets->begin(); i != sockets->end(); i++) { + if ((*i)->getFd() == fd) 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; } + if (i == sockets->end()) + return false; + 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); + vlog.debug("new client, sock %d", sock->getFd()); + sockserv->addSocket(sock); + + return true; } -void XserverDesktop::handleSocketFd(int fd, int xevents) +bool XserverDesktop::handleSocketEvent(int fd, + SocketServer* sockserv, + bool read, bool write) { std::list<Socket*> sockets; std::list<Socket*>::iterator i; - SocketServer *fd_server = NULL; - bool is_http = false; - server->getSockets(&sockets); + sockserv->getSockets(&sockets); for (i = sockets.begin(); i != sockets.end(); i++) { - if ((*i)->getFd() == fd) { - fd_server = server; + if ((*i)->getFd() == fd) 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 (i == sockets.end()) + return false; - if (xevents & X_NOTIFY_WRITE) - fd_server->processSocketWriteEvent(*i); + if (read) + sockserv->processSocketReadEvent(*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); - } + if (write) + sockserv->processSocketWriteEvent(*i); + + return true; } void XserverDesktop::blockHandler(int* timeout) @@ -528,15 +488,13 @@ void XserverDesktop::blockHandler(int* timeout) int fd = (*i)->getFd(); if ((*i)->isShutdown()) { vlog.debug("client gone, sock %d",fd); + vncRemoveNotifyFd(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); + vncSetNotifyFd(fd, screenIndex, true, (*i)->outStream().bufferUsage() > 0); } } if (httpServer) { @@ -545,18 +503,28 @@ void XserverDesktop::blockHandler(int* timeout) int fd = (*i)->getFd(); if ((*i)->isShutdown()) { vlog.debug("http client gone, sock %d",fd); + vncRemoveNotifyFd(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); + vncSetNotifyFd(fd, screenIndex, true, (*i)->outStream().bufferUsage() > 0); } } } + // We are responsible for propagating mouse movement between clients + int cursorX, cursorY; + vncGetPointerPos(&cursorX, &cursorY); + cursorX -= vncGetScreenX(screenIndex); + cursorY -= vncGetScreenY(screenIndex); + if (oldCursorPos.x != cursorX || oldCursorPos.y != cursorY) { + oldCursorPos.x = cursorX; + oldCursorPos.y = cursorY; + server->setCursorPos(oldCursorPos); + } + + // Trigger timers and check when the next will expire int nextTimeout = server->checkTimeouts(); if (nextTimeout > 0 && (*timeout == -1 || nextTimeout < *timeout)) *timeout = nextTimeout; @@ -565,231 +533,11 @@ void XserverDesktop::blockHandler(int* timeout) } } -#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], - // 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 { - int nextTimeout; - - // Add all sockets we want read events for, after purging - // any closed sockets. - for (std::list<network::TcpListener*>::iterator i = listeners.begin(); - i != listeners.end(); - i++) - FD_SET((*i)->getFd(), fds); - for (std::list<network::TcpListener*>::iterator i = httpListeners.begin(); - i != httpListeners.end(); - i++) - FD_SET((*i)->getFd(), fds); - - 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 { - FD_SET(fd, fds); - } - } - 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 { - FD_SET(fd, fds); - } - } - } - - // Then check when the next timer will expire. - // (this unfortunately also triggers any already expired timers) - nextTimeout = server->checkTimeouts(); - if (nextTimeout > 0) { - // No timeout specified? Or later timeout than we need? - if ((*timeout == NULL) || - ((*timeout)->tv_sec > (nextTimeout/1000)) || - (((*timeout)->tv_sec == (nextTimeout/1000)) && - ((*timeout)->tv_usec > ((nextTimeout%1000)*1000)))) { - dixTimeout.tv_sec = nextTimeout/1000; - dixTimeout.tv_usec = (nextTimeout%1000)*1000; - *timeout = &dixTimeout; - } - } - - } catch (rdr::Exception& e) { - vlog.error("XserverDesktop::blockHandler: %s",e.str()); - } -} - -void XserverDesktop::readWakeupHandler(fd_set* fds, int nfds) -{ - try { - // First check for file descriptors with something to do - if (nfds >= 1) { - - for (std::list<network::TcpListener*>::iterator i = listeners.begin(); - i != listeners.end(); - i++) { - if (FD_ISSET((*i)->getFd(), fds)) { - FD_CLR((*i)->getFd(), fds); - Socket* sock = (*i)->accept(); - sock->outStream().setBlocking(false); - server->addSocket(sock); - vlog.debug("new client, sock %d",sock->getFd()); - } - } - - for (std::list<network::TcpListener*>::iterator i = httpListeners.begin(); - i != httpListeners.end(); - i++) { - if (FD_ISSET((*i)->getFd(), fds)) { - FD_CLR((*i)->getFd(), fds); - Socket* sock = (*i)->accept(); - sock->outStream().setBlocking(false); - httpServer->addSocket(sock); - vlog.debug("new http client, sock %d",sock->getFd()); - } - } - - std::list<Socket*> sockets; - server->getSockets(&sockets); - std::list<Socket*>::iterator i; - for (i = sockets.begin(); i != sockets.end(); i++) { - int fd = (*i)->getFd(); - if (FD_ISSET(fd, fds)) { - FD_CLR(fd, fds); - server->processSocketReadEvent(*i); - } - } - - if (httpServer) { - httpServer->getSockets(&sockets); - for (i = sockets.begin(); i != sockets.end(); i++) { - int fd = (*i)->getFd(); - if (FD_ISSET(fd, fds)) { - FD_CLR(fd, fds); - httpServer->processSocketReadEvent(*i); - } - } - } - - // We are responsible for propagating mouse movement between clients - int cursorX, cursorY; - vncGetPointerPos(&cursorX, &cursorY); - cursorX -= vncGetScreenX(screenIndex); - cursorY -= vncGetScreenY(screenIndex); - if (oldCursorPos.x != cursorX || oldCursorPos.y != cursorY) { - oldCursorPos.x = cursorX; - oldCursorPos.y = cursorY; - server->setCursorPos(oldCursorPos); - } - } - - // Then let the timers do some processing. Rescheduling is done in - // blockHandler(). - server->checkTimeouts(); - } catch (rdr::Exception& e) { - vlog.error("XserverDesktop::wakeupHandler: %s",e.str()); - } -} - -void XserverDesktop::writeBlockHandler(fd_set* fds, struct timeval ** timeout) -{ - 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 { - if ((*i)->outStream().bufferUsage() > 0) - FD_SET(fd, fds); - } - } - - 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 { - if ((*i)->outStream().bufferUsage() > 0) - FD_SET(fd, fds); - } - } - } - } catch (rdr::Exception& e) { - vlog.error("XserverDesktop::writeBlockHandler: %s",e.str()); - } -} - -void XserverDesktop::writeWakeupHandler(fd_set* fds, int nfds) -{ - if (nfds < 1) - return; - - 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 (FD_ISSET(fd, fds)) { - FD_CLR(fd, fds); - server->processSocketWriteEvent(*i); - } - } - - if (httpServer) { - httpServer->getSockets(&sockets); - for (i = sockets.begin(); i != sockets.end(); i++) { - int fd = (*i)->getFd(); - if (FD_ISSET(fd, fds)) { - FD_CLR(fd, fds); - httpServer->processSocketWriteEvent(*i); - } - } - } - } catch (rdr::Exception& e) { - vlog.error("XserverDesktop::writeWakeupHandler: %s",e.str()); - } -} - -#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 + vncSetNotifyFd(sock->getFd(), screenIndex, true, false); } void XserverDesktop::disconnectClients() diff --git a/unix/xserver/hw/vnc/XserverDesktop.h b/unix/xserver/hw/vnc/XserverDesktop.h index 9e776274..07bd3995 100644 --- a/unix/xserver/hw/vnc/XserverDesktop.h +++ b/unix/xserver/hw/vnc/XserverDesktop.h @@ -38,13 +38,12 @@ #include <rfb/VNCServerST.h> #include <rdr/SubstitutingInStream.h> #include "Input.h" -#include "xorg-version.h" namespace rfb { class VNCServerST; } -namespace network { class TcpListener; class Socket; } +namespace network { class TcpListener; class Socket; class SocketServer; } class XserverDesktop : public rfb::SDesktop, public rfb::FullFramePixelBuffer, public rdr::Substitutor, @@ -70,16 +69,8 @@ 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 handleSocketEvent(int fd, bool read, bool write); 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(); @@ -114,6 +105,14 @@ public: const char* userName, char** reason); +protected: + bool handleListenerEvent(int fd, + std::list<network::TcpListener*>* sockets, + network::SocketServer* sockserv); + bool handleSocketEvent(int fd, + network::SocketServer* sockserv, + bool read, bool write); + private: rfb::ScreenSet computeScreenLayout(); @@ -124,7 +123,6 @@ private: std::list<network::TcpListener*> httpListeners; bool deferredUpdateTimerSet; bool directFbptr; - struct timeval dixTimeout; uint32_t queryConnectId; network::Socket* queryConnectSocket; diff --git a/unix/xserver/hw/vnc/vncBlockHandler.c b/unix/xserver/hw/vnc/vncBlockHandler.c index baebc3df..604dc4ab 100644 --- a/unix/xserver/hw/vnc/vncBlockHandler.c +++ b/unix/xserver/hw/vnc/vncBlockHandler.c @@ -25,6 +25,7 @@ #include <X11/Xpoll.h> +#include "os.h" #include "dix.h" #include "scrnintstr.h" @@ -33,84 +34,209 @@ #include "xorg-version.h" #if XORG >= 119 +static void vncBlockHandler(void* data, void* timeout); +static void vncSocketNotify(int fd, int xevents, void *data); +#else +static void vncBlockHandler(void * data, OSTimePtr t, void * readmask); +static void vncWakeupHandler(void * data, int nfds, void * readmask); -static void vncBlockHandler(void* data, void* timeout) -{ - vncCallBlockHandlers(timeout); -} +struct vncFdEntry { + int fd; + int read, write; + int scrIdx; + struct vncFdEntry* next; +}; + +static struct vncFdEntry* fdsHead = NULL; +#endif void vncRegisterBlockHandlers(void) { if (!RegisterBlockAndWakeupHandlers(vncBlockHandler, - (ServerWakeupHandlerProcPtr)NoopDDA, 0)) +#if XORG >= 119 + (ServerWakeupHandlerProcPtr)NoopDDA, +#else + vncWakeupHandler, +#endif + 0)) FatalError("RegisterBlockAndWakeupHandlers() failed\n"); } +void vncSetNotifyFd(int fd, int scrIdx, int read, int write) +{ +#if XORG >= 119 + int mask = (read ? X_NOTIFY_READ : 0) | (write ? X_NOTIFY_WRITE : 0); + SetNotifyFd(fd, vncSocketNotify, mask, (void*)scrIdx); #else + static struct vncFdEntry* entry; + + entry = fdsHead; + while (entry) { + if (entry->fd == fd) { + assert(entry->scrIdx == scrIdx); + entry->read = read; + entry->write = write; + return; + } + entry = entry->next; + } -static void vncBlockHandler(void * data, OSTimePtr t, void * readmask); -static void vncWakeupHandler(void * data, int nfds, void * readmask); -void vncWriteBlockHandler(fd_set *fds); -void vncWriteWakeupHandler(int nfds, fd_set *fds); + entry = malloc(sizeof(struct vncFdEntry)); + memset(entry, 0, sizeof(struct vncFdEntry)); -void vncRegisterBlockHandlers(void) + entry->fd = fd; + entry->scrIdx = scrIdx; + entry->read = read; + entry->write = write; + + entry->next = fdsHead; + fdsHead = entry; +#endif +} + +void vncRemoveNotifyFd(int fd) { - if (!RegisterBlockAndWakeupHandlers(vncBlockHandler, vncWakeupHandler, 0)) - FatalError("RegisterBlockAndWakeupHandlers() failed\n"); +#if XORG >= 119 + RemoveNotifyFd(fd); +#else + static struct vncFdEntry** prev; + static struct vncFdEntry* entry; + + prev = &fdsHead; + entry = fdsHead; + while (entry) { + if (entry->fd == fd) { + *prev = entry->next; + return; + } + prev = &entry->next; + entry = entry->next; + } + + assert(FALSE); +#endif } +#if XORG >= 119 +static void vncSocketNotify(int fd, int xevents, void *data) +{ + int scrIdx; + + scrIdx = (int)data; + vncHandleSocketEvent(fd, scrIdx, + xevents & X_NOTIFY_READ, + xevents & X_NOTIFY_WRITE); +} +#endif + +#if XORG < 119 static void vncWriteBlockHandlerFallback(OSTimePtr timeout); static void vncWriteWakeupHandlerFallback(void); +void vncWriteBlockHandler(fd_set *fds); +void vncWriteWakeupHandler(int nfds, fd_set *fds); +#endif // -// vncBlockHandler - called just before the X server goes into select(). Call -// on to the block handler for each desktop. Then check whether any of the -// selections have changed, and if so, notify any interested X clients. +// vncBlockHandler - called just before the X server goes into poll(). +// +// For older versions of X this also allows us to register file +// descriptors that we want read events on. // -static void vncBlockHandler(void * data, OSTimePtr timeout, void * readmask) +#if XORG >= 119 +static void vncBlockHandler(void* data, void* timeout) +#else +static void vncBlockHandler(void * data, OSTimePtr t, void * readmask) +#endif { - fd_set* fds = (fd_set*)readmask; +#if XORG < 119 + int _timeout; + int* timeout = &_timeout; + static struct timeval tv; + + fd_set* fds; + static struct vncFdEntry* entry; + + if (*t == NULL) + _timeout = -1; + else + _timeout = (*t)->tv_sec * 1000 + (*t)->tv_usec / 1000; +#endif + + vncCallBlockHandlers(timeout); - vncWriteBlockHandlerFallback(timeout); +#if XORG < 119 + if (_timeout != -1) { + tv.tv_sec= _timeout / 1000; + tv.tv_usec = (_timeout % 1000) * 1000; + *t = &tv; + } - vncCallReadBlockHandlers(fds, timeout); + fds = (fd_set*)readmask; + entry = fdsHead; + while (entry) { + if (entry->read) + FD_SET(entry->fd, fds); + entry = entry->next; + } + + vncWriteBlockHandlerFallback(t); +#endif } +#if XORG < 119 static void vncWakeupHandler(void * data, int nfds, void * readmask) { fd_set* fds = (fd_set*)readmask; - vncCallReadWakeupHandlers(fds, nfds); + static struct vncFdEntry* entry; + + entry = fdsHead; + while (entry) { + if (entry->read && FD_ISSET(entry->fd, fds)) + vncHandleSocketEvent(entry->fd, entry->scrIdx, TRUE, FALSE); + entry = entry->next; + } vncWriteWakeupHandlerFallback(); } +#endif // -// vncWriteBlockHandler - extra hack to be able to get the main select loop -// to monitor writeable fds and not just readable. This requirers a modified -// Xorg and might therefore not be called. When it is called though, it will -// do so before vncBlockHandler (and vncWriteWakeupHandler called after -// vncWakeupHandler). +// vncWriteBlockHandler - extra hack to be able to get old versions of the X +// server to monitor writeable fds and not just readable. This requirers a +// modified Xorg and might therefore not be called. // +#if XORG < 119 static Bool needFallback = TRUE; static fd_set fallbackFds; static struct timeval tw; void vncWriteBlockHandler(fd_set *fds) { - struct timeval *dummy; + static struct vncFdEntry* entry; needFallback = FALSE; - dummy = NULL; - vncCallWriteBlockHandlers(fds, &dummy); + entry = fdsHead; + while (entry) { + if (entry->write) + FD_SET(entry->fd, fds); + entry = entry->next; + } } void vncWriteWakeupHandler(int nfds, fd_set *fds) { - vncCallWriteWakeupHandlers(fds, nfds); + static struct vncFdEntry* entry; + + entry = fdsHead; + while (entry) { + if (entry->write && FD_ISSET(entry->fd, fds)) + vncHandleSocketEvent(entry->fd, entry->scrIdx, FALSE, TRUE); + entry = entry->next; + } } static void vncWriteBlockHandlerFallback(OSTimePtr timeout) @@ -161,5 +287,4 @@ static void vncWriteWakeupHandlerFallback(void) vncWriteWakeupHandler(ret, &fallbackFds); } - #endif diff --git a/unix/xserver/hw/vnc/vncBlockHandler.h b/unix/xserver/hw/vnc/vncBlockHandler.h index 556528bd..c1bdaac5 100644 --- a/unix/xserver/hw/vnc/vncBlockHandler.h +++ b/unix/xserver/hw/vnc/vncBlockHandler.h @@ -26,6 +26,9 @@ extern "C" { void vncRegisterBlockHandlers(void); +void vncSetNotifyFd(int fd, int scrIdx, int read, int write); +void vncRemoveNotifyFd(int fd); + #ifdef __cplusplus } #endif diff --git a/unix/xserver/hw/vnc/vncExtInit.cc b/unix/xserver/hw/vnc/vncExtInit.cc index 9d70e44b..57bf6d8d 100644 --- a/unix/xserver/hw/vnc/vncExtInit.cc +++ b/unix/xserver/hw/vnc/vncExtInit.cc @@ -40,6 +40,7 @@ #include "vncBlockHandler.h" #include "vncSelection.h" #include "XorgGlue.h" +#include "xorg-version.h" using namespace rfb; @@ -249,47 +250,18 @@ 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++) - if (desktop[scr]) - desktop[scr]->readBlockHandler(fds, timeout); -} - -void vncCallReadWakeupHandlers(fd_set * fds, int nfds) -{ - for (int scr = 0; scr < vncGetScreenCount(); scr++) - if (desktop[scr]) - desktop[scr]->readWakeupHandler(fds, nfds); -} - -void vncCallWriteBlockHandlers(fd_set * fds, struct timeval ** timeout) +void vncHandleSocketEvent(int fd, int scrIdx, int read, int write) { - for (int scr = 0; scr < vncGetScreenCount(); scr++) - if (desktop[scr]) - desktop[scr]->writeBlockHandler(fds, timeout); + desktop[scrIdx]->handleSocketEvent(fd, read, write); } -void vncCallWriteWakeupHandlers(fd_set * fds, int nfds) +void vncCallBlockHandlers(int* timeout) { for (int scr = 0; scr < vncGetScreenCount(); scr++) if (desktop[scr]) - desktop[scr]->writeWakeupHandler(fds, nfds); + desktop[scr]->blockHandler(timeout); } -#endif - int vncGetAvoidShiftNumLock(void) { return (bool)avoidShiftNumLock; diff --git a/unix/xserver/hw/vnc/vncExtInit.h b/unix/xserver/hw/vnc/vncExtInit.h index 31645281..9f8d9e76 100644 --- a/unix/xserver/hw/vnc/vncExtInit.h +++ b/unix/xserver/hw/vnc/vncExtInit.h @@ -22,7 +22,6 @@ #include <stdint.h> #include <stddef.h> #include <sys/select.h> -#include "xorg-version.h" // Only from C++ #ifdef __cplusplus @@ -51,14 +50,8 @@ extern int vncInetdSock; void vncExtensionInit(void); int vncExtensionIsActive(int scrIdx); -#if XORG >= 119 +void vncHandleSocketEvent(int fd, int scrIdx, int read, int write); 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); |