webengine/osswebengine/WebKit/win/WebInspectorClient.cpp
changeset 0 dd21522fd290
equal deleted inserted replaced
-1:000000000000 0:dd21522fd290
       
     1 /*
       
     2  * Copyright (C) 2006, 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 "WebInspectorClient.h"
       
    31 
       
    32 #include "WebInspectorClient.h"
       
    33 #include "WebKit.h"
       
    34 #include "WebMutableURLRequest.h"
       
    35 #include "WebNodeHighlight.h"
       
    36 #include "WebView.h"
       
    37 
       
    38 #pragma warning(push, 0)
       
    39 #include <WebCore/BString.h>
       
    40 #include <WebCore/Element.h>
       
    41 #include <WebCore/FloatRect.h>
       
    42 #include <WebCore/FrameView.h>
       
    43 #include <WebCore/InspectorController.h>
       
    44 #include <WebCore/Page.h>
       
    45 #include <WebCore/RenderObject.h>
       
    46 #pragma warning(pop)
       
    47 
       
    48 #include <tchar.h>
       
    49 #include <wtf/RetainPtr.h>
       
    50 
       
    51 using namespace WebCore;
       
    52 
       
    53 static LPCTSTR kWebInspectorWindowClassName = TEXT("WebInspectorWindowClass");
       
    54 static ATOM registerWindowClass();
       
    55 static LPCTSTR kWebInspectorPointerProp = TEXT("WebInspectorPointer");
       
    56 
       
    57 static const unsigned defaultAttachedHeight = 300;
       
    58 
       
    59 WebInspectorClient::WebInspectorClient(WebView* webView)
       
    60     : m_inspectedWebView(webView)
       
    61     , m_hwnd(0)
       
    62     , m_webViewHwnd(0)
       
    63     , m_originalWebViewWndProc(0)
       
    64     , m_attached(false)
       
    65 {
       
    66     ASSERT(m_inspectedWebView);
       
    67 
       
    68     m_inspectedWebView->viewWindow((OLE_HANDLE*)&m_inspectedWebViewHwnd);
       
    69 
       
    70     // FIXME: Implement window size/position save/restore
       
    71 #if 0
       
    72     [self setWindowFrameAutosaveName:@"Web Inspector"];
       
    73 #endif
       
    74 }
       
    75 
       
    76 WebInspectorClient::~WebInspectorClient()
       
    77 {
       
    78     if (m_hwnd)
       
    79         ::DestroyWindow(m_hwnd);
       
    80 }
       
    81 
       
    82 void WebInspectorClient::inspectorDestroyed()
       
    83 {
       
    84     delete this;
       
    85 }
       
    86 
       
    87 Page* WebInspectorClient::createPage()
       
    88 {
       
    89     if (m_webView)
       
    90         return core(m_webView.get());
       
    91 
       
    92     ASSERT(!m_hwnd);
       
    93 
       
    94     registerWindowClass();
       
    95 
       
    96     m_hwnd = ::CreateWindowEx(0, kWebInspectorWindowClassName, 0, WS_OVERLAPPEDWINDOW,
       
    97                               0, 0, 0, 0,
       
    98                               0, 0, 0, 0);
       
    99     if (!m_hwnd)
       
   100         return 0;
       
   101 
       
   102     ::SetProp(m_hwnd, kWebInspectorPointerProp, reinterpret_cast<HANDLE>(this));
       
   103 
       
   104     m_webView.adoptRef(WebView::createInstance());
       
   105 
       
   106     if (FAILED(m_webView->setHostWindow((OLE_HANDLE)(ULONG64)m_hwnd)))
       
   107         return 0;
       
   108 
       
   109     RECT rect = {0};
       
   110     if (FAILED(m_webView->initWithFrame(rect, 0, 0)))
       
   111         return 0;
       
   112 
       
   113     m_webView->setProhibitsMainFrameScrolling();
       
   114 
       
   115     if (FAILED(m_webView->viewWindow(reinterpret_cast<OLE_HANDLE*>(&m_webViewHwnd))))
       
   116         return 0;
       
   117 
       
   118     COMPtr<WebMutableURLRequest> request;
       
   119     request.adoptRef(WebMutableURLRequest::createInstance());
       
   120 
       
   121     RetainPtr<CFURLRef> htmlURLRef(AdoptCF, ::CFBundleCopyResourceURL(::CFBundleGetBundleWithIdentifier(CFSTR("com.apple.WebKit")), CFSTR("inspector"), CFSTR("html"), CFSTR("inspector")));
       
   122     if (!htmlURLRef)
       
   123         return 0;
       
   124 
       
   125     CFStringRef urlStringRef = ::CFURLGetString(htmlURLRef.get());
       
   126     if (FAILED(request->initWithURL(BString(urlStringRef), WebURLRequestUseProtocolCachePolicy, 60)))
       
   127         return 0;
       
   128 
       
   129     if (FAILED(m_webView->topLevelFrame()->loadRequest(request.get())))
       
   130         return 0;
       
   131 
       
   132     return core(m_webView.get());
       
   133 }
       
   134 
       
   135 void WebInspectorClient::showWindow()
       
   136 {
       
   137     if (!m_hwnd)
       
   138         return;
       
   139 
       
   140     updateWindowTitle();
       
   141     ::SetWindowPos(m_hwnd, HWND_TOP, 60, 200, 750, 650, SWP_SHOWWINDOW);
       
   142     m_inspectedWebView->page()->inspectorController()->setWindowVisible(true);
       
   143 }
       
   144 
       
   145 void WebInspectorClient::closeWindow()
       
   146 {
       
   147     if (!m_webView)
       
   148         return;
       
   149 
       
   150     ::ShowWindow(m_hwnd, SW_HIDE);
       
   151     m_inspectedWebView->page()->inspectorController()->setWindowVisible(false);
       
   152 }
       
   153 
       
   154 bool WebInspectorClient::windowVisible()
       
   155 {
       
   156     return !!::IsWindowVisible(m_hwnd);
       
   157 }
       
   158 
       
   159 void WebInspectorClient::attachWindow()
       
   160 {
       
   161     ASSERT(m_hwnd);
       
   162     ASSERT(m_webView);
       
   163     ASSERT(!m_attached);
       
   164     ASSERT(m_inspectedWebViewHwnd);
       
   165 
       
   166     if (!m_originalWebViewWndProc) {
       
   167         ::SetProp(m_inspectedWebViewHwnd, kWebInspectorPointerProp, reinterpret_cast<HANDLE>(this));
       
   168 #pragma warning(disable: 4244 4312)
       
   169         m_originalWebViewWndProc = (WNDPROC)::SetWindowLongPtr(m_inspectedWebViewHwnd, GWLP_WNDPROC, (LONG_PTR)SubclassedWebViewWndProc);
       
   170     }
       
   171 
       
   172     HWND hostWindow;
       
   173     if (FAILED(m_inspectedWebView->hostWindow((OLE_HANDLE*)&hostWindow)))
       
   174         return;
       
   175 
       
   176     m_webView->setHostWindow((OLE_HANDLE)(ULONG64)hostWindow);
       
   177     ::ShowWindow(m_hwnd, SW_HIDE);
       
   178     m_attached = true;
       
   179 
       
   180     ::SendMessage(hostWindow, WM_SIZE, 0, 0);
       
   181 
       
   182     if (m_highlight && m_highlight->visible())
       
   183         m_highlight->updateWindow();
       
   184 }
       
   185 
       
   186 void WebInspectorClient::detachWindow()
       
   187 {
       
   188     ASSERT(m_attached);
       
   189     ASSERT(m_originalWebViewWndProc);
       
   190 
       
   191     ::SetWindowLongPtr(m_inspectedWebViewHwnd, GWLP_WNDPROC, (LONG_PTR)m_originalWebViewWndProc);
       
   192     ::RemoveProp(m_inspectedWebViewHwnd, kWebInspectorPointerProp);
       
   193     m_originalWebViewWndProc = 0;
       
   194 
       
   195     m_attached = false;
       
   196 
       
   197     m_webView->setHostWindow((OLE_HANDLE)(ULONG64)m_hwnd);
       
   198     ::ShowWindow(m_hwnd, SW_SHOW);
       
   199     ::SendMessage(m_hwnd, WM_SIZE, 0, 0);
       
   200 
       
   201     HWND hostWindow;
       
   202     if (SUCCEEDED(m_inspectedWebView->hostWindow((OLE_HANDLE*)&hostWindow)))
       
   203         ::SendMessage(hostWindow, WM_SIZE, 0, 0);
       
   204 
       
   205     if (m_highlight && m_highlight->visible())
       
   206         m_highlight->updateWindow();
       
   207 }
       
   208 
       
   209 void WebInspectorClient::highlight(Node* node)
       
   210 {
       
   211     ASSERT_ARG(node, node);
       
   212 
       
   213     HWND hwnd;
       
   214     if (FAILED(m_inspectedWebView->viewWindow((OLE_HANDLE*)&hwnd)))
       
   215         return;
       
   216     RECT rect;
       
   217     ::GetClientRect(hwnd, &rect);
       
   218     IntRect webViewRect(rect);
       
   219 
       
   220     RenderObject* renderer = node->renderer();
       
   221     if (!renderer)
       
   222         return;
       
   223     IntRect nodeRect(renderer->absoluteBoundingBoxRect());
       
   224 
       
   225     if (!webViewRect.contains(nodeRect) && !nodeRect.contains(webViewRect)) {
       
   226         Element* element;
       
   227         if (node->isElementNode())
       
   228             element = static_cast<Element*>(node);
       
   229         else
       
   230             element = static_cast<Element*>(node->parent());
       
   231         element->scrollIntoViewIfNeeded();
       
   232     }
       
   233 
       
   234     IntSize offset = m_inspectedWebView->page()->mainFrame()->view()->scrollOffset();
       
   235     nodeRect.move(-offset);
       
   236 
       
   237     if (!m_highlight)
       
   238         m_highlight.set(new WebNodeHighlight(hwnd));
       
   239 
       
   240     m_highlight->highlight(nodeRect);
       
   241 }
       
   242 
       
   243 void WebInspectorClient::hideHighlight()
       
   244 {
       
   245     if (m_highlight)
       
   246         m_highlight->hide();
       
   247 }
       
   248 
       
   249 void WebInspectorClient::inspectedURLChanged(const String& newURL)
       
   250 {
       
   251     m_inspectedURL = newURL;
       
   252     updateWindowTitle();
       
   253 }
       
   254 
       
   255 void WebInspectorClient::updateWindowTitle()
       
   256 {
       
   257     // FIXME: The series of appends should be replaced with a call to String::format()
       
   258     // when it can be figured out how to get the unicode em-dash to show up.
       
   259     String title = "Web Inspector ";
       
   260     title.append((UChar)0x2014); // em-dash
       
   261     title.append(' ');
       
   262     title.append(m_inspectedURL);
       
   263     ::SetWindowText(m_hwnd, title.charactersWithNullTermination());
       
   264 }
       
   265 
       
   266 LRESULT WebInspectorClient::onSize(WPARAM, LPARAM)
       
   267 {
       
   268     RECT rect;
       
   269     ::GetClientRect(m_hwnd, &rect);
       
   270 
       
   271     ::SetWindowPos(m_webViewHwnd, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER);
       
   272 
       
   273     return 0;
       
   274 }
       
   275 
       
   276 LRESULT WebInspectorClient::onClose(WPARAM, LPARAM)
       
   277 {
       
   278     ::ShowWindow(m_hwnd, SW_HIDE);
       
   279     m_inspectedWebView->page()->inspectorController()->setWindowVisible(false);
       
   280 
       
   281     hideHighlight();
       
   282 
       
   283     return 0;
       
   284 }
       
   285 
       
   286 void WebInspectorClient::onWebViewWindowPosChanging(WPARAM, LPARAM lParam)
       
   287 {
       
   288     ASSERT(m_attached);
       
   289 
       
   290     WINDOWPOS* windowPos = reinterpret_cast<WINDOWPOS*>(lParam);
       
   291     ASSERT_ARG(lParam, windowPos);
       
   292 
       
   293     if (windowPos->flags & SWP_NOSIZE)
       
   294         return;
       
   295 
       
   296     windowPos->cy -= defaultAttachedHeight;
       
   297 
       
   298     ::SetWindowPos(m_webViewHwnd, 0, windowPos->x, windowPos->y + windowPos->cy, windowPos->cx, defaultAttachedHeight, SWP_NOZORDER);
       
   299 }
       
   300 
       
   301 static LRESULT CALLBACK WebInspectorWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
       
   302 {
       
   303     WebInspectorClient* client = reinterpret_cast<WebInspectorClient*>(::GetProp(hwnd, kWebInspectorPointerProp));
       
   304     if (!client)
       
   305         return ::DefWindowProc(hwnd, msg, wParam, lParam);
       
   306 
       
   307     switch (msg) {
       
   308         case WM_SIZE:
       
   309             return client->onSize(wParam, lParam);
       
   310         case WM_CLOSE:
       
   311             return client->onClose(wParam, lParam);
       
   312         default:
       
   313             break;
       
   314     }
       
   315 
       
   316     return ::DefWindowProc(hwnd, msg, wParam, lParam);
       
   317 }
       
   318 
       
   319 static LRESULT CALLBACK SubclassedWebViewWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
       
   320 {
       
   321     WebInspectorClient* client = reinterpret_cast<WebInspectorClient*>(::GetProp(hwnd, kWebInspectorPointerProp));
       
   322     ASSERT(client);
       
   323 
       
   324     switch (msg) {
       
   325         case WM_WINDOWPOSCHANGING:
       
   326             client->onWebViewWindowPosChanging(wParam, lParam);
       
   327         default:
       
   328             break;
       
   329     }
       
   330 
       
   331     return ::CallWindowProc(client->m_originalWebViewWndProc, hwnd, msg, wParam, lParam);
       
   332 }
       
   333 
       
   334 static ATOM registerWindowClass()
       
   335 {
       
   336     static bool haveRegisteredWindowClass = false;
       
   337 
       
   338     if (haveRegisteredWindowClass)
       
   339         return true;
       
   340 
       
   341     WNDCLASSEX wcex;
       
   342 
       
   343     wcex.cbSize = sizeof(WNDCLASSEX);
       
   344 
       
   345     wcex.style          = 0;
       
   346     wcex.lpfnWndProc    = WebInspectorWndProc;
       
   347     wcex.cbClsExtra     = 0;
       
   348     wcex.cbWndExtra     = 0;
       
   349     wcex.hInstance      = 0;
       
   350     wcex.hIcon          = 0;
       
   351     wcex.hCursor        = LoadCursor(0, IDC_ARROW);
       
   352     wcex.hbrBackground  = 0;
       
   353     wcex.lpszMenuName   = 0;
       
   354     wcex.lpszClassName  = kWebInspectorWindowClassName;
       
   355     wcex.hIconSm        = 0;
       
   356 
       
   357     haveRegisteredWindowClass = true;
       
   358 
       
   359     return ::RegisterClassEx(&wcex);
       
   360 }