Since the SonOfGrab application works for grabbing the contents of my window, 
even when it is partially offscreen at the time of taking the screen grab I had 
a look at what it was doing differently.

Basically SonOfGrab was passing in CGRectNull into CGWindowListCreateImage 
instead of a defined rectangle. I was defining a rectangle because I wanted the 
content region of the window not the whole window. So instead I passed in 
CGRectNull and then afterwards crop the generated CGImageRef down to exclude 
the window title bar.

This now works as it should and as it does for SonOfGrab.

So now I'm going to ask about why drawing to the windows graphics context 
directly is not ok.

I'm not dealing with any views, just a window created programmatically with its 
one content view. The window cannot be
resized. In this situation I believe the issues around lock focus and the 
calling of draw rect within a view hierarchy may not apply. Are there other 
issues that will hurt me when drawing directly?

Kevin

On 18 Jun 2014, at 17:47, Kyle Sluder <k...@ksluder.com> wrote:

> On Wed, Jun 18, 2014, at 09:01 AM, Kevin Meaney wrote:
>> Drawing happens when I receive an xpc message containing a drawing
>> command. To do the drawing I get the NSGraphicsContext from which I pull
>> the graphicsPort which is a special kind of CGContext. I then use
>> CoreGraphics commands to do the drawing.
> 
> You're still not being specific enough. Where is this code happening?
> Which context is it grabbing?
> 
> If you want to draw to the screen, you send -setNeedsDisplay: to a view
> and wait for the window to come around and ask you to draw. That is the
> ONLY* way to draw to the screen in OS X.
> 
> So this is OK:
> 
> // xpc listener
> - (void)handleIncomingDrawCommand:(id)drawCommand {
>  AppendDrawCommandToQueue(drawCommand);
>  [_myView setNeedsDisplay:YES];
> }
> 
> // view
> - (void)drawRect:(NSRect)dirtyRect {
>  CGContextRef cgContext = [[NSGraphicsContext currentContext]
>  graphicsPort];
>  ApplyDrawCommandsFromQueue(cgContext);
> }
> 
> This is NOT OK:
> 
> - (void)handleIncomingDrawCommand:(id)drawCommand {
>  CGContextRef cgContext = [[NSGraphicsContext currentContext]
>  graphicsPort];
>  ImmediatelyPerformDrawCommand(drawCommand, cgContext); // NO!
> }
> 
> Depending on your application, your listener may need to maintain a
> partial or complete history of draw commands it has received so that it
> can draw them all anew in -drawRect:. If it's too expensive to redraw
> all your commands every time you get sent -drawRect:, you can maintain
> _your own_ offscreen buffer and just blit it to the screen in
> -drawRect:.
> 
> // xpc listener
> NSBitmapImageRep *_offscreenBuffer;
> - (void)handleIncomingDrawCommand:(id)drawCommand {
>  AppendDrawCommandToQueue(drawCommand); // in case we need to resize
>  and redraw the _offscreenBuffer
>  PerformQueuedDrawCommands(_offscreenBuffer);
>  [_myView setNeedsDisplay:YES];
> }
> 
> // view
> - (void)setFrameSize:(NSSize)newSize {
>  ResizeBuffer(_offscreenBuffer, newSize);
>  PerformQueuedDrawCommands(_offscreenBuffer);
>  [super setFrameSize:newSize];
> }
> 
> - (void)drawRect:(NSRect)dirtyRect {
>  [_offscreenBuffer drawAtPoint:self.bounds.origin];
> }
> 
> You can build a CGContextRef around an NSBitmapImageRep by using
> +[NSGraphicsContext graphicsContextWithBitmapImageRep:] and getting the
> result's graphicsPort.
> 
> --Kyle Sluder
> 
> * not really the only way, but the only supported way that works in all
> cases.


_______________________________________________

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

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:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Reply via email to