michael@0: /* -*- Mode: C++; tab-width: 20; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ michael@0: /* This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef nsCocoaUtils_h_ michael@0: #define nsCocoaUtils_h_ michael@0: michael@0: #import michael@0: michael@0: #include "nsRect.h" michael@0: #include "imgIContainer.h" michael@0: #include "npapi.h" michael@0: #include "nsTArray.h" michael@0: michael@0: // This must be the last include: michael@0: #include "nsObjCExceptions.h" michael@0: michael@0: #include "mozilla/EventForwards.h" michael@0: michael@0: // Declare the backingScaleFactor method that we want to call michael@0: // on NSView/Window/Screen objects, if they recognize it. michael@0: @interface NSObject (BackingScaleFactorCategory) michael@0: - (CGFloat)backingScaleFactor; michael@0: @end michael@0: michael@0: class nsIWidget; michael@0: michael@0: namespace mozilla { michael@0: namespace gfx { michael@0: class SourceSurface; michael@0: } michael@0: } michael@0: michael@0: // Used to retain a Cocoa object for the remainder of a method's execution. michael@0: class nsAutoRetainCocoaObject { michael@0: public: michael@0: nsAutoRetainCocoaObject(id anObject) michael@0: { michael@0: mObject = NS_OBJC_TRY_EXPR_ABORT([anObject retain]); michael@0: } michael@0: ~nsAutoRetainCocoaObject() michael@0: { michael@0: NS_OBJC_TRY_ABORT([mObject release]); michael@0: } michael@0: private: michael@0: id mObject; // [STRONG] michael@0: }; michael@0: michael@0: // Provide a local autorelease pool for the remainder of a method's execution. michael@0: class nsAutoreleasePool { michael@0: public: michael@0: nsAutoreleasePool() michael@0: { michael@0: mLocalPool = [[NSAutoreleasePool alloc] init]; michael@0: } michael@0: ~nsAutoreleasePool() michael@0: { michael@0: [mLocalPool release]; michael@0: } michael@0: private: michael@0: NSAutoreleasePool *mLocalPool; michael@0: }; michael@0: michael@0: @interface NSApplication (Undocumented) michael@0: michael@0: // Present in all versions of OS X from (at least) 10.2.8 through 10.5. michael@0: - (BOOL)_isRunningModal; michael@0: - (BOOL)_isRunningAppModal; michael@0: michael@0: // It's sometimes necessary to explicitly remove a window from the "window michael@0: // cache" in order to deactivate it. The "window cache" is an undocumented michael@0: // subsystem, all of whose methods are included in the NSWindowCache category michael@0: // of the NSApplication class (in header files generated using class-dump). michael@0: // Present in all versions of OS X from (at least) 10.2.8 through 10.5. michael@0: - (void)_removeWindowFromCache:(NSWindow *)aWindow; michael@0: michael@0: // Send an event to the current Cocoa app-modal session. Present in all michael@0: // versions of OS X from (at least) 10.2.8 through 10.5. michael@0: - (void)_modalSession:(NSModalSession)aSession sendEvent:(NSEvent *)theEvent; michael@0: michael@0: // Present (and documented) on OS X 10.6 and above. Not present before 10.6. michael@0: // This declaration needed to avoid compiler warnings when compiling on 10.5 michael@0: // and below (or using the 10.5 SDK and below). michael@0: - (void)setHelpMenu:(NSMenu *)helpMenu; michael@0: michael@0: @end michael@0: michael@0: struct KeyBindingsCommand michael@0: { michael@0: SEL selector; michael@0: id data; michael@0: }; michael@0: michael@0: @interface NativeKeyBindingsRecorder : NSResponder michael@0: { michael@0: @private michael@0: nsTArray* mCommands; michael@0: } michael@0: michael@0: - (void)startRecording:(nsTArray&)aCommands; michael@0: michael@0: - (void)doCommandBySelector:(SEL)aSelector; michael@0: michael@0: - (void)insertText:(id)aString; michael@0: michael@0: @end // NativeKeyBindingsRecorder michael@0: michael@0: class nsCocoaUtils michael@0: { michael@0: typedef mozilla::gfx::SourceSurface SourceSurface; michael@0: michael@0: public: michael@0: michael@0: // Get the backing scale factor from an object that supports this selector michael@0: // (NSView/Window/Screen, on 10.7 or later), returning 1.0 if not supported michael@0: static CGFloat michael@0: GetBackingScaleFactor(id aObject) michael@0: { michael@0: if (HiDPIEnabled() && michael@0: [aObject respondsToSelector:@selector(backingScaleFactor)]) { michael@0: return [aObject backingScaleFactor]; michael@0: } michael@0: return 1.0; michael@0: } michael@0: michael@0: // Conversions between Cocoa points and device pixels, given the backing michael@0: // scale factor from a view/window/screen. michael@0: static int32_t michael@0: CocoaPointsToDevPixels(CGFloat aPts, CGFloat aBackingScale) michael@0: { michael@0: return NSToIntRound(aPts * aBackingScale); michael@0: } michael@0: michael@0: static nsIntPoint michael@0: CocoaPointsToDevPixels(const NSPoint& aPt, CGFloat aBackingScale) michael@0: { michael@0: return nsIntPoint(NSToIntRound(aPt.x * aBackingScale), michael@0: NSToIntRound(aPt.y * aBackingScale)); michael@0: } michael@0: michael@0: static nsIntRect michael@0: CocoaPointsToDevPixels(const NSRect& aRect, CGFloat aBackingScale) michael@0: { michael@0: return nsIntRect(NSToIntRound(aRect.origin.x * aBackingScale), michael@0: NSToIntRound(aRect.origin.y * aBackingScale), michael@0: NSToIntRound(aRect.size.width * aBackingScale), michael@0: NSToIntRound(aRect.size.height * aBackingScale)); michael@0: } michael@0: michael@0: static CGFloat michael@0: DevPixelsToCocoaPoints(int32_t aPixels, CGFloat aBackingScale) michael@0: { michael@0: return (CGFloat)aPixels / aBackingScale; michael@0: } michael@0: michael@0: static NSPoint michael@0: DevPixelsToCocoaPoints(const nsIntPoint& aPt, CGFloat aBackingScale) michael@0: { michael@0: return NSMakePoint((CGFloat)aPt.x / aBackingScale, michael@0: (CGFloat)aPt.y / aBackingScale); michael@0: } michael@0: michael@0: static NSRect michael@0: DevPixelsToCocoaPoints(const nsIntRect& aRect, CGFloat aBackingScale) michael@0: { michael@0: return NSMakeRect((CGFloat)aRect.x / aBackingScale, michael@0: (CGFloat)aRect.y / aBackingScale, michael@0: (CGFloat)aRect.width / aBackingScale, michael@0: (CGFloat)aRect.height / aBackingScale); michael@0: } michael@0: michael@0: // Returns the given y coordinate, which must be in screen coordinates, michael@0: // flipped from Gecko to Cocoa or Cocoa to Gecko. michael@0: static float FlippedScreenY(float y); michael@0: michael@0: // The following functions come in "DevPix" variants that work with michael@0: // backing-store (device pixel) coordinates, as well as the original michael@0: // versions that expect coordinates in Cocoa points/CSS pixels. michael@0: // The difference becomes important in HiDPI display modes, where Cocoa michael@0: // points and backing-store pixels are no longer 1:1. michael@0: michael@0: // Gecko rects (nsRect) contain an origin (x,y) in a coordinate michael@0: // system with (0,0) in the top-left of the primary screen. Cocoa rects michael@0: // (NSRect) contain an origin (x,y) in a coordinate system with (0,0) michael@0: // in the bottom-left of the primary screen. Both nsRect and NSRect michael@0: // contain width/height info, with no difference in their use. michael@0: // This function does no scaling, so the Gecko coordinates are michael@0: // expected to be CSS pixels, which we treat as equal to Cocoa points. michael@0: static NSRect GeckoRectToCocoaRect(const nsIntRect &geckoRect); michael@0: michael@0: // Converts aGeckoRect in dev pixels to points in Cocoa coordinates michael@0: static NSRect GeckoRectToCocoaRectDevPix(const nsIntRect &aGeckoRect, michael@0: CGFloat aBackingScale); michael@0: michael@0: // See explanation for geckoRectToCocoaRect, guess what this does... michael@0: static nsIntRect CocoaRectToGeckoRect(const NSRect &cocoaRect); michael@0: michael@0: static nsIntRect CocoaRectToGeckoRectDevPix(const NSRect &aCocoaRect, michael@0: CGFloat aBackingScale); michael@0: michael@0: // Gives the location for the event in screen coordinates. Do not call this michael@0: // unless the window the event was originally targeted at is still alive! michael@0: // anEvent may be nil -- in that case the current mouse location is returned. michael@0: static NSPoint ScreenLocationForEvent(NSEvent* anEvent); michael@0: michael@0: // Determines if an event happened over a window, whether or not the event michael@0: // is for the window. Does not take window z-order into account. michael@0: static BOOL IsEventOverWindow(NSEvent* anEvent, NSWindow* aWindow); michael@0: michael@0: // Events are set up so that their coordinates refer to the window to which they michael@0: // were originally sent. If we reroute the event somewhere else, we'll have michael@0: // to get the window coordinates this way. Do not call this unless the window michael@0: // the event was originally targeted at is still alive! michael@0: static NSPoint EventLocationForWindow(NSEvent* anEvent, NSWindow* aWindow); michael@0: michael@0: static BOOL IsMomentumScrollEvent(NSEvent* aEvent); michael@0: michael@0: // Hides the Menu bar and the Dock. Multiple hide/show requests can be nested. michael@0: static void HideOSChromeOnScreen(bool aShouldHide, NSScreen* aScreen); michael@0: michael@0: static nsIWidget* GetHiddenWindowWidget(); michael@0: michael@0: static void PrepareForNativeAppModalDialog(); michael@0: static void CleanUpAfterNativeAppModalDialog(); michael@0: michael@0: // 3 utility functions to go from a frame of imgIContainer to CGImage and then to NSImage michael@0: // Convert imgIContainer -> CGImageRef, caller owns result michael@0: michael@0: /** Creates a CGImageRef from a frame contained in an imgIContainer. michael@0: Copies the pixel data from the indicated frame of the imgIContainer into a new CGImageRef. michael@0: The caller owns the CGImageRef. michael@0: @param aFrame the frame to convert michael@0: @param aResult the resulting CGImageRef michael@0: @return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise michael@0: */ michael@0: static nsresult CreateCGImageFromSurface(SourceSurface* aSurface, michael@0: CGImageRef* aResult); michael@0: michael@0: /** Creates a Cocoa NSImage from a CGImageRef. michael@0: Copies the pixel data from the CGImageRef into a new NSImage. michael@0: The caller owns the NSImage. michael@0: @param aInputImage the image to convert michael@0: @param aResult the resulting NSImage michael@0: @return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise michael@0: */ michael@0: static nsresult CreateNSImageFromCGImage(CGImageRef aInputImage, NSImage **aResult); michael@0: michael@0: /** Creates a Cocoa NSImage from a frame of an imgIContainer. michael@0: Combines the two methods above. The caller owns the NSImage. michael@0: @param aImage the image to extract a frame from michael@0: @param aWhichFrame the frame to extract (see imgIContainer FRAME_*) michael@0: @param aResult the resulting NSImage michael@0: @param scaleFactor the desired scale factor of the NSImage (2 for a retina display) michael@0: @return NS_OK if the conversion worked, NS_ERROR_FAILURE otherwise michael@0: */ michael@0: static nsresult CreateNSImageFromImageContainer(imgIContainer *aImage, uint32_t aWhichFrame, NSImage **aResult, CGFloat scaleFactor); michael@0: michael@0: /** michael@0: * Returns nsAString for aSrc. michael@0: */ michael@0: static void GetStringForNSString(const NSString *aSrc, nsAString& aDist); michael@0: michael@0: /** michael@0: * Makes NSString instance for aString. michael@0: */ michael@0: static NSString* ToNSString(const nsAString& aString); michael@0: michael@0: /** michael@0: * Returns NSRect for aGeckoRect. michael@0: * Just copies values between the two types; it does no coordinate-system michael@0: * conversion, so both rects must have the same coordinate origin/direction. michael@0: */ michael@0: static void GeckoRectToNSRect(const nsIntRect& aGeckoRect, michael@0: NSRect& aOutCocoaRect); michael@0: michael@0: /** michael@0: * Returns Gecko rect for aCocoaRect. michael@0: * Just copies values between the two types; it does no coordinate-system michael@0: * conversion, so both rects must have the same coordinate origin/direction. michael@0: */ michael@0: static void NSRectToGeckoRect(const NSRect& aCocoaRect, michael@0: nsIntRect& aOutGeckoRect); michael@0: michael@0: /** michael@0: * Makes NSEvent instance for aEventTytpe and aEvent. michael@0: */ michael@0: static NSEvent* MakeNewCocoaEventWithType(NSEventType aEventType, michael@0: NSEvent *aEvent); michael@0: michael@0: /** michael@0: * Initializes aNPCocoaEvent. michael@0: */ michael@0: static void InitNPCocoaEvent(NPCocoaEvent* aNPCocoaEvent); michael@0: michael@0: /** michael@0: * Initializes aPluginEvent for aCocoaEvent. michael@0: */ michael@0: static void InitPluginEvent(mozilla::WidgetPluginEvent &aPluginEvent, michael@0: NPCocoaEvent &aCocoaEvent); michael@0: /** michael@0: * Initializes WidgetInputEvent for aNativeEvent or aModifiers. michael@0: */ michael@0: static void InitInputEvent(mozilla::WidgetInputEvent &aInputEvent, michael@0: NSEvent* aNativeEvent); michael@0: static void InitInputEvent(mozilla::WidgetInputEvent &aInputEvent, michael@0: NSUInteger aModifiers); michael@0: michael@0: /** michael@0: * ConvertToCarbonModifier() returns carbon modifier flags for the cocoa michael@0: * modifier flags. michael@0: * NOTE: The result never includes right*Key. michael@0: */ michael@0: static UInt32 ConvertToCarbonModifier(NSUInteger aCocoaModifier); michael@0: michael@0: /** michael@0: * Whether to support HiDPI rendering. For testing purposes, to be removed michael@0: * once we're comfortable with the HiDPI behavior. michael@0: */ michael@0: static bool HiDPIEnabled(); michael@0: michael@0: /** michael@0: * Keys can optionally be bound by system or user key bindings to one or more michael@0: * commands based on selectors. This collects any such commands in the michael@0: * provided array. michael@0: */ michael@0: static void GetCommandsFromKeyEvent(NSEvent* aEvent, michael@0: nsTArray& aCommands); michael@0: michael@0: /** michael@0: * Converts the string name of a Gecko key (like "VK_HOME") to the michael@0: * corresponding Cocoa Unicode character. michael@0: */ michael@0: static uint32_t ConvertGeckoNameToMacCharCode(const nsAString& aKeyCodeName); michael@0: michael@0: /** michael@0: * Converts a Gecko key code (like NS_VK_HOME) to the corresponding Cocoa michael@0: * Unicode character. michael@0: */ michael@0: static uint32_t ConvertGeckoKeyCodeToMacCharCode(uint32_t aKeyCode); michael@0: }; michael@0: michael@0: #endif // nsCocoaUtils_h_