// This source file is generated automatically from shape.xml

use crate::base::{self, BaseError, BaseEvent, GeEvent, Raw, Reply, WiredIn, WiredOut, Xid};
use crate::ext;
use crate::ffi::base::*;
use crate::ffi::ext::*;
use crate::lat1_str::{Lat1Str, Lat1String, Lat1StrF};
use crate::xproto;
use crate::xproto::PropEl;

use bitflags::bitflags;
use libc::{self, iovec};
use std::convert::TryInto;
use std::hash::{Hash, Hasher};
use std::os::unix::io::RawFd;

/// The official identifier for the `Shape` extension.
pub const XNAME: &str = "SHAPE";
/// The major version of the `Shape` extension.
pub const MAJOR_VERSION: u32 = 1;
/// The minor version of the `Shape` extension.
pub const MINOR_VERSION: u32 = 1;
/// The version string of the `Shape` extension.
pub const VERSION_STRING: &str = "1.1";

pub(crate) static mut FFI_EXT: xcb_extension_t = xcb_extension_t {
    name: "SHAPE\0".as_ptr() as *const _,
    global_id: 0,
};

/// Prefetch server runtime info data of the `Shape` extension.
pub fn prefetch_extension_data(conn: &base::Connection) {
    #[cfg(feature = "dl")]
    base::xcb_get_conn_funcs!(conn, xcb_prefetch_extension_data);
    unsafe {
        xcb_prefetch_extension_data(conn.get_raw_conn(), std::ptr::addr_of_mut!(FFI_EXT));
    }
}

/// Fetch server runtime info data of the `Shape` extension.
///
/// Might be non-blocking if [prefetch_extension_data] was called before.
/// This function is of seldom use as the extensions are initialized by the
/// [Connection](crate::Connection) constructor.
pub fn get_extension_data(conn: &base::Connection) -> std::option::Option<ext::ExtensionData> {
    #[cfg(feature = "dl")]
    base::xcb_get_conn_funcs!(conn, xcb_get_extension_data);
    unsafe {
        let reply = xcb_get_extension_data(conn.get_raw_conn(), std::ptr::addr_of_mut!(FFI_EXT));
        assert!(!reply.is_null(), "Could not fetch Shape extension data");
        let reply = xproto::QueryExtensionReply::from_raw(reply);
        if !reply.present() {
            std::mem::forget(reply);
            return None;
        }
        let res = ext::ExtensionData{
            ext: ext::Extension::Shape,
            major_opcode: reply.major_opcode(),
            first_event: reply.first_event(),
            first_error: reply.first_error(),
        };
        std::mem::forget(reply);
        Some(res)
    }
}

/// The `NotifyEvent` event.
pub struct NotifyEvent {
    raw: *mut xcb_generic_event_t,
}

impl base::Raw<xcb_generic_event_t> for NotifyEvent {
    unsafe fn from_raw(raw: *mut xcb_generic_event_t) -> Self { NotifyEvent { raw } }

    fn as_raw(&self) -> *mut xcb_generic_event_t {
        self.raw
    }
}

impl base::BaseEvent for NotifyEvent {
    const EXTENSION: std::option::Option<ext::Extension> = Some(ext::Extension::Shape);
    const NUMBER: u32 = 0;
}

impl NotifyEvent {
    pub fn new(event_base: u8,
        shape_kind: Sk,
        affected_window: xproto::Window,
        extents_x: i16,
        extents_y: i16,
        extents_width: u16,
        extents_height: u16,
        server_time: xproto::Timestamp,
        shaped: bool,
    ) -> NotifyEvent {
        unsafe {
            let ptr = libc::malloc(32) as *mut u8;
            let wire_buf = std::slice::from_raw_parts_mut(ptr, 32);
            let mut wire_off = 0usize;
            let response_type = event_base;
            let sequence = 0u16;

            wire_off += response_type.serialize(&mut wire_buf[wire_off ..]);
            wire_off += (std::mem::transmute::<_, u32>(shape_kind) as Kind).serialize(&mut wire_buf[wire_off ..]);
            wire_off += sequence.serialize(&mut wire_buf[wire_off ..]);
            wire_off += affected_window.serialize(&mut wire_buf[wire_off ..]);
            wire_off += extents_x.serialize(&mut wire_buf[wire_off ..]);
            wire_off += extents_y.serialize(&mut wire_buf[wire_off ..]);
            wire_off += extents_width.serialize(&mut wire_buf[wire_off ..]);
            wire_off += extents_height.serialize(&mut wire_buf[wire_off ..]);
            wire_off += server_time.serialize(&mut wire_buf[wire_off ..]);
            let shaped: u8 = if shaped { 1 } else { 0 };
            shaped.serialize(&mut wire_buf[wire_off ..]);

            NotifyEvent::from_raw(ptr as *mut xcb_generic_event_t)
        }
    }

    fn wire_ptr(&self) -> *const u8 { self.raw as *const u8 }

    pub fn response_type(&self) -> u8 {
        unsafe {
            let offset = 0usize;
            let ptr = self.wire_ptr().add(offset) as *const u8;
            ptr.read_unaligned()
        }
    }

    pub fn shape_kind(&self) -> Sk {
        unsafe {
            let offset = 1usize;
            let ptr = self.wire_ptr().add(offset) as *const Kind;
            let val = ptr.read_unaligned() as u32;
            std::mem::transmute::<u32, Sk>(val)
        }
    }

    pub fn sequence(&self) -> u16 {
        unsafe {
            let offset = 2usize;
            let ptr = self.wire_ptr().add(offset) as *const u16;
            ptr.read_unaligned()
        }
    }

    pub fn affected_window(&self) -> xproto::Window {
        unsafe {
            let offset = 4usize;
            let ptr = self.wire_ptr().add(offset) as *const xproto::Window;
            ptr.read_unaligned()
        }
    }

    pub fn extents_x(&self) -> i16 {
        unsafe {
            let offset = 8usize;
            let ptr = self.wire_ptr().add(offset) as *const i16;
            ptr.read_unaligned()
        }
    }

    pub fn extents_y(&self) -> i16 {
        unsafe {
            let offset = 10usize;
            let ptr = self.wire_ptr().add(offset) as *const i16;
            ptr.read_unaligned()
        }
    }

    pub fn extents_width(&self) -> u16 {
        unsafe {
            let offset = 12usize;
            let ptr = self.wire_ptr().add(offset) as *const u16;
            ptr.read_unaligned()
        }
    }

    pub fn extents_height(&self) -> u16 {
        unsafe {
            let offset = 14usize;
            let ptr = self.wire_ptr().add(offset) as *const u16;
            ptr.read_unaligned()
        }
    }

    pub fn server_time(&self) -> xproto::Timestamp {
        unsafe {
            let offset = 16usize;
            let ptr = self.wire_ptr().add(offset) as *const xproto::Timestamp;
            ptr.read_unaligned()
        }
    }

    pub fn shaped(&self) -> bool {
        let val = unsafe { *(self.wire_ptr().add(20usize)) };
        val != 0
    }

}

impl std::fmt::Debug for NotifyEvent {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("NotifyEvent")
            .field("response_type", &self.response_type())
            .field("shape_kind", &self.shape_kind())
            .field("sequence", &self.sequence())
            .field("affected_window", &self.affected_window())
            .field("extents_x", &self.extents_x())
            .field("extents_y", &self.extents_y())
            .field("extents_width", &self.extents_width())
            .field("extents_height", &self.extents_height())
            .field("server_time", &self.server_time())
            .field("shaped", &self.shaped())
            .field("pad", &11)
            .finish()
    }
}

impl base::WiredOut for NotifyEvent {
    fn wire_len(&self) -> usize {
        32usize
    }

    fn serialize(&self, wire_buf: &mut[u8]) -> usize {
        debug_assert!(wire_buf.len() >= self.wire_len());
        let raw_slice = unsafe { std::slice::from_raw_parts(self.raw as *const u8, self.wire_len()) };
        wire_buf[0 .. self.wire_len()].copy_from_slice(raw_slice);
        self.wire_len()
    }
}

impl base::WiredIn for NotifyEvent {
    type Params = ();

    unsafe fn compute_wire_len(_ptr: *const u8, _params: ()) -> usize {
        32
    }

    unsafe fn unserialize(ptr: *const u8, _params: (), offset: &mut usize) -> Self {
        let sz = Self::compute_wire_len(ptr, ());
        *offset += sz;
        let raw = libc::malloc(sz) as *mut xcb_generic_event_t;
        std::ptr::copy(ptr as *const xcb_generic_event_t, raw, sz);
        NotifyEvent { raw }
    }
}

impl Drop for NotifyEvent {
    fn drop(&mut self) {
        unsafe { libc::free(self.raw as *mut _); }
    }
}

unsafe impl Send for NotifyEvent {}
unsafe impl Sync for NotifyEvent {}

/// Unified event type for the Shape extension
#[derive(Debug)]
pub enum Event {
    Notify(NotifyEvent),
}

impl Event {
  pub fn as_raw(&self) -> *mut xcb_generic_event_t {
    match self {
      Self::Notify(e) => e.as_raw(),
    }
  }
}

impl base::ResolveWireEvent for Event {
    unsafe fn resolve_wire_event(first_event: u8, raw: *mut xcb_generic_event_t) -> std::option::Option<Self> {
        debug_assert!(!raw.is_null());
        let response_type = (*raw).response_type & 0x7F;
        debug_assert!(response_type != 0, "This is not an event but an error!");
        debug_assert!(response_type != XCB_GE_GENERIC, "This is a GE_GENERIC event!");
        match response_type - first_event {
            0 => std::option::Option::Some(Event::Notify(NotifyEvent::from_raw(raw))),
            _ => std::option::Option::None,
        }
    }
}

pub type Op = u8;

pub type Kind = u8;

#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[repr(u32)]
pub enum So {
    Set = 0,
    Union = 1,
    Intersect = 2,
    Subtract = 3,
    Invert = 4,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[repr(u32)]
pub enum Sk {
    Bounding = 0,
    Clip = 1,
    Input = 2,
}

pub(crate) fn request_name(opcode: u16) -> std::option::Option<&'static str> {
    match opcode {
        0 => Some("shape::QueryVersion"),
        1 => Some("shape::Rectangles"),
        2 => Some("shape::Mask"),
        3 => Some("shape::Combine"),
        4 => Some("shape::Offset"),
        5 => Some("shape::QueryExtents"),
        6 => Some("shape::SelectInput"),
        7 => Some("shape::InputSelected"),
        8 => Some("shape::GetRectangles"),
        _ => None,
    }
}

/// Reply type for [QueryVersion].
///
/// Can be obtained from a [QueryVersionCookie] with [Connection::wait_for_reply](crate::Connection::wait_for_reply)
/// or from a [QueryVersionCookieUnchecked] with [Connection::wait_for_reply_unchecked](crate::Connection::wait_for_reply_unchecked)
pub struct QueryVersionReply {
    raw: *const u8,
}

impl QueryVersionReply {

    fn wire_ptr(&self) -> *const u8 {
        self.raw
    }

    fn wire_len(&self) -> usize {
        (32 + self.length() * 4) as _
    }

    pub fn response_type(&self) -> u8 {
        unsafe {
            let offset = 0usize;
            let ptr = self.wire_ptr().add(offset) as *const u8;
            ptr.read_unaligned()
        }
    }


    pub fn sequence(&self) -> u16 {
        unsafe {
            let offset = 2usize;
            let ptr = self.wire_ptr().add(offset) as *const u16;
            ptr.read_unaligned()
        }
    }

    pub fn length(&self) -> u32 {
        unsafe {
            let offset = 4usize;
            let ptr = self.wire_ptr().add(offset) as *const u32;
            ptr.read_unaligned()
        }
    }

    pub fn major_version(&self) -> u16 {
        unsafe {
            let offset = 8usize;
            let ptr = self.wire_ptr().add(offset) as *const u16;
            ptr.read_unaligned()
        }
    }

