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
bbe7f95e07
commit
568cf48f00
38
src/xcb.h
38
src/xcb.h
|
@ -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.
|
||||||
|
|
80
src/xcb_in.c
80
src/xcb_in.c
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
Loading…
Reference in New Issue