HiDPI retina issue with multi-screen overlay window and Core Animation
HiDPI retina issue with multi-screen overlay window and Core Animation
- Subject: HiDPI retina issue with multi-screen overlay window and Core Animation
- From: "William J. Cheeseman" <email@hidden>
- Date: Sat, 12 Jan 2013 09:08:45 -0500
My Pointer Noodge application displays an animated image surrounding the mouse pointer using a layer-hosting multi-screen view: <http://pfiddlesoft.com/pfiddles>. I am having difficulty upgrading it to handle a mix of retina and non-retina displays. All help appreciated.
The specific problem is that the image surrounding the pointer appears highly pixellated when the pointer moves onto a HiDPI screen. I can see that the correct @2x image has been loaded into the layer's contents, and it appears at the correct size on the HiDPI screen, but it is pixellated.
My implementation creates a borderless transparent overlay window more or less on the model of Apple's FunkyOverlayWindow sample code. The overlay window encompasses all attached screens (which I suspect is the problem; see below). The overlay window's content view is a layer-hosting view. The animated image is implemented using CALayer, which handles all the drawing.
The image surrounding the pointer is an NSImage object containing two image representations, created as a TIFF file by Xcode from a normal and a @2x PNG image file. I have examined the combined TIFF image file in the built application, and it looks correct when opened in Preview. In fact, I can drag the Preview window onto the HiDPI screen and it looks correct -- no pixellation appears in the HiDPI image representation.
The documentation says that an NSImage-based layer will automatically choose the image representation with the correct scale in most situations, but, not surprisingly, this is apparently not one of those situations.
In an attempt to force the CALayer object to draw the correct image representation, I have written a simple routine using NSTrackingArea to detect when the pointer enters a new screen. My implementation of the -[NSResponder mouseEntered:] method is called every time the pointer enters a new screen, and an NSLog() call shows the screen's backingScaleFactor as 2.0 or 1.0 depending on whether it is a retina display screen or not. Another NSLog() call shows that the image contains the two image representations, as expected. I then try a variety of techniques to display the correct representation, but I always see a pixellated image. The simplest technique detects the backingScaleFactor of the newly-entered screen, creates a copy of the NSImage object, removes the representation with the wrong scale, and sets the layer's contents to the resulting NSImage object. An NSLog() call confirms that the layer's contents are the single image representation with the correct scale. But it is drawn pixellated. Setting the contentsScale of the overlay window's contentView to the backingScaleFactor of the screen does not help. Doing the same thing by setting the view to be the layer's delegate and triggering the -displayLayer: delegate method by sending the -setNeedsDisplay message to the layer when the pointer enters a new screen has the same problem.
My best guess is that the problem results from the fact that the overlay window spans all attached screens. An NSLog() call confirms that the window's backingScaleFactor is always 1.0 (because it is initially created on a non-retina display in my testing). There is no NSWindow method to -setBackingScaleFactor, so there appears to be nothing I can do about this. Reading the documentation about CALayer and HiDPI screens very, very carefully, I notice that it always assumes that the layer-hosting view is in a window that is being dragged across screen boundaries. Am I correct in guessing that a fixed multi-screen window simply isn't capable of displaying HiDPI images if the window started out with a backingScaleFactor of 1.0?
If that's correct, I guess I'll have to abandon my multi-screen overlay window and implement a multi-overlay-window solution, which is going to be a ton of work. Unless somebody can suggest a different approach using a multi-screen overlay window.
--
Bill Cheeseman - email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden