// This source file is generated automatically from composite.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::xfixes;
use crate::render;
use crate::shape;
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 `Composite` extension.
pub const XNAME: &str = "Composite";
/// The major version of the `Composite` extension.
pub const MAJOR_VERSION: u32 = 0;
/// The minor version of the `Composite` extension.
pub const MINOR_VERSION: u32 = 4;
/// The version string of the `Composite` extension.
pub const VERSION_STRING: &str = "0.4";

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

/// Prefetch server runtime info data of the `Composite` 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 `Composite` 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 Composite 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::Composite,
            major_opcode: reply.major_opcode(),
            first_event: reply.first_event(),
            first_error: reply.first_error(),
        };
        std::mem::forget(reply);
        Some(res)
    }
}

#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
#[repr(u32)]
pub enum Redirect {
    Automatic = 0,
    Manual = 1,
}

pub(crate) fn request_name(opcode: u16) -> std::option::Option<&'static str> {
    match opcode {
        0 => Some("composite::QueryVersion"),
        1 => Some("composite::RedirectWindow"),
        2 => Some("composite::RedirectSubwindows"),
        3 => Some("composite::UnredirectWindow"),
        4 => Some("composite::UnredirectSubwindows"),
        5 => Some("composite::CreateRegionFromBorderClip"),
        6 => Some("composite::NameWindowPixmap"),
        7 => Some("composite::GetOverlayWindow"),
        8 => Some("composite::ReleaseOverlayWindow"),
        _ => 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) -> u32 {
        unsafe {
            let offset = 8usize;
            let ptr = self.wire_ptr().add(offset) as *const u32;
            ptr.read_unaligned()
        }
    }

    pub fn minor_version(&self) -> u32 {
        unsafe {
            let offset = 12usize;
            let ptr = self.wire_ptr().add(offset) as *const u32;
            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())
            .field("pad", &16)
            .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 {
    pub client_major_version: u32,
    pub client_minor_version: u32,
}

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; 12];
        self.client_major_version.serialize(&mut buf0[4 .. ]);
        self.client_minor_version.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 QueryVersion {
    type Cookie = QueryVersionCookie;
    const IS_VOID: bool = false;
}

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

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

unsafe impl base::RawRequest for RedirectWindow {
    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: 1,
            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.window.serialize(&mut buf0[4 .. ]);
        (std::mem::transmute::<_, u32>(self.update) as u8).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 RedirectWindow {
    type Cookie = base::VoidCookie;
    const IS_VOID: bool = true;
}

impl base::RequestWithoutReply for RedirectWindow {
}

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

unsafe impl base::RawRequest for RedirectSubwindows {
    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; 12];
        self.window.serialize(&mut buf0[4 .. ]);
        (std::mem::transmute::<_, u32>(self.update) as u8).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 RedirectSubwindows {
    type Cookie = base::VoidCookie;
    const IS_VOID: bool = true;
}

impl base::RequestWithoutReply for RedirectSubwindows {
}

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

unsafe impl base::RawRequest for UnredirectWindow {
    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; 12];
        self.window.serialize(&mut buf0[4 .. ]);
        (std::mem::transmute::<_, u32>(self.update) as u8).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 UnredirectWindow {
    type Cookie = base::VoidCookie;
    const IS_VOID: bool = true;
}

impl base::RequestWithoutReply for UnredirectWindow {
}

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

unsafe impl base::RawRequest for UnredirectSubwindows {
    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; 12];
        self.window.serialize(&mut buf0[4 .. ]);
        (std::mem::transmute::<_, u32>(self.update) as u8).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 UnredirectSubwindows {
    type Cookie = base::VoidCookie;
    const IS_VOID: bool = true;
}

impl base::RequestWithoutReply for UnredirectSubwindows {
}

/// The `CreateRegionFromBorderClip` request.
///
/// This request has no reply.
///
/// Associated cookie types are [VoidCookie](crate::VoidCookie) and [VoidCookieChecked](crate::VoidCookieChecked).
#[derive(Clone, Debug)]
pub struct CreateRegionFromBorderClip {
    pub region: xfixes::Region,
    pub window: xproto::Window,
}

unsafe impl base::RawRequest for CreateRegionFromBorderClip {
    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: 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.region.serialize(&mut buf0[4 .. ]);
        self.window.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 CreateRegionFromBorderClip {
    type Cookie = base::VoidCookie;
    const IS_VOID: bool = true;
}

impl base::RequestWithoutReply for CreateRegionFromBorderClip {
}

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

unsafe impl base::RawRequest for NameWindowPixmap {
    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.window.serialize(&mut buf0[4 .. ]);
        self.pixmap.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 NameWindowPixmap {
    type Cookie = base::VoidCookie;
    const IS_VOID: bool = true;
}

impl base::RequestWithoutReply for NameWindowPixmap {
}

/// Reply type for [GetOverlayWindow].
///
/// Can be obtained from a [GetOverlayWindowCookie] with [Connection::wait_for_reply](crate::Connection::wait_for_reply)
/// or from a [GetOverlayWindowCookieUnchecked] with [Connection::wait_for_reply_unchecked](crate::Connection::wait_for_reply_unchecked)
pub struct GetOverlayWindowReply {
    raw: *const u8,
}

impl GetOverlayWindowReply {

    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 overlay_win(&self) -> xproto::Window {
        unsafe {
            let offset = 8usize;
            let ptr = self.wire_ptr().add(offset) as *const xproto::Window;
            ptr.read_unaligned()
        }
    }

}

impl base::Reply for GetOverlayWindowReply {
    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 GetOverlayWindowReply {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("GetOverlayWindowReply")
            .field("response_type", &self.response_type())
            .field("pad", &1)
            .field("sequence", &self.sequence())
            .field("length", &self.length())
            .field("overlay_win", &self.overlay_win())
            .field("pad", &20)
            .finish()
    }
}

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

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

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

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

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

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

unsafe impl base::CookieChecked for GetOverlayWindowCookie {
}

unsafe impl base::CookieWithReplyChecked for GetOverlayWindowCookie {
    type Reply = GetOverlayWindowReply;
}

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

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

unsafe impl base::CookieWithReplyUnchecked for GetOverlayWindowCookieUnchecked {
    type Reply = GetOverlayWindowReply;
}

/// The `GetOverlayWindow` request.
///
/// This request replies [GetOverlayWindowReply].
///
/// Associated cookie types are [GetOverlayWindowCookie] and [GetOverlayWindowCookieUnchecked].
#[derive(Clone, Debug)]
pub struct GetOverlayWindow {
    pub window: xproto::Window,
}

unsafe impl base::RawRequest for GetOverlayWindow {
    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.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 GetOverlayWindow {
    type Cookie = GetOverlayWindowCookie;
    const IS_VOID: bool = false;
}

impl base::RequestWithReply for GetOverlayWindow {
    type Reply = GetOverlayWindowReply;
    type Cookie = GetOverlayWindowCookie;
    type CookieUnchecked = GetOverlayWindowCookieUnchecked;
}

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

unsafe impl base::RawRequest for ReleaseOverlayWindow {
    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: 1,
        };

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

        let buf0: &mut [u8] = &mut [0; 8];
        self.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 ReleaseOverlayWindow {
    type Cookie = base::VoidCookie;
    const IS_VOID: bool = true;
}

impl base::RequestWithoutReply for ReleaseOverlayWindow {
}
