initial import
[vuplus_webkit] / Source / WebKit2 / UIProcess / win / WebInspectorProxyWin.cpp
1 /*
2  * Copyright (C) 2010 Apple 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 INC. AND ITS CONTRIBUTORS ``AS IS''
14  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
15  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
17  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
18  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
19  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
20  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
21  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
22  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
23  * THE POSSIBILITY OF SUCH DAMAGE.
24  */
25
26 #include "config.h"
27 #include "WebInspectorProxy.h"
28
29 #if ENABLE(INSPECTOR)
30
31 #include "WebKitBundle.h"
32 #include "WebPageProxy.h"
33 #include "WebProcessProxy.h"
34 #include "WebView.h"
35 #include <WebCore/InspectorFrontendClientLocal.h>
36 #include <WebCore/WebCoreInstanceHandle.h>
37 #include <WebCore/WindowMessageBroadcaster.h>
38 #include <wtf/PassRefPtr.h>
39 #include <wtf/RetainPtr.h>
40 #include <wtf/text/StringConcatenate.h>
41 #include <wtf/text/WTFString.h>
42
43 using namespace WebCore;
44
45 namespace WebKit {
46
47 static const LPCWSTR kWebKit2InspectorWindowClassName = L"WebKit2InspectorWindowClass";
48
49 bool WebInspectorProxy::registerInspectorViewWindowClass()
50 {
51     static bool haveRegisteredWindowClass = false;
52     if (haveRegisteredWindowClass)
53         return true;
54     haveRegisteredWindowClass = true;
55
56     WNDCLASSEX wcex;
57
58     wcex.cbSize = sizeof(WNDCLASSEX);
59     wcex.style          = CS_DBLCLKS;
60     wcex.lpfnWndProc    = WebInspectorProxy::InspectorViewWndProc;
61     wcex.cbClsExtra     = 0;
62     wcex.cbWndExtra     = sizeof(WebInspectorProxy*);
63     wcex.hInstance      = instanceHandle();
64     wcex.hIcon          = 0;
65     wcex.hCursor        = ::LoadCursor(0, IDC_ARROW);
66     wcex.hbrBackground  = 0;
67     wcex.lpszMenuName   = 0;
68     wcex.lpszClassName  = kWebKit2InspectorWindowClassName;
69     wcex.hIconSm        = 0;
70
71     return !!::RegisterClassEx(&wcex);
72 }
73
74 LRESULT CALLBACK WebInspectorProxy::InspectorViewWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
75 {
76     LONG_PTR longPtr = ::GetWindowLongPtr(hWnd, 0);
77     
78     if (WebInspectorProxy* inspectorView = reinterpret_cast<WebInspectorProxy*>(longPtr))
79         return inspectorView->wndProc(hWnd, message, wParam, lParam);
80
81     if (message == WM_CREATE) {
82         LPCREATESTRUCT createStruct = reinterpret_cast<LPCREATESTRUCT>(lParam);
83
84         // Associate the WebInspectorProxy with the window.
85         ::SetWindowLongPtr(hWnd, 0, (LONG_PTR)createStruct->lpCreateParams);
86         return 0;
87     }
88
89     return ::DefWindowProc(hWnd, message, wParam, lParam);
90 }
91
92 void WebInspectorProxy::windowReceivedMessage(HWND, UINT msg, WPARAM wParam, LPARAM lParam)
93 {
94     ASSERT(m_isAttached);
95
96     switch (msg) {
97     case WM_WINDOWPOSCHANGING:
98         onWebViewWindowPosChangingEvent(wParam, lParam);
99         break;
100     default:
101         break;
102     }
103 }
104
105 LRESULT WebInspectorProxy::wndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
106 {
107     LRESULT lResult = 0;
108     bool handled = true;
109
110     switch (message) {
111     case WM_SIZE:
112         lResult = onSizeEvent(hWnd, message, wParam, lParam, handled);
113         break;
114     case WM_GETMINMAXINFO:
115         lResult = onMinMaxInfoEvent(hWnd, message, wParam, lParam, handled);
116         break;
117     case WM_SETFOCUS:
118         lResult = onSetFocusEvent(hWnd, message, wParam, lParam, handled);
119         break;
120     case WM_CLOSE:
121         lResult = onCloseEvent(hWnd, message, wParam, lParam, handled);
122         break;
123     default:
124         handled = false;
125         break;
126     }
127
128     if (!handled)
129         lResult = ::DefWindowProc(hWnd, message, wParam, lParam);
130
131     return lResult;
132 }
133
134 LRESULT WebInspectorProxy::onSizeEvent(HWND, UINT, WPARAM, LPARAM, bool&)
135 {
136     RECT rect;
137     ::GetClientRect(m_inspectorWindow, &rect);
138
139     ::SetWindowPos(m_inspectorView->window(), 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER);
140
141     return 0;
142 }
143
144 LRESULT WebInspectorProxy::onSetFocusEvent(HWND, UINT, WPARAM, LPARAM lParam, bool&)
145 {    
146     ::SetFocus(m_inspectorView->window());
147
148     return 0;
149 }
150
151 LRESULT WebInspectorProxy::onMinMaxInfoEvent(HWND, UINT, WPARAM, LPARAM lParam, bool&)
152 {
153     MINMAXINFO* info = reinterpret_cast<MINMAXINFO*>(lParam);
154     POINT size = {minimumWindowWidth, minimumWindowHeight};
155     info->ptMinTrackSize = size;
156
157     return 0;
158 }
159
160 LRESULT WebInspectorProxy::onCloseEvent(HWND, UINT, WPARAM, LPARAM, bool&)
161 {
162     ::ShowWindow(m_inspectorWindow, SW_HIDE);
163     close();
164
165     return 0;
166 }
167
168 void WebInspectorProxy::onWebViewWindowPosChangingEvent(WPARAM wParam, LPARAM lParam)
169 {
170     WINDOWPOS* windowPos = reinterpret_cast<WINDOWPOS*>(lParam);
171
172     if (windowPos->flags & SWP_NOSIZE)
173         return;
174
175     HWND inspectorWindow = m_inspectorView->window();
176
177     RECT inspectorRect;
178     ::GetClientRect(inspectorWindow, &inspectorRect);
179     unsigned inspectorHeight = inspectorRect.bottom - inspectorRect.top;
180
181     RECT parentRect;
182     ::GetClientRect(::GetParent(inspectorWindow), &parentRect);
183     inspectorHeight = InspectorFrontendClientLocal::constrainedAttachedWindowHeight(inspectorHeight, parentRect.bottom - parentRect.top);
184
185     windowPos->cy -= inspectorHeight;
186
187     ::SetWindowPos(inspectorWindow, 0, windowPos->x, windowPos->y + windowPos->cy, windowPos->cx, inspectorHeight, SWP_NOZORDER);
188 }
189
190 WebPageProxy* WebInspectorProxy::platformCreateInspectorPage()
191 {
192     ASSERT(!m_inspectorView);
193     ASSERT(!m_inspectorWindow);
194
195     RECT initialRect = { 0, 0, initialWindowWidth, initialWindowHeight };
196     m_inspectorView = WebView::create(initialRect, m_page->process()->context(), inspectorPageGroup(), 0);
197
198     return m_inspectorView->page();
199 }
200
201 void WebInspectorProxy::platformOpen()
202 {
203     registerInspectorViewWindowClass();
204
205     m_inspectorWindow = ::CreateWindowEx(0, kWebKit2InspectorWindowClassName, 0, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN,
206         0, 0, initialWindowWidth, initialWindowHeight, 0, 0, instanceHandle(), this);
207     ASSERT(::IsWindow(m_inspectorWindow));
208
209     m_inspectorView->setParentWindow(m_inspectorWindow);
210
211     if (m_isAttached)
212         platformAttach();
213     else
214         ::ShowWindow(m_inspectorWindow, SW_SHOW);
215 }
216
217 void WebInspectorProxy::platformDidClose()
218 {
219     ASSERT(!m_isAttached);
220     ASSERT(!m_isVisible || m_inspectorWindow);
221     ASSERT(!m_isVisible || m_inspectorView);
222
223     if (m_inspectorWindow) {
224         ASSERT(::IsWindow(m_inspectorWindow));
225         ::DestroyWindow(m_inspectorWindow);
226     }
227
228     m_inspectorWindow = 0;
229     m_inspectorView = 0;
230 }
231
232 void WebInspectorProxy::platformBringToFront()
233 {
234     // FIXME: this will not bring a background tab in Safari to the front, only its window.
235     HWND parentWindow = m_isAttached ? ::GetAncestor(m_page->nativeWindow(), GA_ROOT) : m_inspectorWindow;
236     if (!parentWindow)
237         return;
238
239     ASSERT(::IsWindow(parentWindow));
240     ::SetWindowPos(parentWindow, HWND_TOP, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE);
241 }
242
243 void WebInspectorProxy::platformInspectedURLChanged(const String& urlString)
244 {
245     // FIXME: this should be made localizable once WebKit2 supports it. <rdar://problem/8728860>
246     String title = makeString("Web Inspector ", static_cast<UChar>(0x2014), ' ', urlString);
247     ::SetWindowTextW(m_inspectorWindow, title.charactersWithNullTermination());
248 }
249
250 unsigned WebInspectorProxy::platformInspectedWindowHeight()
251 {
252     HWND inspectedWindow = m_page->nativeWindow();
253
254     RECT inspectedWindowRect;
255     ::GetWindowRect(inspectedWindow, &inspectedWindowRect);
256
257     return static_cast<unsigned>(inspectedWindowRect.bottom - inspectedWindowRect.top);
258 }
259
260 void WebInspectorProxy::platformAttach()
261 {
262     HWND webViewWindow = m_page->nativeWindow();
263     HWND parentWindow = ::GetParent(webViewWindow);
264
265     WindowMessageBroadcaster::addListener(webViewWindow, this);
266     m_inspectorView->setParentWindow(parentWindow);
267     ::ShowWindow(m_inspectorWindow, SW_HIDE);
268
269     ::PostMessage(parentWindow, WM_SIZE, 0, 0);
270 }
271
272 void WebInspectorProxy::platformDetach()
273 {
274     HWND webViewWindow = m_page->nativeWindow();
275     WindowMessageBroadcaster::removeListener(webViewWindow, this);
276
277     m_inspectorView->setParentWindow(m_inspectorWindow);
278
279     if (m_isVisible)
280         ::ShowWindow(m_inspectorWindow, SW_SHOW);
281
282     // Send the detached inspector window and the WebView's parent window WM_SIZE messages
283     // to have them re-layout correctly.
284     ::PostMessage(m_inspectorWindow, WM_SIZE, 0, 0);
285     ::PostMessage(::GetParent(webViewWindow), WM_SIZE, 0, 0);
286 }
287
288 void WebInspectorProxy::platformSetAttachedWindowHeight(unsigned height)
289 {
290     if (!m_isAttached)
291         return;
292
293     HWND inspectedWindow = m_page->nativeWindow();
294     HWND parentWindow = ::GetParent(inspectedWindow);
295
296     RECT parentWindowRect;
297     ::GetWindowRect(parentWindow, &parentWindowRect);
298
299     RECT inspectedWindowRect;
300     ::GetWindowRect(inspectedWindow, &inspectedWindowRect);
301
302     int totalHeight = parentWindowRect.bottom - parentWindowRect.top;
303     int webViewWidth = inspectedWindowRect.right - inspectedWindowRect.left;
304
305     POINT inspectedWindowOrigin = { inspectedWindowRect.left, inspectedWindowRect.top };
306     ::ScreenToClient(parentWindow, &inspectedWindowOrigin);
307
308     HWND inspectorWindow = m_inspectorView->window();
309     ::SetWindowPos(inspectorWindow, 0, inspectedWindowOrigin.x, totalHeight - height, webViewWidth, height, SWP_NOZORDER);
310
311     // We want to set the inspected web view height to the totalHeight, because the height adjustment
312     // of the inspected WebView happens in onWindowPosChanging, not here.
313     ::SetWindowPos(inspectedWindow, 0, inspectedWindowOrigin.x, inspectedWindowOrigin.y, webViewWidth, totalHeight, SWP_NOZORDER);
314
315     ::RedrawWindow(inspectorWindow, 0, 0, RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_UPDATENOW); 
316     ::RedrawWindow(inspectedWindow, 0, 0, RDW_INVALIDATE | RDW_ALLCHILDREN | RDW_UPDATENOW);
317 }
318
319 String WebInspectorProxy::inspectorPageURL() const
320 {
321     RetainPtr<CFURLRef> htmlURLRef(AdoptCF, CFBundleCopyResourceURL(webKitBundle(), CFSTR("inspector"), CFSTR("html"), CFSTR("inspector")));
322     if (!htmlURLRef)
323         return String();
324
325     return String(CFURLGetString(htmlURLRef.get()));
326 }
327
328 } // namespace WebKit
329
330 #endif // ENABLE(INSPECTOR)