summaryrefslogtreecommitdiff
path: root/src/conn_info/cursors.rs
blob: bb547e42df8950ad54885b43d21d2a19a383abc2 (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
use crate::error::Result;
use xcb::{
    x::{CloseFont, CreateGlyphCursor, Cursor, Font, FreeCursor, OpenFont},
    Connection as RawConnection,
};

// https://tronche.com/gui/x/xlib/appendix/b/
const XC_LEFT_PTR: u16 = 68;

/// Caches X11 cursor objects
#[derive(Debug)]
pub struct Cursors {
    #[allow(unused)] // Needs to be kept around since the cursors depend on it
    font: Font,

    normal: Cursor,
}

impl Cursors {
    /// Load default cursors using the given connection.
    pub fn new_with(conn: &RawConnection) -> Result<Self> {
        // Open cursor font
        let font = conn.generate_id();
        conn.check_request(conn.send_request_checked(&OpenFont {
            fid: font,
            name: b"cursor",
        }))?;

        Ok(Self {
            normal: Self::load_cursor(conn, font, XC_LEFT_PTR)?,
            font,
        })
    }

    /// Load the cursor with the given id from `font`
    fn load_cursor(conn: &RawConnection, font: Font, id: u16) -> Result<Cursor> {
        let cid = conn.generate_id();
        // https://github.com/mirror/libX11/blob/ff8706a5eae25b8bafce300527079f68a201d27f/src/Cursor.c#L34
        conn.check_request(conn.send_request_checked(&CreateGlyphCursor {
            cid,
            source_font: font,
            mask_font: font,
            source_char: id,
            mask_char: id + 1,
            fore_red: 0,
            fore_green: 0,
            fore_blue: 0,
            back_red: u16::MAX,
            back_green: u16::MAX,
            back_blue: u16::MAX,
        }))?;

        Ok(cid)
    }

    pub const fn normal(&self) -> Cursor {
        self.normal
    }

    /// Free the associated resources to avoid leaking them.
    /// This object must not be used again after this method is called, as all resources will be invalid.
    pub unsafe fn free(&self, conn: &RawConnection) {
        conn.send_request(&FreeCursor {
            cursor: self.normal,
        });
        conn.send_request(&CloseFont { font: self.font });
    }
}