📄 webnetscapepluginview.mm
字号:
/* * Copyright (C) 2005, 2006, 2007 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of * its contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */#if ENABLE(NETSCAPE_PLUGIN_API)#import "WebNetscapePluginView.h"#import "WebDataSourceInternal.h"#import "WebDefaultUIDelegate.h"#import "WebFrameInternal.h" #import "WebFrameView.h"#import "WebGraphicsExtras.h"#import "WebKitErrorsPrivate.h"#import "WebKitLogging.h"#import "WebKitNSStringExtras.h"#import "WebKitSystemInterface.h"#import "WebNSDataExtras.h"#import "WebNSDictionaryExtras.h"#import "WebNSObjectExtras.h"#import "WebNSURLExtras.h"#import "WebNSURLRequestExtras.h"#import "WebNSViewExtras.h"#import "WebNetscapePluginPackage.h"#import "WebBaseNetscapePluginStream.h"#import "WebNetscapePluginEventHandler.h"#import "WebNullPluginView.h"#import "WebPreferences.h"#import "WebPluginRequest.h"#import "WebViewInternal.h"#import "WebUIDelegatePrivate.h"#import <Carbon/Carbon.h>#import <runtime/JSLock.h>#import <WebCore/npruntime_impl.h>#import <WebCore/DocumentLoader.h>#import <WebCore/Element.h>#import <WebCore/Frame.h> #import <WebCore/FrameLoader.h> #import <WebCore/FrameTree.h>#import <WebCore/HTMLPlugInElement.h>#import <WebCore/Page.h> #import <WebCore/PluginMainThreadScheduler.h>#import <WebCore/ScriptController.h>#import <WebCore/SoftLinking.h> #import <WebCore/WebCoreObjCExtras.h>#import <WebKit/nptextinput.h>#import <WebKit/DOMPrivate.h>#import <WebKit/WebUIDelegate.h>#import <runtime/InitializeThreading.h>#import <wtf/Assertions.h>#import <objc/objc-runtime.h>using std::max;#define LoginWindowDidSwitchFromUserNotification @"WebLoginWindowDidSwitchFromUserNotification"#define LoginWindowDidSwitchToUserNotification @"WebLoginWindowDidSwitchToUserNotification"using namespace WebCore;static inline bool isDrawingModelQuickDraw(NPDrawingModel drawingModel){#ifndef NP_NO_QUICKDRAW return drawingModel == NPDrawingModelQuickDraw;#else return false;#endif};@interface WebNetscapePluginView (Internal)- (NPError)_createPlugin;- (void)_destroyPlugin;- (NSBitmapImageRep *)_printedPluginBitmap;- (void)_redeliverStream;- (BOOL)_shouldCancelSrcStream;@endstatic WebNetscapePluginView *currentPluginView = nil;typedef struct OpaquePortState* PortState;static const double ThrottledTimerInterval = 0.25;class PluginTimer : public TimerBase {public: typedef void (*TimerFunc)(NPP npp, uint32 timerID); PluginTimer(NPP npp, uint32 timerID, uint32 interval, NPBool repeat, TimerFunc timerFunc) : m_npp(npp) , m_timerID(timerID) , m_interval(interval) , m_repeat(repeat) , m_timerFunc(timerFunc) { } void start(bool throttle) { ASSERT(!isActive()); double timeInterval = m_interval / 1000.0; if (throttle) timeInterval = max(timeInterval, ThrottledTimerInterval); if (m_repeat) startRepeating(timeInterval); else startOneShot(timeInterval); }private: virtual void fired() { m_timerFunc(m_npp, m_timerID); if (!m_repeat) delete this; } NPP m_npp; uint32 m_timerID; uint32 m_interval; NPBool m_repeat; TimerFunc m_timerFunc;};#ifndef NP_NO_QUICKDRAW// QuickDraw is not available in 64-bittypedef struct { GrafPtr oldPort; GDHandle oldDevice; Point oldOrigin; RgnHandle oldClipRegion; RgnHandle oldVisibleRegion; RgnHandle clipRegion; BOOL forUpdate;} PortState_QD;#endif /* NP_NO_QUICKDRAW */typedef struct { CGContextRef context;} PortState_CG;@class NSTextInputContext;@interface NSResponder (AppKitDetails)- (NSTextInputContext *)inputContext;@end@interface WebNetscapePluginView (ForwardDeclarations)- (void)setWindowIfNecessary;- (NPError)loadRequest:(NSMutableURLRequest *)request inTarget:(const char *)cTarget withNotifyData:(void *)notifyData sendNotification:(BOOL)sendNotification;@end@implementation WebNetscapePluginView+ (void)initialize{ JSC::initializeThreading();#ifndef BUILDING_ON_TIGER WebCoreObjCFinalizeOnMainThread(self);#endif WKSendUserChangeNotifications();}#pragma mark EVENTS- (BOOL)superviewsHaveSuperviews{ NSView *contentView = [[self window] contentView]; NSView *view; for (view = self; view != nil; view = [view superview]) { if (view == contentView) { return YES; } } return NO;}// The WindowRef created by -[NSWindow windowRef] has a QuickDraw GrafPort that covers // the entire window frame (or structure region to use the Carbon term) rather then just the window content.// We can remove this when <rdar://problem/4201099> is fixed.- (void)fixWindowPort{#ifndef NP_NO_QUICKDRAW ASSERT(isDrawingModelQuickDraw(drawingModel)); NSWindow *currentWindow = [self currentWindow]; if ([currentWindow isKindOfClass:objc_getClass("NSCarbonWindow")]) return; float windowHeight = [currentWindow frame].size.height; NSView *contentView = [currentWindow contentView]; NSRect contentRect = [contentView convertRect:[contentView frame] toView:nil]; // convert to window-relative coordinates CGrafPtr oldPort; GetPort(&oldPort); SetPort(GetWindowPort((WindowRef)[currentWindow windowRef])); MovePortTo(static_cast<short>(contentRect.origin.x), /* Flip Y */ static_cast<short>(windowHeight - NSMaxY(contentRect))); PortSize(static_cast<short>(contentRect.size.width), static_cast<short>(contentRect.size.height)); SetPort(oldPort);#endif}#ifndef NP_NO_QUICKDRAWstatic UInt32 getQDPixelFormatForBitmapContext(CGContextRef context){ UInt32 byteOrder = CGBitmapContextGetBitmapInfo(context) & kCGBitmapByteOrderMask; if (byteOrder == kCGBitmapByteOrderDefault) switch (CGBitmapContextGetBitsPerPixel(context)) { case 16: byteOrder = kCGBitmapByteOrder16Host; break; case 32: byteOrder = kCGBitmapByteOrder32Host; break; } switch (byteOrder) { case kCGBitmapByteOrder16Little: return k16LE555PixelFormat; case kCGBitmapByteOrder32Little: return k32BGRAPixelFormat; case kCGBitmapByteOrder16Big: return k16BE555PixelFormat; case kCGBitmapByteOrder32Big: return k32ARGBPixelFormat; } ASSERT_NOT_REACHED(); return 0;}static inline void getNPRect(const CGRect& cgr, NPRect& npr){ npr.top = static_cast<uint16>(cgr.origin.y); npr.left = static_cast<uint16>(cgr.origin.x); npr.bottom = static_cast<uint16>(CGRectGetMaxY(cgr)); npr.right = static_cast<uint16>(CGRectGetMaxX(cgr));}#endifstatic inline void getNPRect(const NSRect& nr, NPRect& npr){ npr.top = static_cast<uint16>(nr.origin.y); npr.left = static_cast<uint16>(nr.origin.x); npr.bottom = static_cast<uint16>(NSMaxY(nr)); npr.right = static_cast<uint16>(NSMaxX(nr));}- (PortState)saveAndSetNewPortStateForUpdate:(BOOL)forUpdate{ ASSERT([self currentWindow] != nil); // Use AppKit to convert view coordinates to NSWindow coordinates. NSRect boundsInWindow = [self convertRect:[self bounds] toView:nil]; NSRect visibleRectInWindow = [self convertRect:[self visibleRect] toView:nil]; // Flip Y to convert NSWindow coordinates to top-left-based window coordinates. float borderViewHeight = [[self currentWindow] frame].size.height; boundsInWindow.origin.y = borderViewHeight - NSMaxY(boundsInWindow); visibleRectInWindow.origin.y = borderViewHeight - NSMaxY(visibleRectInWindow); #ifndef NP_NO_QUICKDRAW WindowRef windowRef = (WindowRef)[[self currentWindow] windowRef]; ASSERT(windowRef); // Look at the Carbon port to convert top-left-based window coordinates into top-left-based content coordinates. if (isDrawingModelQuickDraw(drawingModel)) { // If drawing with QuickDraw, fix the window port so that it has the same bounds as the NSWindow's // content view. This makes it easier to convert between AppKit view and QuickDraw port coordinates. [self fixWindowPort]; ::Rect portBounds; CGrafPtr port = GetWindowPort(windowRef); GetPortBounds(port, &portBounds); PixMap *pix = *GetPortPixMap(port); boundsInWindow.origin.x += pix->bounds.left - portBounds.left; boundsInWindow.origin.y += pix->bounds.top - portBounds.top; visibleRectInWindow.origin.x += pix->bounds.left - portBounds.left; visibleRectInWindow.origin.y += pix->bounds.top - portBounds.top; }#endif window.type = NPWindowTypeWindow; window.x = (int32)boundsInWindow.origin.x; window.y = (int32)boundsInWindow.origin.y; window.width = static_cast<uint32>(NSWidth(boundsInWindow)); window.height = static_cast<uint32>(NSHeight(boundsInWindow)); // "Clip-out" the plug-in when: // 1) it's not really in a window or off-screen or has no height or width. // 2) window.x is a "big negative number" which is how WebCore expresses off-screen widgets. // 3) the window is miniaturized or the app is hidden // 4) we're inside of viewWillMoveToWindow: with a nil window. In this case, superviews may already have nil // superviews and nil windows and results from convertRect:toView: are incorrect. NSWindow *realWindow = [self window]; if (window.width <= 0 || window.height <= 0 || window.x < -100000 || realWindow == nil || [realWindow isMiniaturized] || [NSApp isHidden] || ![self superviewsHaveSuperviews] || [self isHiddenOrHasHiddenAncestor]) { // The following code tries to give plug-ins the same size they will eventually have. // The specifiedWidth and specifiedHeight variables are used to predict the size that // WebCore will eventually resize us to. // The QuickTime plug-in has problems if you give it a width or height of 0. // Since other plug-ins also might have the same sort of trouble, we make sure // to always give plug-ins a size other than 0,0. if (window.width <= 0) window.width = specifiedWidth > 0 ? specifiedWidth : 100; if (window.height <= 0) window.height = specifiedHeight > 0 ? specifiedHeight : 100; window.clipRect.bottom = window.clipRect.top; window.clipRect.left = window.clipRect.right; } else { getNPRect(visibleRectInWindow, window.clipRect); } // Save the port state, set up the port for entry into the plugin PortState portState; switch (drawingModel) {#ifndef NP_NO_QUICKDRAW case NPDrawingModelQuickDraw: { // Set up NS_Port. ::Rect portBounds; CGrafPtr port = GetWindowPort(windowRef); GetPortBounds(port, &portBounds); nPort.qdPort.port = port; nPort.qdPort.portx = (int32)-boundsInWindow.origin.x; nPort.qdPort.porty = (int32)-boundsInWindow.origin.y; window.window = &nPort; PortState_QD *qdPortState = (PortState_QD*)malloc(sizeof(PortState_QD)); portState = (PortState)qdPortState; GetGWorld(&qdPortState->oldPort, &qdPortState->oldDevice); qdPortState->oldOrigin.h = portBounds.left; qdPortState->oldOrigin.v = portBounds.top; qdPortState->oldClipRegion = NewRgn(); GetPortClipRegion(port, qdPortState->oldClipRegion);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -