Cocoa: Getting the "top/left" logical point of multiple screens - macos

I have 3 External screens on my MBP Retina 15" - Using Preferences/Displays to "arrange" the monitors in a way that mimics how they're arranged in real life.
I have a small mouse position printing utility I got off of the app store. as the mouse travels, it prints the logical location of it-- and it seems to be compatible with the display arrangement.
My task is to write a program that'll enumerate them, and output the logical (top/left) coordinates of each monitor. so that those match the output of that mouse position printing utility when it's at the top/left corner. (that utility already flips the Y-coordinate) so my primary display monitor is 0,0 on the top/left corner.
I am using NSScreen's frame quite successfully, but no matter what I do, i cannot convert the Y axis output (origin.y) to top to bottom instead of cocoa's bottom to top.
How do I flip the frame NSRect on each screen such that the display arrangement is still respected?

To get the screen frames in Quartz coordinates, you can use the Quartz Display Services API:
for(NSScreen* screen in [NSScreen screens])
{
NSRect cocoaScreenFrame = [screen frame];
CGDirectDisplayID displayID = [[screen deviceDescription][#"NSScreenNumber"] unsignedIntValue];
CGRect quartzScreenFrame = CGDisplayBounds(displayID);
NSLog(#"Screen frame in Cocoa coordinate space: %#", NSStringFromRect(cocoaScreenFrame));
NSLog(#"Screen frame in Quartz coordinate space:%#", NSStringFromRect(quartzScreenFrame));
}
If you need to convert arbitrary points or rects (e.g. mouse locations or window frames) to that coordinate space, you can take a look at this answer: In Objective-C (OS X), is the "global display" coordinate space used by Quartz Display Services the same as Cocoa's "screen" coordinate space?

Related

How to adapt Xib views and buttons to fit all devices using Auto layout and contraints

I'm going to show you an image that contains my first UIViewController presented in Interface Builder (using the 600x600 Any/Any View).
MainViewController
For now, just look at the UIButton with the C label and the Play button. I added Align center x to: horizontal constraints to both. When I preview what I have (forgetting about the other views and buttons you see), the 2 buttons are centered properly. However, when I switch different device sizes, they do not change size...which makes sense.
What I want is for a way to make those 2 buttons stay proportionally circular and centered on the superview, but adapt their size and Y-position depending on the device size. What constraints would I need to attach in order for that to work? I don't want the buttons to be stuck in the spots you see in the image, I want them to adapt to the device size.
To talk about this further. The game 'Color Switch' does not appear to use constraints in terms of having any view/image/button/label constrained to a certain y or x position. Going from a 5c to a 6s, it's like looking at a blown up version of the game. The buttons and title label at the top are not constrained to the same y position on each device.
You could create constraints to center the buttons to the top-level view and then make their width proportional to the view width. Then on a larger screen, the buttons will be larger and on a smaller screen, they will be smaller.

DS_ABSALIGN style to avoid calculations

I have a tablet with a stylus, in normal operation it's easy to draw and figure out where the stylus is since hardware feeds the correct coordinates. Then i rotate the monitor 90 ยบ via ChangeDisplaySettingsEx API, in this situation i have to apply a translation (2nd monitor) + rotation which i'd like to avoid. Then i read about this style DS_ABSALIGN in MSDN:
Indicates that the coordinates of the dialog box are screen
coordinates. If this style is not specified, the coordinates are
client coordinates.
I'd like to draw to a DC in screen coordinates which is what i'm being feeded, not client coordinates, but defining that style doesn't make any difference.
//unaffected by the style
DrawIcon(hDevCtx, m_Point.x, m_Point.y, LoadCursor(NULL, IDC_ARROW));
Is it there any way to draw an icon in screen coordinates?
edit: finally i had no choice but to do the calculations for every turn so i close the question
The coordinates you pass to DrawIcon() depend on the kind of DC you have. For example let's say you used GetDC() to get the DC. If you pass it a window handle, the coordinates you pass to DrawIcon() will be relative to the client area of that window. If you pass 0 to GetDC() the coordinates will be relative to desktop screen. If you want to draw on desktop screen then use GetDC(0) or a better method if there is one. If you just want to convert screen coordinates to client coordinates or vice versa use ScreenToClient() or ClientToScreen()

how to draw rect over screen on OS X?

I want draw rectangle over current screen on OS X like rectangle from Grab app when user select area to capture.
Could anybody give me advice about how I can do this?
The way I would do this it to, create your own custom window, you can then give it a transparent background and a border representing your selection rectangle. Do a google search for customer window Cocoa, or irregular shape window cocoa and you will find lots of examples.

About cutting of / cropping a uiview

so i have a uiview that is initialized with a frame that has the height and width that is present for the user, i want the user to be able to draw inside this frame but when the user presses a button, i want the view to cut off that extra wasted space so that the frame is only as big as what the user was drawing. I tried to do something like this
CGRect boundbox = CGPathGetBoundingBox([myPath CGPath]);
boundbox.origin.x = self.frame.origin.x;
boundbox.origin.y = self.frame.origin.y;
self.frame = boundbox;
However, this does not remove that extra wasted space, it only resizes the view, so that the drawn content looks smaller than previously. What i would like to do instead is to remove
that "whitespace", i was thinking if it could be possible to scale up the content of the uiview, but im not sure.
To clarify what i mean:
The red border is the area / frame that the user can draw on, the text in the middle is a drawing, when the user presses a button, i want the frame to only encircle the drawing like in figure 2.
Now lets say i have the following scenario, i have drawn a circle on the middle of the screen.
When i then press the button, the scale remains the same but the circle is still in the same position but we have now changed the draw area, so the circle / drawing will look like its cut off like in figure 4.
What i want to do is to move the drawing / bezier path so that it is positioned in the middle of the frame. So that the red area encircles the blue circle.
[EDIT]
Given your drawings. A UIView will not re-position items in it when you change it's frame property (or it's CGRect). In this case you will need to track the items drawn YOURSELF, and then when the button is pressed perform the object translations yourself.
What that means is you will have to find the object that is left most, the object that is topmost, then move all objects left by that amount, and up by that amount so that all objects are (as a grouping) top-left aligned within the view's frame. After this you will need to self recognize which object is the right most touching and which object is the bottom most touching.
NOW, since you have already moved the items left-top, the right most point will define your frame width, and the bottom most point will define your frame height.
IF YOU SO DESIRE, you should be able to zoom in using the properties below after you have done this.
[First Answer]
If I understand your question correctly, you may want to still perform your box frame manipulation, but if you wish to scale you may want to look into the
contentScaleFactor or
contentStretch
properties.
contentScaleFactor should scale both dimensions based upon a singular floating point value (i.e. xWidth * scaleFactor, yHeight * scale factor).
contentStretch is a CGRect which means that it should scale each dimension (axis) separately.

Cocoa / CoreGraphics / Quartz - borderless Quicktime X like window with rounded edges

I am developing a document based application for Mac OS X. It's a kind of media player, but instead of playing audio or video files it is supposed to open text-files containing meta-data specifying OpenGL animations. I would like to mimic Apples QuickTime X window style. This means, i have to do all the window drawings myself, because Cocoa has no appropriate window style.
There is one thing which gives me headaches: The rounded corners usually to be found on Mac OS X windows. I tried using the borderless window mask and working some CGS magic - there are some private Apple headers which allow window shaping, but they are of course undocumented. I was able to cut rectangular holes in my windows edges, but i couldn't figure out how Apple achieves rounded corners.
Creating a transparent window and drawing the frame myself does not work, because an OpenGL viewport is always rectangular, and the only way to change it is to turn on NSOpenGLCPSurfaceOpacity for alpha transparency and using the stencil buffer or shaders to cut out the edges, which seems like a hell of a lot of overhead.
If i put an OpenGLView into a standard Cocoa window with titlebar, the bottom edges are rounded. It seems this is happening at the NSThemeFrame stage of the view hierarchy. Any ideas how this is done?
Use a layer-backed view, and do your drawing in the CALayer on an invisible window. Layers include automatic handling of rounded corners and borders.
Background for CALayer is in the Core Animation Programming Guide. To create a layer for NSView, you need to call [view setWantsLayer:YES]. You would create a CAOpenGLLayer and assign it to the view using setLayer:.
See CALayerEssentials for sample code demonstrating how to use CAOpenGLLayer among other layer types.
Since Robs suggestion didn't work and no one else contributed to the discussion i settled on using the stencil buffer to crop the windows corners. I did this by creating a texture from the windows background and rendering it into the stencil buffer, discarding all transparent pixels. Looks fine, but is slow when resizing the window :/

Resources