    pub fn minor_version(&self) -> u16 {
        unsafe {
            let offset = 10usize;
            let ptr = self.wire_ptr().add(offset) as *const u16;
            ptr.read_unaligned()
        }
    }
}

impl base::Reply for QueryVersionReply {
    unsafe fn from_raw(raw: *const u8) -> Self {
        Self { raw }
    }

    unsafe fn into_raw(self) -> *const u8 {
        let raw = self.raw;
        std::mem::forget(self);
        raw
    }

    unsafe fn as_raw(&self) -> *const u8 {
        self.raw
    }
}

impl std::fmt::Debug for QueryVersionReply {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("QueryVersionReply")
            .field("response_type", &self.response_type())
            .field("pad", &1)
            .field("sequence", &self.sequence())
            .field("length", &self.length())
            .field("major_version", &self.major_version())
            .field("minor_version", &self.minor_version())
            .finish()
    }
}

impl Drop for QueryVersionReply {
    fn drop(&mut self) {
        unsafe { libc::free(self.raw as *mut _); }
    }
}

unsafe impl std::marker::Send for QueryVersionReply {}
unsafe impl std::marker::Sync for QueryVersionReply {}

/// Cookie type for [QueryVersion].
///
/// This cookie can be used to get a [QueryVersionReply]
/// with [Connection::wait_for_reply](crate::Connection::wait_for_reply)
#[derive(Debug)]
pub struct QueryVersionCookie {
    seq: u64,
}

#[derive(Debug)]
/// Unchecked cookie type for [QueryVersion].
///
/// This cookie can be used to get a [QueryVersionReply]
/// with [Connection::wait_for_reply_unchecked](crate::Connection::wait_for_reply_unchecked)
pub struct QueryVersionCookieUnchecked {
    seq: u64,
}

impl base::Cookie for QueryVersionCookie {
    unsafe fn from_sequence(seq: u64) -> Self {
        QueryVersionCookie { seq }
    }

    fn sequence(&self) -> u64 {
        self.seq
    }
}

unsafe impl base::CookieChecked for QueryVersionCookie {
}

unsafe impl base::CookieWithReplyChecked for QueryVersionCookie {
    type Reply = QueryVersionReply;
}

impl base::Cookie for QueryVersionCookieUnchecked {
    unsafe fn from_sequence(seq: u64) -> Self {
        QueryVersionCookieUnchecked { seq }
    }

    fn sequence(&self) -> u64 {
        self.seq
    }
}

unsafe impl base::CookieWithReplyUnchecked for QueryVersionCookieUnchecked {
    type Reply = QueryVersionReply;
}

/// The `QueryVersion` request.
///
/// This request replies [QueryVersionReply].
///
/// Associated cookie types are [QueryVersionCookie] and [QueryVersionCookieUnchecked].
#[derive(Clone, Debug)]
pub struct QueryVersion {
}

unsafe impl base::RawRequest for QueryVersion {
    fn raw_request(&self, c: &base::Connection, checked: bool) -> u64 { unsafe {
        let mut protocol_request = xcb_protocol_request_t {
            count: 2,
            ext: std::ptr::addr_of_mut!(FFI_EXT),
            opcode: 0,
            isvoid: 0,
        };

        let mut sections: [iovec; 4] = [iovec {
            iov_base: std::ptr::null_mut(),
            iov_len: 0,
        }; 4];

        let buf0: &mut [u8] = &mut [0; 4];
        sections[2].iov_base = buf0.as_mut_ptr() as *mut _;
        sections[2].iov_len = 4;
        sections[3].iov_len = base::align_pad(sections[2].iov_len, 4);

        let flags = if checked { base::RequestFlags::CHECKED } else { base::RequestFlags::NONE };

        #[cfg(feature = "dl")]
        base::xcb_get_conn_funcs!(c, xcb_send_request64);

        xcb_send_request64(
            c.get_raw_conn(),
            flags.bits() as _,
            sections.as_mut_ptr().add(2),
            &mut protocol_request as *mut _,
        )
    }
}}

impl base::Request for QueryVersion {
    type Cookie = QueryVersionCookie;
    const IS_VOID: bool = false;
}

impl base::RequestWithReply for QueryVersion {
    type Reply = QueryVersionReply;
    type Cookie = QueryVersionCookie;
    type CookieUnchecked = QueryVersionCookieUnchecked;
}

/// The `Rectangles` request.
///
/// This request has no reply.
///
/// Associated cookie types are [VoidCookie](crate::VoidCookie) and [VoidCookieChecked](crate::VoidCookieChecked).
#[derive(Clone, Debug)]
pub struct Rectangles<'a> {
    pub operation: So,
    pub destination_kind: Sk,
    pub ordering: xproto::ClipOrdering,
    pub destination_window: xproto::Window,
    pub x_offset: i16,
    pub y_offset: i16,
    pub rectangles: &'a [xproto::Rectangle],
}

unsafe impl<'a> base::RawRequest for Rectangles<'a> {
    fn raw_request(&self, c: &base::Connection, checked: bool) -> u64 { unsafe {
        let mut protocol_request = xcb_protocol_request_t {
            count: 4,
            ext: std::ptr::addr_of_mut!(FFI_EXT),
            opcode: 1,
            isvoid: 1,
        };

        let mut sections: [iovec; 6] = [iovec {
            iov_base: std::ptr::null_mut(),
            iov_len: 0,
        }; 6];

        let buf0: &mut [u8] = &mut [0; 16];
        (std::mem::transmute::<_, u32>(self.operation) as Op).serialize(&mut buf0[4 .. ]);
        (std::mem::transmute::<_, u32>(self.destination_kind) as Kind).serialize(&mut buf0[5 .. ]);
        (std::mem::transmute::<_, u32>(self.ordering) as u8).serialize(&mut buf0[6 .. ]);
        self.destination_window.serialize(&mut buf0[8 .. ]);
        self.x_offset.serialize(&mut buf0[12 .. ]);
        self.y_offset.serialize(&mut buf0[14 .. ]);
        sections[2].iov_base = buf0.as_mut_ptr() as *mut _;
        sections[2].iov_len = 16;
        sections[3].iov_len = base::align_pad(sections[2].iov_len, 4);

        sections[4].iov_base = self.rectangles.as_ptr() as *mut _;
        sections[4].iov_len = self.rectangles.len() * std::mem::size_of::<xproto::Rectangle>();
        sections[5].iov_len = base::align_pad(sections[4].iov_len, 4);

        let flags = if checked { base::RequestFlags::CHECKED } else { base::RequestFlags::NONE };

        #[cfg(feature = "dl")]
        base::xcb_get_conn_funcs!(c, xcb_send_request64);

        xcb_send_request64(
            c.get_raw_conn(),
            flags.bits() as _,
            sections.as_mut_ptr().add(2),
            &mut protocol_request as *mut _,
        )
    }
}}

