1#![allow(non_camel_case_types)]
2
3use crate::xcb_box::XcbBox;
4use bstr::ByteSlice;
5use std::collections::HashMap;
6use std::error::Error;
7use std::fmt::{Debug, Display, Formatter};
8use std::os::raw::c_int;
9use std::{ptr, slice};
10use thiserror::Error;
11use xcb_dl::ffi::*;
12use xcb_dl::Xcb;
13
14#[derive(Clone, Debug)]
15pub struct XcbError {
16 pub error_code: u8,
17 pub sequence: u32,
18 pub major: u8,
19 pub minor: u16,
20 pub ty: XcbErrorType,
21}
22
23impl Display for XcbError {
24 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
25 Display::fmt(&self.ty, f)
26 }
27}
28
29impl Error for XcbError {}
30
31impl From<XcbErrorType> for XcbError {
32 fn from(e: XcbErrorType) -> Self {
33 Self {
34 error_code: 0,
35 sequence: 0,
36 major: 0,
37 minor: 0,
38 ty: e,
39 }
40 }
41}
42
43#[derive(Clone, Error, Debug)]
44#[non_exhaustive]
45pub enum XcbConnectionError {
46 #[error("An unknown error occurred: {0}")]
47 Unknown(c_int),
48 #[error("An IO error occurred")]
49 Io,
50 #[error("The user tried to send a request with an unsupported extension")]
51 UnsupportedExtension,
52 #[error("Out of memory")]
53 OutOfMemory,
54 #[error("The user tried to send a request that is too large for the X server")]
55 MessageLength,
56 #[error("libxcb was unable to parse the DISPLAY string")]
57 DisplayString,
58 #[error("The requested screen is not available")]
59 InvalidScreen,
60 #[error("An error occurred while handling file descriptors passed to and from the X server")]
61 FileDescriptors,
62}
63
64impl From<c_int> for XcbConnectionError {
65 fn from(e: c_int) -> Self {
66 match e {
67 XCB_CONN_ERROR => XcbConnectionError::Io,
68 XCB_CONN_CLOSED_EXT_NOTSUPPORTED => XcbConnectionError::UnsupportedExtension,
69 XCB_CONN_CLOSED_MEM_INSUFFICIENT => XcbConnectionError::OutOfMemory,
70 XCB_CONN_CLOSED_REQ_LEN_EXCEED => XcbConnectionError::MessageLength,
71 XCB_CONN_CLOSED_PARSE_ERR => XcbConnectionError::DisplayString,
72 XCB_CONN_CLOSED_INVALID_SCREEN => XcbConnectionError::InvalidScreen,
73 XCB_CONN_CLOSED_FDPASSING_FAILED => XcbConnectionError::FileDescriptors,
74 _ => XcbConnectionError::Unknown(e),
75 }
76 }
77}
78
79#[derive(Clone, Error, Debug)]
80#[non_exhaustive]
81pub enum XcbErrorType {
82 #[error("An unknown error occurred: {0:?}")]
83 Unknown(xcb_generic_error_t),
84 #[error("The X server did not send a reply to a request")]
85 MissingReply,
86 #[error("The connection was terminated due to an error: {0}")]
87 Connection(XcbConnectionError),
88 #[error(transparent)]
89 Core(core::CoreError),
90 #[error("XVideo extension error: {0}")]
91 Xv(xv::XvError),
92 #[error("XFIXES extension error: {0}")]
93 Xfixes(xfixes::XfixesError),
94 #[error("SHM extension error: {0}")]
95 Shm(shm::ShmError),
96 #[error("DAMAGE extension error: {0}")]
97 Damage(damage::DamageError),
98 #[error("Print extension error: {0}")]
99 XPrint(x_print::XPrintError),
100 #[error("RANDR extension error: {0}")]
101 Randr(randr::RandrError),
102 #[error("RENDER extension error: {0}")]
103 Render(render::RenderError),
104 #[error("SYNC extension error: {0}")]
105 Sync(sync::SyncError),
106 #[error("RECORD extension error: {0}")]
107 Record(record::RecordError),
108 #[error("XKEYBOARD extension error: {0}")]
109 Xkb(xkb::XkbError),
110 #[error("GLX extension error: {0}")]
111 Glx(glx::GlxError),
112 #[error("XInput extension error: {0}")]
113 Input(input::InputError),
114}
115
116#[derive(Debug)]
117pub struct XcbErrorParser {
118 pub(crate) c: *mut xcb_connection_t,
119 parsers: Vec<ErrorParser>,
120}
121
122unsafe fn check_core_error(err: *mut xcb_generic_error_t) -> Result<(), XcbErrorType> {
123 if err.is_null() {
124 return Ok(());
125 }
126 let err = XcbBox::new(err);
127 let mut error_code = err.error_code;
128 assert!(error_code > 0);
129 error_code -= 1;
130 assert!(error_code < core::CONFIG.num_errors);
131 Err((core::CONFIG.parse)(error_code, &*err))
132}
133
134impl XcbErrorParser {
135 pub unsafe fn new(xcb: &Xcb, c: *mut xcb_connection_t) -> Self {
136 let mut bases = HashMap::new();
137 loop {
138 let mut err = ptr::null_mut();
139 let extensions = xcb.xcb_list_extensions_reply(c, xcb.xcb_list_extensions(c), &mut err);
140 if let Err(e) = check_core_error(err) {
141 log::error!("Could not list extensions: {}", e);
142 break;
143 }
144 let extensions = XcbBox::new(extensions);
145 let mut names_iter = xcb.xcb_list_extensions_names_iterator(&*extensions);
146 while names_iter.rem > 0 {
147 let name = xcb.xcb_str_name(names_iter.data);
148 let len = (*names_iter.data).name_len;
149 let ext = xcb.xcb_query_extension_reply(
150 c,
151 xcb.xcb_query_extension(c, len as _, name),
152 &mut err,
153 );
154 if let Err(e) = check_core_error(err) {
155 log::error!("Could not query extension: {}", e);
156 continue;
157 }
158 let ext = XcbBox::new(ext);
159 let name = slice::from_raw_parts(name as *const u8, len as _);
160 bases.insert(name, ext.first_error);
161 xcb.xcb_str_next(&mut names_iter);
162 }
163 break;
164 }
165
166 let mut parsers = vec![];
167 for config in CONFIGS {
168 let min = match config.name {
169 Some(name) => bases.get(name).cloned(),
170 _ => Some(1),
171 };
172 if let Some(min) = min {
173 parsers.push(ErrorParser {
174 min,
175 max_plus_1: min + config.num_errors,
176 config: *config,
177 });
178 }
179 }
180 parsers.sort_by_key(|p| p.min);
181 for w in parsers.windows(2) {
182 assert!(w[0].max_plus_1 <= w[1].min);
183 }
184 Self { c, parsers }
185 }
186
187 pub unsafe fn parse(&self, e: &xcb_generic_error_t) -> XcbError {
188 let ty = 'outer: loop {
189 for p in &self.parsers {
190 if p.min <= e.error_code && e.error_code < p.max_plus_1 {
191 break 'outer (p.config.parse)(e.error_code - p.min, e);
192 }
193 }
194 break XcbErrorType::Unknown(*e);
195 };
196 XcbError {
197 error_code: e.error_code,
198 sequence: e.full_sequence,
199 major: e.major_code,
200 minor: e.minor_code,
201 ty,
202 }
203 }
204
205 #[inline]
206 pub unsafe fn check<T>(
207 &self,
208 xcb: &Xcb,
209 t: *mut T,
210 e: *mut xcb_generic_error_t,
211 ) -> Result<XcbBox<T>, XcbError> {
212 if !e.is_null() {
213 let e = XcbBox::new(e);
214 Err(self.parse(&e))
215 } else {
216 self.check_val(xcb, t)
217 }
218 }
219
220 #[inline]
221 pub unsafe fn check_val<T>(&self, xcb: &Xcb, t: *mut T) -> Result<XcbBox<T>, XcbError> {
222 if t.is_null() {
223 self.check_connection(xcb)
224 .and(Err(XcbErrorType::MissingReply.into()))
225 } else {
226 Ok(XcbBox::new(t))
227 }
228 }
229
230 #[inline]
231 pub unsafe fn check_connection(&self, xcb: &Xcb) -> Result<(), XcbError> {
232 let e = xcb.xcb_connection_has_error(self.c);
233 if e == 0 {
234 Ok(())
235 } else {
236 Err(XcbErrorType::Connection(e.into()).into())
237 }
238 }
239
240 #[inline]
241 pub unsafe fn check_err(&self, e: *mut xcb_generic_error_t) -> Result<(), XcbError> {
242 if !e.is_null() {
243 let e = XcbBox::new(e);
244 Err(self.parse(&e))
245 } else {
246 Ok(())
247 }
248 }
249
250 #[inline]
251 pub unsafe fn check_cookie(
252 &self,
253 xcb: &Xcb,
254 cookie: xcb_void_cookie_t,
255 ) -> Result<(), XcbError> {
256 let err = xcb.xcb_request_check(self.c, cookie);
257 self.check_err(err)
258 }
259}
260
261struct ErrorParser {
262 min: u8,
263 max_plus_1: u8,
264 config: &'static ErrorConfig,
265}
266
267impl Debug for ErrorParser {
268 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
269 let name = self.config.name.unwrap_or(b"Core");
270 write!(
271 f,
272 "{}([{}, {}])",
273 name.as_bstr(),
274 self.min,
275 self.max_plus_1 - 1
276 )
277 }
278}
279
280struct ErrorConfig {
281 name: Option<&'static [u8]>,
282 num_errors: u8,
283 parse: unsafe fn(error_code: u8, e: *const xcb_generic_error_t) -> XcbErrorType,
284}
285
286const CONFIGS: &[&ErrorConfig] = &[
287 &core::CONFIG,
288 &xv::CONFIG,
289 &xfixes::CONFIG,
290 &shm::CONFIG,
291 &damage::CONFIG,
292 &x_print::CONFIG,
293 &randr::CONFIG,
294 &render::CONFIG,
295 &sync::CONFIG,
296 &record::CONFIG,
297 &xkb::CONFIG,
298 &glx::CONFIG,
299 &input::CONFIG,
300];
301
302pub mod core {
303 use super::*;
304
305 #[derive(Clone, Debug, Error)]
306 #[error("{ty} (major: {major_opcode}, minor: {minor_opcode})")]
307 pub struct CoreError {
308 pub major_opcode: u8,
309 pub minor_opcode: u16,
310 pub ty: CoreErrorType,
311 }
312
313 #[derive(Clone, Debug)]
314 pub struct RequestError {
315 pub bad_value: u32,
316 }
317
318 #[derive(Clone, Debug)]
319 pub struct ValueError {
320 pub bad_value: u32,
321 }
322
323 #[derive(Clone, Debug, Error)]
324 pub enum CoreErrorType {
325 #[error("Request error (bad value: {})", .0.bad_value)]
326 Request(RequestError),
327 #[error("Value error (bad value: {})", .0.bad_value)]
328 Value(ValueError),
329 #[error("Window error (bad value: {})", .0.bad_value)]
330 Window(ValueError),
331 #[error("Pixmap error (bad value: {})", .0.bad_value)]
332 Pixmap(ValueError),
333 #[error("Atom error (bad value: {})", .0.bad_value)]
334 Atom(ValueError),
335 #[error("Cursor error (bad value: {})", .0.bad_value)]
336 Cursor(ValueError),
337 #[error("Font error (bad value: {})", .0.bad_value)]
338 Font(ValueError),
339 #[error("Match error (bad value: {})", .0.bad_value)]
340 Match(RequestError),
341 #[error("Drawable error (bad value: {})", .0.bad_value)]
342 Drawable(ValueError),
343 #[error("Access error (bad value: {})", .0.bad_value)]
344 Access(RequestError),
345 #[error("Alloc error (bad value: {})", .0.bad_value)]
346 Alloc(RequestError),
347 #[error("Colormap error (bad value: {})", .0.bad_value)]
348 Colormap(ValueError),
349 #[error("GContext error (bad value: {})", .0.bad_value)]
350 GContext(ValueError),
351 #[error("IDChoice error (bad value: {})", .0.bad_value)]
352 IDChoice(ValueError),
353 #[error("Name error (bad value: {})", .0.bad_value)]
354 Name(RequestError),
355 #[error("Length error (bad value: {})", .0.bad_value)]
356 Length(RequestError),
357 #[error("Implementation error (bad value: {})", .0.bad_value)]
358 Implementation(RequestError),
359 }
360
361 pub(super) const CONFIG: ErrorConfig = ErrorConfig {
362 name: None,
363 num_errors: 17,
364 parse,
365 };
366
367 unsafe fn parse(error_code: u8, e: *const xcb_generic_error_t) -> XcbErrorType {
368 let e = &*(e as *const xcb_request_error_t);
369 let ty = match error_code {
370 0 => CoreErrorType::Request(RequestError {
371 bad_value: e.bad_value,
372 }),
373 1 => CoreErrorType::Value(ValueError {
374 bad_value: e.bad_value,
375 }),
376 2 => CoreErrorType::Window(ValueError {
377 bad_value: e.bad_value,
378 }),
379 3 => CoreErrorType::Pixmap(ValueError {
380 bad_value: e.bad_value,
381 }),
382 4 => CoreErrorType::Atom(ValueError {
383 bad_value: e.bad_value,
384 }),
385 5 => CoreErrorType::Cursor(ValueError {
386 bad_value: e.bad_value,
387 }),
388 6 => CoreErrorType::Font(ValueError {
389 bad_value: e.bad_value,
390 }),
391 7 => CoreErrorType::Match(RequestError {
392 bad_value: e.bad_value,
393 }),
394 8 => CoreErrorType::Drawable(ValueError {
395 bad_value: e.bad_value,
396 }),
397 9 => CoreErrorType::Access(RequestError {
398 bad_value: e.bad_value,
399 }),
400 10 => CoreErrorType::Alloc(RequestError {
401 bad_value: e.bad_value,
402 }),
403 11 => CoreErrorType::Colormap(ValueError {
404 bad_value: e.bad_value,
405 }),
406 12 => CoreErrorType::GContext(ValueError {
407 bad_value: e.bad_value,
408 }),
409 13 => CoreErrorType::IDChoice(ValueError {
410 bad_value: e.bad_value,
411 }),
412 14 => CoreErrorType::Name(RequestError {
413 bad_value: e.bad_value,
414 }),
415 15 => CoreErrorType::Length(RequestError {
416 bad_value: e.bad_value,
417 }),
418 16 => CoreErrorType::Implementation(RequestError {
419 bad_value: e.bad_value,
420 }),
421 _ => unreachable!(),
422 };
423 XcbErrorType::Core(CoreError {
424 major_opcode: e.major_opcode,
425 minor_opcode: e.minor_opcode,
426 ty,
427 })
428 }
429}
430
431pub mod xv {
432 use super::*;
433
434 #[derive(Clone, Debug, Error)]
435 pub enum XvError {
436 #[error("Bad port")]
437 BadPort,
438 #[error("Bad encoding")]
439 BadEncoding,
440 #[error("Bad control")]
441 BadControl,
442 }
443
444 const XCB_XV_NAME: &[u8] = b"XVideo";
445
446 pub(super) const CONFIG: ErrorConfig = ErrorConfig {
447 name: Some(XCB_XV_NAME),
448 num_errors: 3,
449 parse,
450 };
451
452 unsafe fn parse(error_code: u8, _e: *const xcb_generic_error_t) -> XcbErrorType {
453 let e = match error_code {
454 0 => XvError::BadPort,
455 1 => XvError::BadEncoding,
456 2 => XvError::BadControl,
457 _ => unreachable!(),
458 };
459 XcbErrorType::Xv(e)
460 }
461}
462
463pub mod xfixes {
464 use super::*;
465
466 const XCB_XFIXES_NAME: &[u8] = b"XFIXES";
467
468 #[derive(Clone, Debug, Error)]
469 pub enum XfixesError {
470 #[error("Bad region")]
471 BadRegion,
472 }
473
474 pub(super) const CONFIG: ErrorConfig = ErrorConfig {
475 name: Some(XCB_XFIXES_NAME),
476 num_errors: 1,
477 parse,
478 };
479
480 unsafe fn parse(_error_code: u8, _e: *const xcb_generic_error_t) -> XcbErrorType {
481 XcbErrorType::Xfixes(XfixesError::BadRegion)
482 }
483}
484
485pub mod shm {
486 use super::*;
487 use crate::error::core::ValueError;
488
489 const XCB_SHM_NAME: &[u8] = b"MIT-SHM";
490
491 #[repr(C)]
492 struct xcb_value_error_t {
493 pub response_type: u8,
494 pub error_code: u8,
495 pub sequence: u16,
496 pub bad_value: u32,
497 pub minor_opcode: u16,
498 pub major_opcode: u8,
499 pub pad0: u8,
500 }
501
502 type xcb_shm_bad_seg_error_t = xcb_value_error_t;
503
504 #[derive(Clone, Debug, Error)]
505 #[error("{ty} (major: {major_opcode}, minor: {minor_opcode})")]
506 pub struct ShmError {
507 pub major_opcode: u8,
508 pub minor_opcode: u16,
509 pub ty: ShmErrorType,
510 }
511
512 #[derive(Clone, Debug, Error)]
513 pub enum ShmErrorType {
514 #[error("Bad segment (bad value: {})", .0.bad_value)]
515 BadSeg(ValueError),
516 }
517
518 pub(super) const CONFIG: ErrorConfig = ErrorConfig {
519 name: Some(XCB_SHM_NAME),
520 num_errors: 1,
521 parse,
522 };
523
524 unsafe fn parse(_error_code: u8, e: *const xcb_generic_error_t) -> XcbErrorType {
525 let e = &*(e as *const xcb_shm_bad_seg_error_t);
526 XcbErrorType::Shm(ShmError {
527 major_opcode: e.major_opcode,
528 minor_opcode: e.minor_opcode,
529 ty: ShmErrorType::BadSeg(ValueError {
530 bad_value: e.bad_value,
531 }),
532 })
533 }
534}
535
536pub mod damage {
537 use super::*;
538
539 const XCB_DAMAGE_NAME: &[u8] = b"DAMAGE";
540
541 #[derive(Clone, Debug, Error)]
542 pub enum DamageError {
543 #[error("Bad damage")]
544 BadDamage,
545 }
546
547 pub(super) const CONFIG: ErrorConfig = ErrorConfig {
548 name: Some(XCB_DAMAGE_NAME),
549 num_errors: 1,
550 parse,
551 };
552
553 unsafe fn parse(_error_code: u8, _e: *const xcb_generic_error_t) -> XcbErrorType {
554 XcbErrorType::Damage(DamageError::BadDamage)
555 }
556}
557
558pub mod x_print {
559 use super::*;
560
561 const XCB_X_PRINT_NAME: &[u8] = b"XpExtension";
562
563 #[derive(Clone, Debug, Error)]
564 pub enum XPrintError {
565 #[error("Bad context")]
566 BadContext,
567 #[error("Bad sequence")]
568 BadSequence,
569 }
570
571 pub(super) const CONFIG: ErrorConfig = ErrorConfig {
572 name: Some(XCB_X_PRINT_NAME),
573 num_errors: 2,
574 parse,
575 };
576
577 unsafe fn parse(error_code: u8, _e: *const xcb_generic_error_t) -> XcbErrorType {
578 let e = match error_code {
579 0 => XPrintError::BadContext,
580 1 => XPrintError::BadSequence,
581 _ => unreachable!(),
582 };
583 XcbErrorType::XPrint(e)
584 }
585}
586
587pub mod randr {
588 use super::*;
589
590 const XCB_RANDR_NAME: &[u8] = b"RANDR";
591
592 #[derive(Clone, Debug, Error)]
593 pub enum RandrError {
594 #[error("Bad output")]
595 BadOutput,
596 #[error("Bad crtc")]
597 BadCrtc,
598 #[error("Bad mode")]
599 BadMode,
600 #[error("Bad provider")]
601 BadProvider,
602 }
603
604 pub(super) const CONFIG: ErrorConfig = ErrorConfig {
605 name: Some(XCB_RANDR_NAME),
606 num_errors: 4,
607 parse,
608 };
609
610 unsafe fn parse(error_code: u8, _e: *const xcb_generic_error_t) -> XcbErrorType {
611 let e = match error_code {
612 0 => RandrError::BadOutput,
613 1 => RandrError::BadCrtc,
614 2 => RandrError::BadMode,
615 3 => RandrError::BadProvider,
616 _ => unreachable!(),
617 };
618 XcbErrorType::Randr(e)
619 }
620}
621
622pub mod render {
623 use super::*;
624
625 const XCB_RENDER_NAME: &[u8] = b"RENDER";
626
627 #[derive(Clone, Debug, Error)]
628 pub enum RenderError {
629 #[error("Invalid picture format")]
630 PictFormat,
631 #[error("Invalid picture")]
632 Picture,
633 #[error("Invalid picture operation")]
634 PictOp,
635 #[error("Invalid glyph set")]
636 GlyphSet,
637 #[error("Invalid glyph")]
638 Glyph,
639 }
640
641 pub(super) const CONFIG: ErrorConfig = ErrorConfig {
642 name: Some(XCB_RENDER_NAME),
643 num_errors: 5,
644 parse,
645 };
646
647 unsafe fn parse(error_code: u8, _e: *const xcb_generic_error_t) -> XcbErrorType {
648 let e = match error_code {
649 0 => RenderError::PictFormat,
650 1 => RenderError::Picture,
651 2 => RenderError::PictOp,
652 3 => RenderError::GlyphSet,
653 4 => RenderError::Glyph,
654 _ => unreachable!(),
655 };
656 XcbErrorType::Render(e)
657 }
658}
659
660pub mod sync {
661 use super::*;
662
663 const XCB_SYNC_NAME: &[u8] = b"SYNC";
664
665 #[repr(C)]
666 struct xcb_sync_counter_error_t {
667 pub response_type: u8,
668 pub error_code: u8,
669 pub sequence: u16,
670 pub bad_counter: u32,
671 pub minor_opcode: u16,
672 pub major_opcode: u8,
673 }
674
675 #[derive(Clone, Debug)]
676 pub struct CounterError {
677 pub bad_counter: u32,
678 }
679
680 #[derive(Clone, Debug)]
681 pub struct AlarmError {
682 pub bad_alarm: u32,
683 }
684
685 #[derive(Clone, Debug, Error)]
686 #[error("{ty} (major: {major_opcode}, minor: {minor_opcode})")]
687 pub struct SyncError {
688 pub major_opcode: u8,
689 pub minor_opcode: u16,
690 pub ty: SyncErrorType,
691 }
692
693 #[derive(Clone, Debug, Error)]
694 pub enum SyncErrorType {
695 #[error("Bad counter {}", .0.bad_counter)]
696 Counter(CounterError),
697 #[error("Bad alarm {}", .0.bad_alarm)]
698 Alarm(AlarmError),
699 }
700
701 pub(super) const CONFIG: ErrorConfig = ErrorConfig {
702 name: Some(XCB_SYNC_NAME),
703 num_errors: 2,
704 parse,
705 };
706
707 unsafe fn parse(error_code: u8, e: *const xcb_generic_error_t) -> XcbErrorType {
708 let e = &*(e as *const xcb_sync_counter_error_t);
709 let ty = match error_code {
710 0 => SyncErrorType::Counter(CounterError {
711 bad_counter: e.bad_counter,
712 }),
713 1 => SyncErrorType::Alarm(AlarmError {
714 bad_alarm: e.bad_counter,
715 }),
716 _ => unreachable!(),
717 };
718 XcbErrorType::Sync(SyncError {
719 major_opcode: e.major_opcode,
720 minor_opcode: e.minor_opcode,
721 ty,
722 })
723 }
724}
725
726pub mod record {
727 use super::*;
728
729 const XCB_RECORD_NAME: &[u8] = b"RECORD";
730
731 #[repr(C)]
732 struct xcb_record_bad_context_error_t {
733 pub response_type: u8,
734 pub error_code: u8,
735 pub sequence: u16,
736 pub invalid_record: u32,
737 }
738
739 #[derive(Clone, Debug)]
740 pub struct BadContext {
741 pub invalid_record: u32,
742 }
743
744 #[derive(Clone, Debug, Error)]
745 pub enum RecordError {
746 #[error("Bad context (invalid record: {})", .0.invalid_record)]
747 BadContext(BadContext),
748 }
749
750 pub(super) const CONFIG: ErrorConfig = ErrorConfig {
751 name: Some(XCB_RECORD_NAME),
752 num_errors: 1,
753 parse,
754 };
755
756 unsafe fn parse(_error_code: u8, e: *const xcb_generic_error_t) -> XcbErrorType {
757 let e = &*(e as *const xcb_record_bad_context_error_t);
758 XcbErrorType::Record(RecordError::BadContext(BadContext {
759 invalid_record: e.invalid_record,
760 }))
761 }
762}
763
764pub mod xkb {
765 use super::*;
766
767 const XCB_XKB_NAME: &[u8] = b"XKEYBOARD";
768
769 #[repr(C)]
770 struct xcb_xkb_keyboard_error_t {
771 pub response_type: u8,
772 pub error_code: u8,
773 pub sequence: u16,
774 pub value: u32,
775 pub minor_opcode: u16,
776 pub major_opcode: u8,
777 pub pad0: [u8; 21],
778 }
779
780 bitflags::bitflags! {
781 pub struct XkbKeyboardError: u32 {
782 const BAD_DEVICE = 255;
783 const BAD_CLASS = 254;
784 const BAD_ID = 253;
785 }
786 }
787
788 #[derive(Clone, Debug, Error)]
789 #[error("{ty} (major: {major_opcode}, minor: {minor_opcode})")]
790 pub struct XkbError {
791 pub major_opcode: u8,
792 pub minor_opcode: u16,
793 pub ty: XkbErrorType,
794 }
795
796 #[derive(Clone, Debug, Error)]
797 pub enum XkbErrorType {
798 #[error("Keyboard error: {0:?}")]
799 Keyboard(XkbKeyboardError),
800 }
801
802 pub(super) const CONFIG: ErrorConfig = ErrorConfig {
803 name: Some(XCB_XKB_NAME),
804 num_errors: 1,
805 parse,
806 };
807
808 unsafe fn parse(_error_code: u8, e: *const xcb_generic_error_t) -> XcbErrorType {
809 let e = &*(e as *const xcb_xkb_keyboard_error_t);
810 XcbErrorType::Xkb(XkbError {
811 major_opcode: e.major_opcode,
812 minor_opcode: e.minor_opcode,
813 ty: XkbErrorType::Keyboard(XkbKeyboardError::from_bits_unchecked(e.value)),
814 })
815 }
816}
817
818pub mod glx {
819 use super::*;
820
821 const XCB_GLX_NAME: &[u8] = b"GLX";
822
823 #[repr(C)]
824 struct xcb_glx_generic_error_t {
825 pub response_type: u8,
826 pub error_code: u8,
827 pub sequence: u16,
828 pub bad_value: u32,
829 pub minor_opcode: u16,
830 pub major_opcode: u8,
831 pub pad0: [u8; 21],
832 }
833
834 #[derive(Clone, Debug)]
835 pub struct GenericError {
836 pub bad_value: u32,
837 }
838
839 #[derive(Clone, Debug, Error)]
840 #[error("{ty} (major: {major_opcode}, minor: {minor_opcode})")]
841 pub struct GlxError {
842 pub major_opcode: u8,
843 pub minor_opcode: u16,
844 pub ty: GlxErrorType,
845 }
846
847 #[derive(Clone, Debug, Error)]
848 pub enum GlxErrorType {
849 #[error("Bad context (bad value: {})", .0.bad_value)]
850 BadContext(GenericError),
851 #[error("Bad context state (bad value: {})", .0.bad_value)]
852 BadContextState(GenericError),
853 #[error("Bad drawable (bad value: {})", .0.bad_value)]
854 BadDrawable(GenericError),
855 #[error("Bad pixmap (bad value: {})", .0.bad_value)]
856 BadPixmap(GenericError),
857 #[error("Bad context tag (bad value: {})", .0.bad_value)]
858 BadContextTag(GenericError),
859 #[error("Bad current window (bad value: {})", .0.bad_value)]
860 BadCurrentWindow(GenericError),
861 #[error("Bad render request (bad value: {})", .0.bad_value)]
862 BadRenderRequest(GenericError),
863 #[error("Bad large request (bad value: {})", .0.bad_value)]
864 BadLargeRequest(GenericError),
865 #[error("Unsupported private request (bad value: {})", .0.bad_value)]
866 UnsupportedPrivateRequest(GenericError),
867 #[error("Bad framebuffer config (bad value: {})", .0.bad_value)]
868 BadFBConfig(GenericError),
869 #[error("Bad pixel buffer (bad value: {})", .0.bad_value)]
870 BadPbuffer(GenericError),
871 #[error("Bad current drawable (bad value: {})", .0.bad_value)]
872 BadCurrentDrawable(GenericError),
873 #[error("Bad window (bad value: {})", .0.bad_value)]
874 BadWindow(GenericError),
875 #[error("Bad profile (bad value: {})", .0.bad_value)]
876 GLXBadProfileARB(GenericError),
877 }
878
879 pub(super) const CONFIG: ErrorConfig = ErrorConfig {
880 name: Some(XCB_GLX_NAME),
881 num_errors: 14,
882 parse,
883 };
884
885 unsafe fn parse(error_code: u8, e: *const xcb_generic_error_t) -> XcbErrorType {
886 let e = &*(e as *const xcb_glx_generic_error_t);
887 let ge = GenericError {
888 bad_value: e.bad_value,
889 };
890 let ty = match error_code {
891 0 => GlxErrorType::BadContext(ge),
892 1 => GlxErrorType::BadContextState(ge),
893 2 => GlxErrorType::BadDrawable(ge),
894 3 => GlxErrorType::BadPixmap(ge),
895 4 => GlxErrorType::BadContextTag(ge),
896 5 => GlxErrorType::BadCurrentWindow(ge),
897 6 => GlxErrorType::BadRenderRequest(ge),
898 7 => GlxErrorType::BadLargeRequest(ge),
899 8 => GlxErrorType::UnsupportedPrivateRequest(ge),
900 9 => GlxErrorType::BadFBConfig(ge),
901 10 => GlxErrorType::BadPbuffer(ge),
902 11 => GlxErrorType::BadCurrentDrawable(ge),
903 12 => GlxErrorType::BadWindow(ge),
904 13 => GlxErrorType::GLXBadProfileARB(ge),
905 _ => unreachable!(),
906 };
907 XcbErrorType::Glx(GlxError {
908 major_opcode: e.major_opcode,
909 minor_opcode: e.minor_opcode,
910 ty,
911 })
912 }
913}
914
915pub mod input {
916 use super::*;
917
918 const XCB_INPUT_NAME: &[u8] = b"XInputExtension";
919
920 #[derive(Clone, Debug, Error)]
921 pub enum InputError {
922 #[error("Bad device")]
923 Device,
924 #[error("Bad event")]
925 Event,
926 #[error("Bad mode")]
927 Mode,
928 #[error("Device busy")]
929 DeviceBusy,
930 #[error("Bad class")]
931 Class,
932 }
933
934 pub(super) const CONFIG: ErrorConfig = ErrorConfig {
935 name: Some(XCB_INPUT_NAME),
936 num_errors: 5,
937 parse,
938 };
939
940 unsafe fn parse(error_code: u8, _e: *const xcb_generic_error_t) -> XcbErrorType {
941 let e = match error_code {
942 0 => InputError::Device,
943 1 => InputError::Event,
944 2 => InputError::Mode,
945 3 => InputError::DeviceBusy,
946 4 => InputError::Class,
947 _ => unreachable!(),
948 };
949 XcbErrorType::Input(e)
950 }
951}