summaryrefslogtreecommitdiff
path: root/os/connection.c
diff options
context:
space:
mode:
Diffstat (limited to 'os/connection.c')
-rw-r--r--os/connection.c93
1 files changed, 93 insertions, 0 deletions
diff --git a/os/connection.c b/os/connection.c
index 3d33c4170..0df439189 100644
--- a/os/connection.c
+++ b/os/connection.c
@@ -123,6 +123,7 @@ static int lastfdesc; /* maximum file descriptor */
fd_set WellKnownConnections; /* Listener mask */
fd_set EnabledDevices; /* mask for input devices that are on */
+fd_set NotifyReadFds; /* mask for other file descriptors */
fd_set AllSockets; /* select on this */
fd_set AllClients; /* available clients */
fd_set LastSelectMask; /* mask returned from last select call */
@@ -1090,6 +1091,98 @@ RemoveEnabledDevice(int fd)
RemoveGeneralSocket(fd);
}
+struct notify_fd {
+ struct xorg_list list;
+ int fd;
+ int mask;
+ NotifyFdProcPtr notify;
+ void *data;
+};
+
+static struct xorg_list notify_fds;
+
+void
+InitNotifyFds(void)
+{
+ struct notify_fd *s, *next;
+ static int been_here;
+
+ if (been_here)
+ xorg_list_for_each_entry_safe(s, next, &notify_fds, list)
+ RemoveNotifyFd(s->fd);
+
+ xorg_list_init(&notify_fds);
+ been_here = 1;
+}
+
+/*****************
+ * SetNotifyFd
+ * Registers a callback to be invoked when the specified
+ * file descriptor becomes readable.
+ *****************/
+
+Bool
+SetNotifyFd(int fd, NotifyFdProcPtr notify, int mask, void *data)
+{
+ struct notify_fd *n;
+ int changes;
+
+ xorg_list_for_each_entry(n, &notify_fds, list)
+ if (n->fd == fd)
+ break;
+
+ if (&n->list == &notify_fds) {
+ if (mask == 0)
+ return TRUE;
+
+ n = calloc(1, sizeof (struct notify_fd));
+ if (!n)
+ return FALSE;
+ n->fd = fd;
+ xorg_list_add(&n->list, &notify_fds);
+ }
+
+ changes = n->mask ^ mask;
+
+ if (changes & X_NOTIFY_READ) {
+ if (mask & X_NOTIFY_READ) {
+ FD_SET(fd, &NotifyReadFds);
+ AddGeneralSocket(fd);
+ } else {
+ RemoveGeneralSocket(fd);
+ FD_CLR(fd, &NotifyReadFds);
+ }
+ }
+ if (mask == 0) {
+ xorg_list_del(&n->list);
+ free(n);
+ } else {
+ n->mask = mask;
+ n->data = data;
+ n->notify = notify;
+ }
+
+ return TRUE;
+}
+
+/*****************
+ * HandlNotifyFds
+ * A WorkProc to be called when any of the registered
+ * file descriptors are readable.
+ *****************/
+
+void
+HandleNotifyFds(void)
+{
+ struct notify_fd *s, *next;
+
+ xorg_list_for_each_entry_safe(s, next, &notify_fds, list) {
+ if (FD_ISSET(s->fd, &LastSelectMask)) {
+ s->notify(s->fd, X_NOTIFY_READ, s->data);
+ }
+ }
+}
+
/*****************
* OnlyListenToOneClient:
* Only accept requests from one client. Continue to handle new