impl<'a> base::Request for Rectangles<'a> {
    type Cookie = base::VoidCookie;
    const IS_VOID: bool = true;
}

impl<'a> base::RequestWithoutReply for Rectangles<'a> {
}

/// The `Mask` request.
///
/// This request has no reply.
///
/// Associated cookie types are [VoidCookie](crate::VoidCookie) and [VoidCookieChecked](crate::VoidCookieChecked).
#[derive(Clone, Debug)]
pub struct Mask {
    pub operation: So,
    pub destination_kind: Sk,
    pub destination_window: xproto::Window,
    pub x_offset: i16,
    pub y_offset: i16,
    pub source_bitmap: xproto::Pixmap,
}

unsafe impl base::RawRequest for Mask {
    fn raw_request(&self, c: &base::Connection, checked: bool) -> u64 { unsafe {
        let mut protocol_request = xcb_protocol_request_t {
            count: 2,
            ext: std::ptr::addr_of_mut!(FFI_EXT),
            opcode: 2,
            isvoid: 1,
        };

        let mut sections: [iovec; 4] = [iovec {
            iov_base: std::ptr::null_mut(),
            iov_len: 0,
        }; 4];

        let buf0: &mut [u8] = &mut [0; 20];
        (std::mem::transmute::<_, u32>(self.operation) as Op).serialize(&mut buf0[4 .. ]);
        (std::mem::transmute::<_, u32>(self.destination_kind) as Kind).serialize(&mut buf0[5 .. ]);
        self.destination_window.serialize(&mut buf0[8 .. ]);
        self.x_offset.serialize(&mut buf0[12 .. ]);
        self.y_offset.serialize(&mut buf0[14 .. ]);
        self.source_bitmap.serialize(&mut buf0[16 .. ]);
        sections[2].iov_base = buf0.as_mut_ptr() as *mut _;
        sections[2].iov_len = 20;
        sections[3].iov_len = base::align_pad(sections[2].iov_len, 4);

        let flags = if checked { base::RequestFlags::CHECKED } else { base::RequestFlags::NONE };

        #[cfg(feature = "dl")]
        base::xcb_get_conn_funcs!(c, xcb_send_request64);

        xcb_send_request64(
            c.get_raw_conn(),
            flags.bits() as _,
            sections.as_mut_ptr().add(2),
            &mut protocol_request as *mut _,
        )
    }
}}

impl base::Request for Mask {
    type Cookie = base::VoidCookie;
    const IS_VOID: bool = true;
}

impl base::RequestWithoutReply for Mask {
}

/// The `Combine` request.
///
/// This request has no reply.
///
/// Associated cookie types are [VoidCookie](crate::VoidCookie) and [VoidCookieChecked](crate::VoidCookieChecked).
#[derive(Clone, Debug)]
pub struct Combine {
    pub operation: So,
    pub destination_kind: Sk,
    pub source_kind: Sk,
    pub destination_window: xproto::Window,
    pub x_offset: i16,
    pub y_offset: i16,
    pub source_window: xproto::Window,
}

unsafe impl base::RawRequest for Combine {
    fn raw_request(&self, c: &base::Connection, checked: bool) -> u64 { unsafe {
        let mut protocol_request = xcb_protocol_request_t {
            count: 2,
            ext: std::ptr::addr_of_mut!(FFI_EXT),
            opcode: 3,
            isvoid: 1,
        };

        let mut sections: [iovec; 4] = [iovec {
            iov_base: std::ptr::null_mut(),
            iov_len: 0,
        }; 4];

        let buf0: &mut [u8] = &mut [0; 20];
        (std::mem::transmute::<_, u32>(self.operation) as Op).serialize(&mut buf0[4 .. ]);
        (std::mem::transmute::<_, u32>(self.destination_kind) as Kind).serialize(&mut buf0[5 .. ]);
        (std::mem::transmute::<_, u32>(self.source_kind) as Kind).serialize(&mut buf0[6 .. ]);
        self.destination_window.serialize(&mut buf0[8 .. ]);
        self.x_offset.serialize(&mut buf0[12 .. ]);
        self.y_offset.serialize(&mut buf0[14 .. ]);
        self.source_window.serialize(&mut buf0[16 .. ]);
        sections[2].iov_base = buf0.as_mut_ptr() as *mut _;
        sections[2].iov_len = 20;
        sections[3].iov_len = base::align_pad(sections[2].iov_len, 4);

        let flags = if checked { base::RequestFlags::CHECKED } else { base::RequestFlags::NONE };

        #[cfg(feature = "dl")]
        base::xcb_get_conn_funcs!(c, xcb_send_request64);

        xcb_send_request64(
            c.get_raw_conn(),
            flags.bits() as _,
            sections.as_mut_ptr().add(2),
            &mut protocol_request as *mut _,
        )
    }
}}

impl base::Request for Combine {
    type Cookie = base::VoidCookie;
    const IS_VOID: bool = true;
}

impl base::RequestWithoutReply for Combine {
}

/// The `Offset` request.
///
/// This request has no reply.
///
/// Associated cookie types are [VoidCookie](crate::VoidCookie) and [VoidCookieChecked](crate::VoidCookieChecked).
#[derive(Clone, Debug)]
pub struct Offset {
    pub destination_kind: Sk,
    pub destination_window: xproto::Window,
    pub x_offset: i16,
    pub y_offset: i16,
}

