diff options
Diffstat (limited to 'WebKit/wince/WebView.cpp')
| -rw-r--r-- | WebKit/wince/WebView.cpp | 454 |
1 files changed, 454 insertions, 0 deletions
diff --git a/WebKit/wince/WebView.cpp b/WebKit/wince/WebView.cpp new file mode 100644 index 0000000..ce90149 --- /dev/null +++ b/WebKit/wince/WebView.cpp @@ -0,0 +1,454 @@ +/* + * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple, Inc. All rights reserved. + * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com> + * + * 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 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. + */ + +#include "config.h" +#include "WebView.h" + +#include "ChromeClientWinCE.h" +#include "ContextMenuClientWinCE.h" +#include "DragClientWinCE.h" +#include "EditorClientWinCE.h" +#include "FocusController.h" +#include "Frame.h" +#include "FrameLoader.h" +#include "FrameLoaderClientWinCE.h" +#include "FrameView.h" +#include "GraphicsContext.h" +#include "InitializeThreading.h" +#include "InspectorClientWinCE.h" +#include "IntSize.h" +#include "MainThread.h" +#include "NotImplemented.h" +#include "Page.h" +#include "PlatformKeyboardEvent.h" +#include "PlatformMouseEvent.h" +#include "PlatformStrategiesWinCE.h" +#include "PlatformWheelEvent.h" +#include "ResourceRequest.h" +#include "Settings.h" +#include "SharedBuffer.h" +#include "WebCoreInstanceHandle.h" + +using namespace WebCore; + +const LPCWSTR kWebViewWindowClassName = L"WebViewWindowClass"; + + +LRESULT CALLBACK WebView::webViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + if (WebView* webView = reinterpret_cast<WebView*>(GetWindowLong(hWnd, 0))) + return webView->wndProc(hWnd, message, wParam, lParam); + + return DefWindowProc(hWnd, message, wParam, lParam); +} + +PassRefPtr<SharedBuffer> loadResourceIntoBuffer(const char* name) +{ + notImplemented(); + return 0; +} + + +WebView::WebView(HWND hwnd, unsigned features) + : m_frame(0) + , m_page(0) + , m_parentWindowHandle(hwnd) + , m_enableDoubleBuffer(features & EnableDoubleBuffering) +{ + RECT rcClient; + GetClientRect(hwnd, &rcClient); + + m_windowHandle = CreateWindow(kWebViewWindowClassName, 0, WS_CHILD, + CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, hwnd, 0, WebCore::instanceHandle(), 0); + + SetWindowLong(m_windowHandle, 0, reinterpret_cast<LONG>(this)); + + MoveWindow(m_windowHandle, 0, 0, rcClient.right, rcClient.bottom, TRUE); + ShowWindow(m_windowHandle, SW_SHOW); + + Page::PageClients pageClients; + pageClients.chromeClient = new WebKit::ChromeClientWinCE(this); + pageClients.contextMenuClient = new WebKit::ContextMenuClientWinCE(this); + pageClients.editorClient = new WebKit::EditorClientWinCE(this); + pageClients.dragClient = new WebKit::DragClientWinCE(); + pageClients.inspectorClient = new WebKit::InspectorClientWinCE(this); + m_page = new Page(pageClients); + + Settings* settings = m_page->settings(); + settings->setDefaultFixedFontSize(14); + settings->setDefaultFontSize(14); + settings->setMinimumFontSize(8); + settings->setMinimumLogicalFontSize(8); + settings->setJavaScriptEnabled(true); + settings->setLoadsImagesAutomatically(true); + + WebKit::FrameLoaderClientWinCE* loaderClient = new WebKit::FrameLoaderClientWinCE(this); + RefPtr<Frame> frame = Frame::create(m_page, 0, loaderClient); + m_frame = frame.get(); + loaderClient->setFrame(m_frame); + + m_page->mainFrame()->init(); + + if (view()) { + RECT windowRect; + frameRect(&windowRect); + view()->resize(IntRect(windowRect).size()); + } +} + +WebView::~WebView() +{ + delete m_page; + DestroyWindow(m_windowHandle); +} + +void WebView::initialize(HINSTANCE instanceHandle) +{ + JSC::initializeThreading(); + WTF::initializeMainThread(); + PlatformStrategiesWinCE::initialize(); + + WebCore::setInstanceHandle(instanceHandle); + + WNDCLASS wc; + wc.style = CS_DBLCLKS; + wc.lpfnWndProc = WebView::webViewWndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = sizeof(void *); + wc.hInstance = instanceHandle; + wc.hIcon = 0; + wc.hCursor = LoadCursor(0, IDC_ARROW); + wc.hbrBackground = 0; + wc.lpszMenuName = 0; + wc.lpszClassName = kWebViewWindowClassName; + + RegisterClass(&wc); +} + +void WebView::cleanup() +{ + UnregisterClass(kWebViewWindowClassName, WebCore::instanceHandle()); +} + +PassRefPtr<Frame> WebView::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement, const String& referrer, + bool /*allowsScrolling*/, int /*marginWidth*/, int /*marginHeight*/) +{ + Frame* coreFrame = m_frame; + + WebKit::FrameLoaderClientWinCE *loaderClient = new WebKit::FrameLoaderClientWinCE(this); + RefPtr<Frame> childFrame = Frame::create(m_page, ownerElement, loaderClient); + loaderClient->setFrame(childFrame.get()); + + coreFrame->tree()->appendChild(childFrame); + childFrame->tree()->setName(name); + childFrame->init(); + + // The creation of the frame may have run arbitrary JavaScript that removed it from the page already. + if (!childFrame->page()) + return 0; + + childFrame->loader()->loadURLIntoChildFrame(url, referrer, childFrame.get()); + + // The frame's onload handler may have removed it from the document. + if (!childFrame->tree()->parent()) + return 0; + + return childFrame.release(); +} + +void WebView::runJavaScriptAlert(const String& message) +{ + notImplemented(); +} + +bool WebView::runJavaScriptConfirm(const String& message) +{ + notImplemented(); + return false; +} + +bool WebView::runJavaScriptPrompt(const String& message, const String& defaultValue, String& result) +{ + notImplemented(); + return false; +} + +void WebView::frameRect(RECT* rect) const +{ + GetWindowRect(m_windowHandle, rect); +} + +FrameView* WebView::view() const +{ + return m_frame ? m_frame->view() : 0; +} + +void WebView::load(LPCWSTR url) +{ + load(String(url)); +} + +void WebView::load(const String &url) +{ + load(WebCore::ResourceRequest(url)); +} + +void WebView::load(const WebCore::ResourceRequest &request) +{ + frame()->loader()->load(request, false); +} + +void WebView::reload() +{ + frame()->loader()->reload(); +} + +void WebView::stop() +{ + frame()->loader()->stopAllLoaders(); +} + +void WebView::paint(HDC hDC, const IntRect& clipRect) +{ + OwnPtr<HRGN> clipRgn(CreateRectRgn(clipRect.x(), clipRect.y(), clipRect.right(), clipRect.bottom())); + SelectClipRgn(hDC, clipRgn.get()); + + GraphicsContext gc(hDC); + view()->paint(&gc, clipRect); +} + +bool WebView::handlePaint(HWND hWnd) +{ + RECT updateRect; + if (!GetUpdateRect(hWnd, &updateRect, false)) + return false; + + PAINTSTRUCT ps; + HDC hDC = BeginPaint(m_windowHandle, &ps); + + IntRect clipRect(updateRect); + + if (m_enableDoubleBuffer) { + if (!m_doubleBufferDC) { + RECT rcClient; + GetClientRect(m_windowHandle, &rcClient); + + m_doubleBufferDC = adoptPtr(CreateCompatibleDC(hDC)); + m_doubleBufferBitmap = adoptPtr(CreateCompatibleBitmap(hDC, rcClient.right, rcClient.bottom)); + SelectObject(m_doubleBufferDC.get(), m_doubleBufferBitmap.get()); + } + + paint(m_doubleBufferDC.get(), clipRect); + + BitBlt(hDC, clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height(), m_doubleBufferDC.get(), clipRect.x(), clipRect.y(), SRCCOPY); + } else + paint(hDC, clipRect); + + EndPaint(m_windowHandle, &ps); + return true; +} + +bool WebView::handleMouseEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + static LONG globalClickCount; + static IntPoint globalPrevPoint; + static MouseButton globalPrevButton; + static LONG globalPrevMouseDownTime; + + // Create our event. + // On WM_MOUSELEAVE we need to create a mouseout event, so we force the position + // of the event to be at (MINSHORT, MINSHORT). + PlatformMouseEvent mouseEvent(hWnd, message, wParam, lParam); + + bool insideThreshold = abs(globalPrevPoint.x() - mouseEvent.pos().x()) < ::GetSystemMetrics(SM_CXDOUBLECLK) + && abs(globalPrevPoint.y() - mouseEvent.pos().y()) < ::GetSystemMetrics(SM_CYDOUBLECLK); + LONG messageTime = 0; + + bool handled = false; + if (message == WM_LBUTTONDOWN || message == WM_MBUTTONDOWN || message == WM_RBUTTONDOWN) { + // FIXME: I'm not sure if this is the "right" way to do this + // but without this call, we never become focused since we don't allow + // the default handling of mouse events. + SetFocus(m_windowHandle); + + PlatformMouseEvent moveEvent(hWnd, WM_MOUSEMOVE, 0, lParam, false); + moveEvent.setClickCount(0); + m_page->mainFrame()->eventHandler()->handleMouseMoveEvent(moveEvent); + + // Always start capturing events when the mouse goes down in our HWND. + SetCapture(m_windowHandle); + + if (insideThreshold && mouseEvent.button() == globalPrevButton) + globalClickCount++; + else + // Reset the click count. + globalClickCount = 1; + globalPrevMouseDownTime = messageTime; + globalPrevButton = mouseEvent.button(); + globalPrevPoint = mouseEvent.pos(); + + mouseEvent.setClickCount(globalClickCount); + handled = m_page->mainFrame()->eventHandler()->handleMousePressEvent(mouseEvent); + } else if (message == WM_LBUTTONDBLCLK || message == WM_MBUTTONDBLCLK || message == WM_RBUTTONDBLCLK) { + globalClickCount++; + mouseEvent.setClickCount(globalClickCount); + handled = m_page->mainFrame()->eventHandler()->handleMousePressEvent(mouseEvent); + } else if (message == WM_LBUTTONUP || message == WM_MBUTTONUP || message == WM_RBUTTONUP) { + // Record the global position and the button of the up. + globalPrevButton = mouseEvent.button(); + globalPrevPoint = mouseEvent.pos(); + mouseEvent.setClickCount(globalClickCount); + m_page->mainFrame()->eventHandler()->handleMouseReleaseEvent(mouseEvent); + ReleaseCapture(); + } else if (message == WM_MOUSEMOVE) { + if (!insideThreshold) + globalClickCount = 0; + mouseEvent.setClickCount(globalClickCount); + handled = m_page->mainFrame()->eventHandler()->mouseMoved(mouseEvent); + } + + return handled; +} + +bool WebView::handleMouseWheel(HWND hWnd, WPARAM wParam, LPARAM lParam, bool isHorizontal) +{ + PlatformWheelEvent wheelEvent(hWnd, wParam, lParam, isHorizontal); + return frame()->eventHandler()->handleWheelEvent(wheelEvent); +} + +bool WebView::handleKeyDown(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + if (virtualKeyCode == VK_CAPITAL) + frame->eventHandler()->capsLockStateMayHaveChanged(); + + PlatformKeyboardEvent keyEvent(m_windowHandle, virtualKeyCode, keyData, PlatformKeyboardEvent::RawKeyDown, systemKeyDown); + bool handled = frame->eventHandler()->keyEvent(keyEvent); + + // These events cannot be canceled, and we have no default handling for them. + // FIXME: match IE list more closely, see <http://msdn2.microsoft.com/en-us/library/ms536938.aspx>. + if (systemKeyDown && virtualKeyCode != VK_RETURN) + return false; + + if (handled) { + MSG msg; + if (!systemKeyDown) + ::PeekMessage(&msg, m_windowHandle, WM_CHAR, WM_CHAR, PM_REMOVE); + return true; + } + + return handled; +} + +bool WebView::handleKeyPress(WPARAM charCode, LPARAM keyData, bool systemKeyDown) +{ + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + + PlatformKeyboardEvent keyEvent(m_windowHandle, charCode, keyData, PlatformKeyboardEvent::Char, systemKeyDown); + // IE does not dispatch keypress event for WM_SYSCHAR. + if (systemKeyDown) + return frame->eventHandler()->handleAccessKey(keyEvent); + if (frame->eventHandler()->keyEvent(keyEvent)) + return true; + + return false; +} + +bool WebView::handleKeyUp(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown) +{ + PlatformKeyboardEvent keyEvent(m_windowHandle, virtualKeyCode, keyData, PlatformKeyboardEvent::KeyUp, systemKeyDown); + + Frame* frame = m_page->focusController()->focusedOrMainFrame(); + return frame->eventHandler()->keyEvent(keyEvent); +} + +LRESULT WebView::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) +{ + bool handled = false; + + if (view()) { + switch (message) { + case WM_PAINT: + handled = handlePaint(hWnd); + break; + + case WM_MOUSEMOVE: + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_LBUTTONDBLCLK: + case WM_MBUTTONDBLCLK: + case WM_RBUTTONDBLCLK: + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + if (frame()->eventHandler() && view()->didFirstLayout()) + handled = handleMouseEvent(hWnd, message, wParam, lParam); + break; + + case WM_MOUSEWHEEL: + if (frame()->eventHandler() && view()->didFirstLayout()) + handled = handleMouseWheel(hWnd, wParam, lParam, wParam & MK_SHIFT); + break; + + case WM_SYSKEYDOWN: + handled = handleKeyDown(wParam, lParam, true); + break; + + case WM_KEYDOWN: + handled = handleKeyDown(wParam, lParam, false); + break; + + case WM_SYSKEYUP: + handled = handleKeyUp(wParam, lParam, true); + break; + + case WM_KEYUP: + handled = handleKeyUp(wParam, lParam, false); + break; + + case WM_SYSCHAR: + handled = handleKeyPress(wParam, lParam, true); + break; + + case WM_CHAR: + handled = handleKeyPress(wParam, lParam, false); + break; + + case WM_CLOSE: + PostMessage(m_parentWindowHandle, WM_CLOSE, wParam, lParam); + handled = true; + break; + + default: + break; + } + } + + if (handled) + return 0; + + return DefWindowProc(hWnd, message, wParam, lParam); +} |
