From bdf73fcd4c6f60e347fe475cc9354629b8b3f21d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 29 May 2015 11:12:55 +0800 Subject: [PATCH 1/5] Update to the new algorithm of setting webview size --- atom/browser/api/atom_api_web_contents.cc | 102 ++++++++++++++---- atom/browser/api/atom_api_web_contents.h | 37 ++++++- atom/browser/lib/guest-view-manager.coffee | 6 +- .../lib/web-view/guest-view-internal.coffee | 4 +- .../lib/web-view/web-view-attributes.coffee | 2 +- atom/renderer/lib/web-view/web-view.coffee | 3 + 6 files changed, 126 insertions(+), 28 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 1358d41822db..f82a65818a6a 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -44,12 +44,40 @@ #include "atom/common/node_includes.h" +namespace mate { + +template<> +struct Converter { + static bool FromV8(v8::Isolate* isolate, + v8::Local val, + atom::api::SetSizeParams* out) { + mate::Dictionary params; + if (!ConvertFromV8(isolate, val, ¶ms)) + return false; + bool autosize; + if (params.Get("enableAutoSize", &autosize)) + out->enable_auto_size.reset(new bool(true)); + gfx::Size size; + if (params.Get("min", &size)) + out->min_size.reset(new gfx::Size(size)); + if (params.Get("max", &size)) + out->max_size.reset(new gfx::Size(size)); + return true; + } +}; + +} // namespace mate + + namespace atom { namespace api { namespace { +const int kDefaultWidth = 300; +const int kDefaultHeight = 300; + v8::Persistent template_; // Get the window that has the |guest| embedded. @@ -85,7 +113,8 @@ WebContents::WebContents(content::WebContents* web_contents) element_instance_id_(-1), guest_opaque_(true), guest_host_(nullptr), - auto_size_enabled_(false) { + auto_size_enabled_(false), + is_full_page_plugin_(false) { } WebContents::WebContents(const mate::Dictionary& options) @@ -93,7 +122,8 @@ WebContents::WebContents(const mate::Dictionary& options) element_instance_id_(-1), guest_opaque_(true), guest_host_(nullptr), - auto_size_enabled_(false) { + auto_size_enabled_(false), + is_full_page_plugin_(false) { options.Get("guestInstanceId", &guest_instance_id_); auto browser_context = AtomBrowserContext::Get(); @@ -612,31 +642,57 @@ bool WebContents::SendIPCMessage(const base::string16& channel, return Send(new AtomViewMsg_Message(routing_id(), channel, args)); } -void WebContents::SetAutoSize(bool enabled, - const gfx::Size& min_size, - const gfx::Size& max_size) { +void WebContents::SetSize(const SetSizeParams& params) { + bool enable_auto_size = + params.enable_auto_size ? *params.enable_auto_size : auto_size_enabled_; + gfx::Size min_size = params.min_size ? *params.min_size : min_auto_size_; + gfx::Size max_size = params.max_size ? *params.max_size : max_auto_size_; + + if (params.normal_size) + normal_size_ = *params.normal_size; + min_auto_size_ = min_size; min_auto_size_.SetToMin(max_size); max_auto_size_ = max_size; max_auto_size_.SetToMax(min_size); - enabled &= !min_auto_size_.IsEmpty() && !max_auto_size_.IsEmpty(); - if (!enabled && !auto_size_enabled_) - return; - - auto_size_enabled_ = enabled; - - if (!attached()) - return; + enable_auto_size &= !min_auto_size_.IsEmpty() && !max_auto_size_.IsEmpty(); content::RenderViewHost* rvh = web_contents()->GetRenderViewHost(); - if (auto_size_enabled_) { + if (enable_auto_size) { + // Autosize is being enabled. rvh->EnableAutoResize(min_auto_size_, max_auto_size_); + normal_size_.SetSize(0, 0); } else { - rvh->DisableAutoResize(element_size_); - guest_size_ = element_size_; - GuestSizeChangedDueToAutoSize(guest_size_, element_size_); + // Autosize is being disabled. + // Use default width/height if missing from partially defined normal size. + if (normal_size_.width() && !normal_size_.height()) + normal_size_.set_height(GetDefaultSize().height()); + if (!normal_size_.width() && normal_size_.height()) + normal_size_.set_width(GetDefaultSize().width()); + + gfx::Size new_size; + if (!normal_size_.IsEmpty()) { + new_size = normal_size_; + } else if (!guest_size_.IsEmpty()) { + new_size = guest_size_; + } else { + new_size = GetDefaultSize(); + } + + if (auto_size_enabled_) { + // Autosize was previously enabled. + rvh->DisableAutoResize(new_size); + GuestSizeChangedDueToAutoSize(guest_size_, new_size); + } else { + // Autosize was already disabled. + guest_host_->SizeContents(new_size); + } + + guest_size_ = new_size; } + + auto_size_enabled_ = enable_auto_size; } void WebContents::SetAllowTransparency(bool allow) { @@ -727,7 +783,7 @@ mate::ObjectTemplateBuilder WebContents::GetObjectTemplateBuilder( .SetMethod("replace", &WebContents::Replace) .SetMethod("replaceMisspelling", &WebContents::ReplaceMisspelling) .SetMethod("_send", &WebContents::SendIPCMessage) - .SetMethod("setAutoSize", &WebContents::SetAutoSize) + .SetMethod("setSize", &WebContents::SetSize) .SetMethod("setAllowTransparency", &WebContents::SetAllowTransparency) .SetMethod("isGuest", &WebContents::is_guest) .SetMethod("hasServiceWorker", &WebContents::HasServiceWorker) @@ -760,6 +816,16 @@ void WebContents::GuestSizeChangedDueToAutoSize(const gfx::Size& old_size, new_size.width(), new_size.height()); } +gfx::Size WebContents::GetDefaultSize() const { + if (is_full_page_plugin_) { + // Full page plugins default to the size of the owner's viewport. + return embedder_web_contents_->GetRenderWidgetHostView() + ->GetVisibleViewportSize(); + } else { + return gfx::Size(kDefaultWidth, kDefaultHeight); + } +} + // static mate::Handle WebContents::CreateFrom( v8::Isolate* isolate, content::WebContents* web_contents) { diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index c7a8bbbfc04f..63248fd02a21 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -33,6 +33,22 @@ class WebDialogHelper; namespace api { +// A struct of parameters for SetSize(). The parameters are all declared as +// scoped pointers since they are all optional. Null pointers indicate that the +// parameter has not been provided, and the last used value should be used. Note +// that when |enable_auto_size| is true, providing |normal_size| is not +// meaningful. This is because the normal size of the guestview is overridden +// whenever autosizing occurs. +struct SetSizeParams { + SetSizeParams() {} + ~SetSizeParams() {} + + scoped_ptr enable_auto_size; + scoped_ptr min_size; + scoped_ptr max_size; + scoped_ptr normal_size; +}; + class WebContents : public mate::EventEmitter, public content::BrowserPluginGuestDelegate, public content::WebContentsDelegate, @@ -89,10 +105,9 @@ class WebContents : public mate::EventEmitter, bool SendIPCMessage(const base::string16& channel, const base::ListValue& args); - // Toggles autosize mode for corresponding . - void SetAutoSize(bool enabled, - const gfx::Size& min_size, - const gfx::Size& max_size); + // Used to toggle autosize mode for this GuestView, and set both the automatic + // and normal sizes. + void SetSize(const SetSizeParams& params); // Sets the transparency of the guest. void SetAllowTransparency(bool allow); @@ -217,9 +232,17 @@ class WebContents : public mate::EventEmitter, const base::ListValue& args, IPC::Message* message); + // This method is invoked when the contents auto-resized to give the container + // an opportunity to match it if it wishes. + // + // This gives the derived class an opportunity to inform its container element + // or perform other actions. void GuestSizeChangedDueToAutoSize(const gfx::Size& old_size, const gfx::Size& new_size); + // Returns the default size of the guestview. + gfx::Size GetDefaultSize() const; + scoped_ptr web_dialog_helper_; scoped_ptr dialog_manager_; @@ -258,6 +281,12 @@ class WebContents : public mate::EventEmitter, // The minimum size constraints of the container element in autosize mode. gfx::Size min_auto_size_; + // The size that will be used when autosize mode is disabled. + gfx::Size normal_size_; + + // Whether the guest view is inside a plugin document. + bool is_full_page_plugin_; + DISALLOW_COPY_AND_ASSIGN(WebContents); }; diff --git a/atom/browser/lib/guest-view-manager.coffee b/atom/browser/lib/guest-view-manager.coffee index f0d2a89318d6..e59bdb42c009 100644 --- a/atom/browser/lib/guest-view-manager.coffee +++ b/atom/browser/lib/guest-view-manager.coffee @@ -60,7 +60,7 @@ createGuest = (embedder, params) -> @viewInstanceId = params.instanceId min = width: params.minwidth, height: params.minheight max = width: params.maxwidth, height: params.maxheight - @setAutoSize params.autosize, min, max + @setSize params.autosize, min, max if params.src opts = {} @@ -132,8 +132,8 @@ ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', (event, elementInstanceId, ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', (event, id) -> destroyGuest event.sender, id -ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_AUTO_SIZE', (event, id, params) -> - guestInstances[id]?.guest.setAutoSize params.enableAutoSize, params.min, params.max +ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_SIZE', (event, id, params) -> + guestInstances[id]?.guest.setSize params ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_ALLOW_TRANSPARENCY', (event, id, allowtransparency) -> guestInstances[id]?.guest.setAllowTransparency allowtransparency diff --git a/atom/renderer/lib/web-view/guest-view-internal.coffee b/atom/renderer/lib/web-view/guest-view-internal.coffee index 4d5f599b3527..2abc47edffe6 100644 --- a/atom/renderer/lib/web-view/guest-view-internal.coffee +++ b/atom/renderer/lib/web-view/guest-view-internal.coffee @@ -67,8 +67,8 @@ module.exports = destroyGuest: (guestInstanceId) -> ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_DESTROY_GUEST', guestInstanceId - setAutoSize: (guestInstanceId, params) -> - ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_AUTO_SIZE', guestInstanceId, params + setSize: (guestInstanceId, params) -> + ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_SIZE', guestInstanceId, params setAllowTransparency: (guestInstanceId, allowtransparency) -> ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_SET_ALLOW_TRANSPARENCY', guestInstanceId, allowtransparency diff --git a/atom/renderer/lib/web-view/web-view-attributes.coffee b/atom/renderer/lib/web-view/web-view-attributes.coffee index 51dd2475a4e0..d2ea629f50d7 100644 --- a/atom/renderer/lib/web-view/web-view-attributes.coffee +++ b/atom/renderer/lib/web-view/web-view-attributes.coffee @@ -72,7 +72,7 @@ class AutosizeDimensionAttribute extends WebViewAttribute handleMutation: (oldValue, newValue) -> return unless @webViewImpl.guestInstanceId - guestViewInternal.setAutoSize @webViewImpl.guestInstanceId, + guestViewInternal.setSize @webViewImpl.guestInstanceId, enableAutoSize: @webViewImpl.attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue() min: width: parseInt @webViewImpl.attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() || 0 diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index a4edc58a10f2..94cd897d6a34 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -107,6 +107,9 @@ class WebViewImpl minWidth = @attributes[webViewConstants.ATTRIBUTE_MINWIDTH].getValue() | width minHeight = @attributes[webViewConstants.ATTRIBUTE_MINHEIGHT].getValue() | width + minWidth = Math.min minWidth, maxWidth + minHeight = Math.min minHeight, maxHeight + if not @attributes[webViewConstants.ATTRIBUTE_AUTOSIZE].getValue() or (newWidth >= minWidth and newWidth <= maxWidth and From b45ed8d9a202f007474da7e205920a3e76e9986d Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 29 May 2015 11:20:28 +0800 Subject: [PATCH 2/5] pendingGuestCreation is removed --- atom/renderer/lib/web-view/web-view.coffee | 7 ------- 1 file changed, 7 deletions(-) diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index 94cd897d6a34..6a8e3cf05e58 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -13,7 +13,6 @@ class WebViewImpl constructor: (@webviewNode) -> v8Util.setHiddenValue @webviewNode, 'internal', this @attached = false - @pendingGuestCreation = false @elementAttached = false @beforeFirstNavigation = true @@ -122,16 +121,10 @@ class WebViewImpl @dispatchEvent webViewEvent createGuest: -> - return if @pendingGuestCreation params = storagePartitionId: @attributes[webViewConstants.ATTRIBUTE_PARTITION].getValue() guestViewInternal.createGuest 'webview', params, (guestInstanceId) => - @pendingGuestCreation = false - unless @elementAttached - guestViewInternal.destroyGuest guestInstanceId - return @attachWindow guestInstanceId - @pendingGuestCreation = true dispatchEvent: (webViewEvent) -> @webviewNode.dispatchEvent webViewEvent From e4bb456964ce5c622cd539fb3824dccdea4af329 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 29 May 2015 11:44:49 +0800 Subject: [PATCH 3/5] Pass element size when attaching --- atom/browser/api/atom_api_web_contents.cc | 3 +++ atom/browser/lib/guest-view-manager.coffee | 12 +++++----- .../lib/web-view/guest-view-internal.coffee | 4 ++-- atom/renderer/lib/web-view/web-view.coffee | 22 ++++++++++++------- 4 files changed, 26 insertions(+), 15 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index f82a65818a6a..639b875fa975 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -62,6 +62,8 @@ struct Converter { out->min_size.reset(new gfx::Size(size)); if (params.Get("max", &size)) out->max_size.reset(new gfx::Size(size)); + if (params.Get("elementSize", &size)) + out->normal_size.reset(new gfx::Size(size)); return true; } }; @@ -476,6 +478,7 @@ void WebContents::WillAttach(content::WebContents* embedder_web_contents, bool is_full_page_plugin) { embedder_web_contents_ = embedder_web_contents; element_instance_id_ = element_instance_id; + is_full_page_plugin_ = is_full_page_plugin; } void WebContents::Destroy() { diff --git a/atom/browser/lib/guest-view-manager.coffee b/atom/browser/lib/guest-view-manager.coffee index e59bdb42c009..ab8aa8a4ad98 100644 --- a/atom/browser/lib/guest-view-manager.coffee +++ b/atom/browser/lib/guest-view-manager.coffee @@ -41,7 +41,6 @@ createGuest = (embedder, params) -> guest = webContents.create isGuest: true guestInstanceId: id - storagePartitionId: params.storagePartitionId guestInstances[id] = {guest, embedder} # Destroy guest when the embedder is gone or navigated. @@ -58,9 +57,12 @@ createGuest = (embedder, params) -> delete @attachParams @viewInstanceId = params.instanceId - min = width: params.minwidth, height: params.minheight - max = width: params.maxwidth, height: params.maxheight - @setSize params.autosize, min, max + @setSize + enableAutoSize: params.autosize + min: + width: params.minwidth, height: params.minheight + max: + width: params.maxwidth, height: params.maxheight if params.src opts = {} @@ -123,7 +125,7 @@ destroyGuest = (embedder, id) -> delete reverseEmbedderElementsMap[id] delete embedderElementsMap[key] -ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', (event, type, params, requestId) -> +ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', (event, params, requestId) -> event.sender.send "ATOM_SHELL_RESPONSE_#{requestId}", createGuest(event.sender, params) ipc.on 'ATOM_SHELL_GUEST_VIEW_MANAGER_ATTACH_GUEST', (event, elementInstanceId, guestInstanceId, params) -> diff --git a/atom/renderer/lib/web-view/guest-view-internal.coffee b/atom/renderer/lib/web-view/guest-view-internal.coffee index 2abc47edffe6..cc0a7c928e38 100644 --- a/atom/renderer/lib/web-view/guest-view-internal.coffee +++ b/atom/renderer/lib/web-view/guest-view-internal.coffee @@ -55,9 +55,9 @@ module.exports = ipc.removeAllListeners "ATOM_SHELL_GUEST_VIEW_INTERNAL_IPC_MESSAGE-#{viewInstanceId}" ipc.removeAllListeners "ATOM_SHELL_GUEST_VIEW_INTERNAL_SIZE_CHANGED-#{viewInstanceId}" - createGuest: (type, params, callback) -> + createGuest: (params, callback) -> requestId++ - ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', type, params, requestId + ipc.send 'ATOM_SHELL_GUEST_VIEW_MANAGER_CREATE_GUEST', params, requestId ipc.once "ATOM_SHELL_RESPONSE_#{requestId}", callback attachGuest: (elementInstanceId, guestInstanceId, params) -> diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index 6a8e3cf05e58..72961052a055 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -88,7 +88,7 @@ class WebViewImpl return unless @guestInstanceId - guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, @buildAttachParams() + guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, @buildParams() onSizeChanged: (webViewEvent) -> newWidth = webViewEvent.newWidth @@ -121,9 +121,7 @@ class WebViewImpl @dispatchEvent webViewEvent createGuest: -> - params = - storagePartitionId: @attributes[webViewConstants.ATTRIBUTE_PARTITION].getValue() - guestViewInternal.createGuest 'webview', params, (guestInstanceId) => + guestViewInternal.createGuest @buildParams(), (guestInstanceId) => @attachWindow guestInstanceId dispatchEvent: (webViewEvent) -> @@ -156,21 +154,29 @@ class WebViewImpl onAttach: (storagePartitionId) -> @attributes[webViewConstants.ATTRIBUTE_PARTITION].setValue storagePartitionId - buildAttachParams: -> + buildParams: -> params = instanceId: @viewInstanceId userAgentOverride: @userAgentOverride for attributeName, attribute of @attributes params[attributeName] = attribute.getValue() + # When the WebView is not participating in layout (display:none) + # then getBoundingClientRect() would report a width and height of 0. + # However, in the case where the WebView has a fixed size we can + # use that value to initially size the guest so as to avoid a relayout of + # the on display:block. + css = window.getComputedStyle @webviewNode, null + elementRect = @webviewNode.getBoundingClientRect() + params.elementSize = + width: parseInt(elementRect.width) || parseInt(css.getPropertyValue('width')) + height: parseInt(elementRect.height) || parseInt(css.getPropertyValue('height')) params attachWindow: (guestInstanceId) -> @guestInstanceId = guestInstanceId - params = @buildAttachParams() - return true unless @internalInstanceId - guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, params + guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, @buildParams() # Registers browser plugin custom element. registerBrowserPluginElement = -> From b5c9fe78f17ed0a676c4849f130ee909a30a83ca Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 29 May 2015 13:47:09 +0800 Subject: [PATCH 4/5] Listen to ElementSizeChanged event --- atom/browser/api/atom_api_web_contents.cc | 2 +- atom/browser/default_app/default_app.js | 1 - atom/browser/lib/guest-view-manager.coffee | 2 + atom/renderer/api/atom_api_web_frame.cc | 12 ++++++ atom/renderer/api/atom_api_web_frame.h | 4 ++ atom/renderer/guest_view_container.cc | 44 +++++++++++++++++++++- atom/renderer/guest_view_container.h | 23 ++++++++++- atom/renderer/lib/web-view/web-view.coffee | 22 +++++++++-- vendor/native_mate | 2 +- 9 files changed, 104 insertions(+), 8 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index 639b875fa975..d6f934525eb1 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -62,7 +62,7 @@ struct Converter { out->min_size.reset(new gfx::Size(size)); if (params.Get("max", &size)) out->max_size.reset(new gfx::Size(size)); - if (params.Get("elementSize", &size)) + if (params.Get("normal", &size)) out->normal_size.reset(new gfx::Size(size)); return true; } diff --git a/atom/browser/default_app/default_app.js b/atom/browser/default_app/default_app.js index e471b23ae621..6b52d3f280f9 100644 --- a/atom/browser/default_app/default_app.js +++ b/atom/browser/default_app/default_app.js @@ -15,7 +15,6 @@ app.on('ready', function() { mainWindow = new BrowserWindow({ width: 800, height: 600, - resizable: false, 'auto-hide-menu-bar': true, 'use-content-size': true, }); diff --git a/atom/browser/lib/guest-view-manager.coffee b/atom/browser/lib/guest-view-manager.coffee index ab8aa8a4ad98..6e3447eece3e 100644 --- a/atom/browser/lib/guest-view-manager.coffee +++ b/atom/browser/lib/guest-view-manager.coffee @@ -58,6 +58,8 @@ createGuest = (embedder, params) -> @viewInstanceId = params.instanceId @setSize + normal: + width: params.elementWidth, height: params.elementHeight enableAutoSize: params.autosize min: width: params.minwidth, height: params.minheight diff --git a/atom/renderer/api/atom_api_web_frame.cc b/atom/renderer/api/atom_api_web_frame.cc index 21c0592a7c43..7b1666e680c3 100644 --- a/atom/renderer/api/atom_api_web_frame.cc +++ b/atom/renderer/api/atom_api_web_frame.cc @@ -10,9 +10,11 @@ #define USE(WTF_FEATURE) (defined WTF_USE_##WTF_FEATURE && WTF_USE_##WTF_FEATURE) // NOLINT #define ENABLE(WTF_FEATURE) (defined ENABLE_##WTF_FEATURE && ENABLE_##WTF_FEATURE) // NOLINT +#include "atom/common/native_mate_converters/gfx_converter.h" #include "atom/common/native_mate_converters/string16_converter.h" #include "atom/renderer/api/atom_api_spell_check_client.h" #include "content/public/renderer/render_frame.h" +#include "native_mate/callback.h" #include "native_mate/dictionary.h" #include "native_mate/object_template_builder.h" #include "third_party/WebKit/public/web/WebDocument.h" @@ -78,6 +80,14 @@ v8::Local WebFrame::RegisterEmbedderCustomElement( return web_frame_->document().registerEmbedderCustomElement(name, options, c); } +void WebFrame::RegisterElementResizeCallback( + int element_instance_id, + const GuestViewContainer::ResizeCallback& callback) { + auto guest_view_container = GuestViewContainer::FromID(element_instance_id); + if (guest_view_container) + guest_view_container->RegisterElementResizeCallback(callback); +} + void WebFrame::AttachGuest(int id) { content::RenderFrame::FromWebFrame(web_frame_)->AttachGuest(id); } @@ -106,6 +116,8 @@ mate::ObjectTemplateBuilder WebFrame::GetObjectTemplateBuilder( .SetMethod("getZoomFactor", &WebFrame::GetZoomFactor) .SetMethod("registerEmbedderCustomElement", &WebFrame::RegisterEmbedderCustomElement) + .SetMethod("registerElementResizeCallback", + &WebFrame::RegisterElementResizeCallback) .SetMethod("attachGuest", &WebFrame::AttachGuest) .SetMethod("setSpellCheckProvider", &WebFrame::SetSpellCheckProvider) .SetMethod("registerUrlSchemeAsSecure", diff --git a/atom/renderer/api/atom_api_web_frame.h b/atom/renderer/api/atom_api_web_frame.h index f9afa1d1d616..e57efd45cfb8 100644 --- a/atom/renderer/api/atom_api_web_frame.h +++ b/atom/renderer/api/atom_api_web_frame.h @@ -7,6 +7,7 @@ #include +#include "atom/renderer/guest_view_container.h" #include "base/memory/scoped_ptr.h" #include "native_mate/handle.h" #include "native_mate/wrappable.h" @@ -42,6 +43,9 @@ class WebFrame : public mate::Wrappable { v8::Local RegisterEmbedderCustomElement( const base::string16& name, v8::Local options); + void RegisterElementResizeCallback( + int element_instance_id, + const GuestViewContainer::ResizeCallback& callback); void AttachGuest(int element_instance_id); // Set the provider that will be used by SpellCheckClient for spell check. diff --git a/atom/renderer/guest_view_container.cc b/atom/renderer/guest_view_container.cc index f23c36dfd356..638df2177e48 100644 --- a/atom/renderer/guest_view_container.cc +++ b/atom/renderer/guest_view_container.cc @@ -4,12 +4,54 @@ #include "atom/renderer/guest_view_container.h" +#include + +#include "base/lazy_instance.h" + namespace atom { -GuestViewContainer::GuestViewContainer(content::RenderFrame* render_frame) { +namespace { + +using GuestViewContainerMap = std::map; +static base::LazyInstance g_guest_view_container_map = + LAZY_INSTANCE_INITIALIZER; + +} // namespace + +GuestViewContainer::GuestViewContainer(content::RenderFrame* render_frame) + : render_frame_(render_frame) { } GuestViewContainer::~GuestViewContainer() { + if (element_instance_id_ > 0) + g_guest_view_container_map.Get().erase(element_instance_id_); +} + +// static +GuestViewContainer* GuestViewContainer::FromID(int element_instance_id) { + GuestViewContainerMap* guest_view_containers = + g_guest_view_container_map.Pointer(); + auto it = guest_view_containers->find(element_instance_id); + return it == guest_view_containers->end() ? nullptr : it->second; +} + +void GuestViewContainer::RegisterElementResizeCallback( + const ResizeCallback& callback) { + element_resize_callback_ = callback; +} + +void GuestViewContainer::SetElementInstanceID(int element_instance_id) { + element_instance_id_ = element_instance_id; + g_guest_view_container_map.Get().insert( + std::make_pair(element_instance_id, this)); +} + +void GuestViewContainer::DidResizeElement(const gfx::Size& old_size, + const gfx::Size& new_size) { + if (element_resize_callback_.is_null()) + return; + + element_resize_callback_.Run(old_size, new_size); } } // namespace atom diff --git a/atom/renderer/guest_view_container.h b/atom/renderer/guest_view_container.h index 5a21dad028ff..b81f84cbd050 100644 --- a/atom/renderer/guest_view_container.h +++ b/atom/renderer/guest_view_container.h @@ -5,17 +5,38 @@ #ifndef ATOM_RENDERER_GUEST_VIEW_CONTAINER_H_ #define ATOM_RENDERER_GUEST_VIEW_CONTAINER_H_ +#include "base/callback.h" #include "content/public/renderer/browser_plugin_delegate.h" -#include "v8/include/v8.h" + +namespace gfx { +class Size; +} namespace atom { class GuestViewContainer : public content::BrowserPluginDelegate { public: + typedef base::Callback + ResizeCallback; + explicit GuestViewContainer(content::RenderFrame* render_frame); ~GuestViewContainer() override; + static GuestViewContainer* FromID(int element_instance_id); + + void RegisterElementResizeCallback(const ResizeCallback& callback); + + // content::BrowserPluginDelegate: + void SetElementInstanceID(int element_instance_id) final; + void DidResizeElement(const gfx::Size& old_size, + const gfx::Size& new_size) final; + private: + int element_instance_id_; + content::RenderFrame* render_frame_; + + ResizeCallback element_resize_callback_; + DISALLOW_COPY_AND_ASSIGN(GuestViewContainer); }; diff --git a/atom/renderer/lib/web-view/web-view.coffee b/atom/renderer/lib/web-view/web-view.coffee index 72961052a055..da6f55c8fe35 100644 --- a/atom/renderer/lib/web-view/web-view.coffee +++ b/atom/renderer/lib/web-view/web-view.coffee @@ -86,6 +86,9 @@ class WebViewImpl @browserPluginNode.removeAttribute webViewConstants.ATTRIBUTE_INTERNALINSTANCEID @internalInstanceId = parseInt newValue + # Track when the element resizes using the element resize callback. + webFrame.registerElementResizeCallback @internalInstanceId, @onElementResize.bind(this) + return unless @guestInstanceId guestViewInternal.attachGuest @internalInstanceId, @guestInstanceId, @buildParams() @@ -120,6 +123,18 @@ class WebViewImpl # changed. @dispatchEvent webViewEvent + onElementResize: (oldSize, newSize) -> + # Dispatch the 'resize' event. + resizeEvent = new Event('resize', bubbles: true) + resizeEvent.oldWidth = oldSize.width + resizeEvent.oldHeight = oldSize.height + resizeEvent.newWidth = newSize.width + resizeEvent.newHeight = newSize.height + @dispatchEvent resizeEvent + + if @guestInstanceId + guestViewInternal.setSize @guestInstanceId, normal: newSize + createGuest: -> guestViewInternal.createGuest @buildParams(), (guestInstanceId) => @attachWindow guestInstanceId @@ -167,9 +182,10 @@ class WebViewImpl # the on display:block. css = window.getComputedStyle @webviewNode, null elementRect = @webviewNode.getBoundingClientRect() - params.elementSize = - width: parseInt(elementRect.width) || parseInt(css.getPropertyValue('width')) - height: parseInt(elementRect.height) || parseInt(css.getPropertyValue('height')) + params.elementWidth = parseInt(elementRect.width) || + parseInt(css.getPropertyValue('width')) + params.elementHeight = parseInt(elementRect.height) || + parseInt(css.getPropertyValue('height')) params attachWindow: (guestInstanceId) -> diff --git a/vendor/native_mate b/vendor/native_mate index 1696237a3f44..ad207eeabb01 160000 --- a/vendor/native_mate +++ b/vendor/native_mate @@ -1 +1 @@ -Subproject commit 1696237a3f444f0e33a8947749b4d70f6feb511b +Subproject commit ad207eeabb0185f74c017e70ca3411d522627ff0 From a9ad783bcaf81b371643dce9b145eb1f3df9c439 Mon Sep 17 00:00:00 2001 From: Cheng Zhao Date: Fri, 29 May 2015 13:52:14 +0800 Subject: [PATCH 5/5] The ElementSizeChanged has been removed --- atom/browser/api/atom_api_web_contents.cc | 11 ----------- atom/browser/api/atom_api_web_contents.h | 5 ----- 2 files changed, 16 deletions(-) diff --git a/atom/browser/api/atom_api_web_contents.cc b/atom/browser/api/atom_api_web_contents.cc index d6f934525eb1..cfc8304d0611 100644 --- a/atom/browser/api/atom_api_web_contents.cc +++ b/atom/browser/api/atom_api_web_contents.cc @@ -112,7 +112,6 @@ content::ServiceWorkerContext* GetServiceWorkerContext( WebContents::WebContents(content::WebContents* web_contents) : content::WebContentsObserver(web_contents), guest_instance_id_(-1), - element_instance_id_(-1), guest_opaque_(true), guest_host_(nullptr), auto_size_enabled_(false), @@ -121,7 +120,6 @@ WebContents::WebContents(content::WebContents* web_contents) WebContents::WebContents(const mate::Dictionary& options) : guest_instance_id_(-1), - element_instance_id_(-1), guest_opaque_(true), guest_host_(nullptr), auto_size_enabled_(false), @@ -450,14 +448,6 @@ void WebContents::DidAttach(int guest_proxy_routing_id) { Emit("did-attach"); } -void WebContents::ElementSizeChanged(const gfx::Size& size) { - element_size_ = size; - - // Only resize if needed. - if (!size.IsEmpty()) - guest_host_->SizeContents(size); -} - content::WebContents* WebContents::GetOwnerWebContents() const { return embedder_web_contents_; } @@ -477,7 +467,6 @@ void WebContents::WillAttach(content::WebContents* embedder_web_contents, int element_instance_id, bool is_full_page_plugin) { embedder_web_contents_ = embedder_web_contents; - element_instance_id_ = element_instance_id; is_full_page_plugin_ = is_full_page_plugin; } diff --git a/atom/browser/api/atom_api_web_contents.h b/atom/browser/api/atom_api_web_contents.h index 63248fd02a21..062831577aad 100644 --- a/atom/browser/api/atom_api_web_contents.h +++ b/atom/browser/api/atom_api_web_contents.h @@ -211,7 +211,6 @@ class WebContents : public mate::EventEmitter, // content::BrowserPluginGuestDelegate: void DidAttach(int guest_proxy_routing_id) final; - void ElementSizeChanged(const gfx::Size& size) final; content::WebContents* GetOwnerWebContents() const final; void GuestSizeChanged(const gfx::Size& new_size) final; void SetGuestHost(content::GuestHost* guest_host) final; @@ -249,10 +248,6 @@ class WebContents : public mate::EventEmitter, // Unique ID for a guest WebContents. int guest_instance_id_; - // |element_instance_id_| is an identifer that's unique to a particular - // element. - int element_instance_id_; - // Stores whether the contents of the guest can be transparent. bool guest_opaque_;