diff -r 000000000000 -r dd21522fd290 webengine/osswebengine/WebKit/win/WebInspectorClient.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/webengine/osswebengine/WebKit/win/WebInspectorClient.cpp Mon Mar 30 12:54:55 2009 +0300 @@ -0,0 +1,360 @@ +/* + * Copyright (C) 2006, 2007 Apple Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of + * its contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF + * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include "config.h" +#include "WebInspectorClient.h" + +#include "WebInspectorClient.h" +#include "WebKit.h" +#include "WebMutableURLRequest.h" +#include "WebNodeHighlight.h" +#include "WebView.h" + +#pragma warning(push, 0) +#include +#include +#include +#include +#include +#include +#include +#pragma warning(pop) + +#include +#include + +using namespace WebCore; + +static LPCTSTR kWebInspectorWindowClassName = TEXT("WebInspectorWindowClass"); +static ATOM registerWindowClass(); +static LPCTSTR kWebInspectorPointerProp = TEXT("WebInspectorPointer"); + +static const unsigned defaultAttachedHeight = 300; + +WebInspectorClient::WebInspectorClient(WebView* webView) + : m_inspectedWebView(webView) + , m_hwnd(0) + , m_webViewHwnd(0) + , m_originalWebViewWndProc(0) + , m_attached(false) +{ + ASSERT(m_inspectedWebView); + + m_inspectedWebView->viewWindow((OLE_HANDLE*)&m_inspectedWebViewHwnd); + + // FIXME: Implement window size/position save/restore +#if 0 + [self setWindowFrameAutosaveName:@"Web Inspector"]; +#endif +} + +WebInspectorClient::~WebInspectorClient() +{ + if (m_hwnd) + ::DestroyWindow(m_hwnd); +} + +void WebInspectorClient::inspectorDestroyed() +{ + delete this; +} + +Page* WebInspectorClient::createPage() +{ + if (m_webView) + return core(m_webView.get()); + + ASSERT(!m_hwnd); + + registerWindowClass(); + + m_hwnd = ::CreateWindowEx(0, kWebInspectorWindowClassName, 0, WS_OVERLAPPEDWINDOW, + 0, 0, 0, 0, + 0, 0, 0, 0); + if (!m_hwnd) + return 0; + + ::SetProp(m_hwnd, kWebInspectorPointerProp, reinterpret_cast(this)); + + m_webView.adoptRef(WebView::createInstance()); + + if (FAILED(m_webView->setHostWindow((OLE_HANDLE)(ULONG64)m_hwnd))) + return 0; + + RECT rect = {0}; + if (FAILED(m_webView->initWithFrame(rect, 0, 0))) + return 0; + + m_webView->setProhibitsMainFrameScrolling(); + + if (FAILED(m_webView->viewWindow(reinterpret_cast(&m_webViewHwnd)))) + return 0; + + COMPtr request; + request.adoptRef(WebMutableURLRequest::createInstance()); + + RetainPtr htmlURLRef(AdoptCF, ::CFBundleCopyResourceURL(::CFBundleGetBundleWithIdentifier(CFSTR("com.apple.WebKit")), CFSTR("inspector"), CFSTR("html"), CFSTR("inspector"))); + if (!htmlURLRef) + return 0; + + CFStringRef urlStringRef = ::CFURLGetString(htmlURLRef.get()); + if (FAILED(request->initWithURL(BString(urlStringRef), WebURLRequestUseProtocolCachePolicy, 60))) + return 0; + + if (FAILED(m_webView->topLevelFrame()->loadRequest(request.get()))) + return 0; + + return core(m_webView.get()); +} + +void WebInspectorClient::showWindow() +{ + if (!m_hwnd) + return; + + updateWindowTitle(); + ::SetWindowPos(m_hwnd, HWND_TOP, 60, 200, 750, 650, SWP_SHOWWINDOW); + m_inspectedWebView->page()->inspectorController()->setWindowVisible(true); +} + +void WebInspectorClient::closeWindow() +{ + if (!m_webView) + return; + + ::ShowWindow(m_hwnd, SW_HIDE); + m_inspectedWebView->page()->inspectorController()->setWindowVisible(false); +} + +bool WebInspectorClient::windowVisible() +{ + return !!::IsWindowVisible(m_hwnd); +} + +void WebInspectorClient::attachWindow() +{ + ASSERT(m_hwnd); + ASSERT(m_webView); + ASSERT(!m_attached); + ASSERT(m_inspectedWebViewHwnd); + + if (!m_originalWebViewWndProc) { + ::SetProp(m_inspectedWebViewHwnd, kWebInspectorPointerProp, reinterpret_cast(this)); +#pragma warning(disable: 4244 4312) + m_originalWebViewWndProc = (WNDPROC)::SetWindowLongPtr(m_inspectedWebViewHwnd, GWLP_WNDPROC, (LONG_PTR)SubclassedWebViewWndProc); + } + + HWND hostWindow; + if (FAILED(m_inspectedWebView->hostWindow((OLE_HANDLE*)&hostWindow))) + return; + + m_webView->setHostWindow((OLE_HANDLE)(ULONG64)hostWindow); + ::ShowWindow(m_hwnd, SW_HIDE); + m_attached = true; + + ::SendMessage(hostWindow, WM_SIZE, 0, 0); + + if (m_highlight && m_highlight->visible()) + m_highlight->updateWindow(); +} + +void WebInspectorClient::detachWindow() +{ + ASSERT(m_attached); + ASSERT(m_originalWebViewWndProc); + + ::SetWindowLongPtr(m_inspectedWebViewHwnd, GWLP_WNDPROC, (LONG_PTR)m_originalWebViewWndProc); + ::RemoveProp(m_inspectedWebViewHwnd, kWebInspectorPointerProp); + m_originalWebViewWndProc = 0; + + m_attached = false; + + m_webView->setHostWindow((OLE_HANDLE)(ULONG64)m_hwnd); + ::ShowWindow(m_hwnd, SW_SHOW); + ::SendMessage(m_hwnd, WM_SIZE, 0, 0); + + HWND hostWindow; + if (SUCCEEDED(m_inspectedWebView->hostWindow((OLE_HANDLE*)&hostWindow))) + ::SendMessage(hostWindow, WM_SIZE, 0, 0); + + if (m_highlight && m_highlight->visible()) + m_highlight->updateWindow(); +} + +void WebInspectorClient::highlight(Node* node) +{ + ASSERT_ARG(node, node); + + HWND hwnd; + if (FAILED(m_inspectedWebView->viewWindow((OLE_HANDLE*)&hwnd))) + return; + RECT rect; + ::GetClientRect(hwnd, &rect); + IntRect webViewRect(rect); + + RenderObject* renderer = node->renderer(); + if (!renderer) + return; + IntRect nodeRect(renderer->absoluteBoundingBoxRect()); + + if (!webViewRect.contains(nodeRect) && !nodeRect.contains(webViewRect)) { + Element* element; + if (node->isElementNode()) + element = static_cast(node); + else + element = static_cast(node->parent()); + element->scrollIntoViewIfNeeded(); + } + + IntSize offset = m_inspectedWebView->page()->mainFrame()->view()->scrollOffset(); + nodeRect.move(-offset); + + if (!m_highlight) + m_highlight.set(new WebNodeHighlight(hwnd)); + + m_highlight->highlight(nodeRect); +} + +void WebInspectorClient::hideHighlight() +{ + if (m_highlight) + m_highlight->hide(); +} + +void WebInspectorClient::inspectedURLChanged(const String& newURL) +{ + m_inspectedURL = newURL; + updateWindowTitle(); +} + +void WebInspectorClient::updateWindowTitle() +{ + // FIXME: The series of appends should be replaced with a call to String::format() + // when it can be figured out how to get the unicode em-dash to show up. + String title = "Web Inspector "; + title.append((UChar)0x2014); // em-dash + title.append(' '); + title.append(m_inspectedURL); + ::SetWindowText(m_hwnd, title.charactersWithNullTermination()); +} + +LRESULT WebInspectorClient::onSize(WPARAM, LPARAM) +{ + RECT rect; + ::GetClientRect(m_hwnd, &rect); + + ::SetWindowPos(m_webViewHwnd, 0, rect.left, rect.top, rect.right - rect.left, rect.bottom - rect.top, SWP_NOZORDER); + + return 0; +} + +LRESULT WebInspectorClient::onClose(WPARAM, LPARAM) +{ + ::ShowWindow(m_hwnd, SW_HIDE); + m_inspectedWebView->page()->inspectorController()->setWindowVisible(false); + + hideHighlight(); + + return 0; +} + +void WebInspectorClient::onWebViewWindowPosChanging(WPARAM, LPARAM lParam) +{ + ASSERT(m_attached); + + WINDOWPOS* windowPos = reinterpret_cast(lParam); + ASSERT_ARG(lParam, windowPos); + + if (windowPos->flags & SWP_NOSIZE) + return; + + windowPos->cy -= defaultAttachedHeight; + + ::SetWindowPos(m_webViewHwnd, 0, windowPos->x, windowPos->y + windowPos->cy, windowPos->cx, defaultAttachedHeight, SWP_NOZORDER); +} + +static LRESULT CALLBACK WebInspectorWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WebInspectorClient* client = reinterpret_cast(::GetProp(hwnd, kWebInspectorPointerProp)); + if (!client) + return ::DefWindowProc(hwnd, msg, wParam, lParam); + + switch (msg) { + case WM_SIZE: + return client->onSize(wParam, lParam); + case WM_CLOSE: + return client->onClose(wParam, lParam); + default: + break; + } + + return ::DefWindowProc(hwnd, msg, wParam, lParam); +} + +static LRESULT CALLBACK SubclassedWebViewWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + WebInspectorClient* client = reinterpret_cast(::GetProp(hwnd, kWebInspectorPointerProp)); + ASSERT(client); + + switch (msg) { + case WM_WINDOWPOSCHANGING: + client->onWebViewWindowPosChanging(wParam, lParam); + default: + break; + } + + return ::CallWindowProc(client->m_originalWebViewWndProc, hwnd, msg, wParam, lParam); +} + +static ATOM registerWindowClass() +{ + static bool haveRegisteredWindowClass = false; + + if (haveRegisteredWindowClass) + return true; + + WNDCLASSEX wcex; + + wcex.cbSize = sizeof(WNDCLASSEX); + + wcex.style = 0; + wcex.lpfnWndProc = WebInspectorWndProc; + wcex.cbClsExtra = 0; + wcex.cbWndExtra = 0; + wcex.hInstance = 0; + wcex.hIcon = 0; + wcex.hCursor = LoadCursor(0, IDC_ARROW); + wcex.hbrBackground = 0; + wcex.lpszMenuName = 0; + wcex.lpszClassName = kWebInspectorWindowClassName; + wcex.hIconSm = 0; + + haveRegisteredWindowClass = true; + + return ::RegisterClassEx(&wcex); +}