• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2006, 2007, 2008, 2009, 2010 Apple, Inc.  All rights reserved.
3  * Copyright (C) 2010 Patrick Gansterer <paroga@paroga.com>
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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.
13  *
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.
24  */
25 
26 #include "config.h"
27 #include "WebView.h"
28 
29 #include "ChromeClientWinCE.h"
30 #include "ContextMenuClientWinCE.h"
31 #include "DragClientWinCE.h"
32 #include "EditorClientWinCE.h"
33 #include "FocusController.h"
34 #include "Frame.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"
41 #include "IntSize.h"
42 #include "MainThread.h"
43 #include "NotImplemented.h"
44 #include "Page.h"
45 #include "PlatformKeyboardEvent.h"
46 #include "PlatformMouseEvent.h"
47 #include "PlatformStrategiesWinCE.h"
48 #include "PlatformWheelEvent.h"
49 #include "ResourceRequest.h"
50 #include "Settings.h"
51 #include "SharedBuffer.h"
52 #include "WebCoreInstanceHandle.h"
53 
54 using namespace WebCore;
55 
56 const LPCWSTR kWebViewWindowClassName = L"WebViewWindowClass";
57 
58 
webViewWndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)59 LRESULT CALLBACK WebView::webViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
60 {
61     if (WebView* webView = reinterpret_cast<WebView*>(GetWindowLong(hWnd, 0)))
62         return webView->wndProc(hWnd, message, wParam, lParam);
63 
64     return DefWindowProc(hWnd, message, wParam, lParam);
65 }
66 
loadResourceIntoBuffer(const char * name)67 PassRefPtr<SharedBuffer> loadResourceIntoBuffer(const char* name)
68 {
69     notImplemented();
70     return 0;
71 }
72 
73 
WebView(HWND hwnd,unsigned features)74 WebView::WebView(HWND hwnd, unsigned features)
75     : m_frame(0)
76     , m_page(0)
77     , m_parentWindowHandle(hwnd)
78     , m_enableDoubleBuffer(features & EnableDoubleBuffering)
79 {
80     RECT rcClient;
81     GetClientRect(hwnd, &rcClient);
82 
83     m_windowHandle = CreateWindow(kWebViewWindowClassName, 0, WS_CHILD,
84         CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, hwnd, 0, WebCore::instanceHandle(), 0);
85 
86     SetWindowLong(m_windowHandle, 0, reinterpret_cast<LONG>(this));
87 
88     MoveWindow(m_windowHandle, 0, 0, rcClient.right, rcClient.bottom, TRUE);
89     ShowWindow(m_windowHandle, SW_SHOW);
90 
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);
98 
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);
106 
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);
111 
112     m_page->mainFrame()->init();
113 
114     if (view()) {
115         RECT windowRect;
116         frameRect(&windowRect);
117         view()->resize(IntRect(windowRect).size());
118     }
119 }
120 
~WebView()121 WebView::~WebView()
122 {
123     delete m_page;
124     DestroyWindow(m_windowHandle);
125 }
126 
initialize(HINSTANCE instanceHandle)127 void WebView::initialize(HINSTANCE instanceHandle)
128 {
129     JSC::initializeThreading();
130     WTF::initializeMainThread();
131     PlatformStrategiesWinCE::initialize();
132 
133     WebCore::setInstanceHandle(instanceHandle);
134 
135     WNDCLASS wc;
136     wc.style          = CS_DBLCLKS;
137     wc.lpfnWndProc    = WebView::webViewWndProc;
138     wc.cbClsExtra     = 0;
139     wc.cbWndExtra     = sizeof(void *);
140     wc.hInstance      = instanceHandle;
141     wc.hIcon          = 0;
142     wc.hCursor        = LoadCursor(0, IDC_ARROW);
143     wc.hbrBackground  = 0;
144     wc.lpszMenuName   = 0;
145     wc.lpszClassName  = kWebViewWindowClassName;
146 
147     RegisterClass(&wc);
148 }
149 
cleanup()150 void WebView::cleanup()
151 {
152     UnregisterClass(kWebViewWindowClassName, WebCore::instanceHandle());
153 }
154 
createFrame(const KURL & url,const String & name,HTMLFrameOwnerElement * ownerElement,const String & referrer,bool,int,int)155 PassRefPtr<Frame> WebView::createFrame(const KURL& url, const String& name, HTMLFrameOwnerElement* ownerElement, const String& referrer,
156                                        bool /*allowsScrolling*/, int /*marginWidth*/, int /*marginHeight*/)
157 {
158     Frame* coreFrame = m_frame;
159 
160     WebKit::FrameLoaderClientWinCE *loaderClient = new WebKit::FrameLoaderClientWinCE(this);
161     RefPtr<Frame> childFrame = Frame::create(m_page, ownerElement, loaderClient);
162     loaderClient->setFrame(childFrame.get());
163 
164     coreFrame->tree()->appendChild(childFrame);
165     childFrame->tree()->setName(name);
166     childFrame->init();
167 
168     // The creation of the frame may have run arbitrary JavaScript that removed it from the page already.
169     if (!childFrame->page())
170         return 0;
171 
172     coreFrame->loader()->loadURLIntoChildFrame(url, referrer, childFrame.get());
173 
174     // The frame's onload handler may have removed it from the document.
175     if (!childFrame->tree()->parent())
176         return 0;
177 
178     return childFrame.release();
179 }
180 
runJavaScriptAlert(const String & message)181 void WebView::runJavaScriptAlert(const String& message)
182 {
183     notImplemented();
184 }
185 
runJavaScriptConfirm(const String & message)186 bool WebView::runJavaScriptConfirm(const String& message)
187 {
188     notImplemented();
189     return false;
190 }
191 
runJavaScriptPrompt(const String & message,const String & defaultValue,String & result)192 bool WebView::runJavaScriptPrompt(const String& message, const String& defaultValue, String& result)
193 {
194     notImplemented();
195     return false;
196 }
197 
frameRect(RECT * rect) const198 void WebView::frameRect(RECT* rect) const
199 {
200     GetWindowRect(m_windowHandle, rect);
201 }
202 
view() const203 FrameView* WebView::view() const
204 {
205     return m_frame ? m_frame->view() : 0;
206 }
207 
load(LPCWSTR url)208 void WebView::load(LPCWSTR url)
209 {
210     load(String(url));
211 }
212 
load(const String & url)213 void WebView::load(const String &url)
214 {
215     load(WebCore::ResourceRequest(url));
216 }
217 
load(const WebCore::ResourceRequest & request)218 void WebView::load(const WebCore::ResourceRequest &request)
219 {
220     frame()->loader()->load(request, false);
221 }
222 
reload()223 void WebView::reload()
224 {
225     frame()->loader()->reload();
226 }
227 
stop()228 void WebView::stop()
229 {
230     frame()->loader()->stopAllLoaders();
231 }
232 
paint(HDC hDC,const IntRect & clipRect)233 void WebView::paint(HDC hDC, const IntRect& clipRect)
234 {
235     FrameView* frameView = view();
236     if (!frameView)
237         return;
238 
239     OwnPtr<HRGN> clipRgn(CreateRectRgn(clipRect.x(), clipRect.y(), clipRect.maxX(), clipRect.maxY()));
240     SelectClipRgn(hDC, clipRgn.get());
241 
242     frameView->updateLayoutAndStyleIfNeededRecursive();
243 
244     GraphicsContext gc(hDC);
245     frameView->paint(&gc, clipRect);
246 }
247 
handlePaint(HWND hWnd)248 bool WebView::handlePaint(HWND hWnd)
249 {
250     RECT updateRect;
251     if (!GetUpdateRect(hWnd, &updateRect, false))
252         return false;
253 
254     PAINTSTRUCT ps;
255     HDC hDC = BeginPaint(m_windowHandle, &ps);
256 
257     IntRect clipRect(updateRect);
258 
259     if (m_enableDoubleBuffer) {
260         if (!m_doubleBufferDC) {
261             RECT rcClient;
262             GetClientRect(m_windowHandle, &rcClient);
263 
264             m_doubleBufferDC = adoptPtr(CreateCompatibleDC(hDC));
265             m_doubleBufferBitmap = adoptPtr(CreateCompatibleBitmap(hDC, rcClient.right, rcClient.bottom));
266             SelectObject(m_doubleBufferDC.get(), m_doubleBufferBitmap.get());
267         }
268 
269         paint(m_doubleBufferDC.get(), clipRect);
270 
271         BitBlt(hDC, clipRect.x(), clipRect.y(), clipRect.width(), clipRect.height(), m_doubleBufferDC.get(), clipRect.x(), clipRect.y(), SRCCOPY);
272     } else
273         paint(hDC, clipRect);
274 
275     EndPaint(m_windowHandle, &ps);
276     return true;
277 }
278 
handleMouseEvent(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)279 bool WebView::handleMouseEvent(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
280 {
281     static LONG globalClickCount;
282     static IntPoint globalPrevPoint;
283     static MouseButton globalPrevButton;
284     static LONG globalPrevMouseDownTime;
285 
286     // Create our event.
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);
290 
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;
294 
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);
301 
302         PlatformMouseEvent moveEvent(hWnd, WM_MOUSEMOVE, 0, lParam, false);
303         moveEvent.setClickCount(0);
304         m_page->mainFrame()->eventHandler()->handleMouseMoveEvent(moveEvent);
305 
306         // Always start capturing events when the mouse goes down in our HWND.
307         SetCapture(m_windowHandle);
308 
309         if (insideThreshold && mouseEvent.button() == globalPrevButton)
310             globalClickCount++;
311         else
312             // Reset the click count.
313             globalClickCount = 1;
314         globalPrevMouseDownTime = messageTime;
315         globalPrevButton = mouseEvent.button();
316         globalPrevPoint = mouseEvent.pos();
317 
318         mouseEvent.setClickCount(globalClickCount);
319         handled = m_page->mainFrame()->eventHandler()->handleMousePressEvent(mouseEvent);
320     } else if (message == WM_LBUTTONDBLCLK || message == WM_MBUTTONDBLCLK || message == WM_RBUTTONDBLCLK) {
321         globalClickCount++;
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);
330         ReleaseCapture();
331     } else if (message == WM_MOUSEMOVE) {
332         if (!insideThreshold)
333             globalClickCount = 0;
334         mouseEvent.setClickCount(globalClickCount);
335         handled = m_page->mainFrame()->eventHandler()->mouseMoved(mouseEvent);
336     }
337 
338     return handled;
339 }
340 
handleMouseWheel(HWND hWnd,WPARAM wParam,LPARAM lParam,bool isHorizontal)341 bool WebView::handleMouseWheel(HWND hWnd, WPARAM wParam, LPARAM lParam, bool isHorizontal)
342 {
343     PlatformWheelEvent wheelEvent(hWnd, wParam, lParam, isHorizontal);
344     return frame()->eventHandler()->handleWheelEvent(wheelEvent);
345 }
346 
handleKeyDown(WPARAM virtualKeyCode,LPARAM keyData,bool systemKeyDown)347 bool WebView::handleKeyDown(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown)
348 {
349     Frame* frame = m_page->focusController()->focusedOrMainFrame();
350 
351     PlatformKeyboardEvent keyEvent(m_windowHandle, virtualKeyCode, keyData, PlatformKeyboardEvent::RawKeyDown, systemKeyDown);
352     bool handled = frame->eventHandler()->keyEvent(keyEvent);
353 
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)
357         return false;
358 
359     if (handled) {
360         MSG msg;
361         if (!systemKeyDown)
362             ::PeekMessage(&msg, m_windowHandle, WM_CHAR, WM_CHAR, PM_REMOVE);
363         return true;
364     }
365 
366     return handled;
367 }
368 
handleKeyPress(WPARAM charCode,LPARAM keyData,bool systemKeyDown)369 bool WebView::handleKeyPress(WPARAM charCode, LPARAM keyData, bool systemKeyDown)
370 {
371     Frame* frame = m_page->focusController()->focusedOrMainFrame();
372 
373     PlatformKeyboardEvent keyEvent(m_windowHandle, charCode, keyData, PlatformKeyboardEvent::Char, systemKeyDown);
374     // IE does not dispatch keypress event for WM_SYSCHAR.
375     if (systemKeyDown)
376         return frame->eventHandler()->handleAccessKey(keyEvent);
377     if (frame->eventHandler()->keyEvent(keyEvent))
378         return true;
379 
380     return false;
381 }
382 
handleKeyUp(WPARAM virtualKeyCode,LPARAM keyData,bool systemKeyDown)383 bool WebView::handleKeyUp(WPARAM virtualKeyCode, LPARAM keyData, bool systemKeyDown)
384 {
385     PlatformKeyboardEvent keyEvent(m_windowHandle, virtualKeyCode, keyData, PlatformKeyboardEvent::KeyUp, systemKeyDown);
386 
387     Frame* frame = m_page->focusController()->focusedOrMainFrame();
388     return frame->eventHandler()->keyEvent(keyEvent);
389 }
390 
wndProc(HWND hWnd,UINT message,WPARAM wParam,LPARAM lParam)391 LRESULT WebView::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
392 {
393     bool handled = false;
394 
395     if (view()) {
396         switch (message) {
397         case WM_PAINT:
398             handled = handlePaint(hWnd);
399             break;
400 
401         case WM_MOUSEMOVE:
402         case WM_LBUTTONDOWN:
403         case WM_MBUTTONDOWN:
404         case WM_RBUTTONDOWN:
405         case WM_LBUTTONDBLCLK:
406         case WM_MBUTTONDBLCLK:
407         case WM_RBUTTONDBLCLK:
408         case WM_LBUTTONUP:
409         case WM_MBUTTONUP:
410         case WM_RBUTTONUP:
411             if (frame()->eventHandler() && view()->didFirstLayout())
412                 handled = handleMouseEvent(hWnd, message, wParam, lParam);
413             break;
414 
415         case WM_MOUSEWHEEL:
416             if (frame()->eventHandler() && view()->didFirstLayout())
417                 handled = handleMouseWheel(hWnd, wParam, lParam, wParam & MK_SHIFT);
418             break;
419 
420         case WM_SYSKEYDOWN:
421             handled = handleKeyDown(wParam, lParam, true);
422             break;
423 
424         case WM_KEYDOWN:
425             handled = handleKeyDown(wParam, lParam, false);
426             break;
427 
428         case WM_SYSKEYUP:
429             handled = handleKeyUp(wParam, lParam, true);
430             break;
431 
432         case WM_KEYUP:
433             handled = handleKeyUp(wParam, lParam, false);
434             break;
435 
436         case WM_SYSCHAR:
437             handled = handleKeyPress(wParam, lParam, true);
438             break;
439 
440         case WM_CHAR:
441             handled = handleKeyPress(wParam, lParam, false);
442             break;
443 
444         case WM_CLOSE:
445             PostMessage(m_parentWindowHandle, WM_CLOSE, wParam, lParam);
446             handled = true;
447             break;
448 
449         default:
450             break;
451         }
452     }
453 
454     if (handled)
455         return 0;
456 
457     return DefWindowProc(hWnd, message, wParam, lParam);
458 }
459