⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pluginviewwin.cpp

📁 linux下开源浏览器WebKit的源码,市面上的很多商用浏览器都是移植自WebKit
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (C) 2006, 2007, 2008 Apple Inc. All rights reserved. * Copyright (C) 2008 Collabora Ltd. 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. * * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``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 COMPUTER, INC. OR * 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.  */#include "config.h"#include "PluginView.h"#include "Document.h"#include "DocumentLoader.h"#include "Element.h"#include "EventNames.h"#include "FrameLoader.h"#include "FrameLoadRequest.h"#include "FrameTree.h"#include "Frame.h"#include "FrameView.h"#include "GraphicsContext.h"#include "Image.h"#include "HTMLNames.h"#include "HTMLPlugInElement.h"#include "JSDOMWindow.h"#include "KeyboardEvent.h"#include "MIMETypeRegistry.h"#include "MouseEvent.h"#include "NotImplemented.h"#include "Page.h"#include "FocusController.h"#include "PlatformMouseEvent.h"#include "PluginMessageThrottlerWin.h"#include "PluginPackage.h"#include "PluginMainThreadScheduler.h"#include "JSDOMBinding.h"#include "ScriptController.h"#include "PluginDatabase.h"#include "PluginDebug.h"#include "PluginPackage.h"#include "c_instance.h"#include "npruntime_impl.h"#include "runtime_root.h"#include "Settings.h"#include "runtime.h"#include <runtime/JSLock.h>#include <runtime/JSValue.h>#include <wtf/ASCIICType.h>#if PLATFORM(QT)#include <QWidget.h>#endifstatic inline HWND windowHandleForPlatformWidget(PlatformWidget widget){#if PLATFORM(QT)    if (!widget)        return 0;    return widget->winId();#else    return widget;#endif}using JSC::ExecState;using JSC::JSLock;using JSC::JSObject;using JSC::UString;using std::min;using namespace WTF;namespace WebCore {using namespace HTMLNames;const LPCWSTR kWebPluginViewdowClassName = L"WebPluginView";const LPCWSTR kWebPluginViewProperty = L"WebPluginViewProperty";static const char* MozillaUserAgent = "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1) Gecko/20061010 Firefox/2.0";// The code used to hook BeginPaint/EndPaint originally came from// <http://www.fengyuan.com/article/wmprint.html>.// Copyright (C) 2000 by Feng Yuan (www.fengyuan.com).static unsigned beginPaintSysCall;static BYTE* beginPaint;static unsigned endPaintSysCall;static BYTE* endPaint;HDC WINAPI PluginView::hookedBeginPaint(HWND hWnd, PAINTSTRUCT* lpPaint){    PluginView* pluginView = reinterpret_cast<PluginView*>(GetProp(hWnd, kWebPluginViewProperty));    if (pluginView && pluginView->m_wmPrintHDC) {        // We're secretly handling WM_PRINTCLIENT, so set up the PAINTSTRUCT so        // that the plugin will paint into the HDC we provide.        memset(lpPaint, 0, sizeof(PAINTSTRUCT));        lpPaint->hdc = pluginView->m_wmPrintHDC;        GetClientRect(hWnd, &lpPaint->rcPaint);        return pluginView->m_wmPrintHDC;    }    // Call through to the original BeginPaint.    __asm   mov     eax, beginPaintSysCall    __asm   push    lpPaint    __asm   push    hWnd    __asm   call    beginPaint}BOOL WINAPI PluginView::hookedEndPaint(HWND hWnd, const PAINTSTRUCT* lpPaint){    PluginView* pluginView = reinterpret_cast<PluginView*>(GetProp(hWnd, kWebPluginViewProperty));    if (pluginView && pluginView->m_wmPrintHDC) {        // We're secretly handling WM_PRINTCLIENT, so we don't have to do any        // cleanup.        return TRUE;    }    // Call through to the original EndPaint.    __asm   mov     eax, endPaintSysCall    __asm   push    lpPaint    __asm   push    hWnd    __asm   call    endPaint}static void hook(const char* module, const char* proc, unsigned& sysCallID, BYTE*& pProc, const void* pNewProc){    // See <http://www.fengyuan.com/article/wmprint.html> for an explanation of    // how this function works.    HINSTANCE hMod = GetModuleHandleA(module);    pProc = reinterpret_cast<BYTE*>(GetProcAddress(hMod, proc));    if (pProc[0] != 0xB8)        return;    // FIXME: Should we be reading the bytes one-by-one instead of doing an    // unaligned read?    sysCallID = *reinterpret_cast<unsigned*>(pProc + 1);    DWORD flOldProtect;    if (!VirtualProtect(pProc, 5, PAGE_EXECUTE_READWRITE, &flOldProtect))        return;    pProc[0] = 0xE9;    *reinterpret_cast<unsigned*>(pProc + 1) = reinterpret_cast<intptr_t>(pNewProc) - reinterpret_cast<intptr_t>(pProc + 5);    pProc += 5;}static void setUpOffscreenPaintingHooks(HDC (WINAPI*hookedBeginPaint)(HWND, PAINTSTRUCT*), BOOL (WINAPI*hookedEndPaint)(HWND, const PAINTSTRUCT*)){    static bool haveHooked = false;    if (haveHooked)        return;    haveHooked = true;    // Most (all?) windowed plugins don't seem to respond to WM_PRINTCLIENT, so    // we hook into BeginPaint/EndPaint to allow their normal WM_PAINT handling    // to draw into a given HDC. Note that this hooking affects the entire    // process.    hook("user32.dll", "BeginPaint", beginPaintSysCall, beginPaint, hookedBeginPaint);    hook("user32.dll", "EndPaint", endPaintSysCall, endPaint, hookedEndPaint);}static bool registerPluginView(){    static bool haveRegisteredWindowClass = false;    if (haveRegisteredWindowClass)        return true;    haveRegisteredWindowClass = true;#if PLATFORM(QT)    Page::setInstanceHandle((HINSTANCE)(qWinAppInst()));#endif    ASSERT(Page::instanceHandle());    WNDCLASSEX wcex;    wcex.cbSize = sizeof(WNDCLASSEX);    wcex.style          = CS_DBLCLKS;    wcex.lpfnWndProc    = DefWindowProc;    wcex.cbClsExtra     = 0;    wcex.cbWndExtra     = 0;    wcex.hInstance      = Page::instanceHandle();    wcex.hIcon          = 0;    wcex.hCursor        = LoadCursor(0, IDC_ARROW);    wcex.hbrBackground  = (HBRUSH)COLOR_WINDOW;    wcex.lpszMenuName   = 0;    wcex.lpszClassName  = kWebPluginViewdowClassName;    wcex.hIconSm        = 0;    return !!RegisterClassEx(&wcex);}LRESULT CALLBACK PluginView::PluginViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){    PluginView* pluginView = reinterpret_cast<PluginView*>(GetProp(hWnd, kWebPluginViewProperty));    return pluginView->wndProc(hWnd, message, wParam, lParam);}static bool isWindowsMessageUserGesture(UINT message){    switch (message) {        case WM_LBUTTONUP:        case WM_MBUTTONUP:        case WM_RBUTTONUP:        case WM_KEYUP:            return true;        default:            return false;    }}LRESULTPluginView::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam){    // <rdar://5711136> Sometimes Flash will call SetCapture before creating    // a full-screen window and will not release it, which causes the    // full-screen window to never receive mouse events. We set/release capture    // on mouse down/up before sending the event to the plug-in to prevent that.    switch (message) {        case WM_LBUTTONDOWN:        case WM_MBUTTONDOWN:        case WM_RBUTTONDOWN:            ::SetCapture(hWnd);            break;        case WM_LBUTTONUP:        case WM_MBUTTONUP:        case WM_RBUTTONUP:            ::ReleaseCapture();            break;    }    if (message == m_lastMessage &&        m_plugin->quirks().contains(PluginQuirkDontCallWndProcForSameMessageRecursively) &&         m_isCallingPluginWndProc)        return 1;    if (message == WM_USER + 1 &&        m_plugin->quirks().contains(PluginQuirkThrottleWMUserPlusOneMessages)) {        if (!m_messageThrottler)            m_messageThrottler.set(new PluginMessageThrottlerWin(this));        m_messageThrottler->appendMessage(hWnd, message, wParam, lParam);        return 0;    }    m_lastMessage = message;    m_isCallingPluginWndProc = true;    // If the plug-in doesn't explicitly support changing the pop-up state, we enable    // popups for all user gestures.    // Note that we need to pop the state in a timer, because the Flash plug-in     // pops up windows in response to a posted message.    if (m_plugin->pluginFuncs()->version < NPVERS_HAS_POPUPS_ENABLED_STATE &&        isWindowsMessageUserGesture(message) && !m_popPopupsStateTimer.isActive()) {        pushPopupsEnabledState(true);        m_popPopupsStateTimer.startOneShot(0);    }    if (message == WM_PRINTCLIENT) {        // Most (all?) windowed plugins don't respond to WM_PRINTCLIENT, so we        // change the message to WM_PAINT and rely on our hooked versions of        // BeginPaint/EndPaint to make the plugin draw into the given HDC.        message = WM_PAINT;        m_wmPrintHDC = reinterpret_cast<HDC>(wParam);    }    // Call the plug-in's window proc.    LRESULT result = ::CallWindowProc(m_pluginWndProc, hWnd, message, wParam, lParam);    m_wmPrintHDC = 0;    m_isCallingPluginWndProc = false;    return result;}void PluginView::updatePluginWidget(){    if (!parent())        return;    ASSERT(parent()->isFrameView());    FrameView* frameView = static_cast<FrameView*>(parent());    IntRect oldWindowRect = m_windowRect;    IntRect oldClipRect = m_clipRect;    m_windowRect = IntRect(frameView->contentsToWindow(frameRect().location()), frameRect().size());    m_clipRect = windowClipRect();    m_clipRect.move(-m_windowRect.x(), -m_windowRect.y());    if (platformPluginWidget() && (m_windowRect != oldWindowRect || m_clipRect != oldClipRect)) {        HRGN rgn;        setCallingPlugin(true);        // To prevent flashes while scrolling, we disable drawing during the window        // update process by clipping the window to the zero rect.        bool clipToZeroRect = !m_plugin->quirks().contains(PluginQuirkDontClipToZeroRectWhenScrolling);        if (clipToZeroRect) {            rgn = ::CreateRectRgn(0, 0, 0, 0);            ::SetWindowRgn(platformPluginWidget(), rgn, FALSE);        } else {            rgn = ::CreateRectRgn(m_clipRect.x(), m_clipRect.y(), m_clipRect.right(), m_clipRect.bottom());            ::SetWindowRgn(platformPluginWidget(), rgn, TRUE);        }        if (m_windowRect != oldWindowRect)            ::MoveWindow(platformPluginWidget(), m_windowRect.x(), m_windowRect.y(), m_windowRect.width(), m_windowRect.height(), TRUE);        if (clipToZeroRect) {            rgn = ::CreateRectRgn(m_clipRect.x(), m_clipRect.y(), m_clipRect.right(), m_clipRect.bottom());            ::SetWindowRgn(platformPluginWidget(), rgn, TRUE);        }        setCallingPlugin(false);    }}void PluginView::setFocus(){    if (platformPluginWidget())        SetFocus(platformPluginWidget());    Widget::setFocus();}void PluginView::show(){    setSelfVisible(true);    if (isParentVisible() && platformPluginWidget())        ShowWindow(platformPluginWidget(), SW_SHOWNA);    Widget::show();}void PluginView::hide(){    setSelfVisible(false);    if (isParentVisible() && platformPluginWidget())        ShowWindow(platformPluginWidget(), SW_HIDE);    Widget::hide();}bool PluginView::dispatchNPEvent(NPEvent& npEvent){    if (!m_plugin->pluginFuncs()->event)        return true;    bool shouldPop = false;    if (m_plugin->pluginFuncs()->version < NPVERS_HAS_POPUPS_ENABLED_STATE && isWindowsMessageUserGesture(npEvent.event)) {        pushPopupsEnabledState(true);        shouldPop = true;    }    JSC::JSLock::DropAllLocks dropAllLocks(false);    setCallingPlugin(true);    bool result = m_plugin->pluginFuncs()->event(m_instance, &npEvent);    setCallingPlugin(false);    if (shouldPop)         popPopupsEnabledState();    return result;}void PluginView::paintWindowedPluginIntoContext(GraphicsContext* context, const IntRect& rect) const{    ASSERT(m_isWindowed);    ASSERT(context->shouldIncludeChildWindows());    ASSERT(parent()->isFrameView());    IntPoint locationInWindow = static_cast<FrameView*>(parent())->contentsToWindow(frameRect().location());    HDC hdc = context->getWindowsContext(frameRect(), false);    XFORM originalTransform;    GetWorldTransform(hdc, &originalTransform);    // The plugin expects the DC to be in client coordinates, so we translate    // the DC to make that so.    XFORM transform = originalTransform;    transform.eDx = locationInWindow.x();    transform.eDy = locationInWindow.y();    SetWorldTransform(hdc, &transform);    SendMessage(platformPluginWidget(), WM_PRINTCLIENT, reinterpret_cast<WPARAM>(hdc), PRF_CLIENT | PRF_CHILDREN | PRF_OWNED);    SetWorldTransform(hdc, &originalTransform);    context->releaseWindowsContext(hdc, frameRect(), false);}void PluginView::paint(GraphicsContext* context, const IntRect& rect){    if (!m_isStarted) {        // Draw the "missing plugin" image        paintMissingPluginIcon(context, rect);        return;    }    if (context->paintingDisabled())        return;    if (m_isWindowed) {        if (context->shouldIncludeChildWindows())            paintWindowedPluginIntoContext(context, rect);        return;    }    ASSERT(parent()->isFrameView());    IntRect rectInWindow = static_cast<FrameView*>(parent())->contentsToWindow(frameRect());    HDC hdc = context->getWindowsContext(rectInWindow, m_isTransparent);    NPEvent npEvent;    // On Safari/Windows without transparency layers the GraphicsContext returns the HDC    // of the window and the plugin expects that the passed in DC has window coordinates.    // In the Qt port we always draw in an offscreen buffer and therefore need to preserve    // the translation set in getWindowsContext.#if !PLATFORM(QT)    if (!context->inTransparencyLayer()) {        XFORM transform;        GetWorldTransform(hdc, &transform);        transform.eDx = 0;        transform.eDy = 0;        SetWorldTransform(hdc, &transform);    }#endif    m_npWindow.type = NPWindowTypeDrawable;    m_npWindow.window = hdc;    IntPoint p = static_cast<FrameView*>(parent())->contentsToWindow(frameRect().location());        WINDOWPOS windowpos;    memset(&windowpos, 0, sizeof(windowpos));    windowpos.x = p.x();    windowpos.y = p.y();    windowpos.cx = frameRect().width();    windowpos.cy = frameRect().height();    npEvent.event = WM_WINDOWPOSCHANGED;    npEvent.lParam = reinterpret_cast<uint32>(&windowpos);    npEvent.wParam = 0;    dispatchNPEvent(npEvent);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -