NetscapePluginWin.cpp [plain text]
#include "config.h"
#include "NetscapePlugin.h"
#include "PluginController.h"
#include "WebEvent.h"
#include "WindowGeometry.h"
#include <WebCore/DefWndProcWindowClass.h>
#include <WebCore/GraphicsContext.h>
#include <WebCore/LocalWindowsContext.h>
#include <WebCore/NotImplemented.h>
#include <WebCore/WebCoreInstanceHandle.h>
using namespace WebCore;
namespace WebKit {
static NetscapePlugin* currentPlugin;
class CurrentPluginSetter {
WTF_MAKE_NONCOPYABLE(CurrentPluginSetter);
public:
explicit CurrentPluginSetter(NetscapePlugin* plugin)
: m_plugin(plugin)
, m_formerCurrentPlugin(currentPlugin)
{
currentPlugin = m_plugin;
}
~CurrentPluginSetter()
{
ASSERT(currentPlugin == m_plugin);
currentPlugin = m_formerCurrentPlugin;
}
private:
NetscapePlugin* m_plugin;
NetscapePlugin* m_formerCurrentPlugin;
};
static LPCWSTR windowClassName = L"org.webkit.NetscapePluginWindow";
static void registerPluginView()
{
static bool didRegister;
if (didRegister)
return;
didRegister = true;
WNDCLASSW windowClass = {0};
windowClass.style = CS_DBLCLKS;
windowClass.lpfnWndProc = ::DefWindowProcW;
windowClass.hInstance = instanceHandle();
windowClass.hCursor = ::LoadCursorW(0, IDC_ARROW);
windowClass.hbrBackground = reinterpret_cast<HBRUSH>(COLOR_WINDOW + 1);
windowClass.lpszClassName = windowClassName;
::RegisterClassW(&windowClass);
}
HWND NetscapePlugin::containingWindow()
{
return controller()->nativeParentWindow();
}
bool NetscapePlugin::platformPostInitialize()
{
if (!m_isWindowed) {
m_window = 0;
m_pluginModule->module()->installIATHook("user32.dll", "TrackPopupMenu", hookedTrackPopupMenu);
m_contextMenuOwnerWindow = ::CreateWindowExW(0, defWndProcWindowClassName(), 0, WS_CHILD, 0, 0, 0, 0, containingWindow(), 0, instanceHandle(), 0);
return true;
}
registerPluginView();
m_window = ::CreateWindowExW(0, windowClassName, 0, WS_CHILD, 0, 0, 0, 0, containingWindow(), 0, instanceHandle(), 0);
if (!m_window)
return false;
m_npWindow.type = NPWindowTypeWindow;
m_npWindow.window = m_window;
return true;
}
void NetscapePlugin::platformDestroy()
{
if (!m_isWindowed) {
ASSERT(m_contextMenuOwnerWindow);
::DestroyWindow(m_contextMenuOwnerWindow);
ASSERT(!m_window);
return;
}
if (!::IsWindow(m_window))
return;
::DestroyWindow(m_window);
}
bool NetscapePlugin::platformInvalidate(const IntRect& invalidRect)
{
if (!m_isWindowed)
return false;
RECT rect = invalidRect;
::InvalidateRect(m_window, &rect, FALSE);
return true;
}
void NetscapePlugin::platformGeometryDidChange()
{
if (!m_isWindowed)
return;
scheduleWindowedGeometryUpdate();
}
void NetscapePlugin::platformVisibilityDidChange()
{
if (!m_isWindowed)
return;
scheduleWindowedGeometryUpdate();
}
void NetscapePlugin::scheduleWindowedGeometryUpdate()
{
::SetWindowPos(m_window, 0, 0, 0, m_pluginSize.width(), m_pluginSize.height(), SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER);
WindowGeometry geometry;
geometry.window = m_window;
geometry.visible = controller()->isPluginVisible();
geometry.frame = IntRect(convertToRootView(IntPoint()), m_pluginSize);
geometry.clipRect = m_clipRect;
controller()->scheduleWindowedPluginGeometryUpdate(geometry);
}
void NetscapePlugin::platformPaint(GraphicsContext* context, const IntRect& dirtyRect, bool)
{
CurrentPluginSetter setCurrentPlugin(this);
if (m_isWindowed) {
return;
}
controller()->willSendEventToPlugin();
LocalWindowsContext windowsContext(context, dirtyRect, m_isTransparent);
m_npWindow.type = NPWindowTypeDrawable;
m_npWindow.window = windowsContext.hdc();
WINDOWPOS windowpos = { 0, 0, 0, 0, 0, 0, 0 };
IntPoint pluginLocationInRootViewCoordinates = convertToRootView(IntPoint());
windowpos.x = pluginLocationInRootViewCoordinates.x();
windowpos.y = pluginLocationInRootViewCoordinates.y();
windowpos.cx = m_pluginSize.width();
windowpos.cy = m_pluginSize.height();
NPEvent npEvent;
npEvent.event = WM_WINDOWPOSCHANGED;
npEvent.wParam = 0;
npEvent.lParam = reinterpret_cast<uintptr_t>(&windowpos);
NPP_HandleEvent(&npEvent);
callSetWindow();
RECT dirtyWinRect = dirtyRect;
npEvent.event = WM_PAINT;
npEvent.wParam = reinterpret_cast<uintptr_t>(windowsContext.hdc());
npEvent.lParam = reinterpret_cast<uintptr_t>(&dirtyWinRect);
NPP_HandleEvent(&npEvent);
}
NPEvent toNP(const WebMouseEvent& event)
{
NPEvent npEvent;
npEvent.wParam = 0;
if (event.controlKey())
npEvent.wParam |= MK_CONTROL;
if (event.shiftKey())
npEvent.wParam |= MK_SHIFT;
npEvent.lParam = MAKELPARAM(event.position().x(), event.position().y());
switch (event.type()) {
case WebEvent::MouseMove:
npEvent.event = WM_MOUSEMOVE;
switch (event.button()) {
case WebMouseEvent::LeftButton:
npEvent.wParam |= MK_LBUTTON;
break;
case WebMouseEvent::MiddleButton:
npEvent.wParam |= MK_MBUTTON;
break;
case WebMouseEvent::RightButton:
npEvent.wParam |= MK_RBUTTON;
break;
case WebMouseEvent::NoButton:
break;
}
break;
case WebEvent::MouseDown:
switch (event.button()) {
case WebMouseEvent::LeftButton:
npEvent.event = WM_LBUTTONDOWN;
break;
case WebMouseEvent::MiddleButton:
npEvent.event = WM_MBUTTONDOWN;
break;
case WebMouseEvent::RightButton:
npEvent.event = WM_RBUTTONDOWN;
break;
case WebMouseEvent::NoButton:
ASSERT_NOT_REACHED();
break;
}
break;
case WebEvent::MouseUp:
switch (event.button()) {
case WebMouseEvent::LeftButton:
npEvent.event = WM_LBUTTONUP;
break;
case WebMouseEvent::MiddleButton:
npEvent.event = WM_MBUTTONUP;
break;
case WebMouseEvent::RightButton:
npEvent.event = WM_RBUTTONUP;
break;
case WebMouseEvent::NoButton:
ASSERT_NOT_REACHED();
break;
}
break;
default:
ASSERT_NOT_REACHED();
break;
}
return npEvent;
}
bool NetscapePlugin::platformHandleMouseEvent(const WebMouseEvent& event)
{
CurrentPluginSetter setCurrentPlugin(this);
if (m_isWindowed)
return false;
controller()->willSendEventToPlugin();
NPEvent npEvent = toNP(event);
NPP_HandleEvent(&npEvent);
return true;
}
bool NetscapePlugin::platformHandleWheelEvent(const WebWheelEvent&)
{
CurrentPluginSetter setCurrentPlugin(this);
notImplemented();
return false;
}
void NetscapePlugin::platformSetFocus(bool hasFocus)
{
CurrentPluginSetter setCurrentPlugin(this);
if (m_isWindowed)
return;
controller()->willSendEventToPlugin();
NPEvent npEvent;
npEvent.event = hasFocus ? WM_SETFOCUS : WM_KILLFOCUS;
npEvent.wParam = 0;
npEvent.lParam = 0;
NPP_HandleEvent(&npEvent);
}
bool NetscapePlugin::wantsPluginRelativeNPWindowCoordinates()
{
return false;
}
bool NetscapePlugin::platformHandleMouseEnterEvent(const WebMouseEvent& event)
{
CurrentPluginSetter setCurrentPlugin(this);
if (m_isWindowed)
return false;
controller()->willSendEventToPlugin();
NPEvent npEvent = toNP(event);
NPP_HandleEvent(&npEvent);
return true;
}
bool NetscapePlugin::platformHandleMouseLeaveEvent(const WebMouseEvent& event)
{
CurrentPluginSetter setCurrentPlugin(this);
if (m_isWindowed)
return false;
controller()->willSendEventToPlugin();
NPEvent npEvent = toNP(event);
NPP_HandleEvent(&npEvent);
return true;
}
bool NetscapePlugin::platformHandleKeyboardEvent(const WebKeyboardEvent&)
{
CurrentPluginSetter setCurrentPlugin(this);
notImplemented();
return false;
}
BOOL NetscapePlugin::hookedTrackPopupMenu(HMENU hMenu, UINT uFlags, int x, int y, int nReserved, HWND hWnd, const RECT* prcRect)
{
if (::GetWindowThreadProcessId(hWnd, 0) == ::GetCurrentThreadId())
return ::TrackPopupMenu(hMenu, uFlags, x, y, nReserved, hWnd, prcRect);
HWND originalFocusWindow = 0;
ASSERT(currentPlugin);
if (currentPlugin) {
ASSERT(!currentPlugin->m_isWindowed);
ASSERT(currentPlugin->m_contextMenuOwnerWindow);
ASSERT(::GetWindowThreadProcessId(currentPlugin->m_contextMenuOwnerWindow, 0) == ::GetCurrentThreadId());
hWnd = currentPlugin->m_contextMenuOwnerWindow;
originalFocusWindow = ::SetFocus(hWnd);
}
BOOL result = ::TrackPopupMenu(hMenu, uFlags, x, y, nReserved, hWnd, prcRect);
if (originalFocusWindow)
::SetFocus(originalFocusWindow);
return result;
}
}