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/InspectorController.h> 37 #include <WebCore/Page.h> 38 #include <WebCore/WindowMessageBroadcaster.h> 39 #include <wtf/OwnPtr.h> 40 #include <wtf/HashSet.h> 41 42 using namespace WebCore; 43 44 static LPCTSTR kOverlayWindowClassName = TEXT("WebNodeHighlightWindowClass"); 45 static ATOM registerOverlayClass(); 46 static LPCTSTR kWebNodeHighlightPointerProp = TEXT("WebNodeHighlightPointer"); 47 48 WebNodeHighlight::WebNodeHighlight(WebView* webView) 49 : m_inspectedWebView(webView) 50 , m_overlay(0) 51 , m_observedWindow(0) 52 , m_showsWhileWebViewIsVisible(false) 53 { 54 m_inspectedWebView->viewWindow(reinterpret_cast<OLE_HANDLE*>(&m_inspectedWebViewWindow)); 55 } 56 57 WebNodeHighlight::~WebNodeHighlight() 58 { 59 if (m_observedWindow) 60 WindowMessageBroadcaster::removeListener(m_observedWindow, this); 61 if (m_inspectedWebViewWindow) 62 WindowMessageBroadcaster::removeListener(m_inspectedWebViewWindow, this); 63 64 if (m_overlay) 65 ::DestroyWindow(m_overlay); 66 } 67 68 void WebNodeHighlight::setShowsWhileWebViewIsVisible(bool shows) 69 { 70 if (m_showsWhileWebViewIsVisible == shows) 71 return; 72 m_showsWhileWebViewIsVisible = shows; 73 74 if (!m_showsWhileWebViewIsVisible) { 75 hide(); 76 return; 77 } 78 79 bool webViewVisible = isWebViewVisible(); 80 81 if (isShowing() == webViewVisible) 82 return; 83 84 if (webViewVisible) 85 show(); 86 else 87 hide(); 88 } 89 90 bool WebNodeHighlight::isWebViewVisible() const 91 { 92 if (!m_inspectedWebViewWindow) 93 return false; 94 95 return IsWindowVisible(m_inspectedWebViewWindow); 96 } 97 98 void WebNodeHighlight::show() 99 { 100 if (!m_overlay) { 101 registerOverlayClass(); 102 103 m_overlay = ::CreateWindowEx(WS_EX_LAYERED | WS_EX_TOOLWINDOW | WS_EX_TRANSPARENT, kOverlayWindowClassName, 0, WS_POPUP, 104 0, 0, 0, 0, 105 m_inspectedWebViewWindow, 0, 0, 0); 106 if (!m_overlay) 107 return; 108 109 ::SetProp(m_overlay, kWebNodeHighlightPointerProp, reinterpret_cast<HANDLE>(this)); 110 111 m_observedWindow = GetAncestor(m_inspectedWebViewWindow, GA_ROOT); 112 WindowMessageBroadcaster::addListener(m_observedWindow, this); 113 WindowMessageBroadcaster::addListener(m_inspectedWebViewWindow, this); 114 } 115 116 ASSERT(m_showsWhileWebViewIsVisible); 117 118 update(); 119 SetWindowPos(m_overlay, 0, 0, 0, 0, 0, SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE); 120 } 121 122 void WebNodeHighlight::hide() 123 { 124 if (m_overlay) 125 ::ShowWindow(m_overlay, SW_HIDE); 126 } 127 128 bool WebNodeHighlight::isShowing() const 129 { 130 return m_overlay && ::IsWindowVisible(m_overlay); 131 } 132 133 void WebNodeHighlight::update() 134 { 135 ASSERT(m_overlay); 136 137 HDC hdc = ::CreateCompatibleDC(::GetDC(m_overlay)); 138 if (!hdc) 139 return; 140 141 RECT webViewRect; 142 ::GetWindowRect(m_inspectedWebViewWindow, &webViewRect); 143 144 SIZE size; 145 size.cx = webViewRect.right - webViewRect.left; 146 size.cy = webViewRect.bottom - webViewRect.top; 147 148 BitmapInfo bitmapInfo = BitmapInfo::createBottomUp(IntSize(size)); 149 150 void* pixels = 0; 151 OwnPtr<HBITMAP> hbmp(::CreateDIBSection(hdc, &bitmapInfo, DIB_RGB_COLORS, &pixels, 0, 0)); 152 153 ::SelectObject(hdc, hbmp.get()); 154 155 GraphicsContext context(hdc); 156 157 m_inspectedWebView->page()->inspectorController()->drawNodeHighlight(context); 158 159 BLENDFUNCTION bf; 160 bf.BlendOp = AC_SRC_OVER; 161 bf.BlendFlags = 0; 162 bf.SourceConstantAlpha = 255; 163 bf.AlphaFormat = AC_SRC_ALPHA; 164 165 POINT srcPoint; 166 srcPoint.x = 0; 167 srcPoint.y = 0; 168 169 POINT dstPoint; 170 dstPoint.x = webViewRect.left; 171 dstPoint.y = webViewRect.top; 172 173 ::UpdateLayeredWindow(m_overlay, ::GetDC(0), &dstPoint, &size, hdc, &srcPoint, 0, &bf, ULW_ALPHA); 174 175 ::DeleteDC(hdc); 176 } 177 178 void WebNodeHighlight::placeBehindWindow(HWND window) 179 { 180 ASSERT(m_overlay); 181 SetWindowPos(m_overlay, window, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE); 182 } 183 184 static ATOM registerOverlayClass() 185 { 186 static bool haveRegisteredWindowClass = false; 187 188 if (haveRegisteredWindowClass) 189 return true; 190 191 WNDCLASSEX wcex; 192 193 wcex.cbSize = sizeof(WNDCLASSEX); 194 195 wcex.style = 0; 196 wcex.lpfnWndProc = OverlayWndProc; 197 wcex.cbClsExtra = 0; 198 wcex.cbWndExtra = 0; 199 wcex.hInstance = 0; 200 wcex.hIcon = 0; 201 wcex.hCursor = LoadCursor(0, IDC_ARROW); 202 wcex.hbrBackground = 0; 203 wcex.lpszMenuName = 0; 204 wcex.lpszClassName = kOverlayWindowClassName; 205 wcex.hIconSm = 0; 206 207 haveRegisteredWindowClass = true; 208 209 return ::RegisterClassEx(&wcex); 210 } 211 212 LRESULT CALLBACK OverlayWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) 213 { 214 WebNodeHighlight* highlight = reinterpret_cast<WebNodeHighlight*>(::GetProp(hwnd, kWebNodeHighlightPointerProp)); 215 if (!highlight) 216 return ::DefWindowProc(hwnd, msg, wParam, lParam); 217 218 return ::DefWindowProc(hwnd, msg, wParam, lParam); 219 } 220 221 void WebNodeHighlight::onWebViewShowWindow(bool showing) 222 { 223 if (!m_showsWhileWebViewIsVisible) 224 return; 225 226 if (isShowing() == showing) 227 return; 228 229 if (showing) 230 show(); 231 else 232 hide(); 233 } 234 235 void WebNodeHighlight::onWebViewWindowPosChanged(WINDOWPOS* windowPos) 236 { 237 bool sizing = !(windowPos->flags & SWP_NOSIZE); 238 239 if (!sizing) 240 return; 241 242 if (!isShowing()) 243 return; 244 245 update(); 246 } 247 248 void WebNodeHighlight::onRootWindowPosChanged(WINDOWPOS* windowPos) 249 { 250 bool moving = !(windowPos->flags & SWP_NOMOVE); 251 bool sizing = !(windowPos->flags & SWP_NOSIZE); 252 253 if (!moving) 254 return; 255 256 // Size changes are handled by onWebViewWindowPosChanged. 257 if (sizing) 258 return; 259 260 if (!isShowing()) 261 return; 262 263 update(); 264 } 265 266 void WebNodeHighlight::windowReceivedMessage(HWND window, UINT msg, WPARAM wParam, LPARAM lParam) 267 { 268 if (window == m_inspectedWebViewWindow) { 269 switch (msg) { 270 case WM_SHOWWINDOW: 271 onWebViewShowWindow(wParam); 272 break; 273 case WM_WINDOWPOSCHANGED: 274 onWebViewWindowPosChanged(reinterpret_cast<WINDOWPOS*>(lParam)); 275 break; 276 default: 277 break; 278 } 279 280 return; 281 } 282 283 ASSERT(window == m_observedWindow); 284 switch (msg) { 285 case WM_WINDOWPOSCHANGED: 286 onRootWindowPosChanged(reinterpret_cast<WINDOWPOS*>(lParam)); 287 break; 288 default: 289 break; 290 } 291 } 292