Reviewed by Eric.
[WebKit-https.git] / WebKitTools / Spinneret / Spinneret / WebView.cpp
1 /*
2  * Copyright (C) 2006 Apple Computer, Inc.  All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE COMPUTER, INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #include "stdafx.h"
27 #include "config.h"
28
29 #include "WebFrame.h"
30
31 #include "WebView.h"
32 #include "Resource.h"
33 #include "FrameView.h"
34 #include "MouseEvent.h"
35 #include "IntRect.h"
36
37 using namespace WebCore;
38
39 namespace WebKit {
40
41 class WebView::WebViewPrivate {
42 public:
43     WebViewPrivate() {}
44     ~WebViewPrivate()
45     {
46         delete mainFrame;
47     }
48
49     WebFrame* mainFrame;
50     HWND windowHandle;
51 };
52
53 const LPCWSTR kWebViewWindowClassName = L"WebViewWindowClass";
54
55 LRESULT CALLBACK WebViewWndProc(HWND, UINT, WPARAM, LPARAM);
56
57 static ATOM registerWebViewWithInstance(HINSTANCE hInstance)
58 {
59     static bool haveRegisteredWindowClass = false;
60     if (haveRegisteredWindowClass)
61         return true;
62
63     WNDCLASSEX wcex;
64
65     wcex.cbSize = sizeof(WNDCLASSEX);
66
67     wcex.style          = CS_DBLCLKS;
68     wcex.lpfnWndProc    = WebViewWndProc;
69     wcex.cbClsExtra     = 0;
70     wcex.cbWndExtra     = 4; // 4 bytes for the WebView pointer
71     wcex.hInstance      = hInstance;
72     wcex.hIcon          = 0;
73     wcex.hCursor        = LoadCursor(0, IDC_ARROW);
74     wcex.hbrBackground  = 0;
75     wcex.lpszMenuName   = 0;
76     wcex.lpszClassName  = kWebViewWindowClassName;
77     wcex.hIconSm        = 0;
78
79     return RegisterClassEx(&wcex);
80 }
81
82 // FIXME: This should eventually just use the DLL instance, I think.
83 WebView* WebView::createWebView(HINSTANCE hInstance, HWND parent)
84 {
85     // Save away our instace handle for WebCore to use.
86     Widget::instanceHandle = hInstance;
87
88     registerWebViewWithInstance(hInstance);
89
90     HWND hWnd = CreateWindow(kWebViewWindowClassName, 0, WS_CHILD | WS_HSCROLL | WS_VSCROLL,
91        CW_USEDEFAULT, 0, CW_USEDEFAULT, 0, parent, 0, hInstance, 0);
92
93     if (!hWnd)
94         return 0;
95
96     WebView* newWebView = new WebView(hWnd);
97     SetWindowLongPtr(hWnd, 0, (LONG)newWebView);
98     return newWebView;
99 }
100
101 WebView::WebView(HWND hWnd)
102 {
103     d = new WebViewPrivate();
104     d->windowHandle = hWnd;
105     d->mainFrame = new WebFrame("dummy", this);
106     d->mainFrame->loadHTMLString("<p style=\"background-color: #00FF00\">Testing</p><img src=\"http://webkit.opendarwin.org/images/icon-gold.png\" alt=\"Face\"><div style=\"border: solid blue\">div with blue border</div><ul><li>foo<li>bar<li>baz</ul>");
107 }
108
109 WebView::~WebView()
110 {
111     delete d;
112 }
113
114 HWND WebView::windowHandle()
115 {
116     return d->windowHandle;
117 }
118
119 WebFrame* WebView::mainFrame()
120 {
121     return d->mainFrame;
122 }
123
124 void WebView::mouseMoved(HWND hWnd, WPARAM wParam, LPARAM lParam)
125 {
126     MouseEvent mouseEvent(hWnd, wParam, lParam, 0);
127     d->mainFrame->viewImpl()->viewportMouseMoveEvent(&mouseEvent);
128 }
129
130 void WebView::mouseDown(HWND hWnd, WPARAM wParam, LPARAM lParam)
131 {
132     MouseEvent mouseEvent(hWnd, wParam, lParam, 1);
133     d->mainFrame->viewImpl()->viewportMousePressEvent(&mouseEvent);
134 }
135
136 void WebView::mouseUp(HWND hWnd, WPARAM wParam, LPARAM lParam)
137 {
138     MouseEvent mouseEvent(hWnd, wParam, lParam, 1);
139     d->mainFrame->viewImpl()->viewportMouseReleaseEvent(&mouseEvent);
140 }
141
142 void WebView::mouseDoubleClick(HWND hWnd, WPARAM wParam, LPARAM lParam)
143 {
144     MouseEvent mouseEvent(hWnd, wParam, lParam, 2);
145     d->mainFrame->viewImpl()->viewportMouseReleaseEvent(&mouseEvent);
146 }
147
148 #define LINE_SCROLL_SIZE 30
149
150 static int calculateScrollDelta(WPARAM wParam, int oldPosition, int pageSize)
151 {
152     switch (LOWORD(wParam)) {
153         case SB_PAGEUP: 
154             return -(pageSize - LINE_SCROLL_SIZE); 
155          case SB_PAGEDOWN: 
156             return (pageSize - LINE_SCROLL_SIZE); 
157         case SB_LINEUP: 
158             return -LINE_SCROLL_SIZE;
159         case SB_LINEDOWN: 
160             return LINE_SCROLL_SIZE;
161         case SB_THUMBPOSITION: 
162             return HIWORD(wParam) - oldPosition; 
163     }
164     return 0;
165 }
166
167 static int scrollMessageForKey(WPARAM keyCode)
168 {
169     switch (keyCode) {
170     case VK_UP:
171         return SB_LINEUP;
172     case VK_PRIOR: 
173         return SB_PAGEUP;
174     case VK_NEXT:
175         return SB_PAGEDOWN;
176     case VK_DOWN:
177         return SB_LINEDOWN;
178     case VK_HOME:
179         return SB_TOP;
180     case VK_END:
181         return SB_BOTTOM;
182     case VK_SPACE:
183         return (GetKeyState(VK_SHIFT) & 0x8000) ? SB_PAGEUP : SB_PAGEDOWN;
184     }
185     return -1;
186 }
187
188 LRESULT CALLBACK WebViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
189 {
190     int wmId, wmEvent;
191     WebView* webview = (WebView*)GetWindowLongPtr(hWnd, 0);
192     switch (message)
193     {
194     case WM_PAINT:
195         webview->mainFrame()->paint();
196         break;
197     case WM_DESTROY:
198         // Do nothing?
199         break;
200     case WM_MOUSEMOVE:
201         webview->mouseMoved(hWnd, wParam, lParam);
202         break;
203     case WM_LBUTTONDOWN:
204         // Make ourselves the focused window before doing anything else
205         // FIXME: I'm not sure if this is the "right" way to do this
206         // but w/o this call, we never become focused since we don't allow
207         // the default handling of mouse events.
208         SetFocus(hWnd);
209     case WM_MBUTTONDOWN:
210     case WM_RBUTTONDOWN:
211         webview->mouseDown(hWnd, wParam, lParam);
212         break;
213     case WM_LBUTTONUP:
214     case WM_MBUTTONUP:
215     case WM_RBUTTONUP:
216         webview->mouseUp(hWnd, wParam, lParam);
217         break;
218     case WM_LBUTTONDBLCLK:
219     case WM_MBUTTONDBLCLK:
220     case WM_RBUTTONDBLCLK:
221         webview->mouseDoubleClick(hWnd, wParam, lParam);
222         break;
223     case WM_HSCROLL: {
224         ScrollView* view = webview->mainFrame()->impl()->view();
225         view->scrollBy(calculateScrollDelta(wParam, view->contentsX(), view->visibleWidth()), 0);
226         break;
227     }
228     case WM_VSCROLL: {
229         ScrollView* view = webview->mainFrame()->impl()->view();
230         view->scrollBy(0, calculateScrollDelta(wParam, view->contentsY(), view->visibleHeight()));
231         break;
232     }
233     case WM_KEYDOWN: {
234         // FIXME: First we should send key events up through the DOM
235         // to form controls, etc.  If they are not handled, we fall
236         // through to the top level webview and do things like scrolling
237
238         WORD wScrollNotify = scrollMessageForKey(wParam);
239         if (wScrollNotify != -1)
240             SendMessage(hWnd, WM_VSCROLL, MAKELONG(wScrollNotify, 0), 0L);
241         break;
242     }
243     default:
244         return DefWindowProc(hWnd, message, wParam, lParam);
245     }
246     return 0;
247 }
248
249
250 };