OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 #include "media/video/capture/screen/mac/desktop_configuration.h" | |
6 | |
7 #include <math.h> | |
8 #include <algorithm> | |
9 #include <Cocoa/Cocoa.h> | |
10 | |
11 #include "base/logging.h" | |
12 | |
13 #if !defined(MAC_OS_X_VERSION_10_7) || \ | |
14 MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 | |
15 | |
16 @interface NSScreen (LionAPI) | |
17 - (CGFloat)backingScaleFactor; | |
18 - (NSRect)convertRectToBacking:(NSRect)aRect; | |
19 @end | |
20 | |
21 #endif // 10.7 | |
22 | |
23 namespace media { | |
24 | |
25 namespace { | |
26 | |
27 webrtc::DesktopRect NSRectToDesktopRect(const NSRect& ns_rect) { | |
28 return webrtc::DesktopRect::MakeLTRB( | |
29 static_cast<int>(floor(ns_rect.origin.x)), | |
30 static_cast<int>(floor(ns_rect.origin.y)), | |
31 static_cast<int>(ceil(ns_rect.origin.x + ns_rect.size.width)), | |
32 static_cast<int>(ceil(ns_rect.origin.y + ns_rect.size.height))); | |
33 } | |
34 | |
35 webrtc::DesktopRect JoinRects(const webrtc::DesktopRect& a, | |
36 const webrtc::DesktopRect& b) { | |
37 return webrtc::DesktopRect::MakeLTRB( | |
38 std::min(a.left(), b.left()), | |
39 std::min(a.top(), b.top()), | |
40 std::max(a.right(), b.right()), | |
41 std::max(a.bottom(), b.bottom())); | |
42 } | |
43 | |
44 // Inverts the position of |rect| from bottom-up coordinates to top-down, | |
45 // relative to |bounds|. | |
46 void InvertRectYOrigin(const webrtc::DesktopRect& bounds, | |
47 webrtc::DesktopRect* rect) { | |
48 DCHECK_EQ(0, bounds.top()); | |
49 *rect = webrtc::DesktopRect::MakeXYWH( | |
50 rect->left(), bounds.bottom() - rect->bottom(), | |
51 rect->width(), rect->height()); | |
52 } | |
53 | |
54 MacDisplayConfiguration GetConfigurationForScreen(NSScreen* screen) { | |
55 MacDisplayConfiguration display_config; | |
56 | |
57 // Fetch the NSScreenNumber, which is also the CGDirectDisplayID. | |
58 NSDictionary* device_description = [screen deviceDescription]; | |
59 display_config.id = static_cast<CGDirectDisplayID>( | |
60 [[device_description objectForKey:@"NSScreenNumber"] intValue]); | |
61 | |
62 // Determine the display's logical & physical dimensions. | |
63 NSRect ns_bounds = [screen frame]; | |
64 display_config.bounds = NSRectToDesktopRect(ns_bounds); | |
65 | |
66 // If the host is running Mac OS X 10.7+ or later, query the scaling factor | |
67 // between logical and physical (aka "backing") pixels, otherwise assume 1:1. | |
68 if ([screen respondsToSelector:@selector(backingScaleFactor)] && | |
69 [screen respondsToSelector:@selector(convertRectToBacking:)]) { | |
70 display_config.dip_to_pixel_scale = [screen backingScaleFactor]; | |
71 NSRect ns_pixel_bounds = [screen convertRectToBacking: ns_bounds]; | |
72 display_config.pixel_bounds = NSRectToDesktopRect(ns_pixel_bounds); | |
73 } else { | |
74 display_config.pixel_bounds = display_config.bounds; | |
75 } | |
76 | |
77 return display_config; | |
78 } | |
79 | |
80 } // namespace | |
81 | |
82 MacDisplayConfiguration::MacDisplayConfiguration() | |
83 : id(0), | |
84 dip_to_pixel_scale(1.0f) { | |
85 } | |
86 | |
87 MacDesktopConfiguration::MacDesktopConfiguration() | |
88 : dip_to_pixel_scale(1.0f) { | |
89 } | |
90 | |
91 MacDesktopConfiguration::~MacDesktopConfiguration() { | |
92 } | |
93 | |
94 // static | |
95 MacDesktopConfiguration MacDesktopConfiguration::GetCurrent(Origin origin) { | |
96 MacDesktopConfiguration desktop_config; | |
97 | |
98 NSArray* screens = [NSScreen screens]; | |
99 CHECK(screens != NULL); | |
100 | |
101 // Iterator over the monitors, adding the primary monitor and monitors whose | |
102 // DPI match that of the primary monitor. | |
103 for (NSUInteger i = 0; i < [screens count]; ++i) { | |
104 MacDisplayConfiguration display_config = | |
105 GetConfigurationForScreen([screens objectAtIndex: i]); | |
106 | |
107 // Handling mixed-DPI is hard, so we only return displays that match the | |
108 // "primary" display's DPI. The primary display is always the first in the | |
109 // list returned by [NSScreen screens]. | |
110 if (i == 0) { | |
111 desktop_config.dip_to_pixel_scale = display_config.dip_to_pixel_scale; | |
112 } else if (desktop_config.dip_to_pixel_scale != | |
113 display_config.dip_to_pixel_scale) { | |
114 continue; | |
115 } | |
116 | |
117 // Cocoa uses bottom-up coordinates, so if the caller wants top-down then | |
118 // we need to invert the positions of secondary monitors relative to the | |
119 // primary one (the primary monitor's position is (0,0) in both systems). | |
120 if (i > 0 && origin == TopLeftOrigin) { | |
121 InvertRectYOrigin(desktop_config.displays[0].bounds, | |
122 &display_config.bounds); | |
123 InvertRectYOrigin(desktop_config.displays[0].pixel_bounds, | |
124 &display_config.pixel_bounds); | |
125 } | |
126 | |
127 // Add the display to the configuration. | |
128 desktop_config.displays.push_back(display_config); | |
129 | |
130 // Update the desktop bounds to account for this display. | |
131 desktop_config.bounds = | |
132 JoinRects(desktop_config.bounds, display_config.bounds); | |
133 desktop_config.pixel_bounds = | |
134 JoinRects(desktop_config.pixel_bounds, display_config.pixel_bounds); | |
135 } | |
136 | |
137 return desktop_config; | |
138 } | |
139 | |
140 } // namespace media | |
OLD | NEW |