+2007-12-10 Adele Peterson <adele@apple.com>
+
+ Reviewed and partially fixed by Tim Hatcher.
+
+ Remaining part of fix for <rdar://problem/5633400>
+ Transformed <video> is not clipped correctly until a repaint is forced
+
+ Replace the implementation of a QTKit method to avoid repaints from the NSView system associated with the QTMovie
+ from clobbering the WebCore repaints.
+
+ * html/HTMLMediaElement.cpp: (WebCore::HTMLMediaElement::mediaPlayerRepaint): Added.
+ * html/HTMLMediaElement.h:
+ * platform/graphics/MediaPlayer.cpp: (WebCore::MediaPlayer::repaint): Added.
+ * platform/graphics/MediaPlayer.h: (WebCore::MediaPlayerClient::mediaPlayerRepaint): Added.
+
+ * platform/graphics/mac/MediaPlayerPrivateQTKit.h:
+ * platform/graphics/mac/MediaPlayerPrivateQTKit.mm:
+ (method_setImplementation): Added for Tiger.
+
+ (WebCore::MediaPlayerPrivate::~MediaPlayerPrivate): Call detachQTMovieView, which now does more cleanup.
+ (WebCore::MediaPlayerPrivate::cancelLoad): ditto.
+ (WebCore::MediaPlayerPrivate::setVisible): ditto.
+ (WebCore::MediaPlayerPrivate::detachQTMovieView): Clear the delegate as well as m_qtMovieView pointer.
+
+ (WebCore::MediaPlayerPrivate::repaint): Added. Triggers a repaint on the video renderer.
+ (-[WebCoreMovieObserver repaint]): ditto.
+
+ (WebCore::mainThreadSetNeedsDisplay): Added.
+ Does a WebCore repaint instead of going through the view repaint system for QTMovieView.
+ (WebCore::MediaPlayerPrivate::createQTMovieView): Replace the implementation of _mainThreadSetNeedsDisplay.
+
2007-12-10 Geoffrey Garen <ggaren@apple.com>
Reviewed by Sam Weinig.
#import <QTKit/QTKit.h>
#import <objc/objc-runtime.h>
+#ifdef BUILDING_ON_TIGER
+static IMP method_setImplementation(Method m, IMP imp)
+{
+ IMP result = m->method_imp;
+ m->method_imp = imp;
+ return result;
+}
+#endif
+
SOFT_LINK_FRAMEWORK(QTKit)
SOFT_LINK(QTKit, QTMakeTime, QTTime, (long long timeValue, long timeScale), (timeValue, timeScale))
}
-(id)initWithCallback:(MediaPlayerPrivate*)callback;
-(void)disconnect;
+-(void)repaint;
-(void)setDelayCallbacks:(BOOL)shouldDelay;
-(void)loadStateChanged:(NSNotification *)notification;
-(void)rateChanged:(NSNotification *)notification;
MediaPlayerPrivate::~MediaPlayerPrivate()
{
- if (m_qtMovieView)
- [m_qtMovieView.get() removeFromSuperview];
+ detachQTMovieView();
+
[[NSNotificationCenter defaultCenter] removeObserver:m_objcObserver.get()];
[m_objcObserver.get() disconnect];
}
object:m_qtMovie.get()];
}
+static void mainThreadSetNeedsDisplay(id self, SEL _cmd)
+{
+ id movieView = [self superview];
+ ASSERT(!movieView || [movieView isKindOfClass:[QTMovieView class]]);
+ if (!movieView || ![movieView isKindOfClass:[QTMovieView class]])
+ return;
+
+ WebCoreMovieObserver* delegate = [movieView delegate];
+ ASSERT(!delegate || [delegate isKindOfClass:[WebCoreMovieObserver class]]);
+ if (!delegate || ![delegate isKindOfClass:[WebCoreMovieObserver class]])
+ return;
+
+ [delegate repaint];
+}
+
void MediaPlayerPrivate::createQTMovieView()
{
- if (m_qtMovieView) {
- [m_qtMovieView.get() removeFromSuperview];
- m_qtMovieView = nil;
- }
+ detachQTMovieView();
+
if (!m_player->m_parentWidget || !m_qtMovie)
return;
+
+ static bool addedCustomMethods = false;
+ if (!addedCustomMethods) {
+ Class QTMovieContentViewClass = NSClassFromString(@"QTMovieContentView");
+ ASSERT(QTMovieContentViewClass);
+
+ Method mainThreadSetNeedsDisplayMethod = class_getInstanceMethod(QTMovieContentViewClass, @selector(_mainThreadSetNeedsDisplay));
+ ASSERT(mainThreadSetNeedsDisplayMethod);
+
+ method_setImplementation(mainThreadSetNeedsDisplayMethod, reinterpret_cast<IMP>(mainThreadSetNeedsDisplay));
+ addedCustomMethods = true;
+ }
+
m_qtMovieView.adoptNS([[QTMovieView alloc] initWithFrame:m_player->rect()]);
NSView* parentView = static_cast<ScrollView*>(m_player->m_parentWidget)->getDocumentView();
[parentView addSubview:m_qtMovieView.get()];
+ [m_qtMovieView.get() setDelegate:m_objcObserver.get()];
[m_qtMovieView.get() setMovie:m_qtMovie.get()];
[m_qtMovieView.get() setControllerVisible:NO];
[m_qtMovieView.get() setPreservesAspectRatio:YES];
wkQTMovieViewSetDrawSynchronously(m_qtMovieView.get(), YES);
}
+void MediaPlayerPrivate::detachQTMovieView()
+{
+ if (m_qtMovieView) {
+ [m_qtMovieView.get() setDelegate:nil];
+ [m_qtMovieView.get() removeFromSuperview];
+ m_qtMovieView = nil;
+ }
+}
+
QTTime MediaPlayerPrivate::createQTTime(float time) const
{
if (!m_qtMovie)
if (m_networkState < MediaPlayer::Loading || m_networkState == MediaPlayer::Loaded)
return;
- if (m_qtMovieView) {
- [m_qtMovieView.get() removeFromSuperview];
- m_qtMovieView = nil;
- }
+ detachQTMovieView();
m_qtMovie = nil;
updateStates();
{
if (b)
createQTMovieView();
- else if (m_qtMovieView) {
- [m_qtMovieView.get() removeFromSuperview];
- m_qtMovieView = nil;
- }
+ else
+ detachQTMovieView();
+}
+
+void MediaPlayerPrivate::repaint()
+{
+ m_player->repaint();
}
void MediaPlayerPrivate::paint(GraphicsContext* context, const IntRect& r)
m_callback = 0;
}
+-(void)repaint
+{
+ if (m_delayCallbacks)
+ [self performSelector:_cmd withObject:nil afterDelay:0.];
+ else if (m_callback)
+ m_callback->repaint();
+}
+
- (void)loadStateChanged:(NSNotification *)notification
{
if (m_delayCallbacks)