unsafe impl base::RawRequest for Offset {
    fn raw_request(&self, c: &base::Connection, checked: bool) -> u64 { unsafe {
        let mut protocol_request = xcb_protocol_request_t {
            count: 2,
            ext: std::ptr::addr_of_mut!(FFI_EXT),
            opcode: 4,
            isvoid: 1,
        };

        let mut sections: [iovec; 4] = [iovec {
            iov_base: std::ptr::null_mut(),
            iov_len: 0,
        }; 4];

        let buf0: &mut [u8] = &mut [0; 16];
        (std::mem::transmute::<_, u32>(self.destination_kind) as Kind).serialize(&mut buf0[4 .. ]);
        self.destination_window.serialize(&mut buf0[8 .. ]);
        self.x_offset.serialize(&mut buf0[12 .. ]);
        self.y_offset.serialize(&mut buf0[14 .. ]);
        sections[2].iov_base = buf0.as_mut_ptr() as *mut _;
        sections[2].iov_len = 16;
        sections[3].iov_len = base::align_pad(sections[2].iov_len, 4);

        let flags = if checked { base::RequestFlags::CHECKED } else { base::RequestFlags::NONE };

        #[cfg(feature = "dl")]
        base::xcb_get_conn_funcs!(c, xcb_send_request64);

        xcb_send_request64(
            c.get_raw_conn(),
            flags.bits() as _,
            sections.as_mut_ptr().add(2),
            &mut protocol_request as *mut _,
        )
    }
}}

impl base::Request for Offset {
    type Cookie = base::VoidCookie;
    const IS_VOID: bool = true;
}

impl base::RequestWithoutReply for Offset {
}

/// Reply type for [QueryExtents].
///
/// Can be obtained from a [QueryExtentsCookie] with [Connection::wait_for_reply](crate::Connection::wait_for_reply)
/// or from a [QueryExtentsCookieUnchecked] with [Connection::wait_for_reply_unchecked](crate::Connection::wait_for_reply_unchecked)
pub struct QueryExtentsReply {
    raw: *const u8,
}

impl QueryExtentsReply {

    fn wire_ptr(&self) -> *const u8 {
        self.raw
    }

    fn wire_len(&self) -> usize {
        (32 + self.length() * 4) as _
    }

    pub fn response_type(&self) -> u8 {
        unsafe {
            let offset = 0usize;
            let ptr = self.wire_ptr().add(offset) as *const u8;
            ptr.read_unaligned()
        }
    }


    pub fn sequence(&self) -> u16 {
        unsafe {
            let offset = 2usize;
            let ptr = self.wire_ptr().add(offset) as *const u16;
            ptr.read_unaligned()
        }
    }

    pub fn length(&self) -> u32 {
        unsafe {
            let offset = 4usize;
            let ptr = self.wire_ptr().add(offset) as *const u32;
            ptr.read_unaligned()
        }
    }

    pub fn bounding_shaped(&self) -> bool {
        let val = unsafe { *(self.wire_ptr().add(8usize)) };
        val != 0
    }

    pub fn clip_shaped(&self) -> bool {
        let val = unsafe { *(self.wire_ptr().add(9usize)) };
        val != 0
    }


    pub fn bounding_shape_extents_x(&self) -> i16 {
        unsafe {
            let offset = 12usize;
            let ptr = self.wire_ptr().add(offset) as *const i16;
            ptr.read_unaligned()
        }
    }

    pub fn bounding_shape_extents_y(&self) -> i16 {
        unsafe {
            let offset = 14usize;
            let ptr = self.wire_ptr().add(offset) as *const i16;
            ptr.read_unaligned()
        }
    }

    pub fn bounding_shape_extents_width(&self) -> u16 {
        unsafe {
            let offset = 16usize;
            let ptr = self.wire_ptr().add(offset) as *const u16;
            ptr.read_unaligned()
        }
    }

    pub fn bounding_shape_extents_height(&self) -> u16 {
        unsafe {
            let offset = 18usize;
            let ptr = self.wire_ptr().add(offset) as *const u16;
            ptr.read_unaligned()
        }
    }

    pub fn clip_shape_extents_x(&self) -> i16 {
        unsafe {
            let offset = 20usize;
            let ptr = self.wire_ptr().add(offset) as *const i16;
            ptr.read_unaligned()
        }
    }

    pub fn clip_shape_extents_y(&self) -> i16 {
        unsafe {
            let offset = 22usize;
            let ptr = self.wire_ptr().add(offset) as *const i16;
            ptr.read_unaligned()
        }
    }

    pub fn clip_shape_extents_width(&self) -> u16 {
        unsafe {
            let offset = 24usize;
            let ptr = self.wire_ptr().add(offset) as *const u16;
            ptr.read_unaligned()
        }
    }

    pub fn clip_shape_extents_height(&self) -> u16 {
        unsafe {
            let offset = 26usize;
            let ptr = self.wire_ptr().add(offset) as *const u16;
            ptr.read_unaligned()
        }
    }
}

impl base::Reply for QueryExtentsReply {
    unsafe fn from_raw(raw: *const u8) -> Self {
        Self { raw }
    }

    unsafe fn into_raw(self) -> *const u8 {
        let raw = self.raw;
        std::mem::forget(self);
        raw
    }

    unsafe fn as_raw(&self) -> *const u8 {
        self.raw
    }
}

impl std::fmt::Debug for QueryExtentsReply {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("QueryExtentsReply")
            .field("response_type", &self.response_type())
            .field("pad", &1)
            .field("sequence", &self.sequence())
            .field("length", &self.length())
            .field("bounding_shaped", &self.bounding_shaped())
            .field("clip_shaped", &self.clip_shaped())
            .field("pad", &2)
            .field("bounding_shape_extents_x", &self.bounding_shape_extents_x())
            .field("bounding_shape_extents_y", &self.bounding_shape_extents_y())
            .field("bounding_shape_extents_width", &self.bounding_shape_extents_width())
            .field("bounding_shape_extents_height", &self.bounding_shape_extents_height())
            .field("clip_shape_extents_x", &self.clip_shape_extents_x())
            .field("clip_shape_extents_y", &self.clip_shape_extents_y())
            .field("clip_shape_extents_width", &self.clip_shape_extents_width())
            .field("clip_shape_extents_height", &self.clip_shape_extents_height())
            .finish()
    }
}

impl Drop for QueryExtentsReply {
    fn drop(&mut self) {
        unsafe { libc::free(self.raw as *mut _); }
    }
}

unsafe impl std::marker::Send for QueryExtentsReply {}
unsafe impl std::marker::Sync for QueryExtentsReply {}

/// Cookie type for [QueryExtents].
///
/// This cookie can be used to get a [QueryExtentsReply]
/// with [Connection::wait_for_reply](crate::Connection::wait_for_reply)
#[derive(Debug)]
pub struct QueryExtentsCookie {
    seq: u64,
}

#[derive(Debug)]
/// Unchecked cookie type for [QueryExtents].
///
/// This cookie can be used to get a [QueryExtentsReply]
/// with [Connection::wait_for_reply_unchecked](crate::Connection::wait_for_reply_unchecked)
pub struct QueryExtentsCookieUnchecked {
    seq: u64,
}

impl base::Cookie for QueryExtentsCookie {
    unsafe fn from_sequence(seq: u64) -> Self {
        QueryExtentsCookie { seq }
    }

    fn sequence(&self) -> u64 {
        self.seq
    }
}

unsafe impl base::CookieChecked for QueryExtentsCookie {
}

unsafe impl base::CookieWithReplyChecked for QueryExtentsCookie {
    type Reply = QueryExtentsReply;
}

impl base::Cookie for QueryExtentsCookieUnchecked {
    unsafe fn from_sequence(seq: u64) -> Self {
        QueryExtentsCookieUnchecked { seq }
    }

    fn sequence(&self) -> u64 {
        self.seq
    }
}

unsafe impl base::CookieWithReplyUnchecked for QueryExtentsCookieUnchecked {
    type Reply = QueryExtentsReply;
}

/// The `QueryExtents` request.
///
/// This request replies [QueryExtentsReply].
///
/// Associated cookie types are [QueryExtentsCookie] and [QueryExtentsCookieUnchecked].
#[derive(Clone, Debug)]
pub struct QueryExtents {
    pub destination_window: xproto::Window,
}

unsafe impl base::RawRequest for QueryExtents {
    fn raw_request(&self, c: &base::Connection, checked: bool) -> u64 { unsafe {
        let mut protocol_request = xcb_protocol_request_t {
            count: 2,
            ext: std::ptr::addr_of_mut!(FFI_EXT),
            opcode: 5,
            isvoid: 0,
        };

        let mut sections: [iovec; 4] = [iovec {
            iov_base: std::ptr::null_mut(),
            iov_len: 0,
        }; 4];

        let buf0: &mut [u8] = &mut [0; 8];
        self.destination_window.serialize(&mut buf0[4 .. ]);
        sections[2].iov_base = buf0.as_mut_ptr() as *mut _;
        sections[2].iov_len = 8;
        sections[3].iov_len = base::align_pad(sections[2].iov_len, 4);

        let flags = if checked { base::RequestFlags::CHECKED } else { base::RequestFlags::NONE };

        #[cfg(feature = "dl")]
        base::xcb_get_conn_funcs!(c, xcb_send_request64);

        xcb_send_request64(
            c.get_raw_conn(),
            flags.bits() as _,
            sections.as_mut_ptr().add(2),
            &mut protocol_request as *mut _,
        )
    }
}}

impl base::Request for QueryExtents {
    type Cookie = QueryExtentsCookie;
    const IS_VOID: bool = false;
}

impl base::RequestWithReply for QueryExtents {
    type Reply = QueryExtentsReply;
    type Cookie = QueryExtentsCookie;
    type CookieUnchecked = QueryExtentsCookieUnchecked;
}

/// The `SelectInput` request.
///
/// This request has no reply.
///
/// Associated cookie types are [VoidCookie](crate::VoidCookie) and [VoidCookieChecked](crate::VoidCookieChecked).
#[derive(Clone, Debug)]
pub struct SelectInput {
    pub destination_window: xproto::Window,
    pub enable: bool,
}

unsafe impl base::RawRequest for SelectInput {
    fn raw_request(&self, c: &base::Connection, checked: bool) -> u64 { unsafe {
        let mut protocol_request = xcb_protocol_request_t {
            count: 2,
            ext: std::ptr::addr_of_mut!(FFI_EXT),
            opcode: 6,
            isvoid: 1,
        };

        let mut sections: [iovec; 4] = [iovec {
            iov_base: std::ptr::null_mut(),
            iov_len: 0,
        }; 4];

        let buf0: &mut [u8] = &mut [0; 12];
        self.destination_window.serialize(&mut buf0[4 .. ]);
        (if self.enable { 1u8 } else { 0u8 }).serialize(&mut buf0[8 .. ]);
        sections[2].iov_base = buf0.as_mut_ptr() as *mut _;
        sections[2].iov_len = 12;
        sections[3].iov_len = base::align_pad(sections[2].iov_len, 4);

        let flags = if checked { base::RequestFlags::CHECKED } else { base::RequestFlags::NONE };

        #[cfg(feature = "dl")]
        base::xcb_get_conn_funcs!(c, xcb_send_request64);

        xcb_send_request64(
            c.get_raw_conn(),
            flags.bits() as _,
            sections.as_mut_ptr().add(2),
            &mut protocol_request as *mut _,
        )
    }
}}

impl base::Request for SelectInput {
    type Cookie = base::VoidCookie;
    const IS_VOID: bool = true;
}

impl base::RequestWithoutReply for SelectInput {
}

/// Reply type for [InputSelected].
///
/// Can be obtained from a [InputSelectedCookie] with [Connection::wait_for_reply](crate::Connection::wait_for_reply)
/// or from a [InputSelectedCookieUnchecked] with [Connection::wait_for_reply_unchecked](crate::Connection::wait_for_reply_unchecked)
pub struct InputSelectedReply {
    raw: *const u8,
}

