Retina Mac

Can somebody tell me the code to determine a retina screen?

Thanks.

Simon.

Simon,
does this help?

link text

I personally prefer to use Sam’s Retina Kit - it’s so easy to display either a standard image, or the retina image using that.

I do own RetinaKit and I use this in my commercial apps.

The thread is helpful, though. I have studied Sam’s code extensively but I was a little lost.

Simon.

Normally you check if your window has a back scale factor of 2 or more.
E.g. With MBS plugin using window.BackingScaleFactorMBS as double

http://monkeybreadsoftware.net/window-window-method.shtml#4

  #If TargetCocoa Then
    Try
      Soft Declare Function BackingScaleFactor Lib "AppKit" Selector "backingScaleFactor" (target As WindowPtr) As Double
      Return BackingScaleFactor(Self)
    Catch e As ObjCException
      Return 1
    End Try
  #Else
    Return 1
  #Endif

Thank you, Christian and Dave.

If you do a Google search on BackingScaleFactor there are posts that state that you should NOT use this function. But, as far as I can tell, this is only because it should be checked frequently as you may move the window from a retina screen to a non-retina screen and it will get messed up. As long as I check after every move or resize then I don’t see a problem.

Am I right?

Simon.

[quote=194451:@Simon Berridge]Thank you, Christian and Dave.

If you do a Google search on BackingScaleFactor there are posts that state that you should NOT use this function. But, as far as I can tell, this is only because it should be checked frequently as you may move the window from a retina screen to a non-retina screen and it will get messed up. As long as I check after every move or resize then I don’t see a problem.

Am I right?

Simon.[/quote]

You could also check in app.activate since the other way the screen can change scale is in the Preferences.

Thank you, Michel.

If I understand correctly I should check on App.Activate and in the Resizing and/or Resized events in the windows that use the call.

S.

Activate and Resizing are NOT called if the window is simply MOVED
what do you do if you move the window from a RETINA screen to a NON-Retina screen (multi-monitor environment)
or worse. 1/2 the window is on one monitor and the other 1/2 on another

[quote=194455:@Dave S]Activate and Resizing are NOT called if the window is simply MOVED
what do you do if you move the window from a RETINA screen to a NON-Retina screen (multi-monitor environment)
or worse. 1/2 the window is on one monitor and the other 1/2 on another[/quote]
That is the issue, Dave.

So, the question is, what event (if any) is called when the window is moved? I don’t think there is one…

However, surely the various Paint events are fired when a window is moved? If my retina call is in the Paint method then won’t this work?

if not, does that mean that I should have a timer running all the time? No, that can’t be right…

you could keep track of “last_scale”, and in the paint event check if scale changed

but that doesn’t solve the 1/2 and 1/2 issue

You can register for a system notification NSWindowDidChangeBackingPropertiesNotification so you’re not constantly checking…

Paint is not necessarily called when the window moves, but it will fire when moving to a different resolution screen or when the current screen changes resolution, and checking in the paint event should work (but might not be 100% guaranteed).

[quote=194454:@Simon Berridge]Thank you, Michel.

If I understand correctly I should check on App.Activate and in the Resizing and/or Resized events in the windows that use the call.

S.[/quote]

Cases where you can go from normal to Retina :

  • If the scale is changed in Preferences : check in activate
  • If the window is moved from a normal screen to a Retina one or the opposite in a multiscreen setup : check in Moved
  • Unknown : make sure in Paint.

As Dave pointed out, when the window is in between, how do you decide where it stands ? I believe the lower denominator should be picked. A window drawn for a standard screen will display on Retina (albeit kind of blurry), the opposite won’t.

[quote=194505:@Michel Bujardet]As Dave pointed out, when the window is in between, how do you decide where it stands ? I believe the lower denominator should be picked. A window drawn for a standard screen will display on Retina (albeit kind of blurry), the opposite won’t.

[/quote]
A quick test shows that a window cannot be in between different resolution screens. The system seems to decide which screen has most of the window and doesn’t draw the part on the other screen. (tested on 10.10.3)

is this just “Retina” vs “Non-Retina” or as you stated “different resolutions”

I have a 27" iMac (2560x1440) with two 19" monitors (1280x1024) running 10.10.3 and the windows flow from one to the other just fine… Now this is all NON-RETINA

Sorry should have been more explicit. I was using resolution to mean having different backingScales. So yes. Retina vs non-retina.

Thank you all.

So, it seems to me that I should be checking in the Paint event every time. I use Sam’s RetinaKit but this was just an exercise in learning for me so it was non-urgent anyway.

Interesting conversation, thanks.

Simon.

The question is why do you want to know? In theory if you’re doing it correctly, you don’t need to know the backing scale.

Sam,

I use your RetinaKit so the question I originally posed was basically mute anyway.

It comes from a simple interrogation of your code in the RetinaKit where I wanted to see where you actually determined which bitmap to use (regular or @2x). I couldn’t find the code as I am not a ‘real’ Mac person but a hobbyist and, so, I don’t understand the declares. This thread has told me that the actual work is done under the hood by the OS. However, that made me think about loading general images and how I would tell if I was on a Retina screen or not in general - hence the question.

You made an interesting statement - “In theory if you’re doing it correctly,”. I actually don’t know what “doing it correctly” means!

Simon.

I see…

Sorry for not being so clear, and re-reading my post last night, it actually comes across as a little arrogant and I’m sorry for that.

In theory/concept, handling Retina correctly, actually means not worrying about it and letting the OS deal with it. For instance, the Retina Kit never actually loads an image (1x or 2x) it asks the OS to create a image object that can have multiple representations of the same image (1x, 2x and at some point 3x). The OS doesn’t decode the image until it actually needs to be drawn to screen (or other places), at that point the OS checks to see which version of the image it needs, decodes it, displays it (whilst caching it). If your window changes screen, the OS will automatically re-evaluate which representation is required and utilize that instead.

So when you’re using the correct functions (which the Retina Kit does), all you need to worry about is that you have the right representations on disk (and in your resources folder).

When it comes to drawing lines and shapes, as long as you draw directly to the canvas (not to an image and then the canvas), the OS will automatically scale the drawings for you.

I’m on the wrong machine at the moment, so I don’t have the Retina Kit Source code to hand, but there is one function where Xojo and the OS don’t communicate very well and I had to manually intervene. At that point I needed to know what the best representation was, 1x, 2x or 3x. The correct way to figure this out is to say to the OS, I want to draw an image, at this size and the OS will then tell you what the source size needs to be. i.e. 100 x 100 on a Retina MacBook is 200 x 200.

I hope that this makes sense.