Add event queue splitting

This allows apps to peel off certain XGE events into separate queues
for custom handling. Designed to support the Present extension

Signed-off-by: Keith Packard <keithp@keithp.com>
Reviewed-By: Uli Schlachter <psychon@znc.in>
This commit is contained in:
Keith Packard 2013-04-12 20:15:41 -07:00
parent bbe7f95e07
commit 568cf48f00
3 changed files with 107 additions and 12 deletions

View File

@ -291,6 +291,39 @@ xcb_generic_event_t *xcb_poll_for_event(xcb_connection_t *c);
*/ */
xcb_generic_event_t *xcb_poll_for_queued_event(xcb_connection_t *c); xcb_generic_event_t *xcb_poll_for_queued_event(xcb_connection_t *c);
typedef struct xcb_special_event xcb_special_event_t;
/**
* @brief Returns the next event from a special queue
*/
xcb_generic_event_t *xcb_poll_for_special_event(xcb_connection_t *c,
xcb_special_event_t *se);
/**
* @brief Returns the next event from a special queue, blocking until one arrives
*/
xcb_generic_event_t *xcb_wait_for_special_event(xcb_connection_t *c,
xcb_special_event_t *se);
/**
* @typedef typedef struct xcb_extension_t xcb_extension_t
*/
typedef struct xcb_extension_t xcb_extension_t; /**< Opaque structure used as key for xcb_get_extension_data_t. */
/**
* @brief Listen for a special event
*/
xcb_special_event_t *xcb_register_for_special_xge(xcb_connection_t *c,
xcb_extension_t *ext,
uint32_t eid,
uint32_t *stamp);
/**
* @brief Stop listening for a special event
*/
void xcb_unregister_for_special_event(xcb_connection_t *c,
xcb_special_event_t *se);
/** /**
* @brief Return the error for a request, or NULL if none can ever arrive. * @brief Return the error for a request, or NULL if none can ever arrive.
* @param c: The connection to the X server. * @param c: The connection to the X server.
@ -328,11 +361,6 @@ void xcb_discard_reply(xcb_connection_t *c, unsigned int sequence);
/* xcb_ext.c */ /* xcb_ext.c */
/**
* @typedef typedef struct xcb_extension_t xcb_extension_t
*/
typedef struct xcb_extension_t xcb_extension_t; /**< Opaque structure used as key for xcb_get_extension_data_t. */
/** /**
* @brief Caches reply information from QueryExtension requests. * @brief Caches reply information from QueryExtension requests.
* @param c: The connection. * @param c: The connection.

View File

@ -60,6 +60,23 @@ struct event_list {
struct event_list *next; 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 { struct reply_list {
void *reply; void *reply;
struct reply_list *next; struct reply_list *next;
@ -104,6 +121,46 @@ static int read_fds(xcb_connection_t *c, int *fds, int nfd)
} }
#endif #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) static int read_packet(xcb_connection_t *c)
{ {
xcb_generic_reply_t genrep; xcb_generic_reply_t genrep;
@ -268,9 +325,12 @@ static int read_packet(xcb_connection_t *c)
} }
event->event = buf; event->event = buf;
event->next = 0; event->next = 0;
*c->in.events_tail = event;
c->in.events_tail = &event->next; if (!event_special(c, event)) {
pthread_cond_signal(&c->in.event_cond); *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... */ return 1; /* I have something for you... */
} }
@ -661,17 +721,21 @@ xcb_generic_event_t *xcb_wait_for_special_event(xcb_connection_t *c,
xcb_special_event_t * xcb_special_event_t *
xcb_register_for_special_xge(xcb_connection_t *c, xcb_register_for_special_xge(xcb_connection_t *c,
uint8_t extension, xcb_extension_t *ext,
uint32_t eid, uint32_t eid,
uint32_t *stamp) uint32_t *stamp)
{ {
xcb_special_event_t *se; xcb_special_event_t *se;
const xcb_query_extension_reply_t *ext_reply;
if(c->has_error) if(c->has_error)
return NULL; return NULL;
ext_reply = xcb_get_extension_data(c, ext);
if (!ext_reply)
return NULL;
pthread_mutex_lock(&c->iolock); pthread_mutex_lock(&c->iolock);
for (se = c->in.special_events; se; se = se->next) { for (se = c->in.special_events; se; se = se->next) {
if (se->extension == extension && if (se->extension == ext_reply->major_opcode &&
se->eid == eid) { se->eid == eid) {
pthread_mutex_unlock(&c->iolock); pthread_mutex_unlock(&c->iolock);
return NULL; return NULL;
@ -683,7 +747,7 @@ xcb_register_for_special_xge(xcb_connection_t *c,
return NULL; return NULL;
} }
se->extension = extension; se->extension = ext_reply->major_opcode;
se->eid = eid; se->eid = eid;
se->events = NULL; se->events = NULL;
@ -694,7 +758,6 @@ xcb_register_for_special_xge(xcb_connection_t *c,
se->next = c->in.special_events; se->next = c->in.special_events;
c->in.special_events = se; c->in.special_events = se;
pthread_mutex_unlock(&c->iolock); pthread_mutex_unlock(&c->iolock);
return se; return se;
} }
@ -706,6 +769,9 @@ xcb_unregister_for_special_event(xcb_connection_t *c,
xcb_special_event_t *s, **prev; xcb_special_event_t *s, **prev;
struct event_list *events, *next; struct event_list *events, *next;
if (!se)
return;
if (c->has_error) if (c->has_error)
return; return;

View File

@ -155,6 +155,7 @@ typedef struct _xcb_in {
#if HAVE_SENDMSG #if HAVE_SENDMSG
_xcb_fd in_fd; _xcb_fd in_fd;
#endif #endif
struct xcb_special_event *special_events;
} _xcb_in; } _xcb_in;
int _xcb_in_init(_xcb_in *in); int _xcb_in_init(_xcb_in *in);