Retinafying my app

I’m trying to finish the retinafication (that’s a word, right?) process of one of my apps. I am having trouble with the NSStatusItem menu and its icon and how to make it retinafied. I used macoslib for the NSStatusItem. I have emailed Sam at Ohanaware regarding Retina Kit to see if that would help. In the meantime, has anyone done this successfully?

I would imagine that it could, but I would also imagine that you would be able to do this by just using the functions in the MacOSLib.

The function you’re looking for is.

- (void)setImage:(NSImage *)image

You need to pass it a NSImage, which you can get either from using the RetinaKit HIDPIPicture.NSImage or by using the NSImage functions in the MacOSLib.

The key is to create the two images in your resources folder

icon.png icon@2x.png

with the @2x version being twice the size and resolution of the regular.

When you load the NSImage, you need to use the imageNamed function and the OS will then load the correct instance when it’s required.

If your image is dynamically created in code, then there are functions in the RetinaKit that will help you to convert a pair of Xojo pictures into a NSImage capable for Retina display.

Thanks very much for the replies Sam. Don’t I need to check for the BackingScaleFactor property? I know Xcode will automatically load the retina images but I assumed here that I needed to check If BackingScaleFactor = 2 Then load in the retina image.

Frustratingly, I’m on a little road trip now until next week and only have my 11" Air with me so can’t do HiDPI to test but grateful for any further clarification.

#1 You shouldn’t check that property, it’s actually been depreciated with 10.7.

#2 By using NSImage (which is the correct way of handling Retina images), the OS will handle which representation to display and when. The RetinaKit is built around using NSImage. All you need to do is to make sure that A) You have the images (using the split png is the easiest way and uses less disk space) and B) you use NSImage and the correct APIs for utilizing them.

The thing to remember is that everything done in a Obj-C application made with Xcode, uses the same Cocoa framework as Xojo. Almost everything that can be done in Xcode can be done in Xojo. Somethings require more work than others. To solve the Sandboxing issues I had, I spent weeks pulling apart an Xcode application and probing Apple engineers until I found the right APIs that a Obj-C application uses and then translated them into Xojo code (With modifications here and there).

Great info, thanks Sam. Think I was overcomplicating it. Will try it out when I get back to the office iMac.

I’m using a Retina-ready Statusitem in iClip.

I solved it using NSStatusItemMBS, and loading the fitting image depending on the screen resolution, then creating an NSImage via NSBitmapImageRepMBS.

Basically, I think, the solution is to provide the image(s) as a NSImage.

Is BackingScaleFactor a property? I always thought of it as a function that returns 1 on normal displays, 2 on Retina.

Maybe I’m mixing something up, but BackingScaleFactor was INTRODUCED with 10.7 and does not exist in MacOS X systems before Lion as no Mac till then had a Retina display. So older systems don’t have the required functions in their OS which causes a nasty crash if you use the function without testing for its existence first.

Function ScalingFactor(Extends w As Window) As Single #If TargetCocoa Then If System.IsFunctionAvailable("BackingScaleFactor", "AppKit") Then Declare Function BackingScaleFactor Lib "AppKit" Selector "backingScaleFactor" (Target As WindowPtr) As Double Return BackingScaleFactor( w ) End If #Endif Return 1 // in all non-Cocoa cases return 1 End Function

Markus, you are quite correct. It is userSpaceScaleFactor that was depreciated in 10.7 and replaced by backingScale.

Apple do advise to not use this function directly and instead use the convertRect functions instead.

One thing you should avoid is caching the value of any of these mechanisms, when you need to always re-evaluate. Otherwise your app will not enable Retina when moved across screens or in response to resolution changes.

Ideally you want to get your application into a position where you don’t need to worry about Retina and just let the OS handle it for you.