impl InputSelectedReply {

    fn wire_ptr(&self) -> *const u8 {
        self.raw
    }

    fn wire_len(&self) -> usize {
        (32 + self.length() * 4) as _
    }

    pub fn response_type(&self) -> u8 {
        unsafe {
            let offset = 0usize;
            let ptr = self.wire_ptr().add(offset) as *const u8;
            ptr.read_unaligned()
        }
    }

    pub fn enabled(&self) -> bool {
        let val = unsafe { *(self.wire_ptr().add(1usize)) };
        val != 0
    }

    pub fn sequence(&self) -> u16 {
        unsafe {
            let offset = 2usize;
            let ptr = self.wire_ptr().add(offset) as *const u16;
            ptr.read_unaligned()
        }
    }

    pub fn length(&self) -> u32 {
        unsafe {
            let offset = 4usize;
            let ptr = self.wire_ptr().add(offset) as *const u32;
            ptr.read_unaligned()
        }
    }
}

impl base::Reply for InputSelectedReply {
    unsafe fn from_raw(raw: *const u8) -> Self {
        Self { raw }
    }

    unsafe fn into_raw(self) -> *const u8 {
        let raw = self.raw;
        std::mem::forget(self);
        raw
    }

    unsafe fn as_raw(&self) -> *const u8 {
        self.raw
    }
}

impl std::fmt::Debug for InputSelectedReply {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("InputSelectedReply")
            .field("response_type", &self.response_type())
            .field("enabled", &self.enabled())
            .field("sequence", &self.sequence())
            .field("length", &self.length())
            .finish()
    }
}

impl Drop for InputSelectedReply {
    fn drop(&mut self) {
        unsafe { libc::free(self.raw as *mut _); }
    }
}

unsafe impl std::marker::Send for InputSelectedReply {}
unsafe impl std::marker::Sync for InputSelectedReply {}

/// Cookie type for [InputSelected].
///
/// This cookie can be used to get a [InputSelectedReply]
/// with [Connection::wait_for_reply](crate::Connection::wait_for_reply)
#[derive(Debug)]
pub struct InputSelectedCookie {
    seq: u64,
}

#[derive(Debug)]
/// Unchecked cookie type for [InputSelected].
///
/// This cookie can be used to get a [InputSelectedReply]
/// with [Connection::wait_for_reply_unchecked](crate::Connection::wait_for_reply_unchecked)
pub struct InputSelectedCookieUnchecked {
    seq: u64,
}

impl base::Cookie for InputSelectedCookie {
    unsafe fn from_sequence(seq: u64) -> Self {
        InputSelectedCookie { seq }
    }

    fn sequence(&self) -> u64 {
        self.seq
    }
}

unsafe impl base::CookieChecked for InputSelectedCookie {
}

unsafe impl base::CookieWithReplyChecked for InputSelectedCookie {
    type Reply = InputSelectedReply;
}

impl base::Cookie for InputSelectedCookieUnchecked {
    unsafe fn from_sequence(seq: u64) -> Self {
        InputSelectedCookieUnchecked { seq }
    }

    fn sequence(&self) -> u64 {
        self.seq
    }
}

unsafe impl base::CookieWithReplyUnchecked for InputSelectedCookieUnchecked {
    type Reply = InputSelectedReply;
}

/// The `InputSelected` request.
///
/// This request replies [InputSelectedReply].
///
/// Associated cookie types are [InputSelectedCookie] and [InputSelectedCookieUnchecked].
#[derive(Clone, Debug)]
pub struct InputSelected {
    pub destination_window: xproto::Window,
}

unsafe impl base::RawRequest for InputSelected {
    fn raw_request(&self, c: &base::Connection, checked: bool) -> u64 { unsafe {
        let mut protocol_request = xcb_protocol_request_t {
            count: 2,
            ext: std::ptr::addr_of_mut!(FFI_EXT),
            opcode: 7,
            isvoid: 0,
        };

        let mut sections: [iovec; 4] = [iovec {
            iov_base: std::ptr::null_mut(),
            iov_len: 0,
        }; 4];

        let buf0: &mut [u8] = &mut [0; 8];
        self.destination_window.serialize(&mut buf0[4 .. ]);
        sections[2].iov_base = buf0.as_mut_ptr() as *mut _;
        sections[2].iov_len = 8;
        sections[3].iov_len = base::align_pad(sections[2].iov_len, 4);

        let flags = if checked { base::RequestFlags::CHECKED } else { base::RequestFlags::NONE };

        #[cfg(feature = "dl")]
        base::xcb_get_conn_funcs!(c, xcb_send_request64);

        xcb_send_request64(
            c.get_raw_conn(),
            flags.bits() as _,
            sections.as_mut_ptr().add(2),
            &mut protocol_request as *mut _,
        )
    }
}}

impl base::Request for InputSelected {
    type Cookie = InputSelectedCookie;
    const IS_VOID: bool = false;
}

impl base::RequestWithReply for InputSelected {
    type Reply = InputSelectedReply;
    type Cookie = InputSelectedCookie;
    type CookieUnchecked = InputSelectedCookieUnchecked;
}

/// Reply type for [GetRectangles].
///
/// Can be obtained from a [GetRectanglesCookie] with [Connection::wait_for_reply](crate::Connection::wait_for_reply)
/// or from a [GetRectanglesCookieUnchecked] with [Connection::wait_for_reply_unchecked](crate::Connection::wait_for_reply_unchecked)
pub struct GetRectanglesReply {
    raw: *const u8,
}

impl GetRectanglesReply {

    fn wire_ptr(&self) -> *const u8 {
        self.raw
    }

    fn wire_len(&self) -> usize {
        (32 + self.length() * 4) as _
    }

    unsafe fn compute_len(ptr: *const u8, _params: ()) -> usize {
        let mut sz = 0;
        // response_type
        sz += 1usize;
        // ordering
        sz += 1usize;
        // sequence
        sz += 2usize;
        // length
        sz += 4usize;
        // rectangles_len
        let rectangles_len = *(ptr.add(sz) as *const u32);
        sz += 4usize;
        // pad
        sz += 20usize;
        // rectangles
        sz += ((rectangles_len as usize) * 8usize);
        sz
    }

