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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
use crate::{point, size, Bounds, DisplayId, GlobalPixels, PlatformDisplay};
use anyhow::Result;
use core_foundation::uuid::{CFUUIDGetUUIDBytes, CFUUIDRef};
use core_graphics::{
    display::{CGDirectDisplayID, CGDisplayBounds, CGGetActiveDisplayList},
    geometry::{CGPoint, CGRect, CGSize},
};
use std::any::Any;
use uuid::Uuid;

#[derive(Debug)]
pub struct MacDisplay(pub(crate) CGDirectDisplayID);

unsafe impl Send for MacDisplay {}

impl MacDisplay {
    /// Get the screen with the given [DisplayId].
    pub fn find_by_id(id: DisplayId) -> Option<Self> {
        Self::all().find(|screen| screen.id() == id)
    }

    /// Get the screen with the given persistent [Uuid].
    pub fn find_by_uuid(uuid: Uuid) -> Option<Self> {
        Self::all().find(|screen| screen.uuid().ok() == Some(uuid))
    }

    /// Get the primary screen - the one with the menu bar, and whose bottom left
    /// corner is at the origin of the AppKit coordinate system.
    pub fn primary() -> Self {
        Self::all().next().unwrap()
    }

    /// Obtains an iterator over all currently active system displays.
    pub fn all() -> impl Iterator<Item = Self> {
        unsafe {
            let mut display_count: u32 = 0;
            let result = CGGetActiveDisplayList(0, std::ptr::null_mut(), &mut display_count);

            if result == 0 {
                let mut displays = Vec::with_capacity(display_count as usize);
                CGGetActiveDisplayList(display_count, displays.as_mut_ptr(), &mut display_count);
                displays.set_len(display_count as usize);

                displays.into_iter().map(|display| MacDisplay(display))
            } else {
                panic!("Failed to get active display list");
            }
        }
    }
}

#[link(name = "ApplicationServices", kind = "framework")]
extern "C" {
    pub fn CGDisplayCreateUUIDFromDisplayID(display: CGDirectDisplayID) -> CFUUIDRef;
}

/// Convert the given rectangle from CoreGraphics' native coordinate space to GPUI's coordinate space.
///
/// CoreGraphics' coordinate space has its origin at the bottom left of the primary screen,
/// with the Y axis pointing upwards.
///
/// Conversely, in GPUI's coordinate system, the origin is placed at the top left of the primary
/// screen, with the Y axis pointing downwards.
pub(crate) fn display_bounds_from_native(rect: CGRect) -> Bounds<GlobalPixels> {
    let primary_screen_size = unsafe { CGDisplayBounds(MacDisplay::primary().id().0) }.size;

    Bounds {
        origin: point(
            GlobalPixels(rect.origin.x as f32),
            GlobalPixels(
                primary_screen_size.height as f32 - rect.origin.y as f32 - rect.size.height as f32,
            ),
        ),
        size: size(
            GlobalPixels(rect.size.width as f32),
            GlobalPixels(rect.size.height as f32),
        ),
    }
}

/// Convert the given rectangle from GPUI's coordinate system to CoreGraphics' native coordinate space.
///
/// CoreGraphics' coordinate space has its origin at the bottom left of the primary screen,
/// with the Y axis pointing upwards.
///
/// Conversely, in GPUI's coordinate system, the origin is placed at the top left of the primary
/// screen, with the Y axis pointing downwards.
pub(crate) fn display_bounds_to_native(bounds: Bounds<GlobalPixels>) -> CGRect {
    let primary_screen_height = MacDisplay::primary().bounds().size.height;

    CGRect::new(
        &CGPoint::new(
            bounds.origin.x.into(),
            (primary_screen_height - bounds.origin.y - bounds.size.height).into(),
        ),
        &CGSize::new(bounds.size.width.into(), bounds.size.height.into()),
    )
}

impl PlatformDisplay for MacDisplay {
    fn id(&self) -> DisplayId {
        DisplayId(self.0)
    }

    fn uuid(&self) -> Result<Uuid> {
        let cfuuid = unsafe { CGDisplayCreateUUIDFromDisplayID(self.0 as CGDirectDisplayID) };
        anyhow::ensure!(
            !cfuuid.is_null(),
            "AppKit returned a null from CGDisplayCreateUUIDFromDisplayID"
        );

        let bytes = unsafe { CFUUIDGetUUIDBytes(cfuuid) };
        Ok(Uuid::from_bytes([
            bytes.byte0,
            bytes.byte1,
            bytes.byte2,
            bytes.byte3,
            bytes.byte4,
            bytes.byte5,
            bytes.byte6,
            bytes.byte7,
            bytes.byte8,
            bytes.byte9,
            bytes.byte10,
            bytes.byte11,
            bytes.byte12,
            bytes.byte13,
            bytes.byte14,
            bytes.byte15,
        ]))
    }

    fn as_any(&self) -> &dyn Any {
        self
    }

    fn bounds(&self) -> Bounds<GlobalPixels> {
        unsafe {
            let native_bounds = CGDisplayBounds(self.0);
            display_bounds_from_native(native_bounds)
        }
    }
}