Re: Runloops and Window Dragging
Re: Runloops and Window Dragging
- Subject: Re: Runloops and Window Dragging
- From: Caylan Larson <email@hidden>
- Date: Sun, 06 Oct 2013 12:50:43 -0500
On Oct 2, 2013, at 2:21 PM, Ken Thomases <email@hidden> wrote:
> On Oct 2, 2013, at 1:36 PM, Caylan Larson wrote:
>
>> I am using CGWindowListCreateImage to fetch an image of the windows behind my app. This works beautifully and is OK for my needs. Except...
>>
>> I have problems when I drag the window. The goal is near real-time image updates during the drag event.
>>
>> The runloop never seems to fully display the results of my drawRect (I can log in drawRect, but the results are not displayed). I've tried operation queues, using mouseDragged, spinning off a thread on a window move notification using detachNewThreadSelector and looking for mouse up using nextEventMatchingMask --- all the while sending setNeedsDisplay:YES to the view or, heaven forbid, sending drawRect straight away (doesn't make a difference). I've made sure "Can Draw Concurrently" is checked at every level as well as the window setting for allowsConcurrentViewDrawing.
>>
>> My next step was to ditch drawRect and instead use an embedded imageView in a scrollView. In windowWillMove I stuff the whole screen's image in the imageView and then scrollPoint to the window's frame origin. This still doesn't get me real-time scrolling of the scrollView when the window is dragged.
>>
>> My hunch is that the window drag event makes the runloop run in NSEventTrackingRunLoopMode, which limits drawRect's efficacy. Any way around this condition?
>
> First, unless you call [yourWindow setMovable:NO], moves are largely handled in the window server with only occasional notifications to your app that the frame has changed. If you do call that, then you have to handle clicks and drags in the window frame by overriding -[NSWindow sendEvent:] and processing the appropriate events. It's non-trivial, but at least you have full control.
>
> Second, when the framework (or anything) runs an internal run loop, you can't rely on the windows being updated. You can try calling -displayIfNeeded and/or -flushWindow.
>
> Third, I doubt you're going to get real-time performance out of the CGWindow API. Apple recommends using the AV Foundation for that:
> Technical Q&A QA1740: How to capture screen activity to a movie file using AV Foundation on Mac OS X Lion
> https://developer.apple.com/library/mac/qa/qa1740/_index.html
>
> The AVScreenShack sample code may also be useful:
> https://developer.apple.com/library/mac/samplecode/AVScreenShack/Introduction/Intro.html
I looked at the AV Foundation docs and it seems like there is not a way to get a screenshot without my window (like kCGWindowSharingNone). There seems to be a serious problem in CGWindowListCreateImage when called too frequently.
From the user's POV, the UI freezes until I "kill -9" via SSH. The recovery looks like:
Oct 6 12:22:38 Caylans-MacBook-Pro.local WindowServer[100]: CGXDisableUpdate: UI updates were forcibly disabled by application "Xcode" for over 1.00 seconds. Server has re-enabled them.
Oct 6 12:22:38 Caylans-MacBook-Pro.local WindowServer[100]: reenable_update_for_connection: UI updates were finally reenabled by application "Xcode" after 160.03 seconds (server forcibly re-enabled them after 160.02 seconds)
Someone told me that this could be due to calls to CGXDisableUpdate without a balanced CGXEnableUpdate. What is the best way to squeeze performance out of CGWindowListCreateImage without getting hosed/throttled by WindowServer? Or is this a race condition that is beyond my reach?
Help :-)
Caylan
_______________________________________________
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