Add media query support for wide gamut displays on Mac
[WebKit-https.git] / Source / WebCore / platform / mac / PlatformScreenMac.mm
1 /*
2  * Copyright (C) 2006 Apple Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #import "config.h"
27 #import "PlatformScreen.h"
28
29 #import "CoreGraphicsSPI.h"
30 #import "FloatRect.h"
31 #import "FrameView.h"
32 #import "HostWindow.h"
33
34 #import <ColorSync/ColorSync.h>
35
36 extern "C" {
37 bool CGDisplayUsesInvertedPolarity(void);
38 bool CGDisplayUsesForceToGray(void);
39 }
40
41 namespace WebCore {
42
43 static PlatformDisplayID displayIDFromScreen(NSScreen *screen)
44 {
45     return (PlatformDisplayID)[[[screen deviceDescription] objectForKey:@"NSScreenNumber"] intValue];
46 }
47
48 // These functions scale between screen and page coordinates because JavaScript/DOM operations
49 // assume that the screen and the page share the same coordinate system.
50
51 static PlatformDisplayID displayFromWidget(Widget* widget)
52 {
53     if (!widget)
54         return 0;
55
56     FrameView* view = widget->root();
57     if (!view)
58         return 0;
59
60     return view->hostWindow()->displayID();
61 }
62
63 static NSScreen *screenForWidget(Widget* widget, NSWindow *window)
64 {
65     // Widget is in an NSWindow, use its screen.
66     if (window)
67         return screenForWindow(window);
68
69     // Didn't get an NSWindow; probably WebKit2. Try using the Widget's display ID.
70     if (NSScreen *screen = screenForDisplayID(displayFromWidget(widget)))
71         return screen;
72
73     // Widget's window is offscreen, or no screens. Fall back to the first screen if available.
74     return screenForWindow(nil);
75 }
76
77 int screenDepth(Widget* widget)
78 {
79     NSWindow *window = widget ? [widget->platformWidget() window] : nil;
80     NSScreen *screen = screenForWidget(widget, window);
81     return NSBitsPerPixelFromDepth(screen.depth);
82 }
83
84 int screenDepthPerComponent(Widget* widget)
85 {
86     NSWindow *window = widget ? [widget->platformWidget() window] : nil;
87     NSScreen *screen = screenForWidget(widget, window);
88     return NSBitsPerSampleFromDepth(screen.depth);
89 }
90
91 bool screenIsMonochrome(Widget*)
92 {
93     // At the moment this is a system-wide accessibility setting,
94     // so we don't need to check the screen we're using.
95     return CGDisplayUsesForceToGray();
96 }
97
98 bool screenHasInvertedColors()
99 {
100     // At the moment this is a system-wide accessibility setting,
101     // so we don't need to check the screen we're using.
102     return CGDisplayUsesInvertedPolarity();
103 }
104
105 FloatRect screenRect(Widget* widget)
106 {
107     NSWindow *window = widget ? [widget->platformWidget() window] : nil;
108     NSScreen *screen = screenForWidget(widget, window);
109     return toUserSpace([screen frame], window);
110 }
111
112 FloatRect screenAvailableRect(Widget* widget)
113 {
114     NSWindow *window = widget ? [widget->platformWidget() window] : nil;
115     NSScreen *screen = screenForWidget(widget, window);
116     return toUserSpace([screen visibleFrame], window);
117 }
118
119 NSScreen *screenForWindow(NSWindow *window)
120 {
121     NSScreen *screen = [window screen]; // nil if the window is off-screen
122     if (screen)
123         return screen;
124
125     NSArray *screens = [NSScreen screens];
126     if ([screens count] > 0)
127         return [screens objectAtIndex:0]; // screen containing the menubar
128
129     return nil;
130 }
131
132 NSScreen *screenForDisplayID(PlatformDisplayID displayID)
133 {
134     for (NSScreen *screen in [NSScreen screens]) {
135         if (displayIDFromScreen(screen) == displayID)
136             return screen;
137     }
138     return nil;
139 }
140
141 bool screenSupportsExtendedColor(Widget* widget)
142 {
143 #if __MAC_OS_X_VERSION_MIN_REQUIRED < 101100
144     UNUSED_PARAM(widget);
145     return false;
146 #else
147     if (!widget)
148         return false;
149
150     NSWindow *window = [widget->platformWidget() window];
151     NSScreen *screen = screenForWidget(widget, window);
152     CGColorSpaceRef colorSpace = screen.colorSpace.CGColorSpace;
153
154 #if __MAC_OS_X_VERSION_MIN_REQUIRED >= 101200
155     return CGColorSpaceIsWideGamutRGB(colorSpace);
156 #else
157     bool isWideGamut = false;
158     RetainPtr<CFDataRef> iccData = adoptCF(CGColorSpaceCopyICCProfile(colorSpace));
159     RetainPtr<ColorSyncProfileRef> profile = adoptCF(ColorSyncProfileCreate(iccData.get(), NULL));
160     if (profile)
161         isWideGamut = ColorSyncProfileIsWideGamut(profile.get());
162     return isWideGamut;
163 #endif
164 #endif
165 }
166
167 FloatRect toUserSpace(const NSRect& rect, NSWindow *destination)
168 {
169     FloatRect userRect = rect;
170     userRect.setY(NSMaxY([screenForWindow(destination) frame]) - (userRect.y() + userRect.height())); // flip
171     return userRect;
172 }
173
174 NSRect toDeviceSpace(const FloatRect& rect, NSWindow *source)
175 {
176     FloatRect deviceRect = rect;
177     deviceRect.setY(NSMaxY([screenForWindow(source) frame]) - (deviceRect.y() + deviceRect.height())); // flip
178     return deviceRect;
179 }
180
181 NSPoint flipScreenPoint(const NSPoint& screenPoint, NSScreen *screen)
182 {
183     NSPoint flippedPoint = screenPoint;
184     flippedPoint.y = NSMaxY([screen frame]) - flippedPoint.y;
185     return flippedPoint;
186 }
187
188 } // namespace WebCore