aboutsummaryrefslogtreecommitdiff
path: root/libxcb
diff options
context:
space:
mode:
Diffstat (limited to 'libxcb')
-rw-r--r--libxcb/src/c_client.py103
-rw-r--r--libxcb/src/xcb_in.c1
-rw-r--r--libxcb/src/xcb_out.c85
-rw-r--r--libxcb/src/xcbext.h77
-rw-r--r--libxcb/xcb-proto/doc/xml-xcb.txt11
-rw-r--r--libxcb/xcb-proto/src/present.xml10
-rw-r--r--libxcb/xcb-proto/src/xprint.xml8
7 files changed, 207 insertions, 88 deletions
diff --git a/libxcb/src/c_client.py b/libxcb/src/c_client.py
index e55fc3c6b..70f842933 100644
--- a/libxcb/src/c_client.py
+++ b/libxcb/src/c_client.py
@@ -629,8 +629,7 @@ def _c_helper_resolve_field_names (prefix):
all_fields = {}
tmp_prefix = []
# look for fields in the remaining containers
- for idx, p in enumerate(prefix):
- name, sep, obj = p
+ for idx, (name, sep, obj) in enumerate(prefix):
if ''==sep:
# sep can be preset in prefix, if not, make a sensible guess
sep = '.' if (obj.is_switch or obj.is_case_or_bitcase) else '->'
@@ -1033,7 +1032,7 @@ def _c_serialize_helper_fields_fixed_size(context, self, field,
if not self.is_case_or_bitcase:
code_lines.append('%s /* %s.%s */' % (space, self.c_type, field.c_field_name))
else:
- scoped_name = [p[2].c_type if idx==0 else p[0] for idx, p in enumerate(prefix)]
+ scoped_name = [obj.c_type if idx==0 else name for idx, (name, _, obj) in enumerate(prefix)]
typename = ".".join(scoped_name)
code_lines.append('%s /* %s.%s */' % (space, typename, field.c_field_name))
@@ -1327,7 +1326,7 @@ def _c_serialize(context, self):
for p in params:
typespec, pointerspec, field_name = p
spacing = ' '*(maxtypelen-len(typespec)-len(pointerspec))
- param_str.append("%s%s%s %s%s /**< */" % (indent, typespec, spacing, pointerspec, field_name))
+ param_str.append("%s%s%s %s%s" % (indent, typespec, spacing, pointerspec, field_name))
# insert function name
param_str[0] = "%s (%s" % (func_name, param_str[0].strip())
param_str = ["%s," % x for x in param_str]
@@ -1520,9 +1519,9 @@ def _c_iterator(self, name):
_h(' * @brief %s', self.c_iterator_type)
_h(' **/')
_h('typedef struct %s {', self.c_iterator_type)
- _h(' %s *data; /**< */', self.c_type)
- _h(' int%s rem; /**< */', ' ' * (len(self.c_type) - 2))
- _h(' int%s index; /**< */', ' ' * (len(self.c_type) - 2))
+ _h(' %s *data;', self.c_type)
+ _h(' int%s rem;', ' ' * (len(self.c_type) - 2))
+ _h(' int%s index;', ' ' * (len(self.c_type) - 2))
# add additional params of the type "self" as fields to the iterator struct
# so that they can be passed to the sizeof-function by the iterator's next-function
params = _c_get_additional_type_params(self)
@@ -1546,8 +1545,8 @@ def _c_iterator(self, name):
_h(' */')
_c('')
_hc('void')
- _h('%s (%s *i /**< */);', self.c_next_name, self.c_iterator_type)
- _c('%s (%s *i /**< */)', self.c_next_name, self.c_iterator_type)
+ _h('%s (%s *i);', self.c_next_name, self.c_iterator_type)
+ _c('%s (%s *i)', self.c_next_name, self.c_iterator_type)
_c('{')
if not self.fixed_size():
@@ -1592,8 +1591,8 @@ def _c_iterator(self, name):
_h(' */')
_c('')
_hc('xcb_generic_iterator_t')
- _h('%s (%s i /**< */);', self.c_end_name, self.c_iterator_type)
- _c('%s (%s i /**< */)', self.c_end_name, self.c_iterator_type)
+ _h('%s (%s i);', self.c_end_name, self.c_iterator_type)
+ _c('%s (%s i)', self.c_end_name, self.c_iterator_type)
_c('{')
_c(' xcb_generic_iterator_t ret;')
@@ -1749,8 +1748,8 @@ def _c_accessors_field(self, field):
if field.type.is_simple:
_hc('')
_hc('%s', field.c_field_type)
- _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
- _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
+ _h('%s (const %s *R);', field.c_accessor_name, c_type)
+ _c('%s (const %s *R)', field.c_accessor_name, c_type)
_c('{')
if field.prev_varsized_field is None:
_c(' return (%s *) (R + 1);', field.c_field_type)
@@ -1767,8 +1766,8 @@ def _c_accessors_field(self, field):
return_type = '%s *' % field.c_field_type
_hc(return_type)
- _h('%s (const %s *R /**< */);', field.c_accessor_name, c_type)
- _c('%s (const %s *R /**< */)', field.c_accessor_name, c_type)
+ _h('%s (const %s *R);', field.c_accessor_name, c_type)
+ _c('%s (const %s *R)', field.c_accessor_name, c_type)
_c('{')
if field.prev_varsized_field is None:
_c(' return (%s) (R + 1);', return_type)
@@ -1867,7 +1866,7 @@ def _c_accessors_list(self, field):
if len(additional_params) == 0:
return ''
else:
- return (',\n' + indent).join([''] + ['%s %s /**< */' % p for p in additional_params])
+ return (',\n' + indent).join([''] + ['%s %s' % p for p in additional_params])
_h_setlevel(1)
_c_setlevel(1)
@@ -1876,8 +1875,8 @@ def _c_accessors_list(self, field):
_hc('')
_hc('%s *', field.c_field_type)
- _h('%s (%s /**< */);', field.c_accessor_name, params[idx][0])
- _c('%s (%s /**< */)', field.c_accessor_name, params[idx][0])
+ _h('%s (%s);', field.c_accessor_name, params[idx][0])
+ _c('%s (%s)', field.c_accessor_name, params[idx][0])
_c('{')
if switch_obj is not None:
@@ -1902,12 +1901,12 @@ def _c_accessors_list(self, field):
spacing = ' '*(len(field.c_length_name)+2)
add_param_str = additional_params_to_str(spacing)
if switch_obj is not None:
- _hc('%s (const %s *R /**< */,', field.c_length_name, R_obj.c_type)
- _h('%sconst %s *S /**< */%s);', spacing, S_obj.c_type, add_param_str)
- _c('%sconst %s *S /**< */%s)', spacing, S_obj.c_type, add_param_str)
+ _hc('%s (const %s *R,', field.c_length_name, R_obj.c_type)
+ _h('%sconst %s *S%s);', spacing, S_obj.c_type, add_param_str)
+ _c('%sconst %s *S%s)', spacing, S_obj.c_type, add_param_str)
else:
- _h('%s (const %s *R /**< */%s);', field.c_length_name, c_type, add_param_str)
- _c('%s (const %s *R /**< */%s)', field.c_length_name, c_type, add_param_str)
+ _h('%s (const %s *R%s);', field.c_length_name, c_type, add_param_str)
+ _c('%s (const %s *R%s)', field.c_length_name, c_type, add_param_str)
_c('{')
length = _c_accessor_get_expr(field.type.expr, fields)
_c(' return %s;', length)
@@ -1919,12 +1918,12 @@ def _c_accessors_list(self, field):
spacing = ' '*(len(field.c_end_name)+2)
add_param_str = additional_params_to_str(spacing)
if switch_obj is not None:
- _hc('%s (const %s *R /**< */,', field.c_end_name, R_obj.c_type)
- _h('%sconst %s *S /**< */%s);', spacing, S_obj.c_type, add_param_str)
- _c('%sconst %s *S /**< */%s)', spacing, S_obj.c_type, add_param_str)
+ _hc('%s (const %s *R,', field.c_end_name, R_obj.c_type)
+ _h('%sconst %s *S%s);', spacing, S_obj.c_type, add_param_str)
+ _c('%sconst %s *S%s)', spacing, S_obj.c_type, add_param_str)
else:
- _h('%s (const %s *R /**< */%s);', field.c_end_name, c_type, add_param_str)
- _c('%s (const %s *R /**< */%s)', field.c_end_name, c_type, add_param_str)
+ _h('%s (const %s *R%s);', field.c_end_name, c_type, add_param_str)
+ _c('%s (const %s *R%s)', field.c_end_name, c_type, add_param_str)
_c('{')
_c(' xcb_generic_iterator_t i;')
@@ -1952,12 +1951,12 @@ def _c_accessors_list(self, field):
spacing = ' '*(len(field.c_iterator_name)+2)
add_param_str = additional_params_to_str(spacing)
if switch_obj is not None:
- _hc('%s (const %s *R /**< */,', field.c_iterator_name, R_obj.c_type)
- _h('%sconst %s *S /**< */%s);', spacing, S_obj.c_type, add_param_str)
- _c('%sconst %s *S /**< */%s)', spacing, S_obj.c_type, add_param_str)
+ _hc('%s (const %s *R,', field.c_iterator_name, R_obj.c_type)
+ _h('%sconst %s *S%s);', spacing, S_obj.c_type, add_param_str)
+ _c('%sconst %s *S%s)', spacing, S_obj.c_type, add_param_str)
else:
- _h('%s (const %s *R /**< */%s);', field.c_iterator_name, c_type, add_param_str)
- _c('%s (const %s *R /**< */%s)', field.c_iterator_name, c_type, add_param_str)
+ _h('%s (const %s *R%s);', field.c_iterator_name, c_type, add_param_str)
+ _c('%s (const %s *R%s)', field.c_iterator_name, c_type, add_param_str)
_c('{')
_c(' %s i;', field.c_iterator_type)
@@ -2063,10 +2062,10 @@ def _c_complex(self, force_packed = False):
# necessary for unserialize to work
(self.is_switch and field.type.is_switch)):
spacing = ' ' * (maxtypelen - len(field.c_field_type))
- _h('%s %s%s %s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
+ _h('%s %s%s %s%s;', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
else:
spacing = ' ' * (maxtypelen - (len(field.c_field_type) + 1))
- _h('%s %s%s *%s%s; /**< */', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
+ _h('%s %s%s *%s%s;', space, field.c_field_type, spacing, field.c_field_name, field.c_subscript)
if not self.is_switch:
for field in struct_fields:
@@ -2243,9 +2242,9 @@ def _c_request_helper(self, name, void, regular, aux=False, reply_fds=False):
spacing = ' ' * (maxtypelen - len('xcb_connection_t'))
comma = ',' if len(param_fields) else ');'
- _h('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
+ _h('%s (xcb_connection_t%s *c%s', func_name, spacing, comma)
comma = ',' if len(param_fields) else ')'
- _c('%s (xcb_connection_t%s *c /**< */%s', func_name, spacing, comma)
+ _c('%s (xcb_connection_t%s *c%s', func_name, spacing, comma)
func_spacing = ' ' * (len(func_name) + 2)
count = len(param_fields)
@@ -2258,10 +2257,10 @@ def _c_request_helper(self, name, void, regular, aux=False, reply_fds=False):
c_pointer = '*'
spacing = ' ' * (maxtypelen - len(c_field_const_type))
comma = ',' if count else ');'
- _h('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
+ _h('%s%s%s %s%s%s', func_spacing, c_field_const_type,
spacing, c_pointer, field.c_field_name, comma)
comma = ',' if count else ')'
- _c('%s%s%s %s%s /**< */%s', func_spacing, c_field_const_type,
+ _c('%s%s%s %s%s%s', func_spacing, c_field_const_type,
spacing, c_pointer, field.c_field_name, comma)
count = 2
@@ -2291,13 +2290,16 @@ def _c_request_helper(self, name, void, regular, aux=False, reply_fds=False):
_c(' void *xcb_aux = 0;')
- for idx, f in enumerate(serial_fields):
+ for idx, _ in enumerate(serial_fields):
if aux:
_c(' void *xcb_aux%d = 0;' % (idx))
if list_with_var_size_elems:
_c(' unsigned int i;')
_c(' unsigned int xcb_tmp_len;')
_c(' char *xcb_tmp;')
+ num_fds = len([field for field in param_fields if field.isfd])
+ if num_fds > 0:
+ _c(' int fds[%d];' % (num_fds))
_c('')
# fixed size fields
@@ -2398,11 +2400,16 @@ def _c_request_helper(self, name, void, regular, aux=False, reply_fds=False):
# no padding necessary - _serialize() keeps track of padding automatically
_c('')
+ fd_index = 0
for field in param_fields:
if field.isfd:
- _c(' xcb_send_fd(c, %s);', field.c_field_name)
+ _c(' fds[%d] = %s;', fd_index, field.c_field_name)
+ fd_index = fd_index + 1
- _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
+ if num_fds == 0:
+ _c(' xcb_ret.sequence = xcb_send_request(c, %s, xcb_parts + 2, &xcb_req);', func_flags)
+ else:
+ _c(' xcb_ret.sequence = xcb_send_request_with_fds(c, %s, xcb_parts + 2, &xcb_req, %d, fds);', func_flags, num_fds)
# free dyn. all. data, if any
for f in free_calls:
@@ -2457,10 +2464,10 @@ def _c_reply(self, name):
_h(' */')
_c('')
_hc('%s *', self.c_reply_type)
- _hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_name, spacing1)
+ _hc('%s (xcb_connection_t%s *c,', self.c_reply_name, spacing1)
_hc('%s%s cookie /**< */,', spacing3, self.c_cookie_type)
- _h('%sxcb_generic_error_t%s **e /**< */);', spacing3, spacing2)
- _c('%sxcb_generic_error_t%s **e /**< */)', spacing3, spacing2)
+ _h('%sxcb_generic_error_t%s **e);', spacing3, spacing2)
+ _c('%sxcb_generic_error_t%s **e)', spacing3, spacing2)
_c('{')
if len(unserialize_fields)>0:
@@ -2515,8 +2522,8 @@ def _c_reply_fds(self, name):
_c('')
_hc('int *')
_hc('%s (xcb_connection_t%s *c /**< */,', self.c_reply_fds_name, spacing1)
- _h('%s%s *reply /**< */);', spacing3, self.c_reply_type)
- _c('%s%s *reply /**< */)', spacing3, self.c_reply_type)
+ _h('%s%s *reply);', spacing3, self.c_reply_type)
+ _c('%s%s *reply)', spacing3, self.c_reply_type)
_c('{')
_c(' return xcb_get_reply_fds(c, reply, sizeof(%s) + 4 * reply->length);', self.c_reply_type)
@@ -2543,7 +2550,7 @@ def _c_cookie(self, name):
_h(' * @brief %s', self.c_cookie_type)
_h(' **/')
_h('typedef struct %s {', self.c_cookie_type)
- _h(' unsigned int sequence; /**< */')
+ _h(' unsigned int sequence;')
_h('} %s;', self.c_cookie_type)
def _man_request(self, name, void, aux):
diff --git a/libxcb/src/xcb_in.c b/libxcb/src/xcb_in.c
index 623a0a803..322bed816 100644
--- a/libxcb/src/xcb_in.c
+++ b/libxcb/src/xcb_in.c
@@ -761,6 +761,7 @@ xcb_generic_event_t *xcb_wait_for_special_event(xcb_connection_t *c,
if(!_xcb_conn_wait(c, &se->special_event_cond, 0, 0))
break;
+ _xcb_in_wake_up_next_reader(c);
pthread_mutex_unlock(&c->iolock);
return event;
}
diff --git a/libxcb/src/xcb_out.c b/libxcb/src/xcb_out.c
index 8cc5be868..3601a5fa4 100644
--- a/libxcb/src/xcb_out.c
+++ b/libxcb/src/xcb_out.c
@@ -177,15 +177,59 @@ uint32_t xcb_get_maximum_request_length(xcb_connection_t *c)
return c->out.maximum_request_length.value;
}
-uint64_t xcb_send_request64(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *req)
+static void close_fds(int *fds, unsigned int num_fds)
+{
+ for (unsigned int index = 0; index < num_fds; index++)
+ close(fds[index]);
+}
+
+static void send_fds(xcb_connection_t *c, int *fds, unsigned int num_fds)
+{
+#if HAVE_SENDMSG
+ /* Calling _xcb_out_flush_to() can drop the iolock and wait on a condition
+ * variable if another thread is currently writing (c->out.writing > 0).
+ * This call waits for writers to be done and thus _xcb_out_flush_to() will
+ * do the work itself (in which case we are a writer and
+ * prepare_socket_request() will wait for us to be done if another threads
+ * tries to send fds, too). Thanks to this, we can atomically write out FDs.
+ */
+ prepare_socket_request(c);
+
+ while (num_fds > 0) {
+ while (c->out.out_fd.nfd == XCB_MAX_PASS_FD && !c->has_error) {
+ /* XXX: if c->out.writing > 0, this releases the iolock and
+ * potentially allows other threads to interfere with their own fds.
+ */
+ _xcb_out_flush_to(c, c->out.request);
+
+ if (c->out.out_fd.nfd == XCB_MAX_PASS_FD) {
+ /* We need some request to send FDs with */
+ _xcb_out_send_sync(c);
+ }
+ }
+ if (c->has_error)
+ break;
+
+ c->out.out_fd.fd[c->out.out_fd.nfd++] = fds[0];
+ fds++;
+ num_fds--;
+ }
+#endif
+ close_fds(fds, num_fds);
+}
+
+uint64_t xcb_send_request_with_fds64(xcb_connection_t *c, int flags, struct iovec *vector,
+ const xcb_protocol_request_t *req, unsigned int num_fds, int *fds)
{
uint64_t request;
uint32_t prefix[2];
int veclen = req->count;
enum workarounds workaround = WORKAROUND_NONE;
- if(c->has_error)
+ if(c->has_error) {
+ close_fds(fds, num_fds);
return 0;
+ }
assert(c != 0);
assert(vector != 0);
@@ -204,6 +248,7 @@ uint64_t xcb_send_request64(xcb_connection_t *c, int flags, struct iovec *vector
const xcb_query_extension_reply_t *extension = xcb_get_extension_data(c, req->ext);
if(!(extension && extension->present))
{
+ close_fds(fds, num_fds);
_xcb_conn_shutdown(c, XCB_CONN_CLOSED_EXT_NOTSUPPORTED);
return 0;
}
@@ -234,6 +279,7 @@ uint64_t xcb_send_request64(xcb_connection_t *c, int flags, struct iovec *vector
}
else if(longlen > xcb_get_maximum_request_length(c))
{
+ close_fds(fds, num_fds);
_xcb_conn_shutdown(c, XCB_CONN_CLOSED_REQ_LEN_EXCEED);
return 0; /* server can't take this; maybe need BIGREQUESTS? */
}
@@ -264,6 +310,11 @@ uint64_t xcb_send_request64(xcb_connection_t *c, int flags, struct iovec *vector
/* get a sequence number and arrange for delivery. */
pthread_mutex_lock(&c->iolock);
+ /* send FDs before establishing a good request number, because this might
+ * call send_sync(), too
+ */
+ send_fds(c, fds, num_fds);
+
prepare_socket_request(c);
/* send GetInputFocus (sync_req) when 64k-2 requests have been sent without
@@ -272,7 +323,7 @@ uint64_t xcb_send_request64(xcb_connection_t *c, int flags, struct iovec *vector
* applications see sequence 0 as that is used to indicate
* an error in sending the request
*/
-
+
while ((req->isvoid && c->out.request == c->in.request_expected + (1 << 16) - 2) ||
(unsigned int) (c->out.request + 1) == 0)
{
@@ -287,6 +338,18 @@ uint64_t xcb_send_request64(xcb_connection_t *c, int flags, struct iovec *vector
}
/* request number are actually uint64_t internally but keep API compat with unsigned int */
+unsigned int xcb_send_request_with_fds(xcb_connection_t *c, int flags, struct iovec *vector,
+ const xcb_protocol_request_t *req, unsigned int num_fds, int *fds)
+{
+ return xcb_send_request_with_fds64(c, flags, vector, req, num_fds, fds);
+}
+
+uint64_t xcb_send_request64(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *req)
+{
+ return xcb_send_request_with_fds64(c, flags, vector, req, 0, NULL);
+}
+
+/* request number are actually uint64_t internally but keep API compat with unsigned int */
unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *req)
{
return xcb_send_request64(c, flags, vector, req);
@@ -295,19 +358,15 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
void
xcb_send_fd(xcb_connection_t *c, int fd)
{
-#if HAVE_SENDMSG
- if (c->has_error)
+ int fds[1] = { fd };
+
+ if (c->has_error) {
+ close(fd);
return;
- pthread_mutex_lock(&c->iolock);
- while (c->out.out_fd.nfd == XCB_MAX_PASS_FD) {
- _xcb_out_flush_to(c, c->out.request);
- if (c->has_error)
- break;
}
- if (!c->has_error)
- c->out.out_fd.fd[c->out.out_fd.nfd++] = fd;
+ pthread_mutex_lock(&c->iolock);
+ send_fds(c, &fds[0], 1);
pthread_mutex_unlock(&c->iolock);
-#endif
}
int xcb_take_socket(xcb_connection_t *c, void (*return_socket)(void *closure), void *closure, int flags, uint64_t *sent)
diff --git a/libxcb/src/xcbext.h b/libxcb/src/xcbext.h
index b2575f7e3..44d789eee 100644
--- a/libxcb/src/xcbext.h
+++ b/libxcb/src/xcbext.h
@@ -68,13 +68,13 @@ enum xcb_send_request_flags_t {
*
* This function sends a new request to the X server. The data of the request is
* given as an array of @c iovecs in the @p vector argument. The length of that
- * array and the neccessary management information are given in the @p request
+ * array and the necessary management information are given in the @p request
* argument.
*
* When this function returns, the request might or might not be sent already.
* Use xcb_flush() to make sure that it really was sent.
*
- * Please note that this function is not the prefered way for sending requests.
+ * Please note that this function is not the preferred way for sending requests.
* It's better to use the generated wrapper functions.
*
* Please note that xcb might use index -1 and -2 of the @p vector array internally,
@@ -83,6 +83,37 @@ enum xcb_send_request_flags_t {
unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *request);
/**
+ * @brief Send a request to the server.
+ * @param c: The connection to the X server.
+ * @param flags: A combination of flags from the xcb_send_request_flags_t enumeration.
+ * @param vector: Data to send; must have two iovecs before start for internal use.
+ * @param request: Information about the request to be sent.
+ * @param num_fds: Number of additional file descriptors to send to the server
+ * @param fds: Additional file descriptors that should be send to the server.
+ * @return The request's sequence number on success, 0 otherwise.
+ *
+ * This function sends a new request to the X server. The data of the request is
+ * given as an array of @c iovecs in the @p vector argument. The length of that
+ * array and the necessary management information are given in the @p request
+ * argument.
+ *
+ * If @p num_fds is non-zero, @p fds points to an array of file descriptors that
+ * will be sent to the X server along with this request. After this function
+ * returns, all file descriptors sent are owned by xcb and will be closed
+ * eventually.
+ *
+ * When this function returns, the request might or might not be sent already.
+ * Use xcb_flush() to make sure that it really was sent.
+ *
+ * Please note that this function is not the preferred way for sending requests.
+ *
+ * Please note that xcb might use index -1 and -2 of the @p vector array internally,
+ * so they must be valid!
+ */
+unsigned int xcb_send_request_with_fds(xcb_connection_t *c, int flags, struct iovec *vector,
+ const xcb_protocol_request_t *request, unsigned int num_fds, int *fds);
+
+/**
* @brief Send a request to the server, with 64-bit sequence number returned.
* @param c: The connection to the X server.
* @param flags: A combination of flags from the xcb_send_request_flags_t enumeration.
@@ -92,13 +123,13 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
*
* This function sends a new request to the X server. The data of the request is
* given as an array of @c iovecs in the @p vector argument. The length of that
- * array and the neccessary management information are given in the @p request
+ * array and the necessary management information are given in the @p request
* argument.
*
* When this function returns, the request might or might not be sent already.
* Use xcb_flush() to make sure that it really was sent.
*
- * Please note that this function is not the prefered way for sending requests.
+ * Please note that this function is not the preferred way for sending requests.
* It's better to use the generated wrapper functions.
*
* Please note that xcb might use index -1 and -2 of the @p vector array internally,
@@ -107,6 +138,38 @@ unsigned int xcb_send_request(xcb_connection_t *c, int flags, struct iovec *vect
uint64_t xcb_send_request64(xcb_connection_t *c, int flags, struct iovec *vector, const xcb_protocol_request_t *request);
/**
+ * @brief Send a request to the server, with 64-bit sequence number returned.
+ * @param c: The connection to the X server.
+ * @param flags: A combination of flags from the xcb_send_request_flags_t enumeration.
+ * @param vector: Data to send; must have two iovecs before start for internal use.
+ * @param request: Information about the request to be sent.
+ * @param num_fds: Number of additional file descriptors to send to the server
+ * @param fds: Additional file descriptors that should be send to the server.
+ * @return The request's sequence number on success, 0 otherwise.
+ *
+ * This function sends a new request to the X server. The data of the request is
+ * given as an array of @c iovecs in the @p vector argument. The length of that
+ * array and the necessary management information are given in the @p request
+ * argument.
+ *
+ * If @p num_fds is non-zero, @p fds points to an array of file descriptors that
+ * will be sent to the X server along with this request. After this function
+ * returns, all file descriptors sent are owned by xcb and will be closed
+ * eventually.
+ *
+ * When this function returns, the request might or might not be sent already.
+ * Use xcb_flush() to make sure that it really was sent.
+ *
+ * Please note that this function is not the preferred way for sending requests.
+ * It's better to use the generated wrapper functions.
+ *
+ * Please note that xcb might use index -1 and -2 of the @p vector array internally,
+ * so they must be valid!
+ */
+uint64_t xcb_send_request_with_fds64(xcb_connection_t *c, int flags, struct iovec *vector,
+ const xcb_protocol_request_t *request, unsigned int num_fds, int *fds);
+
+/**
* @brief Send a file descriptor to the server in the next call to xcb_send_request.
* @param c: The connection to the X server.
* @param fd: The file descriptor to send.
@@ -114,9 +177,9 @@ uint64_t xcb_send_request64(xcb_connection_t *c, int flags, struct iovec *vector
* After this function returns, the file descriptor given is owned by xcb and
* will be closed eventually.
*
- * FIXME: How the heck is this supposed to work in a thread-safe way? There is a
- * race between two threads doing xcb_send_fd(); xcb_send_request(); at the same
- * time.
+ * @deprecated This function cannot be used in a thread-safe way. Two threads
+ * that run xcb_send_fd(); xcb_send_request(); could mix up their file
+ * descriptors. Instead, xcb_send_request_with_fds() should be used.
*/
void xcb_send_fd(xcb_connection_t *c, int fd);
diff --git a/libxcb/xcb-proto/doc/xml-xcb.txt b/libxcb/xcb-proto/doc/xml-xcb.txt
index f8129ea9c..12c0881a9 100644
--- a/libxcb/xcb-proto/doc/xml-xcb.txt
+++ b/libxcb/xcb-proto/doc/xml-xcb.txt
@@ -218,13 +218,6 @@ enum; the value is restricted to one of the constants named in the enum.
of the list in terms of other fields in the structure. See the section
"Expressions" for details on the expression representation.
-<localfield type="identifier" name="identifier" />
-
- This element represents a parameter in a request that is not sent over the
- wire. The field can be referenced in the length expressions of lists or in
- an exprfield. The type attribute declares the data type of the field, and
- the name attribute gives the name of the field.
-
<exprfield type="identifier" name="identifier">expression</exprfield>
This element represents a field in a request that is calculated rather than
@@ -244,8 +237,8 @@ enum; the value is restricted to one of the constants named in the enum.
<switch> instead for new protocol definitions.
<switch name="identifier"> switch expression
- <bitcase> bitcase expression(s), fields </bitcase>
- <case> case expression(s), fields </case>
+ <bitcase [name="identifier"]> bitcase expression(s), fields </bitcase>
+ <case [name="identifier"]> case expression(s), fields </case>
</switch>
This element represents conditional inclusion of fields. It can be viewed
diff --git a/libxcb/xcb-proto/src/present.xml b/libxcb/xcb-proto/src/present.xml
index 95fee0181..513388c1c 100644
--- a/libxcb/xcb-proto/src/present.xml
+++ b/libxcb/xcb-proto/src/present.xml
@@ -199,15 +199,7 @@ OF THIS SOFTWARE.
<field type="CARD64" name="target_msc" />
<field type="CARD64" name="divisor" />
<field type="CARD64" name="remainder" />
- <list type="Notify" name="notifies">
- <op op="/">
- <op op="-">
- <fieldref>length</fieldref>
- <value>18</value>
- </op>
- <value>2</value>
- </op>
- </list>
+ <list type="Notify" name="notifies" />
</event>
</xcb>
diff --git a/libxcb/xcb-proto/src/xprint.xml b/libxcb/xcb-proto/src/xprint.xml
index dc23dd0da..4da49b0a9 100644
--- a/libxcb/xcb-proto/src/xprint.xml
+++ b/libxcb/xcb-proto/src/xprint.xml
@@ -178,9 +178,13 @@ authorization from the authors.
<fieldref>len_data</fieldref>
</list>
<!-- padding -->
- <list type="STRING8" name="doc_format" />
+ <list type="STRING8" name="doc_format">
+ <fieldref>len_fmt</fieldref>
+ </list>
<!-- padding -->
- <list type="STRING8" name="options" />
+ <list type="STRING8" name="options">
+ <fieldref>len_options</fieldref>
+ </list>
</request>
<request name="PrintGetDocumentData" opcode="12">