1 use std::collections::VecDeque;
2 use std::fmt;
3
4 use cocoa::appkit::NSScreen;
5 use cocoa::base::{id, nil};
6 use cocoa::foundation::{NSString, NSUInteger};
7 use core_graphics::display::{CGDirectDisplayID, CGDisplay, CGDisplayBounds};
8
9 use {PhysicalPosition, PhysicalSize};
10 use super::EventsLoop;
11 use super::window::{IdRef, Window2};
12
13 #[derive(Clone, PartialEq)]
14 pub struct MonitorId(CGDirectDisplayID);
15
get_available_monitors() -> VecDeque<MonitorId>16 fn get_available_monitors() -> VecDeque<MonitorId> {
17 if let Ok(displays) = CGDisplay::active_displays() {
18 let mut monitors = VecDeque::with_capacity(displays.len());
19 for d in displays {
20 monitors.push_back(MonitorId(d));
21 }
22 monitors
23 } else {
24 VecDeque::with_capacity(0)
25 }
26 }
27
get_primary_monitor() -> MonitorId28 pub fn get_primary_monitor() -> MonitorId {
29 let id = MonitorId(CGDisplay::main().id);
30 id
31 }
32
33 impl EventsLoop {
34 #[inline]
get_available_monitors(&self) -> VecDeque<MonitorId>35 pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
36 get_available_monitors()
37 }
38
39 #[inline]
get_primary_monitor(&self) -> MonitorId40 pub fn get_primary_monitor(&self) -> MonitorId {
41 get_primary_monitor()
42 }
43
make_monitor_from_display(id: CGDirectDisplayID) -> MonitorId44 pub fn make_monitor_from_display(id: CGDirectDisplayID) -> MonitorId {
45 let id = MonitorId(id);
46 id
47 }
48 }
49
50 impl Window2 {
51 #[inline]
get_available_monitors(&self) -> VecDeque<MonitorId>52 pub fn get_available_monitors(&self) -> VecDeque<MonitorId> {
53 get_available_monitors()
54 }
55
56 #[inline]
get_primary_monitor(&self) -> MonitorId57 pub fn get_primary_monitor(&self) -> MonitorId {
58 get_primary_monitor()
59 }
60 }
61
62 impl fmt::Debug for MonitorId {
fmt(&self, f: &mut fmt::Formatter) -> fmt::Result63 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
64 #[derive(Debug)]
65 struct MonitorId {
66 name: Option<String>,
67 native_identifier: u32,
68 dimensions: PhysicalSize,
69 position: PhysicalPosition,
70 hidpi_factor: f64,
71 }
72
73 let monitor_id_proxy = MonitorId {
74 name: self.get_name(),
75 native_identifier: self.get_native_identifier(),
76 dimensions: self.get_dimensions(),
77 position: self.get_position(),
78 hidpi_factor: self.get_hidpi_factor(),
79 };
80
81 monitor_id_proxy.fmt(f)
82 }
83 }
84
85 impl MonitorId {
get_name(&self) -> Option<String>86 pub fn get_name(&self) -> Option<String> {
87 let MonitorId(display_id) = *self;
88 let screen_num = CGDisplay::new(display_id).model_number();
89 Some(format!("Monitor #{}", screen_num))
90 }
91
92 #[inline]
get_native_identifier(&self) -> u3293 pub fn get_native_identifier(&self) -> u32 {
94 self.0
95 }
96
get_dimensions(&self) -> PhysicalSize97 pub fn get_dimensions(&self) -> PhysicalSize {
98 let MonitorId(display_id) = *self;
99 let display = CGDisplay::new(display_id);
100 let height = display.pixels_high();
101 let width = display.pixels_wide();
102 PhysicalSize::from_logical(
103 (width as f64, height as f64),
104 self.get_hidpi_factor(),
105 )
106 }
107
108 #[inline]
get_position(&self) -> PhysicalPosition109 pub fn get_position(&self) -> PhysicalPosition {
110 let bounds = unsafe { CGDisplayBounds(self.get_native_identifier()) };
111 PhysicalPosition::from_logical(
112 (bounds.origin.x as f64, bounds.origin.y as f64),
113 self.get_hidpi_factor(),
114 )
115 }
116
get_hidpi_factor(&self) -> f64117 pub fn get_hidpi_factor(&self) -> f64 {
118 let screen = match self.get_nsscreen() {
119 Some(screen) => screen,
120 None => return 1.0, // default to 1.0 when we can't find the screen
121 };
122 unsafe { NSScreen::backingScaleFactor(screen) as f64 }
123 }
124
get_nsscreen(&self) -> Option<id>125 pub(crate) fn get_nsscreen(&self) -> Option<id> {
126 unsafe {
127 let native_id = self.get_native_identifier();
128 let screens = NSScreen::screens(nil);
129 let count: NSUInteger = msg_send![screens, count];
130 let key = IdRef::new(NSString::alloc(nil).init_str("NSScreenNumber"));
131 let mut matching_screen: Option<id> = None;
132 for i in 0..count {
133 let screen = msg_send![screens, objectAtIndex: i as NSUInteger];
134 let device_description = NSScreen::deviceDescription(screen);
135 let value: id = msg_send![device_description, objectForKey:*key];
136 if value != nil {
137 let screen_number: NSUInteger = msg_send![value, unsignedIntegerValue];
138 if screen_number as u32 == native_id {
139 matching_screen = Some(screen);
140 break;
141 }
142 }
143 }
144 matching_screen
145 }
146 }
147 }
148