use crate::{
auto::xproto::{AllocColorReply, AllocColorRequest, Colormap},
display::prelude::*,
Display, RequestCookie,
};
#[cfg(feature = "async")]
use crate::{
display::{
futures::{ExchangeRequestFuture, MapFuture, SendRequestFuture},
AsyncDisplay,
},
util::BoxedFnOnce,
};
#[cfg(feature = "async")]
use alloc::boxed::Box;
#[inline]
#[must_use]
pub const fn rgb(r: u8, g: u8, b: u8) -> u32 {
let r = r as u32;
let g = g as u32;
let b = b as u32;
b + (g << 8) + (r << 16)
}
#[derive(Debug, Clone, Copy)]
pub enum ColorAllocation {
NoChange(u32),
Changed {
pixel: u32,
red: u16,
green: u16,
blue: u16,
},
}
impl ColorAllocation {
#[inline]
#[must_use]
pub fn pixel(&self) -> u32 {
match self {
Self::NoChange(pixel) | Self::Changed { pixel, .. } => *pixel,
}
}
#[inline]
#[must_use]
pub fn from_alloc_color_reply(acr: AllocColorReply, r: u16, g: u16, b: u16) -> Self {
if acr.red == r && acr.green == g && acr.blue == b {
Self::NoChange(acr.pixel)
} else {
Self::Changed {
red: acr.red,
green: acr.green,
blue: acr.blue,
pixel: acr.pixel,
}
}
}
}
impl From<ColorAllocation> for u32 {
#[inline]
fn from(ca: ColorAllocation) -> u32 {
ca.pixel()
}
}
impl Colormap {
#[inline]
fn alloc_color_request(self, r: u16, g: u16, b: u16) -> AllocColorRequest {
AllocColorRequest {
cmap: self,
red: r,
green: g,
blue: b,
..Default::default()
}
}
#[inline]
pub fn alloc_color<Dpy: Display + ?Sized>(
self,
dpy: &mut Dpy,
r: u16,
g: u16,
b: u16,
) -> crate::Result<RequestCookie<AllocColorRequest>> {
dpy.send_request(self.alloc_color_request(r, g, b))
}
#[cfg(feature = "async")]
#[inline]
pub async fn alloc_color_async<Dpy: AsyncDisplay + ?Sized>(
self,
dpy: &mut Dpy,
r: u16,
g: u16,
b: u16,
) -> SendRequestFuture<'_, Dpy, AllocColorRequest> {
dpy.send_request_async(self.alloc_color_request(r, g, b))
}
#[inline]
pub fn alloc_color_immediate<Dpy: Display + ?Sized>(
self,
dpy: &mut Dpy,
r: u16,
g: u16,
b: u16,
) -> crate::Result<ColorAllocation> {
let tok = self.alloc_color(dpy, r, g, b)?;
Ok(ColorAllocation::from_alloc_color_reply(
dpy.resolve_request(tok)?,
r,
g,
b,
))
}
#[cfg(feature = "async")]
#[inline]
pub async fn alloc_color_immediate_async<Dpy: AsyncDisplay + ?Sized>(
self,
dpy: &mut Dpy,
r: u16,
g: u16,
b: u16,
) -> MapFuture<
ExchangeRequestFuture<'_, Dpy, AllocColorRequest>,
BoxedFnOnce<AllocColorReply, ColorAllocation>,
> {
MapFuture::run(
dpy.exchange_request_async(self.alloc_color_request(r, g, b)),
Box::new(move |acr| ColorAllocation::from_alloc_color_reply(acr, r, g, b)),
)
}
}