summaryrefslogtreecommitdiffstats
path: root/webkit/tools/test_shell/mac/webwidget_host.mm
diff options
context:
space:
mode:
Diffstat (limited to 'webkit/tools/test_shell/mac/webwidget_host.mm')
-rw-r--r--webkit/tools/test_shell/mac/webwidget_host.mm260
1 files changed, 260 insertions, 0 deletions
diff --git a/webkit/tools/test_shell/mac/webwidget_host.mm b/webkit/tools/test_shell/mac/webwidget_host.mm
new file mode 100644
index 0000000..bf38fc4
--- /dev/null
+++ b/webkit/tools/test_shell/mac/webwidget_host.mm
@@ -0,0 +1,260 @@
+// Copyright (c) 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.
+
+#import <Cocoa/Cocoa.h>
+
+#include "webkit/tools/test_shell/webwidget_host.h"
+
+#include "base/gfx/platform_canvas_mac.h"
+#include "base/gfx/rect.h"
+#include "base/gfx/size.h"
+#include "base/logging.h"
+#include "webkit/glue/webinputevent.h"
+#include "webkit/glue/webwidget.h"
+
+/*static*/
+WebWidgetHost* WebWidgetHost::Create(NSWindow* parent_window,
+ WebWidgetDelegate* delegate) {
+ WebWidgetHost* host = new WebWidgetHost();
+
+ NSRect content_rect = [parent_window frame];
+ content_rect.origin.y += 64;
+ content_rect.size.height -= 64;
+ host->view_ = [[NSView alloc] initWithFrame:content_rect];
+ [[parent_window contentView] addSubview:host->view_];
+
+ // win_util::SetWindowUserData(host->hwnd_, host);
+
+ host->webwidget_ = WebWidget::Create(delegate);
+ host->webwidget_->Resize(gfx::Size(content_rect.size.width,
+ content_rect.size.height));
+ return host;
+}
+
+/*static*/
+WebWidgetHost* WebWidgetHost::FromWindow(NSWindow* hwnd) {
+ return NULL;
+}
+
+/*static*/
+void WebWidgetHost::HandleEvent(NSWindow *window, NSEvent *event) {
+ WebWidgetHost* host = FromWindow(window);
+ if (host) {
+ switch ([event type]) {
+ case NSLeftMouseDown:
+ case NSLeftMouseUp:
+ case NSRightMouseDown:
+ case NSRightMouseUp:
+ case NSOtherMouseDown:
+ case NSOtherMouseUp:
+ case NSMouseEntered:
+ case NSMouseExited:
+ host->MouseEvent(event);
+ break;
+
+ case NSScrollWheel:
+ host->WheelEvent(event);
+ break;
+
+ case NSKeyDown:
+ case NSKeyUp:
+ host->KeyEvent(event);
+ break;
+
+ case NSAppKitDefined:
+ switch ([event subtype]) {
+ case NSApplicationActivatedEventType:
+ host->SetFocus(true);
+ break;
+ case NSApplicationDeactivatedEventType:
+ host->SetFocus(false);
+ break;
+ }
+ break;
+ }
+ }
+}
+
+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);
+
+ NSRect r = NSRectFromCGRect(damaged_rect.ToCGRect());
+ [view_ setNeedsDisplayInRect:r];
+}
+
+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;
+
+ NSRect r = NSRectFromCGRect(clip_rect.ToCGRect());
+ [view_ setNeedsDisplayInRect:r];
+}
+
+// void WebWidgetHost::SetCursor(HCURSOR cursor) {
+// }
+
+void WebWidgetHost::DiscardBackingStore() {
+ canvas_.reset();
+}
+
+WebWidgetHost::WebWidgetHost()
+ : view_(NULL),
+ webwidget_(NULL),
+ scroll_dx_(0),
+ scroll_dy_(0),
+ track_mouse_leave_(false)
+{
+ set_painting(false);
+}
+
+WebWidgetHost::~WebWidgetHost() {
+ // win_util::SetWindowUserData(hwnd_, 0);
+
+ TrackMouseLeave(false);
+
+ webwidget_->Close();
+ webwidget_->Release();
+}
+
+void WebWidgetHost::Paint() {
+ NSRect r = [view_ frame];
+ gfx::Rect client_rect(NSRectToCGRect(r));
+ NSGraphicsContext* view_context = [NSGraphicsContext currentContext];
+ CGContextRef context = static_cast<CGContextRef>([view_context graphicsPort]);
+
+ // 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));
+ }
+
+ // make sure webkit draws into our bitmap, not the window
+ CGContextRef bitmap_context =
+ canvas_->getTopPlatformDevice().GetBitmapContext();
+ [NSGraphicsContext setCurrentContext:
+ [NSGraphicsContext graphicsContextWithGraphicsPort:bitmap_context
+ flipped:NO]];
+
+ // This may result in more invalidation
+ webwidget_->Layout();
+
+ // Scroll the canvas if necessary
+ scroll_rect_ = client_rect.Intersect(scroll_rect_);
+ if (!scroll_rect_.IsEmpty()) {
+ // add to invalidate rect, since there's no equivalent of ScrollDC.
+ paint_rect_.Union(scroll_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());
+
+ // set the context back to our window
+ [NSGraphicsContext setCurrentContext: view_context];
+
+ // Paint to the screen
+ if ([view_ lockFocusIfCanDraw]) {
+ CGRect paint_rect = NSRectToCGRect(r);
+ int bitmap_height = CGBitmapContextGetHeight(bitmap_context);
+ int bitmap_width = CGBitmapContextGetWidth(bitmap_context);
+ CGRect bitmap_rect = { { 0, 0 },
+ { bitmap_width, bitmap_height } };
+ canvas_->getTopPlatformDevice().DrawToContext(
+ context, 0, client_rect.height() - bitmap_height, &bitmap_rect);
+
+ [view_ unlockFocus];
+ }
+
+ // Draw children
+ // UpdateWindow(hwnd_);
+}
+
+void WebWidgetHost::Resize(const gfx::Rect& rect) {
+ // Force an entire re-paint. TODO(darin): Maybe reuse this memory buffer.
+ DiscardBackingStore();
+ webwidget_->Resize(gfx::Size(rect.width(), rect.height()));
+}
+
+void WebWidgetHost::MouseEvent(NSEvent *event) {
+ WebMouseEvent web_event(event);
+ switch (event.type) {
+ case WebInputEvent::MOUSE_MOVE:
+ TrackMouseLeave(true);
+ break;
+ case WebInputEvent::MOUSE_LEAVE:
+ TrackMouseLeave(false);
+ break;
+ case WebInputEvent::MOUSE_DOWN:
+ break;
+ case WebInputEvent::MOUSE_UP:
+ break;
+ }
+ webwidget_->HandleInputEvent(&web_event);
+}
+
+void WebWidgetHost::WheelEvent(NSEvent *event) {
+ WebMouseWheelEvent web_event(event);
+ webwidget_->HandleInputEvent(&web_event);
+}
+
+void WebWidgetHost::KeyEvent(NSEvent *event) {
+ WebKeyboardEvent web_event(event);
+ webwidget_->HandleInputEvent(&web_event);
+}
+
+void WebWidgetHost::SetFocus(bool enable) {
+ webwidget_->SetFocus(enable);
+}
+
+void WebWidgetHost::TrackMouseLeave(bool track) {
+}
+
+void WebWidgetHost::ResetScrollRect() {
+ scroll_rect_ = gfx::Rect();
+ scroll_dx_ = 0;
+ scroll_dy_ = 0;
+}
+
+void WebWidgetHost::PaintRect(const gfx::Rect& rect) {
+ DCHECK(!painting_);
+ DCHECK(canvas_.get());
+
+ set_painting(true);
+ webwidget_->Paint(canvas_.get(), rect);
+ set_painting(false);
+}