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:
parent
71500d0792
commit
e390fbe5b6
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -58,6 +58,8 @@ class WebViewHost : public WebWidgetHost {
|
|||
virtual void SetFocus(bool enable);
|
||||
#endif
|
||||
|
||||
virtual bool IsTransparent();
|
||||
|
||||
protected:
|
||||
explicit WebViewHost(BrowserWebViewDelegate* delegate);
|
||||
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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.
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -136,8 +136,6 @@ void ClientOSRenderer::Render() {
|
|||
// Disable alpha blending.
|
||||
glDisable(GL_BLEND);
|
||||
}
|
||||
|
||||
glFlush();
|
||||
}
|
||||
|
||||
void ClientOSRenderer::OnPopupShow(CefRefPtr<CefBrowser> browser,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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;"> </span>
|
||||
<br>
|
||||
|
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue