struct event_list *next;
};
+struct xcb_special_event {
+
+ struct xcb_special_event *next;
+
+ /* Match XGE events for the specific extension and event ID (the
+ * first 32 bit word after evtype)
+ */
+ uint8_t extension;
+ uint32_t eid;
+ uint32_t *stamp;
+
+ struct event_list *events;
+ struct event_list **events_tail;
+
+ pthread_cond_t special_event_cond;
+};
+
struct reply_list {
void *reply;
struct reply_list *next;
}
#endif
+typedef struct xcb_ge_special_event_t {
+ uint8_t response_type; /**< */
+ uint8_t extension; /**< */
+ uint16_t sequence; /**< */
+ uint32_t length; /**< */
+ uint16_t evtype; /**< */
+ uint8_t pad0[2]; /**< */
+ uint32_t eid; /**< */
+ uint8_t pad1[16]; /**< */
+} xcb_ge_special_event_t;
+
+static int event_special(xcb_connection_t *c,
+ struct event_list *event)
+{
+ struct xcb_special_event *special_event;
+ struct xcb_ge_special_event_t *ges = (void *) event->event;
+
+ /* Special events are always XGE events */
+ if ((ges->response_type & 0x7f) != XCB_XGE_EVENT)
+ return 0;
+
+ for (special_event = c->in.special_events;
+ special_event;
+ special_event = special_event->next)
+ {
+ if (ges->extension == special_event->extension &&
+ ges->eid == special_event->eid)
+ {
+ *special_event->events_tail = event;
+ special_event->events_tail = &event->next;
+ if (special_event->stamp)
+ ++(*special_event->stamp);
+ pthread_cond_signal(&special_event->special_event_cond);
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
static int read_packet(xcb_connection_t *c)
{
xcb_generic_reply_t genrep;
c->in.request_completed = c->in.request_read - 1;
}
- while(c->in.pending_replies &&
+ while(c->in.pending_replies &&
c->in.pending_replies->workaround != WORKAROUND_EXTERNAL_SOCKET_OWNER &&
- XCB_SEQUENCE_COMPARE (c->in.pending_replies->last_request, <=, c->in.request_completed))
+ XCB_SEQUENCE_COMPARE (c->in.pending_replies->last_request, <=, c->in.request_completed))
{
pending_reply *oldpend = c->in.pending_replies;
c->in.pending_replies = oldpend->next;
}
event->event = buf;
event->next = 0;
- *c->in.events_tail = event;
- c->in.events_tail = &event->next;
- pthread_cond_signal(&c->in.event_cond);
+
+ if (!event_special(c, event)) {
+ *c->in.events_tail = event;
+ c->in.events_tail = &event->next;
+ pthread_cond_signal(&c->in.event_cond);
+ }
return 1; /* I have something for you... */
}
FD_ZERO(&fds);
FD_SET(fd, &fds);
- /* Initializing errno here makes sure that for Win32 this loop will execute only once */
- errno = 0;
- do {
- ret = select(fd + 1, &fds, 0, 0, 0);
- } while (ret == -1 && errno == EINTR);
+ /* Initializing errno here makes sure that for Win32 this loop will execute only once */
+ errno = 0;
+ do {
+ ret = select(fd + 1, &fds, 0, 0, 0);
+ } while (ret == -1 && errno == EINTR);
#endif /* USE_POLL */
}
if(ret <= 0)
xcb_special_event_t *
xcb_register_for_special_xge(xcb_connection_t *c,
- uint8_t extension,
+ xcb_extension_t *ext,
uint32_t eid,
uint32_t *stamp)
{
xcb_special_event_t *se;
+ const xcb_query_extension_reply_t *ext_reply;
if(c->has_error)
return NULL;
+ ext_reply = xcb_get_extension_data(c, ext);
+ if (!ext_reply)
+ return NULL;
pthread_mutex_lock(&c->iolock);
for (se = c->in.special_events; se; se = se->next) {
- if (se->extension == extension &&
+ if (se->extension == ext_reply->major_opcode &&
se->eid == eid) {
pthread_mutex_unlock(&c->iolock);
return NULL;
pthread_mutex_unlock(&c->iolock);
return NULL;
}
-
- se->extension = extension;
+
+ se->extension = ext_reply->major_opcode;
se->eid = eid;
se->events = NULL;
se->next = c->in.special_events;
c->in.special_events = se;
-
pthread_mutex_unlock(&c->iolock);
return se;
}
xcb_special_event_t *s, **prev;
struct event_list *events, *next;
+ if (!se)
+ return;
+
if (c->has_error)
return;
.iov_base = c->in.queue + c->in.queue_len,
.iov_len = sizeof(c->in.queue) - c->in.queue_len,
};
- struct {
- struct cmsghdr cmsghdr;
- int fd[XCB_MAX_PASS_FD];
- } fds;
+ union {
+ struct cmsghdr cmsghdr;
+ char buf[CMSG_SPACE(XCB_MAX_PASS_FD * sizeof(int))];
+ } cmsgbuf;
struct msghdr msg = {
.msg_name = NULL,
.msg_namelen = 0,
.msg_iov = &iov,
.msg_iovlen = 1,
- .msg_control = &fds,
- .msg_controllen = sizeof (struct cmsghdr) + sizeof(int) * (XCB_MAX_PASS_FD - c->in.in_fd.nfd),
+ .msg_control = cmsgbuf.buf,
+ .msg_controllen = CMSG_SPACE(sizeof(int) * (XCB_MAX_PASS_FD - c->in.in_fd.nfd)),
};
n = recvmsg(c->fd, &msg, 0);
#endif
if(n > 0) {
#if HAVE_SENDMSG
- if (msg.msg_controllen > sizeof (struct cmsghdr))
- {
- if (fds.cmsghdr.cmsg_level == SOL_SOCKET &&
- fds.cmsghdr.cmsg_type == SCM_RIGHTS)
- {
- int nfd = (msg.msg_controllen - sizeof (struct cmsghdr)) / sizeof (int);
- memmove(&c->in.in_fd.fd[c->in.in_fd.nfd],
- fds.fd,
- nfd);
- c->in.in_fd.nfd += nfd;
+ struct cmsghdr *hdr;
+
+ if (msg.msg_controllen >= sizeof (struct cmsghdr)) {
+ for (hdr = CMSG_FIRSTHDR(&msg); hdr; hdr = CMSG_NXTHDR(&msg, hdr)) {
+ if (hdr->cmsg_level == SOL_SOCKET && hdr->cmsg_type == SCM_RIGHTS) {
+ int nfd = (hdr->cmsg_len - CMSG_LEN(0)) / sizeof (int);
+ memcpy(&c->in.in_fd.fd[c->in.in_fd.nfd], CMSG_DATA(hdr), nfd * sizeof (int));
+ c->in.in_fd.nfd += nfd;
+ }
}
}
#endif