    pub fn response_type(&self) -> u8 {
        unsafe {
            let offset = 0usize;
            let ptr = self.wire_ptr().add(offset) as *const u8;
            ptr.read_unaligned()
        }
    }

    pub fn ordering(&self) -> xproto::ClipOrdering {
        unsafe {
            let offset = 1usize;
            let ptr = self.wire_ptr().add(offset) as *const u8;
            let val = ptr.read_unaligned() as u32;
            std::mem::transmute::<u32, xproto::ClipOrdering>(val)
        }
    }

    pub fn sequence(&self) -> u16 {
        unsafe {
            let offset = 2usize;
            let ptr = self.wire_ptr().add(offset) as *const u16;
            ptr.read_unaligned()
        }
    }

    pub fn length(&self) -> u32 {
        unsafe {
            let offset = 4usize;
            let ptr = self.wire_ptr().add(offset) as *const u32;
            ptr.read_unaligned()
        }
    }

    fn rectangles_len(&self) -> u32 {
        unsafe {
            let offset = 8usize;
            let ptr = self.wire_ptr().add(offset) as *const u32;
            ptr.read_unaligned()
        }
    }


    pub fn rectangles(&self) -> &[xproto::Rectangle] {
        unsafe {
            let offset = 32usize;
            let len = (self.rectangles_len() as usize) as _;
            let ptr = self.wire_ptr().add(offset) as *const xproto::Rectangle;
            std::slice::from_raw_parts(ptr, len)
        }
    }
}

impl base::Reply for GetRectanglesReply {
    unsafe fn from_raw(raw: *const u8) -> Self {
        Self { raw }
    }

    unsafe fn into_raw(self) -> *const u8 {
        let raw = self.raw;
        std::mem::forget(self);
        raw
    }

    unsafe fn as_raw(&self) -> *const u8 {
        self.raw
    }
}

impl std::fmt::Debug for GetRectanglesReply {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("GetRectanglesReply")
            .field("response_type", &self.response_type())
            .field("ordering", &self.ordering())
            .field("sequence", &self.sequence())
            .field("length", &self.length())
            .field("rectangles_len", &self.rectangles_len())
            .field("pad", &20)
            .field("rectangles", &self.rectangles())
            .finish()
    }
}

impl Drop for GetRectanglesReply {
    fn drop(&mut self) {
        unsafe { libc::free(self.raw as *mut _); }
    }
}

unsafe impl std::marker::Send for GetRectanglesReply {}
unsafe impl std::marker::Sync for GetRectanglesReply {}

/// Cookie type for [GetRectangles].
///
/// This cookie can be used to get a [GetRectanglesReply]
/// with [Connection::wait_for_reply](crate::Connection::wait_for_reply)
#[derive(Debug)]
pub struct GetRectanglesCookie {
    seq: u64,
}

#[derive(Debug)]
/// Unchecked cookie type for [GetRectangles].
///
/// This cookie can be used to get a [GetRectanglesReply]
/// with [Connection::wait_for_reply_unchecked](crate::Connection::wait_for_reply_unchecked)
pub struct GetRectanglesCookieUnchecked {
    seq: u64,
}

impl base::Cookie for GetRectanglesCookie {
    unsafe fn from_sequence(seq: u64) -> Self {
        GetRectanglesCookie { seq }
    }

    fn sequence(&self) -> u64 {
        self.seq
    }
}

unsafe impl base::CookieChecked for GetRectanglesCookie {
}

unsafe impl base::CookieWithReplyChecked for GetRectanglesCookie {
    type Reply = GetRectanglesReply;
}

impl base::Cookie for GetRectanglesCookieUnchecked {
    unsafe fn from_sequence(seq: u64) -> Self {
        GetRectanglesCookieUnchecked { seq }
    }

    fn sequence(&self) -> u64 {
        self.seq
    }
}

unsafe impl base::CookieWithReplyUnchecked for GetRectanglesCookieUnchecked {
    type Reply = GetRectanglesReply;
}

/// The `GetRectangles` request.
///
/// This request replies [GetRectanglesReply].
///
/// Associated cookie types are [GetRectanglesCookie] and [GetRectanglesCookieUnchecked].
#[derive(Clone, Debug)]
pub struct GetRectangles {
    pub window: xproto::Window,
    pub source_kind: Sk,
}

unsafe impl base::RawRequest for GetRectangles {
    fn raw_request(&self, c: &base::Connection, checked: bool) -> u64 { unsafe {
        let mut protocol_request = xcb_protocol_request_t {
            count: 2,
            ext: std::ptr::addr_of_mut!(FFI_EXT),
            opcode: 8,
            isvoid: 0,
        };

        let mut sections: [iovec; 4] = [iovec {
            iov_base: std::ptr::null_mut(),
            iov_len: 0,
        }; 4];

        let buf0: &mut [u8] = &mut [0; 12];
        self.window.serialize(&mut buf0[4 .. ]);
        (std::mem::transmute::<_, u32>(self.source_kind) as Kind).serialize(&mut buf0[8 .. ]);
        sections[2].iov_base = buf0.as_mut_ptr() as *mut _;
        sections[2].iov_len = 12;
        sections[3].iov_len = base::align_pad(sections[2].iov_len, 4);

        let flags = if checked { base::RequestFlags::CHECKED } else { base::RequestFlags::NONE };

        #[cfg(feature = "dl")]
        base::xcb_get_conn_funcs!(c, xcb_send_request64);

        xcb_send_request64(
            c.get_raw_conn(),
            flags.bits() as _,
            sections.as_mut_ptr().add(2),
            &mut protocol_request as *mut _,
        )
    }
}}

impl base::Request for GetRectangles {
    type Cookie = GetRectanglesCookie;
    const IS_VOID: bool = false;
}

impl base::RequestWithReply for GetRectangles {
    type Reply = GetRectanglesReply;
    type Cookie = GetRectanglesCookie;
    type CookieUnchecked = GetRectanglesCookieUnchecked;
}
