From 4a9c00b2e735ac17c9e92a8ae4ac8083ceca8c6f Mon Sep 17 00:00:00 2001 From: Marshall Greenblatt Date: Tue, 14 Aug 2012 23:34:56 +0000 Subject: [PATCH] Merge revision 739 changes: - Add the ability to customize the animation frame rate (issue #697). git-svn-id: https://chromiumembedded.googlecode.com/svn/branches/1025@740 5089003a-bbd8-11dd-ad1f-f1f9622dbc98 --- include/internal/cef_types.h | 7 +++ include/internal/cef_types_wrappers.h | 1 + libcef/browser_impl_gtk.cc | 2 + libcef/browser_impl_mac.mm | 2 + libcef/browser_impl_win.cc | 2 + libcef/webwidget_host.cc | 84 +++++++++++++++++++------- libcef/webwidget_host.h | 17 ++++-- libcef/webwidget_host_gtk.cc | 21 +------ libcef/webwidget_host_mac.mm | 16 +---- libcef/webwidget_host_win.cc | 15 +---- patch/patch.cfg | 5 -- patch/patches/base.patch | 33 ---------- tests/cefclient/cefclient.cpp | 4 ++ tests/cefclient/cefclient_switches.cpp | 1 + tests/cefclient/cefclient_switches.h | 1 + tests/cefclient/osrplugin.cpp | 30 +++++++++ 16 files changed, 128 insertions(+), 113 deletions(-) delete mode 100644 patch/patches/base.patch diff --git a/include/internal/cef_types.h b/include/internal/cef_types.h index e3b266eed..56e9fcaa5 100644 --- a/include/internal/cef_types.h +++ b/include/internal/cef_types.h @@ -224,6 +224,13 @@ typedef struct _cef_browser_settings_t { /// bool history_disabled; + /// + // The number of frames per second (fps) for the requestAnimationFrame timer + // and calls to CefRenderHandler::OnPaint(). The value must be between 0 and + // 90. Specify zero for the default frame rate of 30 fps. + /// + int animation_frame_rate; + // The below values map to WebPreferences settings. /// diff --git a/include/internal/cef_types_wrappers.h b/include/internal/cef_types_wrappers.h index 2f1cbd9c5..c37f9d112 100644 --- a/include/internal/cef_types_wrappers.h +++ b/include/internal/cef_types_wrappers.h @@ -331,6 +331,7 @@ struct CefBrowserSettingsTraits { target->drag_drop_disabled = src->drag_drop_disabled; target->load_drops_disabled = src->load_drops_disabled; target->history_disabled = src->history_disabled; + target->animation_frame_rate = src->animation_frame_rate; cef_string_set(src->standard_font_family.str, src->standard_font_family.length, &target->standard_font_family, copy); diff --git a/libcef/browser_impl_gtk.cc b/libcef/browser_impl_gtk.cc index 28fa2cd0e..56a0835ce 100644 --- a/libcef/browser_impl_gtk.cc +++ b/libcef/browser_impl_gtk.cc @@ -92,6 +92,8 @@ bool CefBrowserImpl::UIT_CreateBrowser(const CefString& url) { if (!settings_.developer_tools_disabled) dev_tools_agent_->SetWebView(webviewhost_->webview()); + webviewhost_->SetFrameRate(settings_.animation_frame_rate); + window_info_.m_Widget = webviewhost_->view_handle(); g_signal_connect(G_OBJECT(window_info_.m_Widget), "destroy", G_CALLBACK(window_destroyed), this); diff --git a/libcef/browser_impl_mac.mm b/libcef/browser_impl_mac.mm index f8054ff91..f85672a79 100644 --- a/libcef/browser_impl_mac.mm +++ b/libcef/browser_impl_mac.mm @@ -108,6 +108,8 @@ bool CefBrowserImpl::UIT_CreateBrowser(const CefString& url) { if (!settings_.developer_tools_disabled) dev_tools_agent_->SetWebView(webviewhost_->webview()); + webviewhost_->SetFrameRate(settings_.animation_frame_rate); + BrowserWebView* browserView = (BrowserWebView*)webviewhost_->view_handle(); browserView.browser = this; window_info_.m_View = browserView; diff --git a/libcef/browser_impl_win.cc b/libcef/browser_impl_win.cc index 0b4e6e015..779ab576c 100644 --- a/libcef/browser_impl_win.cc +++ b/libcef/browser_impl_win.cc @@ -219,6 +219,8 @@ bool CefBrowserImpl::UIT_CreateBrowser(const CefString& url) { if (!settings_.developer_tools_disabled) dev_tools_agent_->SetWebView(webviewhost_->webview()); + webviewhost_->SetFrameRate(settings_.animation_frame_rate); + Unlock(); if (!window_info_.m_bWindowRenderingDisabled) { diff --git a/libcef/webwidget_host.cc b/libcef/webwidget_host.cc index 5b03d0236..7b4488635 100644 --- a/libcef/webwidget_host.cc +++ b/libcef/webwidget_host.cc @@ -14,24 +14,15 @@ using webkit::npapi::WebPluginGeometry; using WebKit::WebSize; +const int WebWidgetHost::kDefaultFrameRate = 30; +const int WebWidgetHost::kMaxFrameRate = 90; void WebWidgetHost::ScheduleComposite() { - if (invalidate_timer_.IsRunning()) - return; - - // Try to paint at 60fps. - static int64 kDesiredRate = 16; - - // Maintain the desired rate. - invalidate_timer_.Start( - FROM_HERE, - base::TimeDelta::FromMilliseconds(kDesiredRate), - this, - &WebWidgetHost::Invalidate); + ScheduleInvalidateTimer(); } void WebWidgetHost::ScheduleAnimation() { - ScheduleComposite(); + ScheduleInvalidateTimer(); } void WebWidgetHost::UpdatePaintRect(const gfx::Rect& rect) { @@ -49,6 +40,12 @@ void WebWidgetHost::UpdateRedrawRect(const gfx::Rect& rect) { redraw_rect_ = redraw_rect_.Union(rect); } +void WebWidgetHost::InvalidateRect(const gfx::Rect& rect) { + if (rect.IsEmpty()) + return; + DidInvalidateRect(rect); +} + void WebWidgetHost::SetSize(int width, int height) { webwidget_->resize(WebSize(width, height)); DidInvalidateRect(gfx::Rect(0, 0, width, height)); @@ -98,28 +95,69 @@ gfx::PluginWindowHandle WebWidgetHost::GetWindowedPluginAt(int x, int y) { return gfx::kNullPluginWindow; } +void WebWidgetHost::SetFrameRate(int frames_per_second) { + if (frames_per_second <= 0) + frames_per_second = kDefaultFrameRate; + if (frames_per_second > kMaxFrameRate) + frames_per_second = kMaxFrameRate; + + frame_delay_ = 1000 / frames_per_second; +} + +void WebWidgetHost::ScheduleInvalidateTimer() { + if (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, - base::TimeDelta::FromMilliseconds(0), // Fire immediately. + delta, this, &WebWidgetHost::DoPaint); } void WebWidgetHost::DoPaint() { - if (MessageLoop::current()->IsIdle()) { - // Paint to the delegate. #if defined(OS_MACOSX) - SkRegion region; - Paint(region); + SkRegion region; + Paint(region); #else - Paint(); + Paint(); #endif - } else { - // Try again later. - SchedulePaintTimer(); - } + + last_paint_time_ = base::TimeTicks::Now(); } diff --git a/libcef/webwidget_host.h b/libcef/webwidget_host.h index 369ee36ff..21f8acb02 100644 --- a/libcef/webwidget_host.h +++ b/libcef/webwidget_host.h @@ -85,10 +85,6 @@ class WebWidgetHost { // Called for requestAnimationFrame animations. void ScheduleAnimation(); - // Invalidate the complete client area. This is called at a reasonable frame - // rate by the Schedule*() methods. - void Invalidate(); - #if defined(OS_WIN) void SetCursor(HCURSOR cursor); #endif @@ -139,6 +135,8 @@ class WebWidgetHost { void MoveWindowedPlugin(const webkit::npapi::WebPluginGeometry& geometry); gfx::PluginWindowHandle GetWindowedPluginAt(int x, int y); + void SetFrameRate(int frames_per_second); + void set_popup(bool popup) { popup_ = popup; } bool popup() { return popup_; } @@ -147,6 +145,10 @@ class WebWidgetHost { protected: WebWidgetHost(); + // Called from the Schedule*() methods. + void ScheduleInvalidateTimer(); + void DoInvalidate(); + // If window rendering is disabled paint messages are generated after all // other pending messages have been processed. void SchedulePaintTimer(); @@ -240,9 +242,13 @@ class WebWidgetHost { // Used to coalesce DidInvalidateRect() events into a single DoPaint() call. // Used when window rendering is disabled. base::OneShotTimer paint_timer_; + base::TimeTicks last_paint_time_; // Used to coalesce Schedule*() events into a single Invalidate() call. base::OneShotTimer invalidate_timer_; + base::TimeTicks last_invalidate_time_; + + int64 frame_delay_; #if defined(OS_WIN) // Used to call UpdateImeInputState() while IME is active. @@ -293,6 +299,9 @@ class WebWidgetHost { bool painting_; bool layouting_; + + static const int kDefaultFrameRate; + static const int kMaxFrameRate; }; #endif // CEF_LIBCEF_WEBWIDGET_HOST_H_ diff --git a/libcef/webwidget_host_gtk.cc b/libcef/webwidget_host_gtk.cc index 9d07401e3..7e50a3f8a 100644 --- a/libcef/webwidget_host_gtk.cc +++ b/libcef/webwidget_host_gtk.cc @@ -290,26 +290,14 @@ void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) { DidInvalidateRect(clip_rect); } -void WebWidgetHost::Invalidate() { - int width = logical_size_.width(); - int height = logical_size_.height(); - GdkRectangle grect = { - 0, - 0, - width, - height - }; - GdkWindow* window = view_->window; - gdk_window_invalidate_rect(window, &grect, 0); -} - WebWidgetHost::WebWidgetHost() : view_(NULL), paint_delegate_(NULL), webwidget_(NULL), canvas_w_(0), canvas_h_(0), - popup_(false) { + popup_(false), + frame_delay_(1000 / kDefaultFrameRate) { set_painting(false); } @@ -406,11 +394,6 @@ void WebWidgetHost::SetTooltipText(const CefString& tooltip_text) { // TODO(port): Implement this method as part of tooltip support. } -void WebWidgetHost::InvalidateRect(const gfx::Rect& rect) { - // TODO(port): Implement this method as part of off-screen rendering support. - NOTIMPLEMENTED(); -} - bool WebWidgetHost::GetImage(int width, int height, void* rgba_buffer) { if (!canvas_.get()) return false; diff --git a/libcef/webwidget_host_mac.mm b/libcef/webwidget_host_mac.mm index 3d3b255e2..a7e58722e 100644 --- a/libcef/webwidget_host_mac.mm +++ b/libcef/webwidget_host_mac.mm @@ -82,6 +82,7 @@ WebWidgetHost::WebWidgetHost() canvas_w_(0), canvas_h_(0), popup_(false), + frame_delay_(1000 / kDefaultFrameRate), mouse_modifiers_(0), painting_(false), layouting_(false) { @@ -320,25 +321,10 @@ void WebWidgetHost::Paint(SkRegion& update_rgn) { } } -void WebWidgetHost::Invalidate() { - if (!webwidget_) - return; - - WebSize size = webwidget_->size(); - InvalidateRect(gfx::Rect(0, 0, size.width, size.height)); -} - void WebWidgetHost::SetTooltipText(const CefString& tooltip_text) { // TODO(port): Implement this method as part of tooltip support. } -void WebWidgetHost::InvalidateRect(const gfx::Rect& rect) { - if (rect.IsEmpty()) - return; - - DidInvalidateRect(rect); -} - bool WebWidgetHost::GetImage(int width, int height, void* rgba_buffer) { if (!canvas_.get()) return false; diff --git a/libcef/webwidget_host_win.cc b/libcef/webwidget_host_win.cc index cb16771ea..9d8a0ff47 100644 --- a/libcef/webwidget_host_win.cc +++ b/libcef/webwidget_host_win.cc @@ -316,13 +316,6 @@ void WebWidgetHost::DidScrollRect(int dx, int dy, const gfx::Rect& clip_rect) { ::InvalidateRect(view_, &r, FALSE); } -void WebWidgetHost::Invalidate() { - if (!webwidget_) - return; - WebSize size = webwidget_->size(); - InvalidateRect(gfx::Rect(0, 0, size.width, size.height)); -} - void WebWidgetHost::SetCursor(HCURSOR cursor) { DCHECK(view_); SetClassLong(view_, GCL_HCURSOR, @@ -338,6 +331,7 @@ WebWidgetHost::WebWidgetHost() canvas_h_(0), popup_(false), track_mouse_leave_(false), + frame_delay_(1000 / kDefaultFrameRate), tooltip_view_(NULL), tooltip_showing_(false), ime_notification_(false), @@ -530,13 +524,6 @@ void WebWidgetHost::Paint() { } } -void WebWidgetHost::InvalidateRect(const gfx::Rect& rect) { - if (rect.IsEmpty()) - return; - - DidInvalidateRect(rect); -} - bool WebWidgetHost::GetImage(int width, int height, void* buffer) { const SkBitmap& bitmap = canvas_->getDevice()->accessBitmap(false); DCHECK(bitmap.config() == SkBitmap::kARGB_8888_Config); diff --git a/patch/patch.cfg b/patch/patch.cfg index 0a1e6a961..6eb2ba647 100644 --- a/patch/patch.cfg +++ b/patch/patch.cfg @@ -11,11 +11,6 @@ patches = [ 'name': 'build', 'path': '../build/', }, - { - # http://codereview.chromium.org/6730028/ - 'name': 'base', - 'path': '../base/', - }, { # http://code.google.com/p/gyp/issues/detail?id=223 # http://codereview.chromium.org/10383117/ diff --git a/patch/patches/base.patch b/patch/patches/base.patch deleted file mode 100644 index cee67dc03..000000000 --- a/patch/patches/base.patch +++ /dev/null @@ -1,33 +0,0 @@ -Index: message_loop.cc -=================================================================== ---- message_loop.cc (revision 119867) -+++ message_loop.cc (working copy) -@@ -362,9 +362,13 @@ - } - - void MessageLoop::AssertIdle() const { -+ DCHECK(IsIdle()); -+} -+ -+bool MessageLoop::IsIdle() const { - // We only check |incoming_queue_|, since we don't want to lock |work_queue_|. - base::AutoLock lock(incoming_queue_lock_); -- DCHECK(incoming_queue_.empty()); -+ return incoming_queue_.empty(); - } - - bool MessageLoop::is_running() const { -Index: message_loop.h -=================================================================== ---- message_loop.h (revision 119867) -+++ message_loop.h (working copy) -@@ -345,6 +345,9 @@ - // Asserts that the MessageLoop is "idle". - void AssertIdle() const; - -+ // Returns true if the MessageLoop is "idle". -+ bool IsIdle() const; -+ - #if defined(OS_WIN) - void set_os_modal_loop(bool os_modal_loop) { - os_modal_loop_ = os_modal_loop; diff --git a/tests/cefclient/cefclient.cpp b/tests/cefclient/cefclient.cpp index dc9c124ab..7b8da0fb2 100644 --- a/tests/cefclient/cefclient.cpp +++ b/tests/cefclient/cefclient.cpp @@ -297,6 +297,10 @@ void AppGetBrowserSettings(CefBrowserSettings& settings) { g_command_line->HasSwitch(cefclient::kLoadDropsDisabled); settings.history_disabled = g_command_line->HasSwitch(cefclient::kHistoryDisabled); + + settings.animation_frame_rate = GetIntValue( + g_command_line->GetSwitchValue(cefclient::kAnimationFrameRate)); + settings.remote_fonts_disabled = g_command_line->HasSwitch(cefclient::kRemoteFontsDisabled); diff --git a/tests/cefclient/cefclient_switches.cpp b/tests/cefclient/cefclient_switches.cpp index 40c420e55..39971dac1 100644 --- a/tests/cefclient/cefclient_switches.cpp +++ b/tests/cefclient/cefclient_switches.cpp @@ -38,6 +38,7 @@ const char kPackLoadingDisabled[] = "pack-loading-disabled"; const char kDragDropDisabled[] = "drag-drop-disabled"; const char kLoadDropsDisabled[] = "load-drops-disabled"; const char kHistoryDisabled[] = "history-disabled"; +const char kAnimationFrameRate[] = "animation-frame-rate"; const char kRemoteFontsDisabled[] = "remote-fonts-disabled"; const char kDefaultEncoding[] = "default-encoding"; const char kEncodingDetectorEnabled[] = "encoding-detector-enabled"; diff --git a/tests/cefclient/cefclient_switches.h b/tests/cefclient/cefclient_switches.h index da1edeb81..e02cf7260 100644 --- a/tests/cefclient/cefclient_switches.h +++ b/tests/cefclient/cefclient_switches.h @@ -40,6 +40,7 @@ extern const char kPackLoadingDisabled[]; extern const char kDragDropDisabled[]; extern const char kLoadDropsDisabled[]; extern const char kHistoryDisabled[]; +extern const char kAnimationFrameRate[]; extern const char kRemoteFontsDisabled[]; extern const char kDefaultEncoding[]; extern const char kEncodingDetectorEnabled[]; diff --git a/tests/cefclient/osrplugin.cpp b/tests/cefclient/osrplugin.cpp index 5bbc95c01..e8d3befb3 100644 --- a/tests/cefclient/osrplugin.cpp +++ b/tests/cefclient/osrplugin.cpp @@ -64,6 +64,11 @@ class ClientOSRHandler : public CefClient, ~ClientOSRHandler() { } + // Called immediately before the plugin is destroyed. + void Detach() { + plugin_ = NULL; + } + // CefClient methods virtual CefRefPtr GetLifeSpanHandler() OVERRIDE { return this; @@ -202,6 +207,9 @@ class ClientOSRHandler : public CefClient, CefRect& rect) OVERRIDE { REQUIRE_UI_THREAD(); + if (!plugin_) + return false; + // The simulated screen and view rectangle are the same. This is necessary // for popup menus to be located and sized inside the view. RECT clientRect; @@ -225,6 +233,9 @@ class ClientOSRHandler : public CefClient, int& screenY) OVERRIDE { REQUIRE_UI_THREAD(); + if (!plugin_) + return false; + // Convert the point from view coordinates to actual screen coordinates. POINT screen_pt = {viewX, viewY}; MapWindowPoints(plugin_->hWnd, HWND_DESKTOP, &screen_pt, 1); @@ -236,12 +247,20 @@ class ClientOSRHandler : public CefClient, virtual void OnPopupShow(CefRefPtr browser, bool show) OVERRIDE { REQUIRE_UI_THREAD(); + + if (!plugin_) + return; + plugin_->renderer.OnPopupShow(browser, show); } virtual void OnPopupSize(CefRefPtr browser, const CefRect& rect) OVERRIDE { REQUIRE_UI_THREAD(); + + if (!plugin_) + return; + plugin_->renderer.OnPopupSize(browser, rect); } @@ -251,6 +270,9 @@ class ClientOSRHandler : public CefClient, const void* buffer) OVERRIDE { REQUIRE_UI_THREAD(); + if (!plugin_) + return; + wglMakeCurrent(plugin_->hDC, plugin_->hRC); plugin_->renderer.OnPaint(browser, type, dirtyRects, buffer); } @@ -259,6 +281,9 @@ class ClientOSRHandler : public CefClient, CefCursorHandle cursor) OVERRIDE { REQUIRE_UI_THREAD(); + if (!plugin_) + return; + // Change the plugin window's cursor. SetClassLong(plugin_->hWnd, GCL_HCURSOR, static_cast(reinterpret_cast(cursor))); @@ -357,6 +382,11 @@ NPError NPP_DestroyImpl(NPP instance, NPSavedData** save) { ClientPlugin* plugin = reinterpret_cast(instance->pdata); if (plugin) { + if (g_offscreenBrowser.get()) { + CefRefPtr handler = + static_cast(g_offscreenBrowser->GetClient().get()); + handler->Detach(); + } if (plugin->hWnd) { DestroyWindow(plugin->hWnd); DisableGL(plugin);