summary refs log tree commit diff
path: root/src/x/color.rs
blob: d7703792d5169bafe65816a10328634f641aaad9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/*   Color management in X has become an obscure topic because everyone prefers
 * to assume they have 24-bit direct. In dealing with it, [1] has been an
 * important resource.
 *
 * [1] https://xcb.freedesktop.org/xlibtoxcbtranslationguide/
 */
use crate::x::connection::*;
use crate::x::display::*;

use x11::xrender::XRenderColor;
use x11::xft::XftColor;
use xcb::x::{ AllocColor, Visualtype };


pub struct Color {
  /*   We need to store both the original 16-bit components and the pixel
   * value. Additionally, there are situations in which we need to return
   * an XftColor, which contains both of those. So, we might as well use it
   * as the authoritative format.
   *
   *   We treat the contents as opaque, to allow us to pretend it's
   * something cleaner. :)
   */
  font_color: XftColor,
}


impl Color {
  /* Please notice that the constructor is private. */
  fn new(pixel: u32, red: u16, green: u16, blue: u16) -> Self {
    Color {
      font_color: XftColor {
	pixel: pixel as u64,
	color: XRenderColor {
	  red, green, blue,
	  alpha: 65535,
	}
      }
    }
  }

  pub fn as_pixel(&self) -> u32 {
    self.font_color.pixel as u32
  }

  pub fn as_xft_color(&self) -> &XftColor {
    &self.font_color
  }
}


pub trait DisplayColorExt: DisplayExt {
  /*   This is sufficiently obscure knowledge that it's worth keeping here
   * even though it's unused.
   */
  #[allow(dead_code)]
  fn find_root_visual(&self) -> Option<&Visualtype> {
    let visual_id = self.screen().root_visual();

    for depth in self.screen().allowed_depths() {
      for visual in depth.visuals() {
        if visual_id == visual.visual_id() {
          return Some(visual);
        }
      }
    }

    None
  }

  fn allocate_color(&self, red: u16, green: u16, blue: u16)
    -> xcb::Result<Color>
  {
    let connection = self.connection();

    let colormap = self.screen().default_colormap();

    let cookie = connection.send_request(&AllocColor {
      cmap: colormap,
      red, green, blue,
    });

    let pixel = connection.wait_for_reply(cookie)?.pixel();

    Ok(Color::new(pixel, red, green, blue))
  }
}

impl<T: DisplayExt> DisplayColorExt for T { }