2 * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple, Inc. All rights reserved.
3 * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
15 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
17 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
19 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
20 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
21 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 #include "ChromeClientWinCE.h"
30 #include "ContextMenuClientWinCE.h"
31 #include "DragClientWinCE.h"
32 #include "EditorClientWinCE.h"
33 #include "FocusController.h"
35 #include "FrameLoader.h"
36 #include "FrameLoaderClientWinCE.h"
37 #include "FrameView.h"
38 #include "GraphicsContext.h"
39 #include "InitializeThreading.h"
40 #include "InspectorClientWinCE.h"
42 #include "MainThread.h"
43 #include "NotImplemented.h"
45 #include "PlatformKeyboardEvent.h"
46 #include "PlatformMouseEvent.h"
47 #include "PlatformStrategiesWinCE.h"
48 #include "PlatformWheelEvent.h"
49 #include "ResourceRequest.h"
51 #include "SharedBuffer.h"
52 #include "WebCoreInstanceHandle.h"
54 using namespace WebCore;
56 const LPCWSTR kWebViewWindowClassName = L"WebViewWindowClass";
59 LRESULT CALLBACK WebView::webViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
61 if (WebView* webView = reinterpret_cast<WebView*>(GetWindowLong(hWnd, 0)))
62 return webView->wndProc(hWnd, message, wParam, lParam);
64 return DefWindowProc(hWnd, message, wParam, lParam);
67 PassRefPtr<SharedBuffer> loadResourceIntoBuffer(const char* name)
74 WebView::WebView(HWND hwnd, unsigned features)
77 , m_parentWindowHandle(hwnd)
78 , m_enableDoubleBuffer(features & EnableDoubleBuffering)
81 GetClientRect(hwnd, &rcClient);
83 m_windowHandle = CreateWindow(kWebViewWindowClassName, 0, WS_CHILD,
84 CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, hwnd, 0, WebCore::instanceHandle(), 0);
86 SetWindowLong(m_windowHandle, 0, reinterpret_cast<LONG>(this));
88 MoveWindow(m_windowHandle, 0, 0, rcClient.right, rcClient.bottom, TRUE);
89 ShowWindow(m_windowHandle, SW_SHOW);
91 Page::PageClients pageClients;
92 pageClients.chromeClient = new WebKit::ChromeClientWinCE(this);
93 pageClients.contextMenuClient = new WebKit::ContextMenuClientWinCE(this);
94 pageClients.editorClient = new WebKit::EditorClientWinCE(this);
95 pageClients.dragClient = new WebKit::DragClientWinCE();
96 pageClients.inspectorClient = new WebKit::InspectorClientWinCE(this);
97 m_page = new Page(pageClients);
99 Settings* settings = m_page->settings();
100 settings->setDefaultFixedFontSize(14);
101 settings->setDefaultFontSize(14);
102 settings->setMinimumFontSize(8);
103 settings->setMinimumLogicalFontSize(8);
104 settings->setJavaScriptEnabled(true);
105 settings->setLoadsImagesAutomatically(true);
107 WebKit::FrameLoaderClientWinCE* loaderClient = new WebKit::FrameLoaderClientWinCE(this);
108 RefPtr<Frame> frame = Frame::create(m_page, 0, loaderClient);
109 m_frame = frame.get();
110 loaderClient->setFrame(m_frame);
112 m_page->mainFrame()->init();
116 frameRect(&windowRect);
117 view()->resize(IntRect(windowRect).size());
124 DestroyWindow(m_windowHandle);
127 void WebView::initialize(HINSTANCE instanceHandle)
129 JSC::initializeThreading();
130 WTF::initializeMainThread();
131 PlatformStrategiesWinCE::initialize();
133 WebCore::setInstanceHandle(instanceHandle);
136 wc.style = CS_DBLCLKS;
137 wc.lpfnWndProc = WebView::webViewWndProc;
139 wc.cbWndExtra = sizeof(void *);
140 wc.hInstance = instanceHandle;
142 wc.hCursor = LoadCursor(0, IDC_ARROW);
143 wc.hbrBackground = 0;
145 wc.lpszClassName = kWebViewWindowClassName;
150 void WebView::cleanup()
152 UnregisterClass(kWebViewWindowClassName, WebCore::instanceHandle());
155 PassRefPtr<Frame> WebView::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement, const String& referrer,
156 bool /*allowsScrolling*/, int /*marginWidth*/, int /*marginHeight*/)
158 Frame* coreFrame = m_frame;
160 WebKit::FrameLoaderClientWinCE *loaderClient = new WebKit::FrameLoaderClientWinCE(this);
161 RefPtr<Frame> childFrame = Frame::create(m_page, ownerElement, loaderClient);
162 loaderClient->setFrame(childFrame.get());
164 coreFrame->tree()->appendChild(childFrame);
165 childFrame->tree()->setName(name);
168 // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
169 if (!childFrame->page())
172 coreFrame->loader()->loadURLIntoChildFrame(url, referrer, childFrame.get());
174 // The frame's onload handler may have removed it from the document.
175 if (!childFrame->tree()->parent())
178 return childFrame.release();
181 void WebView::runJavaScriptAlert(const String& message)
186 bool WebView::runJavaScriptConfirm(const String& message)
192 bool WebView::runJavaScriptPrompt(const String& message, const String& defaultValue, String& result)
198 void WebView::frameRect(RECT* rect) const
200 GetWindowRect(m_windowHandle, rect);
203 FrameView* WebView::view() const
205 return m_frame ? m_frame->view() : 0;
208 void WebView::load(LPCWSTR url)
213 void WebView::load(const String &url)
215 load(WebCore::ResourceRequest(url));
218 void WebView::load(const WebCore::ResourceRequest &request)
220 frame()->loader()->load(request, false);
223 void WebView::reload()
225 frame()->loader()->reload();
230 frame()->loader()->stopAllLoaders();
233 void WebView::paint(HDC hDC, const IntRect& clipRect)
235 FrameView* frameView = view();
239 OwnPtr<HRGN> clipRgn(CreateRectRgn(clipRect.x(), clipRect.y(), clipRect.maxX(), clipRect.maxY()));
240 SelectClipRgn(hDC, clipRgn.get());
242 frameView->updateLayoutAndStyleIfNeededRecursive();
244 GraphicsContext gc(hDC);
245 frameView->paint(&gc, clipRect);
248 bool WebView::handlePaint(HWND hWnd)
251 if (!GetUpdateRect(hWnd, &updateRect, false))
255 HDC hDC = BeginPaint(m_windowHandle, &ps);
257 IntRect clipRect(updateRect);
259 if (m_enableDoubleBuffer) {
260 if (!m_doubleBufferDC) {
262 GetClientRect(m_windowHandle, &rcClient);
264 m_doubleBufferDC = adoptPtr(CreateCompatibleDC(hDC));
265 m_doubleBufferBitmap = adoptPtr(CreateCompatibleBitmap(hDC, rcClient.right, rcClient.bottom));
266 SelectObject(m_doubleBufferDC.get(), m_doubleBufferBitmap.get());
269 paint(m_doubleBufferDC.get(), clipRect);
271 BitBlt(hDC, clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height(), m_doubleBufferDC.get(), clipRect.x(), clipRect.y(), SRCCOPY);
273 paint(hDC, clipRect);
275 EndPaint(m_windowHandle, &ps);
279 bool WebView::handleMouseEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
281 static LONG globalClickCount;
282 static IntPoint globalPrevPoint;
283 static MouseButton globalPrevButton;
284 static LONG globalPrevMouseDownTime;
287 // On WM_MOUSELEAVE we need to create a mouseout event, so we force the position
288 // of the event to be at (MINSHORT, MINSHORT).
289 PlatformMouseEvent mouseEvent(hWnd, message, wParam, lParam);
291 bool insideThreshold = abs(globalPrevPoint.x() - mouseEvent.pos().x()) < ::GetSystemMetrics(SM_CXDOUBLECLK)
292 && abs(globalPrevPoint.y() - mouseEvent.pos().y()) < ::GetSystemMetrics(SM_CYDOUBLECLK);
293 LONG messageTime = 0;
295 bool handled = false;
296 if (message == WM_LBUTTONDOWN || message == WM_MBUTTONDOWN || message == WM_RBUTTONDOWN) {
297 // FIXME: I'm not sure if this is the "right" way to do this
298 // but without this call, we never become focused since we don't allow
299 // the default handling of mouse events.
300 SetFocus(m_windowHandle);
302 PlatformMouseEvent moveEvent(hWnd, WM_MOUSEMOVE, 0, lParam, false);
303 moveEvent.setClickCount(0);
304 m_page->mainFrame()->eventHandler()->handleMouseMoveEvent(moveEvent);
306 // Always start capturing events when the mouse goes down in our HWND.
307 SetCapture(m_windowHandle);
309 if (insideThreshold && mouseEvent.button() == globalPrevButton)
312 // Reset the click count.
313 globalClickCount = 1;
314 globalPrevMouseDownTime = messageTime;
315 globalPrevButton = mouseEvent.button();
316 globalPrevPoint = mouseEvent.pos();
318 mouseEvent.setClickCount(globalClickCount);
319 handled = m_page->mainFrame()->eventHandler()->handleMousePressEvent(mouseEvent);
320 } else if (message == WM_LBUTTONDBLCLK || message == WM_MBUTTONDBLCLK || message == WM_RBUTTONDBLCLK) {
322 mouseEvent.setClickCount(globalClickCount);
323 handled = m_page->mainFrame()->eventHandler()->handleMousePressEvent(mouseEvent);
324 } else if (message == WM_LBUTTONUP || message == WM_MBUTTONUP || message == WM_RBUTTONUP) {
325 // Record the global position and the button of the up.
326 globalPrevButton = mouseEvent.button();
327 globalPrevPoint = mouseEvent.pos();
328 mouseEvent.setClickCount(globalClickCount);
329 m_page->mainFrame()->eventHandler()->handleMouseReleaseEvent(mouseEvent);
331 } else if (message == WM_MOUSEMOVE) {
332 if (!insideThreshold)
333 globalClickCount = 0;
334 mouseEvent.setClickCount(globalClickCount);
335 handled = m_page->mainFrame()->eventHandler()->mouseMoved(mouseEvent);
341 bool WebView::handleMouseWheel(HWND hWnd, WPARAM wParam, LPARAM lParam, bool isHorizontal)
343 PlatformWheelEvent wheelEvent(hWnd, wParam, lParam, isHorizontal);
344 return frame()->eventHandler()->handleWheelEvent(wheelEvent);
347 bool WebView::handleKeyDown(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown)
349 Frame* frame = m_page->focusController()->focusedOrMainFrame();
351 PlatformKeyboardEvent keyEvent(m_windowHandle, virtualKeyCode, keyData, PlatformKeyboardEvent::RawKeyDown, systemKeyDown);
352 bool handled = frame->eventHandler()->keyEvent(keyEvent);
354 // These events cannot be canceled, and we have no default handling for them.
355 // FIXME: match IE list more closely, see <http://msdn2.microsoft.com/en-us/library/ms536938.aspx>.
356 if (systemKeyDown && virtualKeyCode != VK_RETURN)
362 ::PeekMessage(&msg, m_windowHandle, WM_CHAR, WM_CHAR, PM_REMOVE);
369 bool WebView::handleKeyPress(WPARAM charCode, LPARAM keyData, bool systemKeyDown)
371 Frame* frame = m_page->focusController()->focusedOrMainFrame();
373 PlatformKeyboardEvent keyEvent(m_windowHandle, charCode, keyData, PlatformKeyboardEvent::Char, systemKeyDown);
374 // IE does not dispatch keypress event for WM_SYSCHAR.
376 return frame->eventHandler()->handleAccessKey(keyEvent);
377 if (frame->eventHandler()->keyEvent(keyEvent))
383 bool WebView::handleKeyUp(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown)
385 PlatformKeyboardEvent keyEvent(m_windowHandle, virtualKeyCode, keyData, PlatformKeyboardEvent::KeyUp, systemKeyDown);
387 Frame* frame = m_page->focusController()->focusedOrMainFrame();
388 return frame->eventHandler()->keyEvent(keyEvent);
391 LRESULT WebView::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
393 bool handled = false;
398 handled = handlePaint(hWnd);
405 case WM_LBUTTONDBLCLK:
406 case WM_MBUTTONDBLCLK:
407 case WM_RBUTTONDBLCLK:
411 if (frame()->eventHandler() && view()->didFirstLayout())
412 handled = handleMouseEvent(hWnd, message, wParam, lParam);
416 if (frame()->eventHandler() && view()->didFirstLayout())
417 handled = handleMouseWheel(hWnd, wParam, lParam, wParam & MK_SHIFT);
421 handled = handleKeyDown(wParam, lParam, true);
425 handled = handleKeyDown(wParam, lParam, false);
429 handled = handleKeyUp(wParam, lParam, true);
433 handled = handleKeyUp(wParam, lParam, false);
437 handled = handleKeyPress(wParam, lParam, true);
441 handled = handleKeyPress(wParam, lParam, false);
445 PostMessage(m_parentWindowHandle, WM_CLOSE, wParam, lParam);
457 return DefWindowProc(hWnd, message, wParam, lParam);