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:
parent
7983bf0fbd
commit
79019541e7
38
src/xcb.h
38
src/xcb.h
|
@ -290,6 +290,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);
|
||||
|
||||
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.
|
||||
* @param c: The connection to the X server.
|
||||
|
@ -327,11 +360,6 @@ void xcb_discard_reply(xcb_connection_t *c, unsigned int sequence);
|
|||
|
||||
/* 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.
|
||||
* @param c: The connection.
|
||||
|
|
74
src/xcb_in.c
74
src/xcb_in.c
|
@ -60,6 +60,23 @@ struct event_list {
|
|||
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;
|
||||
|
@ -104,6 +121,46 @@ static int read_fds(xcb_connection_t *c, int *fds, int nfd)
|
|||
}
|
||||
#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;
|
||||
|
@ -268,9 +325,12 @@ static int read_packet(xcb_connection_t *c)
|
|||
}
|
||||
event->event = buf;
|
||||
event->next = 0;
|
||||
|
||||
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... */
|
||||
}
|
||||
|
||||
|
@ -661,17 +721,21 @@ xcb_generic_event_t *xcb_wait_for_special_event(xcb_connection_t *c,
|
|||
|
||||
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;
|
||||
|
@ -683,7 +747,7 @@ xcb_register_for_special_xge(xcb_connection_t *c,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
se->extension = extension;
|
||||
se->extension = ext_reply->major_opcode;
|
||||
se->eid = eid;
|
||||
|
||||
se->events = NULL;
|
||||
|
@ -694,7 +758,6 @@ xcb_register_for_special_xge(xcb_connection_t *c,
|
|||
|
||||
se->next = c->in.special_events;
|
||||
c->in.special_events = se;
|
||||
|
||||
pthread_mutex_unlock(&c->iolock);
|
||||
return se;
|
||||
}
|
||||
|
@ -706,6 +769,9 @@ xcb_unregister_for_special_event(xcb_connection_t *c,
|
|||
xcb_special_event_t *s, **prev;
|
||||
struct event_list *events, *next;
|
||||
|
||||
if (!se)
|
||||
return;
|
||||
|
||||
if (c->has_error)
|
||||
return;
|
||||
|
||||
|
|
|
@ -154,6 +154,7 @@ typedef struct _xcb_in {
|
|||
#if HAVE_SENDMSG
|
||||
_xcb_fd in_fd;
|
||||
#endif
|
||||
struct xcb_special_event *special_events;
|
||||
} _xcb_in;
|
||||
|
||||
int _xcb_in_init(_xcb_in *in);
|
||||
|
|
Loading…
Reference in New Issue