Merge revision 745 changes:

- Improve the handling of invalidation/painting for off-screen rendering (issue #695).

git-svn-id: https://chromiumembedded.googlecode.com/svn/branches/1025@746 5089003a-bbd8-11dd-ad1f-f1f9622dbc98
This commit is contained in:
Marshall Greenblatt 2012-08-21 19:49:11 +00:00
parent 71500d0792
commit e390fbe5b6
14 changed files with 254 additions and 341 deletions

View File

@ -1055,10 +1055,6 @@ void CefBrowserImpl::UIT_Invalidate(const CefRect& dirtyRect) {
gfx::Rect rect(dirtyRect.x, dirtyRect.y, dirtyRect.width,
dirtyRect.height);
// Used when window rendering is disabled to send the specified region to
// the paint delegate when WebWidget::Paint() is next called.
host->UpdateRedrawRect(rect);
// Cause WebWidget::Paint() to be called when next appropriate.
host->InvalidateRect(rect);
}

View File

@ -509,13 +509,13 @@ WebCookieJar* BrowserWebViewDelegate::GetCookieJar() {
void BrowserWebViewDelegate::didInvalidateRect(const WebRect& rect) {
if (WebWidgetHost* host = GetWidgetHost())
host->DidInvalidateRect(rect);
host->InvalidateRect(rect);
}
void BrowserWebViewDelegate::didScrollRect(int dx, int dy,
const WebRect& clip_rect) {
if (WebWidgetHost* host = GetWidgetHost())
host->DidScrollRect(dx, dy, clip_rect);
host->ScrollRect(dx, dy, clip_rect);
}
void BrowserWebViewDelegate::scheduleComposite() {

View File

@ -321,7 +321,8 @@ void ExtractUnderlines(
[super setFrame:frameRect];
if (browser_ && browser_->UIT_GetWebView()) {
const NSRect bounds = [self bounds];
browser_->UIT_GetWebViewHost()->Resize(gfx::Rect(NSRectToCGRect(bounds)));
browser_->UIT_GetWebViewHost()->SetSize(bounds.size.width,
bounds.size.height);
}
}

View File

@ -3,6 +3,7 @@
// can be found in the LICENSE file.
#include "libcef/webview_host.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
WebViewHost::WebViewHost(BrowserWebViewDelegate* delegate)
: delegate_(delegate) {
@ -12,3 +13,7 @@ WebViewHost::WebViewHost(BrowserWebViewDelegate* delegate)
WebViewHost::~WebViewHost() {
}
#endif
bool WebViewHost::IsTransparent() {
return static_cast<WebKit::WebView*>(webwidget_)->isTransparent();
}

View File

@ -58,6 +58,8 @@ class WebViewHost : public WebWidgetHost {
virtual void SetFocus(bool enable);
#endif
virtual bool IsTransparent();
protected:
explicit WebViewHost(BrowserWebViewDelegate* delegate);

View File

@ -10,6 +10,7 @@
#include "base/message_loop.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebWidget.h"
#include "webkit/glue/webkit_glue.h"
using webkit::npapi::WebPluginGeometry;
using WebKit::WebSize;
@ -17,38 +18,67 @@ using WebKit::WebSize;
const int WebWidgetHost::kDefaultFrameRate = 30;
const int WebWidgetHost::kMaxFrameRate = 90;
void WebWidgetHost::ScheduleComposite() {
ScheduleInvalidateTimer();
}
void WebWidgetHost::ScheduleAnimation() {
ScheduleInvalidateTimer();
}
void WebWidgetHost::UpdatePaintRect(const gfx::Rect& rect) {
#if defined(OS_WIN) || defined(OS_MACOSX)
paint_rgn_.op(rect.x(), rect.y(), rect.right(), rect.bottom(),
SkRegion::kUnion_Op);
#else
// TODO(cef): Update all ports to use regions instead of rectangles.
paint_rect_ = paint_rect_.Union(rect);
#endif
}
void WebWidgetHost::UpdateRedrawRect(const gfx::Rect& rect) {
if (!view_)
redraw_rect_ = redraw_rect_.Union(rect);
}
void WebWidgetHost::InvalidateRect(const gfx::Rect& rect) {
if (rect.IsEmpty())
return;
DidInvalidateRect(rect);
int width, height;
GetSize(width, height);
const gfx::Rect client_rect(width, height);
const gfx::Rect rect_in_client = client_rect.Intersect(rect);
if (rect_in_client.IsEmpty())
return;
UpdatePaintRect(rect_in_client);
if (view_)
InvalidateWindowRect(rect_in_client);
else
ScheduleTimer();
}
void WebWidgetHost::ScheduleComposite() {
ScheduleTimer();
}
void WebWidgetHost::ScheduleAnimation() {
ScheduleTimer();
}
bool WebWidgetHost::GetImage(int width, int height, void* rgba_buffer) {
if (!canvas_.get())
return false;
const SkBitmap& bitmap = canvas_->getDevice()->accessBitmap(false);
DCHECK(bitmap.config() == SkBitmap::kARGB_8888_Config);
if (width == canvas_->getDevice()->width() &&
height == canvas_->getDevice()->height()) {
// The specified width and height values are the same as the canvas size.
// Return the existing canvas contents.
const void* pixels = bitmap.getPixels();
memcpy(rgba_buffer, pixels, width * height * 4);
return true;
}
// Create a new canvas of the requested size.
scoped_ptr<skia::PlatformCanvas> new_canvas(
new skia::PlatformCanvas(width, height, true));
new_canvas->writePixels(bitmap, 0, 0);
const SkBitmap& new_bitmap = new_canvas->getDevice()->accessBitmap(false);
DCHECK(new_bitmap.config() == SkBitmap::kARGB_8888_Config);
// Return the new canvas contents.
const void* pixels = new_bitmap.getPixels();
memcpy(rgba_buffer, pixels, width * height * 4);
return true;
}
void WebWidgetHost::SetSize(int width, int height) {
webwidget_->resize(WebSize(width, height));
DidInvalidateRect(gfx::Rect(0, 0, width, height));
InvalidateRect(gfx::Rect(0, 0, width, height));
EnsureTooltip();
}
@ -104,61 +134,94 @@ void WebWidgetHost::SetFrameRate(int frames_per_second) {
frame_delay_ = 1000 / frames_per_second;
}
void WebWidgetHost::ScheduleInvalidateTimer() {
// Invalidation is only required when window rendering is enabled.
if (!view_ || invalidate_timer_.IsRunning())
return;
// Maintain the desired rate.
base::TimeDelta delta = base::TimeTicks::Now() - last_invalidate_time_;
int64 actualRate = delta.InMilliseconds();
if (actualRate >= frame_delay_)
delta = base::TimeDelta::FromMilliseconds(1);
else
delta = base::TimeDelta::FromMilliseconds(frame_delay_ - actualRate);
invalidate_timer_.Start(
FROM_HERE,
delta,
this,
&WebWidgetHost::DoInvalidate);
}
void WebWidgetHost::DoInvalidate() {
if (!webwidget_)
return;
WebSize size = webwidget_->size();
InvalidateRect(gfx::Rect(0, 0, size.width, size.height));
last_invalidate_time_ = base::TimeTicks::Now();
}
void WebWidgetHost::SchedulePaintTimer() {
if (layouting_ || paint_timer_.IsRunning())
return;
// Maintain the desired rate.
base::TimeDelta delta = base::TimeTicks::Now() - last_paint_time_;
int64 actualRate = delta.InMilliseconds();
if (actualRate >= frame_delay_)
delta = base::TimeDelta::FromMilliseconds(1);
else
delta = base::TimeDelta::FromMilliseconds(frame_delay_ - actualRate);
paint_timer_.Start(
FROM_HERE,
delta,
this,
&WebWidgetHost::DoPaint);
}
void WebWidgetHost::DoPaint() {
#if defined(OS_MACOSX)
SkRegion region;
Paint(region);
void WebWidgetHost::UpdatePaintRect(const gfx::Rect& rect) {
#if defined(OS_WIN) || defined(OS_MACOSX)
paint_rgn_.op(rect.x(), rect.y(), rect.right(), rect.bottom(),
SkRegion::kUnion_Op);
#else
Paint();
// TODO(cef): Update all ports to use regions instead of rectangles.
paint_rect_ = paint_rect_.Union(rect);
#endif
last_paint_time_ = base::TimeTicks::Now();
}
void WebWidgetHost::PaintRect(const gfx::Rect& rect) {
#ifndef NDEBUG
DCHECK(!painting_);
#endif
DCHECK(canvas_.get());
if (rect.IsEmpty())
return;
if (IsTransparent()) {
// When using transparency mode clear the rectangle before painting.
SkPaint clearpaint;
clearpaint.setARGB(0, 0, 0, 0);
clearpaint.setXfermodeMode(SkXfermode::kClear_Mode);
SkRect skrc;
skrc.set(rect.x(), rect.y(), rect.right(), rect.bottom());
canvas_->drawRect(skrc, clearpaint);
}
set_painting(true);
webwidget_->paint(webkit_glue::ToWebCanvas(canvas_.get()), rect);
set_painting(false);
}
void WebWidgetHost::ScheduleTimer() {
if (timer_.IsRunning())
return;
// This method may be called multiple times while the timer callback is
// executing. If so re-execute this method a single time after the callback
// has completed.
if (timer_executing_) {
if (!timer_wanted_)
timer_wanted_ = true;
return;
}
// Maintain the desired rate.
base::TimeDelta delta = base::TimeTicks::Now() - timer_last_;
int64 actualRate = delta.InMilliseconds();
if (actualRate >= frame_delay_)
delta = base::TimeDelta::FromMilliseconds(1);
else
delta = base::TimeDelta::FromMilliseconds(frame_delay_ - actualRate);
timer_.Start(
FROM_HERE,
delta,
this,
&WebWidgetHost::DoTimer);
}
void WebWidgetHost::DoTimer() {
timer_executing_ = true;
if (view_) {
// Window rendering is enabled and we've received a requestAnimationFrame
// or similar call. Trigger the OS to invalidate/repaint the client area at
// the requested frequency.
InvalidateWindow();
} else {
// Window rendering is disabled. Generate OnPaint() calls at the requested
// frequency.
#if defined(OS_MACOSX)
SkRegion region;
Paint(region);
#else
Paint();
#endif
}
timer_executing_ = false;
timer_last_ = base::TimeTicks::Now();
if (timer_wanted_) {
timer_wanted_ = false;
ScheduleTimer();
}
}

View File

@ -76,8 +76,9 @@ class WebWidgetHost {
gfx::NativeView view_handle() const { return view_; }
WebKit::WebWidget* webwidget() const { return webwidget_; }
void DidInvalidateRect(const gfx::Rect& rect);
void DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect);
void InvalidateRect(const gfx::Rect& rect);
void ScrollRect(int dx, int dy, const gfx::Rect& clip_rect);
// Called for accelerated content like WebGL.
void ScheduleComposite();
@ -89,20 +90,11 @@ class WebWidgetHost {
void SetCursor(HCURSOR cursor);
#endif
// Update the region that will be painted to the canvas by WebKit the next
// time that Paint() is called.
void UpdatePaintRect(const gfx::Rect& rect);
// Update the region that will be drawn to the device the next time Paint()
// is called. This is only used when window rendering is disabled.
void UpdateRedrawRect(const gfx::Rect& rect);
#if defined(OS_MACOSX)
void Paint(SkRegion& update_rgn);
#else
void Paint();
#endif
void InvalidateRect(const gfx::Rect& rect);
bool GetImage(int width, int height, void* buffer);
@ -115,8 +107,6 @@ class WebWidgetHost {
WebKit::WebKeyboardEvent GetLastKeyEvent() const { return last_key_event_; }
void PaintRect(const gfx::Rect& rect);
void SetTooltipText(const CefString& tooltip_text);
void SendKeyEvent(cef_key_type_t type, const cef_key_info_t& keyInfo,
@ -137,6 +127,8 @@ class WebWidgetHost {
void SetFrameRate(int frames_per_second);
virtual bool IsTransparent() { return false; }
void set_popup(bool popup) { popup_ = popup; }
bool popup() { return popup_; }
@ -145,20 +137,26 @@ class WebWidgetHost {
protected:
WebWidgetHost();
// Called from the Schedule*() methods.
void ScheduleInvalidateTimer();
void DoInvalidate();
// Update the region that will be painted to the canvas by WebKit the next
// time that Paint() is called.
void UpdatePaintRect(const gfx::Rect& rect);
// If window rendering is disabled paint messages are generated after all
// other pending messages have been processed.
void SchedulePaintTimer();
void DoPaint();
void PaintRect(const gfx::Rect& rect);
// Trigger the OS to invalidate/repaint the window.
void InvalidateWindow();
void InvalidateWindowRect(const gfx::Rect& rect);
// When window rendering is enabled this method invalidates the client area to
// trigger repaint via the OS. When window rendering is disabled this method
// is used to generate CefRenderHandler::OnPaint() calls.
void ScheduleTimer();
void DoTimer();
#if defined(OS_WIN)
// Per-class wndproc. Returns true if the event should be swallowed.
virtual bool WndProc(UINT message, WPARAM wparam, LPARAM lparam);
void Resize(LPARAM lparam);
virtual void MouseEvent(UINT message, WPARAM wparam, LPARAM lparam);
void WheelEvent(WPARAM wparam, LPARAM lparam);
virtual void KeyEvent(UINT message, WPARAM wparam, LPARAM lparam);
@ -181,7 +179,6 @@ class WebWidgetHost {
#elif defined(OS_MACOSX)
// These need to be called from a non-subclass, so they need to be public.
public:
void Resize(const gfx::Rect& rect);
virtual void MouseEvent(NSEvent* event);
void WheelEvent(NSEvent* event);
virtual void KeyEvent(NSEvent* event);
@ -202,7 +199,6 @@ class WebWidgetHost {
// ---------------------------------------------------------------------------
static gfx::NativeView CreateWidget(gfx::NativeView parent_view,
WebWidgetHost* host);
void Resize(const gfx::Size& size);
virtual void KeyEvent(GdkEventKey* event);
#endif
@ -239,14 +235,10 @@ class WebWidgetHost {
gfx::Rect paint_rect_;
#endif
// Used to coalesce DidInvalidateRect() events into a single DoPaint() call.
// Used when window rendering is disabled.
base::OneShotTimer<WebWidgetHost> paint_timer_;
base::TimeTicks last_paint_time_;
// Used to coalesce Schedule*() events into a single Invalidate() call.
base::OneShotTimer<WebWidgetHost> invalidate_timer_;
base::TimeTicks last_invalidate_time_;
base::OneShotTimer<WebWidgetHost> timer_;
base::TimeTicks timer_last_;
bool timer_executing_;
bool timer_wanted_;
int64 frame_delay_;
@ -255,9 +247,6 @@ class WebWidgetHost {
base::RepeatingTimer<WebWidgetHost> ime_timer_;
#endif
// Redraw rectangle requested by an explicit call to CefBrowser::Invalidate().
gfx::Rect redraw_rect_;
// The map of windowed plugins that need to be drawn when window rendering is
// disabled.
typedef std::map<gfx::PluginWindowHandle, webkit::npapi::WebPluginGeometry>
@ -289,12 +278,6 @@ class WebWidgetHost {
WebKit::WebMouseEvent::Button mouse_button_down_;
#endif
#if defined(TOOLKIT_GTK)
// Since GtkWindow resize is asynchronous, we have to stash the dimensions,
// so that the backing store doesn't have to wait for sizing to take place.
gfx::Size logical_size_;
#endif
WebKit::WebKeyboardEvent last_key_event_;
bool painting_;

View File

@ -128,14 +128,14 @@ class WebWidgetHostGtkWidget {
static void HandleSizeAllocate(GtkWidget* widget,
GtkAllocation* allocation,
WebWidgetHost* host) {
host->Resize(WebSize(allocation->width, allocation->height));
host->SetSize(allocation->width, allocation->height);
}
// Size, position, or stacking of the GdkWindow changed.
static gboolean HandleConfigure(GtkWidget* widget,
GdkEventConfigure* config,
WebWidgetHost* host) {
host->Resize(WebSize(config->width, config->height));
host->SetSize(config->width, config->height);
return FALSE;
}
@ -146,7 +146,7 @@ class WebWidgetHostGtkWidget {
// See comments above about what g_handling_expose is for.
g_handling_expose = true;
gfx::Rect rect(expose->area);
host->UpdatePaintRect(rect);
host->InvalidateRect(rect);
host->Paint();
g_handling_expose = false;
return FALSE;
@ -273,21 +273,10 @@ WebWidgetHost* WebWidgetHost::Create(GtkWidget* parent_view,
return host;
}
void WebWidgetHost::DidInvalidateRect(const gfx::Rect& damaged_rect) {
DLOG_IF(WARNING, painting_) << "unexpected invalidation while painting";
UpdatePaintRect(damaged_rect);
if (!g_handling_expose) {
gtk_widget_queue_draw_area(GTK_WIDGET(view_), damaged_rect.x(),
damaged_rect.y(), damaged_rect.width(), damaged_rect.height());
}
}
void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) {
void WebWidgetHost::ScrollRect(int dx, int dy, const gfx::Rect& clip_rect) {
// This is used for optimizing painting when the renderer is scrolled. We're
// currently not doing any optimizations so just invalidate the region.
DidInvalidateRect(clip_rect);
InvalidateRect(clip_rect);
}
WebWidgetHost::WebWidgetHost()
@ -297,6 +286,8 @@ WebWidgetHost::WebWidgetHost()
canvas_w_(0),
canvas_h_(0),
popup_(false),
timer_executing_(false),
timer_wanted_(false),
frame_delay_(1000 / kDefaultFrameRate) {
set_painting(false);
}
@ -311,14 +302,24 @@ WebWidgetHost::~WebWidgetHost() {
// webwidget_->close();
}
void WebWidgetHost::Resize(const gfx::Size &newsize) {
logical_size_ = newsize;
SetSize(newsize.width(), newsize.height());
void WebWidgetHost::InvalidateWindow() {
int width, height;
GetSize(width, height);
const gfx::Rect client_rect(width, height);
InvalidateWindowRect(client_rect);
}
void WebWidgetHost::InvalidateWindowRect(const gfx::Rect& rect) {
DCHECK(view_);
if (!g_handling_expose) {
gtk_widget_queue_draw_area(GTK_WIDGET(view_), rect.x(),
rect.y(), rect.width(), rect.height());
}
}
void WebWidgetHost::Paint() {
int width = logical_size_.width();
int height = logical_size_.height();
int width, height;
GetSize(width, height);
gfx::Rect client_rect(width, height);
// Number of pixels that the canvas is allowed to differ from the client area.
@ -394,27 +395,12 @@ void WebWidgetHost::SetTooltipText(const CefString& tooltip_text) {
// TODO(port): Implement this method as part of tooltip support.
}
bool WebWidgetHost::GetImage(int width, int height, void* rgba_buffer) {
if (!canvas_.get())
return false;
// TODO(port): Implement this method as part of off-screen rendering support.
NOTIMPLEMENTED();
return false;
}
WebScreenInfo WebWidgetHost::GetScreenInfo() {
Display* display = GtkWidgetGetDisplay(view_);
int screen_num = GtkWidgetGetScreenNum(view_);
return WebScreenInfoFactory::screenInfo(display, screen_num);
}
void WebWidgetHost::PaintRect(const gfx::Rect& rect) {
set_painting(true);
webwidget_->paint(canvas_.get(), rect);
set_painting(false);
}
void WebWidgetHost::SendKeyEvent(cef_key_type_t type,
const cef_key_info_t& keyInfo,
int modifiers) {

View File

@ -22,12 +22,10 @@ MSVC_POP_WARNING();
#import "third_party/WebKit/Source/WebKit/chromium/public/WebInputEvent.h"
#import "third_party/WebKit/Source/WebKit/chromium/public/WebPopupMenu.h"
#import "third_party/WebKit/Source/WebKit/chromium/public/WebScreenInfo.h"
#import "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#import "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h"
#import "third_party/skia/include/core/SkRegion.h"
#import "ui/gfx/rect.h"
#import "ui/gfx/size.h"
#import "webkit/glue/webkit_glue.h"
using webkit::npapi::WebPluginGeometry;
using WebKit::WebInputEvent;
@ -82,6 +80,8 @@ WebWidgetHost::WebWidgetHost()
canvas_w_(0),
canvas_h_(0),
popup_(false),
timer_executing_(false),
timer_wanted_(false),
frame_delay_(1000 / kDefaultFrameRate),
mouse_modifiers_(0),
painting_(false),
@ -92,27 +92,7 @@ WebWidgetHost::WebWidgetHost()
WebWidgetHost::~WebWidgetHost() {
}
void WebWidgetHost::DidInvalidateRect(const gfx::Rect& damaged_rect) {
int width, height;
GetSize(width, height);
const gfx::Rect client_rect(width, height);
const gfx::Rect damaged_rect_in_client = client_rect.Intersect(damaged_rect);
if (damaged_rect_in_client.IsEmpty())
return;
UpdatePaintRect(damaged_rect_in_client);
if (view_) {
NSRect cocoa_rect = NSRectFromCGRect(damaged_rect_in_client.ToCGRect());
cocoa_rect.origin.y = client_rect.height() - NSMaxY(cocoa_rect);
[view_ setNeedsDisplayInRect:cocoa_rect];
} else {
SchedulePaintTimer();
}
}
void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) {
void WebWidgetHost::ScrollRect(int dx, int dy, const gfx::Rect& clip_rect) {
DCHECK(dx || dy);
int width, height;
@ -137,7 +117,7 @@ void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) {
// of the view means we can just invalidate the entire scroll rect.
if (!view_ || [view_ canDraw] || painting_ || layouting_ || Dx >= w ||
Dy >= h) {
DidInvalidateRect(clip_rect);
InvalidateRect(clip_rect);
return;
}
@ -161,7 +141,7 @@ void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) {
// to the screen buffer.
rect = gfx::Rect(dx>=0? x: r - Dx, dy>=0? y: b - Dy,
dx>0? Dx: w, dy>0? Dy: h);
DidInvalidateRect(rect);
InvalidateRect(rect);
// If any part of the scrolled rect was marked as dirty make sure to redraw
// it in the new scrolled-to location. Otherwise we can end up with artifacts
@ -170,7 +150,7 @@ void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) {
SkRegion moved_paint_rgn(paint_rgn_);
moved_paint_rgn.translate(dx, dy);
moved_paint_rgn.op(convertToSkiaRect(client_rect), SkRegion::kIntersect_Op);
DidInvalidateRect(convertFromSkiaRect(moved_paint_rgn.getBounds()));
InvalidateRect(convertFromSkiaRect(moved_paint_rgn.getBounds()));
}
void WebWidgetHost::Paint(SkRegion& update_rgn) {
@ -179,12 +159,6 @@ void WebWidgetHost::Paint(SkRegion& update_rgn) {
gfx::Rect client_rect(width, height);
SkRegion damaged_rgn;
if (!view_ && !redraw_rect_.IsEmpty()) {
// At a minimum we need to send the delegate the rectangle that was
// requested by calling CefBrowser::InvalidateRect().
damaged_rgn.setRect(convertToSkiaRect(redraw_rect_));
redraw_rect_ = gfx::Rect();
}
if (view_) {
// Union the rectangle that WebKit think needs repainting with the rectangle
@ -325,44 +299,10 @@ void WebWidgetHost::SetTooltipText(const CefString& tooltip_text) {
// TODO(port): Implement this method as part of tooltip support.
}
bool WebWidgetHost::GetImage(int width, int height, void* rgba_buffer) {
if (!canvas_.get())
return false;
const SkBitmap& bitmap = canvas_->getDevice()->accessBitmap(false);
DCHECK(bitmap.config() == SkBitmap::kARGB_8888_Config);
if (width == canvas_->getDevice()->width() &&
height == canvas_->getDevice()->height()) {
// The specified width and height values are the same as the canvas size.
// Return the existing canvas contents.
const void* pixels = bitmap.getPixels();
memcpy(rgba_buffer, pixels, width * height * 4);
return true;
}
// Create a new canvas of the requested size.
scoped_ptr<skia::PlatformCanvas> new_canvas(
new skia::PlatformCanvas(width, height, true));
new_canvas->writePixels(bitmap, 0, 0);
const SkBitmap& new_bitmap = new_canvas->getDevice()->accessBitmap(false);
DCHECK(new_bitmap.config() == SkBitmap::kARGB_8888_Config);
// Return the new canvas contents.
const void* pixels = new_bitmap.getPixels();
memcpy(rgba_buffer, pixels, width * height * 4);
return true;
}
WebScreenInfo WebWidgetHost::GetScreenInfo() {
return WebScreenInfoFactory::screenInfo(view_);
}
void WebWidgetHost::Resize(const gfx::Rect& rect) {
SetSize(rect.width(), rect.height());
}
void WebWidgetHost::MouseEvent(NSEvent *event) {
const WebMouseEvent& web_event = WebInputEventFactory::mouseEvent(
event, view_);
@ -421,31 +361,6 @@ void WebWidgetHost::SetFocus(bool enable) {
webwidget_->setFocus(enable);
}
void WebWidgetHost::PaintRect(const gfx::Rect& rect) {
#ifndef NDEBUG
DCHECK(!painting_);
#endif
DCHECK(canvas_.get());
if (rect.IsEmpty())
return;
if (!popup() && ((WebKit::WebView*)webwidget_)->isTransparent()) {
// When using transparency mode clear the rectangle before painting.
SkPaint clearpaint;
clearpaint.setARGB(0, 0, 0, 0);
clearpaint.setXfermodeMode(SkXfermode::kClear_Mode);
SkRect skrc;
skrc.set(rect.x(), rect.y(), rect.right(), rect.bottom());
canvas_->drawRect(skrc, clearpaint);
}
set_painting(true);
webwidget_->paint(webkit_glue::ToWebCanvas(canvas_.get()), rect);
set_painting(false);
}
void WebWidgetHost::SendKeyEvent(cef_key_type_t type,
const cef_key_info_t& keyInfo,
int modifiers) {
@ -636,6 +551,23 @@ void WebWidgetHost::SendFocusEvent(bool setFocus) {
void WebWidgetHost::SendCaptureLostEvent() {
}
void WebWidgetHost::InvalidateWindow() {
DCHECK(view_);
[view_ setNeedsDisplay:YES];
}
void WebWidgetHost::InvalidateWindowRect(const gfx::Rect& rect) {
DCHECK(view_);
int width, height;
GetSize(width, height);
const gfx::Rect client_rect(width, height);
NSRect cocoa_rect = NSRectFromCGRect(rect.ToCGRect());
cocoa_rect.origin.y = client_rect.height() - NSMaxY(cocoa_rect);
[view_ setNeedsDisplayInRect:cocoa_rect];
}
void WebWidgetHost::EnsureTooltip() {
// TODO(port): Implement this method as part of tooltip support.
}

View File

@ -20,7 +20,6 @@
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebSize.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebVector.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/win/WebInputEventFactory.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/win/WebScreenInfoFactory.h"
#include "third_party/skia/include/core/SkRegion.h"
@ -134,9 +133,12 @@ LRESULT CALLBACK WebWidgetHost::WndProc(HWND hwnd, UINT message, WPARAM wparam,
// during painting.
return 0;
case WM_SIZE:
host->Resize(lparam);
case WM_SIZE: {
int width = LOWORD(lparam);
int height = HIWORD(lparam);
host->SetSize(width, height);
return 0;
}
case WM_MOUSEMOVE:
case WM_MOUSELEAVE:
@ -266,26 +268,7 @@ LRESULT CALLBACK WebWidgetHost::WndProc(HWND hwnd, UINT message, WPARAM wparam,
return DefWindowProc(hwnd, message, wparam, lparam);
}
void WebWidgetHost::DidInvalidateRect(const gfx::Rect& damaged_rect) {
int width, height;
GetSize(width, height);
const gfx::Rect client_rect(width, height);
const gfx::Rect damaged_rect_in_client = client_rect.Intersect(damaged_rect);
if (damaged_rect_in_client.IsEmpty())
return;
UpdatePaintRect(damaged_rect_in_client);
if (view_) {
RECT r = damaged_rect_in_client.ToRECT();
::InvalidateRect(view_, &r, FALSE);
} else {
SchedulePaintTimer();
}
}
void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) {
void WebWidgetHost::ScrollRect(int dx, int dy, const gfx::Rect& clip_rect) {
DCHECK(dx || dy);
// Invalidate and re-paint the entire scroll rect if:
@ -296,7 +279,7 @@ void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) {
if (!view_ || !canvas_.get() || layouting_ || painting_ ||
abs(dx) >= clip_rect.width() || abs(dy) >= clip_rect.height() ||
paint_rgn_.intersects(convertToSkiaRect(clip_rect))) {
DidInvalidateRect(clip_rect);
InvalidateRect(clip_rect);
return;
}
@ -330,6 +313,8 @@ WebWidgetHost::WebWidgetHost()
canvas_w_(0),
canvas_h_(0),
popup_(false),
timer_executing_(false),
timer_wanted_(false),
track_mouse_leave_(false),
frame_delay_(1000 / kDefaultFrameRate),
tooltip_view_(NULL),
@ -350,6 +335,20 @@ WebWidgetHost::~WebWidgetHost() {
}
}
void WebWidgetHost::InvalidateWindow() {
int width, height;
GetSize(width, height);
const gfx::Rect client_rect(width, height);
InvalidateWindowRect(client_rect);
}
void WebWidgetHost::InvalidateWindowRect(const gfx::Rect& rect) {
DCHECK(view_);
RECT r = rect.ToRECT();
::InvalidateRect(view_, &r, FALSE);
}
bool WebWidgetHost::WndProc(UINT message, WPARAM wparam, LPARAM lparam) {
switch (message) {
case WM_ACTIVATE:
@ -370,12 +369,6 @@ void WebWidgetHost::Paint() {
// Damaged rectangle used for drawing when window rendering is disabled.
SkRegion damaged_rgn;
if (!view_ && !redraw_rect_.IsEmpty()) {
// At a minimum we need to send the delegate the rectangle that was
// requested by calling CefBrowser::InvalidateRect().
damaged_rgn.setRect(convertToSkiaRect(redraw_rect_));
redraw_rect_ = gfx::Rect();
}
if (view_ && !webwidget_->isAcceleratedCompositingActive()) {
// Number of pixels that the canvas is allowed to differ from the client
@ -524,41 +517,10 @@ void WebWidgetHost::Paint() {
}
}
bool WebWidgetHost::GetImage(int width, int height, void* buffer) {
const SkBitmap& bitmap = canvas_->getDevice()->accessBitmap(false);
DCHECK(bitmap.config() == SkBitmap::kARGB_8888_Config);
if (width == canvas_->getDevice()->width() &&
height == canvas_->getDevice()->height()) {
// The specified width and height values are the same as the canvas size.
// Return the existing canvas contents.
const void* pixels = bitmap.getPixels();
memcpy(buffer, pixels, width * height * 4);
return true;
}
// Create a new canvas of the requested size.
scoped_ptr<skia::PlatformCanvas> new_canvas(
new skia::PlatformCanvas(width, height, true));
new_canvas->writePixels(bitmap, 0, 0);
const SkBitmap& new_bitmap = new_canvas->getDevice()->accessBitmap(false);
DCHECK(new_bitmap.config() == SkBitmap::kARGB_8888_Config);
// Return the new canvas contents.
const void* pixels = new_bitmap.getPixels();
memcpy(buffer, pixels, width * height * 4);
return true;
}
WebScreenInfo WebWidgetHost::GetScreenInfo() {
return WebScreenInfoFactory::screenInfo(view_);
}
void WebWidgetHost::Resize(LPARAM lparam) {
SetSize(LOWORD(lparam), HIWORD(lparam));
}
void WebWidgetHost::MouseEvent(UINT message, WPARAM wparam, LPARAM lparam) {
const WebMouseEvent& event = WebInputEventFactory::mouseEvent(
view_, message, wparam, lparam);
@ -727,28 +689,6 @@ void WebWidgetHost::TrackMouseLeave(bool track) {
TrackMouseEvent(&tme);
}
void WebWidgetHost::PaintRect(const gfx::Rect& rect) {
#ifndef NDEBUG
DCHECK(!painting_);
#endif
DCHECK(canvas_.get());
if (!popup() && ((WebKit::WebView*)webwidget_)->isTransparent()) {
// When using transparency mode clear the rectangle before painting.
SkPaint clearpaint;
clearpaint.setARGB(0, 0, 0, 0);
clearpaint.setXfermodeMode(SkXfermode::kClear_Mode);
SkRect skrc;
skrc.set(rect.x(), rect.y(), rect.right(), rect.bottom());
canvas_->drawRect(skrc, clearpaint);
}
set_painting(true);
webwidget_->paint(canvas_.get(), rect);
set_painting(false);
}
void WebWidgetHost::SendKeyEvent(cef_key_type_t type,
const cef_key_info_t& keyInfo,
int modifiers) {

View File

@ -136,8 +136,6 @@ void ClientOSRenderer::Render() {
// Disable alpha blending.
glDisable(GL_BLEND);
}
glFlush();
}
void ClientOSRenderer::OnPopupShow(CefRefPtr<CefBrowser> browser,

View File

@ -61,6 +61,10 @@ void RunOSRPluginTest(CefRefPtr<CefBrowser> browser, bool transparent) {
// Transparency test.
browser->GetMainFrame()->LoadURL(
"http://tests/transparency");
} else if(elementId == "testAnimation") {
// requestAnimationFrame test.
browser->GetMainFrame()->LoadURL(
"http://mrdoob.com/lab/javascript/requestanimationframe/");
} else if (elementId == "testWindowlessPlugin") {
// Load flash, which is a windowless plugin.
browser->GetMainFrame()->LoadURL(
@ -99,6 +103,7 @@ void RunOSRPluginTest(CefRefPtr<CefBrowser> browser, bool transparent) {
RegisterClickListener(document, listener, "reload");
RegisterClickListener(document, listener, "go");
RegisterClickListener(document, listener, "testTransparency");
RegisterClickListener(document, listener, "testAnimation");
RegisterClickListener(document, listener, "testWindowlessPlugin");
RegisterClickListener(document, listener, "viewSource");
}
@ -109,7 +114,7 @@ void RunOSRPluginTest(CefRefPtr<CefBrowser> browser, bool transparent) {
// Center the window on the screen.
int screenX = GetSystemMetrics(SM_CXFULLSCREEN);
int screenY = GetSystemMetrics(SM_CYFULLSCREEN);
int width = 1000, height = 760;
int width = 1000, height = 780;
int x = (screenX - width) / 2;
int y = (screenY - height) / 2;

View File

@ -25,12 +25,13 @@
<li>Click and drag the view with the left mouse button while holding the shift key.</li>
<li>Enter a URL and click the "Go!" button to browse to a new Website.</li>
<li><a href="#" id="testTransparency">Click here</a> to test transparency.</li>
<li><a href="#" id="testAnimation">Click here</a> to test requestAnimationFrame.</li>
<li><a href="#" id="testWindowlessPlugin">Click here</a> to test a windowless plugin.</li>
</ul>
</td>
</tr>
</table>
<div style="padding: 2px; margin: 5px; width: 960px;" align="left">
<span id="title" style="font-size: 12pt; font-weight: bold;">&nbsp;</span>
<br>

View File

@ -21,6 +21,7 @@
<li>Click and drag the view with the left mouse button while holding the shift key.</li>
<li>Enter a URL and click the "Go!" button to browse to a new Website.</li>
<li><a href="http://tests/transparency">Click here</a> to test transparency.</li>
<li><a href="http://mrdoob.com/lab/javascript/requestanimationframe/">Click here</a> to test requestAnimationFrame.</li>
<li><a href="http://www.adobe.com/software/flash/about/">Click here</a> to test a windowless plugin.</li>
</ul>
</td>