[Release] Webkit2-efl-123997_0.11.86
[framework/web/webkit-efl.git] / Source / WebKit / win / WebNodeHighlight.cpp
1 /*
2  * Copyright (C) 2007 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  *
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  * 3.  Neither the name of Apple Computer, Inc. ("Apple") nor the names of
14  *     its contributors may be used to endorse or promote products derived
15  *     from this software without specific prior written permission. 
16  *
17  * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
18  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
19  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
20  * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
21  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
22  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
23  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
24  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27  */
28
29 #include "config.h"
30 #include "WebNodeHighlight.h"
31
32 #include "WebView.h"
33 #include <WebCore/BitmapInfo.h>
34 #include <WebCore/Color.h>
35 #include <WebCore/GraphicsContext.h>
36 #include <WebCore/HWndDC.h>
37 #include <WebCore/InspectorController.h>
38 #include <WebCore/Page.h>
39 #include <WebCore/WindowMessageBroadcaster.h>
40 #include <wtf/HashSet.h>
41 #include <wtf/OwnPtr.h>
42
43 using namespace WebCore;
44
45 static LPCTSTR kOverlayWindowClassName = TEXT("WebNodeHighlightWindowClass");
46 static ATOM registerOverlayClass();
47 static LPCTSTR kWebNodeHighlightPointerProp = TEXT("WebNodeHighlightPointer");
48
49 WebNodeHighlight::WebNodeHighlight(WebView* webView)
50     : 
51 #if ENABLE(INSPECTOR)    
52       m_inspectedWebView(webView),
53 #endif // ENABLE(INSPECTOR)
54       m_overlay(0)
55     , m_observedWindow(0)
56     , m_showsWhileWebViewIsVisible(false)
57 {
58 #if ENABLE(INSPECTOR)
59     m_inspectedWebView->viewWindow(reinterpret_cast<OLE_HANDLE*>(&m_inspectedWebViewWindow));
60 #endif // ENABLE(INSPECTOR)
61 }
62
63 WebNodeHighlight::~WebNodeHighlight()
64 {
65     if (m_observedWindow)
66         WindowMessageBroadcaster::removeListener(m_observedWindow, this);
67     if (m_inspectedWebViewWindow)
68         WindowMessageBroadcaster::removeListener(m_inspectedWebViewWindow, this);
69
70     if (m_overlay)
71         ::DestroyWindow(m_overlay);
72 }
73
74 void WebNodeHighlight::setShowsWhileWebViewIsVisible(bool shows)
75 {
76     if (m_showsWhileWebViewIsVisible == shows)
77         return;
78     m_showsWhileWebViewIsVisible = shows;
79
80     if (!m_showsWhileWebViewIsVisible) {
81         hide();
82         return;
83     }
84
85     bool webViewVisible = isWebViewVisible();
86
87     if (isShowing() == webViewVisible)
88         return;
89
90     if (webViewVisible)
91         show();
92     else
93         hide();
94 }
95
96 bool WebNodeHighlight::isWebViewVisible() const
97 {
98     if (!m_inspectedWebViewWindow)
99         return false;
100
101     return IsWindowVisible(m_inspectedWebViewWindow);
102 }
103
104 void WebNodeHighlight::show()
105 {
106     if (!m_overlay) {
107         registerOverlayClass();
108
109         m_overlay = ::CreateWindowEx(WS_EX_LAYERED | WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT, kOverlayWindowClassName, 0, WS_POPUP,
110                                      0, 0, 0, 0,
111                                      m_inspectedWebViewWindow, 0, 0, 0);
112         if (!m_overlay)
113             return;
114
115         ::SetProp(m_overlay, kWebNodeHighlightPointerProp, reinterpret_cast<HANDLE>(this));
116
117         m_observedWindow = GetAncestor(m_inspectedWebViewWindow, GA_ROOT);
118         WindowMessageBroadcaster::addListener(m_observedWindow, this);
119         WindowMessageBroadcaster::addListener(m_inspectedWebViewWindow, this);
120     }
121
122     ASSERT(m_showsWhileWebViewIsVisible);
123
124     update();
125     SetWindowPos(m_overlay, 0, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
126 }
127
128 void WebNodeHighlight::hide()
129 {
130     if (m_overlay)
131         ::ShowWindow(m_overlay, SW_HIDE);
132 }
133
134 bool WebNodeHighlight::isShowing() const
135 {
136     return m_overlay && ::IsWindowVisible(m_overlay);
137 }
138
139 void WebNodeHighlight::update()
140 {
141     ASSERT(m_overlay);
142
143     HDC hdc = ::CreateCompatibleDC(HWndDC(m_overlay));
144     if (!hdc)
145         return;
146
147     RECT webViewRect;
148     ::GetWindowRect(m_inspectedWebViewWindow, &webViewRect);
149
150     SIZE size;
151     size.cx = webViewRect.right - webViewRect.left;
152     size.cy = webViewRect.bottom - webViewRect.top;
153
154     if (!size.cx || !size.cy)
155         return;
156
157     BitmapInfo bitmapInfo = BitmapInfo::createBottomUp(IntSize(size));
158
159     void* pixels = 0;
160     OwnPtr<HBITMAP> hbmp = adoptPtr(::CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0));
161     ASSERT_WITH_MESSAGE(hbmp, "::CreateDIBSection failed with error %lu", ::GetLastError());
162
163     ::SelectObject(hdc, hbmp.get());
164
165     GraphicsContext context(hdc);
166 #if ENABLE(INSPECTOR)
167     m_inspectedWebView->page()->inspectorController()->drawHighlight(context);
168 #endif // ENABLE(INSPECTOR)
169
170     BLENDFUNCTION bf;
171     bf.BlendOp = AC_SRC_OVER;
172     bf.BlendFlags = 0;
173     bf.SourceConstantAlpha = 255;
174     bf.AlphaFormat = AC_SRC_ALPHA;
175
176     POINT srcPoint;
177     srcPoint.x = 0;
178     srcPoint.y = 0;
179
180     POINT dstPoint;
181     dstPoint.x = webViewRect.left;
182     dstPoint.y = webViewRect.top;
183
184     ::UpdateLayeredWindow(m_overlay, HWndDC(0), &dstPoint, &size, hdc, &srcPoint, 0, &bf, ULW_ALPHA);
185     ::DeleteDC(hdc);
186 }
187
188 void WebNodeHighlight::placeBehindWindow(HWND window)
189 {
190     ASSERT(m_overlay);
191     SetWindowPos(m_overlay, window, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
192 }
193
194 static ATOM registerOverlayClass()
195 {
196     static bool haveRegisteredWindowClass = false;
197
198     if (haveRegisteredWindowClass)
199         return true;
200
201     WNDCLASSEX wcex;
202
203     wcex.cbSize = sizeof(WNDCLASSEX);
204
205     wcex.style          = 0;
206     wcex.lpfnWndProc    = OverlayWndProc;
207     wcex.cbClsExtra     = 0;
208     wcex.cbWndExtra     = 0;
209     wcex.hInstance      = 0;
210     wcex.hIcon          = 0;
211     wcex.hCursor        = LoadCursor(0, IDC_ARROW);
212     wcex.hbrBackground  = 0;
213     wcex.lpszMenuName   = 0;
214     wcex.lpszClassName  = kOverlayWindowClassName;
215     wcex.hIconSm        = 0;
216
217     haveRegisteredWindowClass = true;
218
219     return ::RegisterClassEx(&wcex);
220 }
221
222 LRESULT CALLBACK OverlayWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
223 {
224     WebNodeHighlight* highlight = reinterpret_cast<WebNodeHighlight*>(::GetProp(hwnd, kWebNodeHighlightPointerProp));
225     if (!highlight)
226         return ::DefWindowProc(hwnd, msg, wParam, lParam);
227
228     return ::DefWindowProc(hwnd, msg, wParam, lParam);
229 }
230
231 void WebNodeHighlight::onWebViewShowWindow(bool showing)
232 {
233     if (!m_showsWhileWebViewIsVisible)
234         return;
235
236     if (isShowing() == showing)
237         return;
238
239     if (showing)
240         show();
241     else
242         hide();
243 }
244
245 void WebNodeHighlight::onWebViewWindowPosChanged(WINDOWPOS* windowPos)
246 {
247     bool sizing = !(windowPos->flags & SWP_NOSIZE);
248
249     if (!sizing)
250         return;
251
252     if (!isShowing())
253         return;
254
255     update();
256 }
257
258 void WebNodeHighlight::onRootWindowPosChanged(WINDOWPOS* windowPos)
259 {
260     bool moving = !(windowPos->flags & SWP_NOMOVE);
261     bool sizing = !(windowPos->flags & SWP_NOSIZE);
262
263     if (!moving)
264         return;
265
266     // Size changes are handled by onWebViewWindowPosChanged.
267     if (sizing)
268         return;
269
270     if (!isShowing())
271         return;
272
273     update();
274 }
275
276 void WebNodeHighlight::windowReceivedMessage(HWND window, UINT msg, WPARAM wParam, LPARAM lParam)
277 {
278     if (window == m_inspectedWebViewWindow) {
279         switch (msg) {
280             case WM_SHOWWINDOW:
281                 onWebViewShowWindow(wParam);
282                 break;
283             case WM_WINDOWPOSCHANGED:
284                 onWebViewWindowPosChanged(reinterpret_cast<WINDOWPOS*>(lParam));
285                 break;
286             default:
287                 break;
288         }
289
290         return;
291     }
292
293     ASSERT(window == m_observedWindow);
294     switch (msg) {
295         case WM_WINDOWPOSCHANGED:
296             onRootWindowPosChanged(reinterpret_cast<WINDOWPOS*>(lParam));
297             break;
298         default:
299             break;
300     }
301 }