diff options
author | tc@google.com <tc@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-19 01:00:50 +0000 |
---|---|---|
committer | tc@google.com <tc@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2008-11-19 01:00:50 +0000 |
commit | 64d0ff791dc2a4e9f0b397589d25eb510da82ee8 (patch) | |
tree | 9bfd86babdcf5cb099d7c86b12397e0d8d7c02b2 /webkit/tools/test_shell/webwidget_host_win.cc | |
parent | 2184367eefb0d13efa8aacd12d94111929079ee0 (diff) | |
download | chromium_src-64d0ff791dc2a4e9f0b397589d25eb510da82ee8.zip chromium_src-64d0ff791dc2a4e9f0b397589d25eb510da82ee8.tar.gz chromium_src-64d0ff791dc2a4e9f0b397589d25eb510da82ee8.tar.bz2 |
rename webwidget_host.cc to webwidget_host_win.cc
Review URL: http://codereview.chromium.org/11251
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@5659 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit/tools/test_shell/webwidget_host_win.cc')
-rw-r--r-- | webkit/tools/test_shell/webwidget_host_win.cc | 340 |
1 files changed, 340 insertions, 0 deletions
diff --git a/webkit/tools/test_shell/webwidget_host_win.cc b/webkit/tools/test_shell/webwidget_host_win.cc new file mode 100644 index 0000000..5c384a5 --- /dev/null +++ b/webkit/tools/test_shell/webwidget_host_win.cc @@ -0,0 +1,340 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "webkit/tools/test_shell/webwidget_host.h" + +#include "base/gfx/platform_canvas.h" +#include "base/gfx/platform_canvas_win.h" +#include "base/gfx/rect.h" +#include "base/logging.h" +#include "base/win_util.h" +#include "webkit/glue/webinputevent.h" +#include "webkit/glue/webwidget.h" + +static const wchar_t kWindowClassName[] = L"WebWidgetHost"; + +/*static*/ +WebWidgetHost* WebWidgetHost::Create(gfx::WindowHandle parent_window, + WebWidgetDelegate* delegate) { + WebWidgetHost* host = new WebWidgetHost(); + + static bool registered_class = false; + if (!registered_class) { + WNDCLASSEX wcex = {0}; + wcex.cbSize = sizeof(wcex); + wcex.style = CS_DBLCLKS; + wcex.lpfnWndProc = WebWidgetHost::WndProc; + wcex.hInstance = GetModuleHandle(NULL); + wcex.hCursor = LoadCursor(NULL, IDC_ARROW); + wcex.lpszClassName = kWindowClassName; + RegisterClassEx(&wcex); + registered_class = true; + } + + host->view_ = CreateWindowEx(WS_EX_TOOLWINDOW, + kWindowClassName, kWindowClassName, WS_POPUP, + 0, 0, 0, 0, + parent_window, NULL, GetModuleHandle(NULL), NULL); + + win_util::SetWindowUserData(host->view_, host); + + host->webwidget_ = WebWidget::Create(delegate); + + return host; +} + +/*static*/ +WebWidgetHost* WebWidgetHost::FromWindow(gfx::WindowHandle hwnd) { + return reinterpret_cast<WebWidgetHost*>(win_util::GetWindowUserData(hwnd)); +} + +/*static*/ +LRESULT CALLBACK WebWidgetHost::WndProc(HWND hwnd, UINT message, WPARAM wparam, + LPARAM lparam) { + WebWidgetHost* host = FromWindow(hwnd); + if (host && !host->WndProc(message, wparam, lparam)) { + switch (message) { + case WM_DESTROY: + delete host; + break; + + case WM_PAINT: { + RECT rect; + if (GetUpdateRect(hwnd, &rect, FALSE)) { + host->UpdatePaintRect(gfx::Rect(rect)); + } + host->Paint(); + return 0; + } + + case WM_ERASEBKGND: + // Do nothing here to avoid flashing, the background will be erased + // during painting. + return 0; + + case WM_SIZE: + host->Resize(lparam); + return 0; + + case WM_MOUSEMOVE: + case WM_MOUSELEAVE: + case WM_LBUTTONDOWN: + case WM_MBUTTONDOWN: + case WM_RBUTTONDOWN: + case WM_LBUTTONUP: + case WM_MBUTTONUP: + case WM_RBUTTONUP: + case WM_LBUTTONDBLCLK: + case WM_MBUTTONDBLCLK: + case WM_RBUTTONDBLCLK: + host->MouseEvent(message, wparam, lparam); + break; + + case WM_MOUSEWHEEL: + host->WheelEvent(wparam, lparam); + break; + + case WM_CAPTURECHANGED: + case WM_CANCELMODE: + host->CaptureLostEvent(); + break; + + // TODO(darin): add WM_SYSKEY{DOWN/UP} to capture ALT key actions + case WM_KEYDOWN: + case WM_KEYUP: + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + case WM_CHAR: + case WM_SYSCHAR: + case WM_IME_CHAR: + host->KeyEvent(message, wparam, lparam); + break; + + case WM_SETFOCUS: + host->SetFocus(true); + break; + + case WM_KILLFOCUS: + host->SetFocus(false); + break; + } + } + + return DefWindowProc(hwnd, message, wparam, lparam);; +} + +void WebWidgetHost::DidInvalidateRect(const gfx::Rect& damaged_rect) { + DLOG_IF(WARNING, painting_) << "unexpected invalidation while painting"; + + // If this invalidate overlaps with a pending scroll, then we have to + // downgrade to invalidating the scroll rect. + if (damaged_rect.Intersects(scroll_rect_)) { + paint_rect_ = paint_rect_.Union(scroll_rect_); + ResetScrollRect(); + } + paint_rect_ = paint_rect_.Union(damaged_rect); + + RECT r = damaged_rect.ToRECT(); + InvalidateRect(view_, &r, FALSE); +} + +void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) { + DCHECK(dx || dy); + + // If we already have a pending scroll operation or if this scroll operation + // intersects the existing paint region, then just failover to invalidating. + if (!scroll_rect_.IsEmpty() || paint_rect_.Intersects(clip_rect)) { + paint_rect_ = paint_rect_.Union(scroll_rect_); + ResetScrollRect(); + paint_rect_ = paint_rect_.Union(clip_rect); + } + + // We will perform scrolling lazily, when requested to actually paint. + scroll_rect_ = clip_rect; + scroll_dx_ = dx; + scroll_dy_ = dy; + + RECT r = clip_rect.ToRECT(); + InvalidateRect(view_, &r, FALSE); +} + +void WebWidgetHost::SetCursor(HCURSOR cursor) { + SetClassLong(view_, GCL_HCURSOR, + static_cast<LONG>(reinterpret_cast<LONG_PTR>(cursor))); + ::SetCursor(cursor); +} + +void WebWidgetHost::DiscardBackingStore() { + canvas_.reset(); +} + +WebWidgetHost::WebWidgetHost() + : view_(NULL), + webwidget_(NULL), + track_mouse_leave_(false), + scroll_dx_(0), + scroll_dy_(0) { + set_painting(false); +} + +WebWidgetHost::~WebWidgetHost() { + win_util::SetWindowUserData(view_, 0); + + TrackMouseLeave(false); + + webwidget_->Close(); + webwidget_->Release(); +} + +bool WebWidgetHost::WndProc(UINT message, WPARAM wparam, LPARAM lparam) { + switch (message) { + case WM_ACTIVATE: + if (wparam == WA_INACTIVE) { + PostMessage(view_, WM_CLOSE, 0, 0); + return true; + } + break; + } + + return false; +} + +void WebWidgetHost::UpdatePaintRect(const gfx::Rect& rect) { + paint_rect_ = paint_rect_.Union(rect); +} + +void WebWidgetHost::Paint() { + RECT r; + GetClientRect(view_, &r); + gfx::Rect client_rect(r); + + // Allocate a canvas if necessary + if (!canvas_.get()) { + ResetScrollRect(); + paint_rect_ = client_rect; + canvas_.reset(new gfx::PlatformCanvas( + paint_rect_.width(), paint_rect_.height(), true)); + } + + // This may result in more invalidation + webwidget_->Layout(); + + // Scroll the canvas if necessary + scroll_rect_ = client_rect.Intersect(scroll_rect_); + if (!scroll_rect_.IsEmpty()) { + HDC hdc = canvas_->getTopPlatformDevice().getBitmapDC(); + + RECT damaged_rect, r = scroll_rect_.ToRECT(); + ScrollDC(hdc, scroll_dx_, scroll_dy_, NULL, &r, NULL, &damaged_rect); + + PaintRect(gfx::Rect(damaged_rect)); + } + ResetScrollRect(); + + // Paint the canvas if necessary. Allow painting to generate extra rects the + // first time we call it. This is necessary because some WebCore rendering + // objects update their layout only when painted. + for (int i = 0; i < 2; ++i) { + paint_rect_ = client_rect.Intersect(paint_rect_); + if (!paint_rect_.IsEmpty()) { + gfx::Rect rect(paint_rect_); + paint_rect_ = gfx::Rect(); + + DLOG_IF(WARNING, i == 1) << "painting caused additional invalidations"; + PaintRect(rect); + } + } + DCHECK(paint_rect_.IsEmpty()); + + // Paint to the screen + PAINTSTRUCT ps; + BeginPaint(view_, &ps); + canvas_->getTopPlatformDevice().drawToHDC(ps.hdc, + ps.rcPaint.left, + ps.rcPaint.top, + &ps.rcPaint); + EndPaint(view_, &ps); + + // Draw children + UpdateWindow(view_); +} + +void WebWidgetHost::Resize(LPARAM lparam) { + // Force an entire re-paint. TODO(darin): Maybe reuse this memory buffer. + DiscardBackingStore(); + + webwidget_->Resize(gfx::Size(LOWORD(lparam), HIWORD(lparam))); +} + +void WebWidgetHost::MouseEvent(UINT message, WPARAM wparam, LPARAM lparam) { + WebMouseEvent event(view_, message, wparam, lparam); + switch (event.type) { + case WebInputEvent::MOUSE_MOVE: + TrackMouseLeave(true); + break; + case WebInputEvent::MOUSE_LEAVE: + TrackMouseLeave(false); + break; + case WebInputEvent::MOUSE_DOWN: + SetCapture(view_); + break; + case WebInputEvent::MOUSE_UP: + if (GetCapture() == view_) + ReleaseCapture(); + break; + } + webwidget_->HandleInputEvent(&event); +} + +void WebWidgetHost::WheelEvent(WPARAM wparam, LPARAM lparam) { + WebMouseWheelEvent event(view_, WM_MOUSEWHEEL, wparam, lparam); + webwidget_->HandleInputEvent(&event); +} + +void WebWidgetHost::KeyEvent(UINT message, WPARAM wparam, LPARAM lparam) { + WebKeyboardEvent event(view_, message, wparam, lparam); + webwidget_->HandleInputEvent(&event); +} + +void WebWidgetHost::CaptureLostEvent() { + webwidget_->MouseCaptureLost(); +} + +void WebWidgetHost::SetFocus(bool enable) { + webwidget_->SetFocus(enable); +} + +void WebWidgetHost::TrackMouseLeave(bool track) { + if (track == track_mouse_leave_) + return; + track_mouse_leave_ = track; + + DCHECK(view_); + + TRACKMOUSEEVENT tme; + tme.cbSize = sizeof(TRACKMOUSEEVENT); + tme.dwFlags = TME_LEAVE; + if (!track_mouse_leave_) + tme.dwFlags |= TME_CANCEL; + tme.hwndTrack = view_; + + TrackMouseEvent(&tme); +} + +void WebWidgetHost::ResetScrollRect() { + scroll_rect_ = gfx::Rect(); + scroll_dx_ = 0; + scroll_dy_ = 0; +} + +void WebWidgetHost::PaintRect(const gfx::Rect& rect) { +#ifndef NDEBUG + DCHECK(!painting_); +#endif + DCHECK(canvas_.get()); + + set_painting(true); + webwidget_->Paint(canvas_.get(), rect); + set_painting(false); +} |