|
1 /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ |
|
2 /* This Source Code Form is subject to the terms of the Mozilla Public |
|
3 * License, v. 2.0. If a copy of the MPL was not distributed with this |
|
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ |
|
5 |
|
6 #ifndef nsCocoaUtils_h_ |
|
7 #define nsCocoaUtils_h_ |
|
8 |
|
9 #import <Cocoa/Cocoa.h> |
|
10 |
|
11 #include "nsRect.h" |
|
12 #include "imgIContainer.h" |
|
13 #include "npapi.h" |
|
14 #include "nsTArray.h" |
|
15 |
|
16 // This must be the last include: |
|
17 #include "nsObjCExceptions.h" |
|
18 |
|
19 #include "mozilla/EventForwards.h" |
|
20 |
|
21 // Declare the backingScaleFactor method that we want to call |
|
22 // on NSView/Window/Screen objects, if they recognize it. |
|
23 @interface NSObject (BackingScaleFactorCategory) |
|
24 - (CGFloat)backingScaleFactor; |
|
25 @end |
|
26 |
|
27 class nsIWidget; |
|
28 |
|
29 namespace mozilla { |
|
30 namespace gfx { |
|
31 class SourceSurface; |
|
32 } |
|
33 } |
|
34 |
|
35 // Used to retain a Cocoa object for the remainder of a method's execution. |
|
36 class nsAutoRetainCocoaObject { |
|
37 public: |
|
38 nsAutoRetainCocoaObject(id anObject) |
|
39 { |
|
40 mObject = NS_OBJC_TRY_EXPR_ABORT([anObject retain]); |
|
41 } |
|
42 ~nsAutoRetainCocoaObject() |
|
43 { |
|
44 NS_OBJC_TRY_ABORT([mObject release]); |
|
45 } |
|
46 private: |
|
47 id mObject; // [STRONG] |
|
48 }; |
|
49 |
|
50 // Provide a local autorelease pool for the remainder of a method's execution. |
|
51 class nsAutoreleasePool { |
|
52 public: |
|
53 nsAutoreleasePool() |
|
54 { |
|
55 mLocalPool = [[NSAutoreleasePool alloc] init]; |
|
56 } |
|
57 ~nsAutoreleasePool() |
|
58 { |
|
59 [mLocalPool release]; |
|
60 } |
|
61 private: |
|
62 NSAutoreleasePool *mLocalPool; |
|
63 }; |
|
64 |
|
65 @interface NSApplication (Undocumented) |
|
66 |
|
67 // Present in all versions of OS X from (at least) 10.2.8 through 10.5. |
|
68 - (BOOL)_isRunningModal; |
|
69 - (BOOL)_isRunningAppModal; |
|
70 |
|
71 // It's sometimes necessary to explicitly remove a window from the "window |
|
72 // cache" in order to deactivate it. The "window cache" is an undocumented |
|
73 // subsystem, all of whose methods are included in the NSWindowCache category |
|
74 // of the NSApplication class (in header files generated using class-dump). |
|
75 // Present in all versions of OS X from (at least) 10.2.8 through 10.5. |
|
76 - (void)_removeWindowFromCache:(NSWindow *)aWindow; |
|
77 |
|
78 // Send an event to the current Cocoa app-modal session. Present in all |
|
79 // versions of OS X from (at least) 10.2.8 through 10.5. |
|
80 - (void)_modalSession:(NSModalSession)aSession sendEvent:(NSEvent *)theEvent; |
|
81 |
|
82 // Present (and documented) on OS X 10.6 and above. Not present before 10.6. |
|
83 // This declaration needed to avoid compiler warnings when compiling on 10.5 |
|
84 // and below (or using the 10.5 SDK and below). |
|
85 - (void)setHelpMenu:(NSMenu *)helpMenu; |
|
86 |
|
87 @end |
|
88 |
|
89 struct KeyBindingsCommand |
|
90 { |
|
91 SEL selector; |
|
92 id data; |
|
93 }; |
|
94 |
|
95 @interface NativeKeyBindingsRecorder : NSResponder |
|
96 { |
|
97 @private |
|
98 nsTArray<KeyBindingsCommand>* mCommands; |
|
99 } |
|
100 |
|
101 - (void)startRecording:(nsTArray<KeyBindingsCommand>&)aCommands; |
|
102 |
|
103 - (void)doCommandBySelector:(SEL)aSelector; |
|
104 |
|
105 - (void)insertText:(id)aString; |
|
106 |
|
107 @end // NativeKeyBindingsRecorder |
|
108 |
|
109 class nsCocoaUtils |
|
110 { |
|
111 typedef mozilla::gfx::SourceSurface SourceSurface; |
|
112 |
|
113 public: |
|
114 |
|
115 // Get the backing scale factor from an object that supports this selector |
|
116 // (NSView/Window/Screen, on 10.7 or later), returning 1.0 if not supported |
|
117 static CGFloat |
|
118 GetBackingScaleFactor(id aObject) |
|
119 { |
|
120 if (HiDPIEnabled() && |
|
121 [aObject respondsToSelector:@selector(backingScaleFactor)]) { |
|
122 return [aObject backingScaleFactor]; |
|
123 } |
|
124 return 1.0; |
|
125 } |
|
126 |
|
127 // Conversions between Cocoa points and device pixels, given the backing |
|
128 // scale factor from a view/window/screen. |
|
129 static int32_t |
|
130 CocoaPointsToDevPixels(CGFloat aPts, CGFloat aBackingScale) |
|
131 { |
|
132 return NSToIntRound(aPts * aBackingScale); |
|
133 } |
|
134 |
|
135 static nsIntPoint |
|
136 CocoaPointsToDevPixels(const NSPoint& aPt, CGFloat aBackingScale) |
|
137 { |
|
138 return nsIntPoint(NSToIntRound(aPt.x * aBackingScale), |
|
139 NSToIntRound(aPt.y * aBackingScale)); |
|
140 } |
|
141 |
|
142 static nsIntRect |
|
143 CocoaPointsToDevPixels(const NSRect& aRect, CGFloat aBackingScale) |
|
144 { |
|
145 return nsIntRect(NSToIntRound(aRect.origin.x * aBackingScale), |
|
146 NSToIntRound(aRect.origin.y * aBackingScale), |
|
147 NSToIntRound(aRect.size.width * aBackingScale), |
|
148 NSToIntRound(aRect.size.height * aBackingScale)); |
|
149 } |
|
150 |
|
151 static CGFloat |
|
152 DevPixelsToCocoaPoints(int32_t aPixels, CGFloat aBackingScale) |
|
153 { |
|
154 return (CGFloat)aPixels / aBackingScale; |
|
155 } |
|
156 |
|
157 static NSPoint |
|
158 DevPixelsToCocoaPoints(const nsIntPoint& aPt, CGFloat aBackingScale) |
|
159 { |
|
160 return NSMakePoint((CGFloat)aPt.x / aBackingScale, |
|
161 (CGFloat)aPt.y / aBackingScale); |
|
162 } |
|
163 |
|
164 static NSRect |
|
165 DevPixelsToCocoaPoints(const nsIntRect& aRect, CGFloat aBackingScale) |
|
166 { |
|
167 return NSMakeRect((CGFloat)aRect.x / aBackingScale, |
|
168 (CGFloat)aRect.y / aBackingScale, |
|
169 (CGFloat)aRect.width / aBackingScale, |
|
170 (CGFloat)aRect.height / aBackingScale); |
|
171 } |
|
172 |
|
173 // Returns the given y coordinate, which must be in screen coordinates, |
|
174 // flipped from Gecko to Cocoa or Cocoa to Gecko. |
|
175 static float FlippedScreenY(float y); |
|
176 |
|
177 // The following functions come in "DevPix" variants that work with |
|
178 // backing-store (device pixel) coordinates, as well as the original |
|
179 // versions that expect coordinates in Cocoa points/CSS pixels. |
|
180 // The difference becomes important in HiDPI display modes, where Cocoa |
|
181 // points and backing-store pixels are no longer 1:1. |
|
182 |
|
183 // Gecko rects (nsRect) contain an origin (x,y) in a coordinate |
|
184 // system with (0,0) in the top-left of the primary screen. Cocoa rects |
|
185 // (NSRect) contain an origin (x,y) in a coordinate system with (0,0) |
|
186 // in the bottom-left of the primary screen. Both nsRect and NSRect |
|
187 // contain width/height info, with no difference in their use. |
|
188 // This function does no scaling, so the Gecko coordinates are |
|
189 // expected to be CSS pixels, which we treat as equal to Cocoa points. |
|
190 static NSRect GeckoRectToCocoaRect(const nsIntRect &geckoRect); |
|
191 |
|
192 // Converts aGeckoRect in dev pixels to points in Cocoa coordinates |
|
193 static NSRect GeckoRectToCocoaRectDevPix(const nsIntRect &aGeckoRect, |
|
194 CGFloat aBackingScale); |
|
195 |
|
196 // See explanation for geckoRectToCocoaRect, guess what this does... |
|
197 static nsIntRect CocoaRectToGeckoRect(const NSRect &cocoaRect); |
|
198 |
|
199 static nsIntRect CocoaRectToGeckoRectDevPix(const NSRect &aCocoaRect, |
|
200 CGFloat aBackingScale); |
|
201 |
|
202 // Gives the location for the event in screen coordinates. Do not call this |
|
203 // unless the window the event was originally targeted at is still alive! |
|
204 // anEvent may be nil -- in that case the current mouse location is returned. |
|
205 static NSPoint ScreenLocationForEvent(NSEvent* anEvent); |
|
206 |
|
207 // Determines if an event happened over a window, whether or not the event |
|
208 // is for the window. Does not take window z-order into account. |
|
209 static BOOL IsEventOverWindow(NSEvent* anEvent, NSWindow* aWindow); |
|
210 |
|
211 // Events are set up so that their coordinates refer to the window to which they |
|
212 // were originally sent. If we reroute the event somewhere else, we'll have |
|
213 // to get the window coordinates this way. Do not call this unless the window |
|
214 // the event was originally targeted at is still alive! |
|
215 static NSPoint EventLocationForWindow(NSEvent* anEvent, NSWindow* aWindow); |
|
216 |
|
217 static BOOL IsMomentumScrollEvent(NSEvent* aEvent); |
|
218 |
|
219 // Hides the Menu bar and the Dock. Multiple hide/show requests can be nested. |
|
220 static void HideOSChromeOnScreen(bool aShouldHide, NSScreen* aScreen); |
|
221 |
|
222 static nsIWidget* GetHiddenWindowWidget(); |
|
223 |
|
224 static void PrepareForNativeAppModalDialog(); |
|
225 static void CleanUpAfterNativeAppModalDialog(); |
|
226 |
|
227 // 3 utility functions to go from a frame of imgIContainer to CGImage and then to NSImage |
|
228 // Convert imgIContainer -> CGImageRef, caller owns result |
|
229 |
|
230 /** Creates a <code>CGImageRef</code> from a frame contained in an <code>imgIContainer</code>. |
|
231 Copies the pixel data from the indicated frame of the <code>imgIContainer</code> into a new <code>CGImageRef</code>. |
|
232 The caller owns the <code>CGImageRef</code>. |
|
233 @param aFrame the frame to convert |
|
234 @param aResult the resulting CGImageRef |
|
235 @return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise |
|
236 */ |
|
237 static nsresult CreateCGImageFromSurface(SourceSurface* aSurface, |
|
238 CGImageRef* aResult); |
|
239 |
|
240 /** Creates a Cocoa <code>NSImage</code> from a <code>CGImageRef</code>. |
|
241 Copies the pixel data from the <code>CGImageRef</code> into a new <code>NSImage</code>. |
|
242 The caller owns the <code>NSImage</code>. |
|
243 @param aInputImage the image to convert |
|
244 @param aResult the resulting NSImage |
|
245 @return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise |
|
246 */ |
|
247 static nsresult CreateNSImageFromCGImage(CGImageRef aInputImage, NSImage **aResult); |
|
248 |
|
249 /** Creates a Cocoa <code>NSImage</code> from a frame of an <code>imgIContainer</code>. |
|
250 Combines the two methods above. The caller owns the <code>NSImage</code>. |
|
251 @param aImage the image to extract a frame from |
|
252 @param aWhichFrame the frame to extract (see imgIContainer FRAME_*) |
|
253 @param aResult the resulting NSImage |
|
254 @param scaleFactor the desired scale factor of the NSImage (2 for a retina display) |
|
255 @return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise |
|
256 */ |
|
257 static nsresult CreateNSImageFromImageContainer(imgIContainer *aImage, uint32_t aWhichFrame, NSImage **aResult, CGFloat scaleFactor); |
|
258 |
|
259 /** |
|
260 * Returns nsAString for aSrc. |
|
261 */ |
|
262 static void GetStringForNSString(const NSString *aSrc, nsAString& aDist); |
|
263 |
|
264 /** |
|
265 * Makes NSString instance for aString. |
|
266 */ |
|
267 static NSString* ToNSString(const nsAString& aString); |
|
268 |
|
269 /** |
|
270 * Returns NSRect for aGeckoRect. |
|
271 * Just copies values between the two types; it does no coordinate-system |
|
272 * conversion, so both rects must have the same coordinate origin/direction. |
|
273 */ |
|
274 static void GeckoRectToNSRect(const nsIntRect& aGeckoRect, |
|
275 NSRect& aOutCocoaRect); |
|
276 |
|
277 /** |
|
278 * Returns Gecko rect for aCocoaRect. |
|
279 * Just copies values between the two types; it does no coordinate-system |
|
280 * conversion, so both rects must have the same coordinate origin/direction. |
|
281 */ |
|
282 static void NSRectToGeckoRect(const NSRect& aCocoaRect, |
|
283 nsIntRect& aOutGeckoRect); |
|
284 |
|
285 /** |
|
286 * Makes NSEvent instance for aEventTytpe and aEvent. |
|
287 */ |
|
288 static NSEvent* MakeNewCocoaEventWithType(NSEventType aEventType, |
|
289 NSEvent *aEvent); |
|
290 |
|
291 /** |
|
292 * Initializes aNPCocoaEvent. |
|
293 */ |
|
294 static void InitNPCocoaEvent(NPCocoaEvent* aNPCocoaEvent); |
|
295 |
|
296 /** |
|
297 * Initializes aPluginEvent for aCocoaEvent. |
|
298 */ |
|
299 static void InitPluginEvent(mozilla::WidgetPluginEvent &aPluginEvent, |
|
300 NPCocoaEvent &aCocoaEvent); |
|
301 /** |
|
302 * Initializes WidgetInputEvent for aNativeEvent or aModifiers. |
|
303 */ |
|
304 static void InitInputEvent(mozilla::WidgetInputEvent &aInputEvent, |
|
305 NSEvent* aNativeEvent); |
|
306 static void InitInputEvent(mozilla::WidgetInputEvent &aInputEvent, |
|
307 NSUInteger aModifiers); |
|
308 |
|
309 /** |
|
310 * ConvertToCarbonModifier() returns carbon modifier flags for the cocoa |
|
311 * modifier flags. |
|
312 * NOTE: The result never includes right*Key. |
|
313 */ |
|
314 static UInt32 ConvertToCarbonModifier(NSUInteger aCocoaModifier); |
|
315 |
|
316 /** |
|
317 * Whether to support HiDPI rendering. For testing purposes, to be removed |
|
318 * once we're comfortable with the HiDPI behavior. |
|
319 */ |
|
320 static bool HiDPIEnabled(); |
|
321 |
|
322 /** |
|
323 * Keys can optionally be bound by system or user key bindings to one or more |
|
324 * commands based on selectors. This collects any such commands in the |
|
325 * provided array. |
|
326 */ |
|
327 static void GetCommandsFromKeyEvent(NSEvent* aEvent, |
|
328 nsTArray<KeyBindingsCommand>& aCommands); |
|
329 |
|
330 /** |
|
331 * Converts the string name of a Gecko key (like "VK_HOME") to the |
|
332 * corresponding Cocoa Unicode character. |
|
333 */ |
|
334 static uint32_t ConvertGeckoNameToMacCharCode(const nsAString& aKeyCodeName); |
|
335 |
|
336 /** |
|
337 * Converts a Gecko key code (like NS_VK_HOME) to the corresponding Cocoa |
|
338 * Unicode character. |
|
339 */ |
|
340 static uint32_t ConvertGeckoKeyCodeToMacCharCode(uint32_t aKeyCode); |
|
341 }; |
|
342 |
|
343 #endif // nsCocoaUtils_h_ |