WebNodeHighlight.cpp 8.6 KB

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