]> source.dussan.org Git - tigervnc.git/commitdiff
Merge X server block handling code paths
authorPierre Ossman <ossman@cendio.se>
Wed, 5 Oct 2016 11:46:01 +0000 (13:46 +0200)
committerPierre Ossman <ossman@cendio.se>
Wed, 5 Oct 2016 11:46:01 +0000 (13:46 +0200)
Use the new X server API as the reference system and emulate it on
the older API. Avoids a lot of code duplication.

unix/xserver/hw/vnc/XserverDesktop.cc
unix/xserver/hw/vnc/XserverDesktop.h
unix/xserver/hw/vnc/vncBlockHandler.c
unix/xserver/hw/vnc/vncBlockHandler.h
unix/xserver/hw/vnc/vncExtInit.cc
unix/xserver/hw/vnc/vncExtInit.h

index 8cc0b0b7f0a28f39ae1573e5dd46fd9a69a8513e..f6e6a7fe7869a1405e03fed7e9d08ddab2d4f273 100644 (file)
@@ -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()
index 9e776274ebfb4be973c9a96916080278d376be89..07bd39953017933bc75d1d3949cba83e5f7e3e10 100644 (file)
 #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 &region);
   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;
index baebc3df29712446242673d0ab5ae81e02361c17..604dc4abb81f2d0ed0144663221aef5c8cb929bf 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <X11/Xpoll.h>
 
+#include "os.h"
 #include "dix.h"
 #include "scrnintstr.h"
 
 #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
index 556528bd951444bc0a2268fcaf4f04986a3baef9..c1bdaac51e99f84abf4f10d4ec5f07685d305974 100644 (file)
@@ -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
index 9d70e44b647047faeb3c287de0f2bbd9edc38b26..57bf6d8d27ddd86d990036d8da75715ca72d95b8 100644 (file)
@@ -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;
index 316452810f37949a56384b8575cc3e9dc2caf94a..9f8d9e76f2364e542a403c41235eb280298e48e4 100644 (file)
@@ -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);