Server:
10666 Client: p4web-viewer
Path:
 
Files   Submitted   Branches   Labels   Clients   Users   Jobs   Settings  
Display tree view Display revision history Display revision history Display revision history thumbnails Show branching history View head revision text Cancel operation Show recent activity Show P4 command input Information Help
View File Revision Text:  
//webkit/Dreamweaver-CS4/WebKit/WebKit/win/WebInspectorClient.cpp #1
Type: text Client: //p4web-viewer/webkit/Dreamweaver-CS4/WebKit/WebKit/win/WebInspectorClient.cpp Size: 10.70 KB
Head: #1

Show line numbers
/*
 * 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 <WebCore/BString.h>
#include <WebCore/Element.h>
#include <WebCore/FloatRect.h>
#include <WebCore/FrameView.h>
#include <WebCore/InspectorController.h>
#include <WebCore/Page.h>
#include <WebCore/RenderObject.h>
#pragma warning(pop)

#include <tchar.h>
#include <wtf/RetainPtr.h>

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<HANDLE>(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<OLE_HANDLE*>(&m_webViewHwnd))))
        return 0;

    COMPtr<WebMutableURLRequest> request;
    request.adoptRef(WebMutableURLRequest::createInstance());

    RetainPtr<CFURLRef> 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<HANDLE>(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<Element*>(node);
        else
            element = static_cast<Element*>(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<WINDOWPOS*>(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<WebInspectorClient*>(::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<WebInspectorClient*>(::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);
}
Copyright 2008 Perforce Software. All rights reserved.