ScreenSaverView/NSQuickDrawView/Opaque issue [update]
ScreenSaverView/NSQuickDrawView/Opaque issue [update]
- Subject: ScreenSaverView/NSQuickDrawView/Opaque issue [update]
- From: "Andy O'Meara" <email@hidden>
- Date: Fri, 03 Jun 2005 09:17:09 -0400
I was hoping to get some bites on my help request from a few days ago
(appended below), but nothing thus far. After several additional hours of
experimentation, guessing, and checking I've made some progress (I thought I
left this kind of workflow behind with Windows programming, but I guess
not).
So that folks like me may benefit, I wanted to share my root
issues/mysteries (and this doesn't just apply to screen savers--if you use
NSQuickDrawView, this is also for you). I apologize in advance if some of
there are novice Cocoa comments/mysteries... If anyone can shed some light
on the following issues, I'd be very grateful.
- Is there anyway to have an NSQuickDrawView *not* erase the entire pane
rect each drawRect? My child class of NSQuickDrawView overrides drawRect()
and I do a CopyBits to the view's qdPort during that. Apparently, unless I
CopyBits over the entire pane rect, the part I don't copy over is black (vs.
going unchanged from whatever was there). For example, my visual engine
blts a splash frame and then does no drawing for the following couple frames
while it bootstraps, so what's seen is an initial flash of my splash
followed by a couple seconds of blackness, followed by normal output. So,
again, is there any way to have an NSQuickDrawView *not* erase the entire
pane rect each draw? I don't think it's very impressive that the
documentation page for NSQuickDrawView consists of a total of three
sentences.
- Suppose you put your child class of NSQuickDrawView inside a NSView (or
ScreenSaverView in my case). If you override your NSQuickDrawView's
isOpaque to return YES, drawRect() never gets called (in my case, triggered
from calling setNeedsDisplay from my ScreenSaverView's animateOneFrame()).
Sure, the NSQuickDrawView will get drawRect() following window layer changes
and obscures, but setNeedsDisplay won't cause a redraw weather I send it to
the parent view of my NSQuickDrawView or the NSQuickDrawView itself. This
one baffles me.
- Overriding my ScreenSaverView's drawRect() proc, surprisingly causes the
setNeedsDisplay calls (made from animateOneFrame) to no longer trigger
drawRect() calls to my NSQuickDrawView. In other words, NSView's drawRect()
appears do more than just draw a black rect--it appears to draw its subviews
as well. However, since there's no NSView implementation to look at, I'm
all of sudden a little helpless to mimic NSView's drawRect (but without a
black rect). So, it would be nice to have access Apple's implementation of
NSView to see what goes in certain NSView calls by default. Back when
Metrowerks CodeWarrior was the big kid on the block for serious Mac OS app
development, there was no better way to learn Classic/Carbon Mac OS *and*
PowerPlant than by looking at how PowerPlant implemented its core classes.
That said, can the the core AppKit implementations be found anywhere? -- I'd
take that over the one-sentence descriptions found in Apple's Reference any
day of the week...
Thanks in advance for any assistance...
Andy
------ Previous Message ------
From: Andy O'Meara <email@hidden>
Date: Tue, 31 May 2005 21:12:06 -0400
To: Cocoa-Dev Mail <email@hidden>
Subject: ScreenSaverView/Opaque/Update issue
I've already searched the archives and spent a long time on this, so I'm
really hoping someone has some insight on this seemingly simple
ScreenSaverView issue...
I currently create each output frame in an off-screen GWorld, and when tone
is done, I call CopyBits() to a NSQuickDrawView that's inside my
ScreenSaverView. This is very similar to the method used in Apple's
"MungSaver".
So everything is working well with my ScreenSaverView, with the exception of
a nasty flicker that happens after the first frame is drawn... After
investigating, it seems that that since NSView::isOpaque returns NO by
default, the "Desktop & Screen Saver" window went to draw the superview
before drawing the frame (accounting for the nasty initial flicker). No
problem, I say, I'll just override isOpaque to return YES... The good news
is that the initial flicker is of course gone, but the baffling issue is
that now new frames only seem to appear when the host window changes layers
or needs to get refreshed. Otherwise, the frame is never updated. My logs
clearly show that *both* animateOneFrame and drawRect are firing, yet the
the ScreenSaverView rect is only ever visibly updated when I activate any
window in the OS. It's as if the window store wasn't getting flushed to
screen despite the fact setNeedsDisplay is set to YES (keep in mind:
changing isOpaque() to always return NO makes this problem go away with no
other changes to the code).
I've already tried things like putting a shotgun of lockFocus and
unlockFocus calls everywhere, and sticking in flush and update calls, but no
go. Below are the relevant snippets...
Thanks in advance,
Andy
- (id)initWithFrame:(NSRect)frame isPreview:(BOOL)isPreview
{
...
// Make the NSQuickDrawView
mQDView = [[NSQuickDrawView alloc] initWithFrame:NSZeroRect];
// make sure the subview resizes
[ self setAutoresizesSubviews:YES ];
[ self addSubview:mQDView ];
[ mQDView release ];
...
}
- (void)startAnimation
{
[super startAnimation];
...
// the first time lockFocus is called on the NSQuickDrawView
// it creates a valid qdPort - we need this to draw into and
// before this is done, qdPort is NULL
if ( [mQDView qdPort] == NULL ) {
[mQDView lockFocus];
[mQDView unlockFocus];
}
...
}
- (void)animateOneFrame
{
[self setNeedsDisplay: YES];
}
- (void)drawRect:(NSRect)rect
{
...
CopyBits( ... , [mQDView qdPort], ... );
...
}
// end snippets
------ End of Forwarded Message
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden