diff options
Diffstat (limited to 'webkit/glue')
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl.cc | 45 | ||||
-rw-r--r-- | webkit/glue/plugins/webplugin_delegate_impl.h | 14 | ||||
-rwxr-xr-x | webkit/glue/stacking_order_iterator.cc | 137 | ||||
-rwxr-xr-x | webkit/glue/stacking_order_iterator.h | 73 | ||||
-rw-r--r-- | webkit/glue/webcursor.cc | 2 | ||||
-rw-r--r-- | webkit/glue/webplugin.h | 3 | ||||
-rw-r--r-- | webkit/glue/webplugin_delegate.h | 16 | ||||
-rw-r--r-- | webkit/glue/webplugin_impl.cc | 67 | ||||
-rw-r--r-- | webkit/glue/webplugin_impl.h | 18 |
9 files changed, 342 insertions, 33 deletions
diff --git a/webkit/glue/plugins/webplugin_delegate_impl.cc b/webkit/glue/plugins/webplugin_delegate_impl.cc index 4e1c713..fa2a64f 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl.cc +++ b/webkit/glue/plugins/webplugin_delegate_impl.cc @@ -6,6 +6,7 @@ #include "base/file_util.h" #include "base/message_loop.h" +#include "base/gfx/gdi_util.h" #include "base/gfx/point.h" #include "base/stats_counters.h" #include "webkit/default_plugin/plugin_impl.h" @@ -250,13 +251,15 @@ void WebPluginDelegateImpl::DestroyInstance() { } } -void WebPluginDelegateImpl::UpdateGeometry(const gfx::Rect& window_rect, - const gfx::Rect& clip_rect, - bool visible) { +void WebPluginDelegateImpl::UpdateGeometry( + const gfx::Rect& window_rect, + const gfx::Rect& clip_rect, + const std::vector<gfx::Rect>& cutout_rects, + bool visible) { if (windowless_) { WindowlessUpdateGeometry(window_rect, clip_rect); } else { - WindowedUpdateGeometry(window_rect, clip_rect, visible); + WindowedUpdateGeometry(window_rect, clip_rect, cutout_rects, visible); } // Initiate a download on the plugin url. This should be done for the @@ -344,10 +347,12 @@ void WebPluginDelegateImpl::InstallMissingPlugin() { instance()->NPP_HandleEvent(&evt); } -void WebPluginDelegateImpl::WindowedUpdateGeometry(const gfx::Rect& window_rect, - const gfx::Rect& clip_rect, - bool visible) { - if (WindowedReposition(window_rect, clip_rect, visible) || +void WebPluginDelegateImpl::WindowedUpdateGeometry( + const gfx::Rect& window_rect, + const gfx::Rect& clip_rect, + const std::vector<gfx::Rect>& cutout_rects, + bool visible) { + if (WindowedReposition(window_rect, clip_rect, cutout_rects, visible) || !windowed_did_set_window_) { // Let the plugin know that it has been moved WindowedSetWindow(); @@ -584,14 +589,17 @@ bool WebPluginDelegateImpl::CreateDummyWindowForActivation() { return true; } -void WebPluginDelegateImpl::MoveWindow(HWND window, - const gfx::Rect& window_rect, - const gfx::Rect& clip_rect, - bool visible) { +void WebPluginDelegateImpl::MoveWindow( + HWND window, + const gfx::Rect& window_rect, + const gfx::Rect& clip_rect, + const std::vector<gfx::Rect>& cutout_rects, + bool visible) { HRGN hrgn = ::CreateRectRgn(clip_rect.x(), clip_rect.y(), clip_rect.right(), clip_rect.bottom()); + gfx::SubtractRectanglesFromRegion(hrgn, cutout_rects); // Note: System will own the hrgn after we call SetWindowRgn, // so we don't need to call DeleteObject(hrgn) @@ -612,20 +620,24 @@ void WebPluginDelegateImpl::MoveWindow(HWND window, flags); } -bool WebPluginDelegateImpl::WindowedReposition(const gfx::Rect& window_rect, - const gfx::Rect& clip_rect, - bool visible) { +bool WebPluginDelegateImpl::WindowedReposition( + const gfx::Rect& window_rect, + const gfx::Rect& clip_rect, + const std::vector<gfx::Rect>& cutout_rects, + bool visible) { if (!windowed_handle_) { NOTREACHED(); return false; } if (window_rect_ == window_rect && clip_rect_ == clip_rect && + cutout_rects == cutout_rects_ && initial_plugin_resize_done_) return false; window_rect_ = window_rect; clip_rect_ = clip_rect; + cutout_rects_ = cutout_rects; if (!initial_plugin_resize_done_) { // We need to ensure that the plugin process continues to reposition @@ -636,7 +648,7 @@ bool WebPluginDelegateImpl::WindowedReposition(const gfx::Rect& window_rect, // We created the window with 0 width and height since we didn't know it // at the time. Now that we know the geometry, we we can update its size // since the browser only calls SetWindowPos when scrolling occurs. - MoveWindow(windowed_handle_, window_rect, clip_rect, visible); + MoveWindow(windowed_handle_, window_rect, clip_rect, cutout_rects, visible); // Ensure that the entire window gets repainted. ::InvalidateRect(windowed_handle_, NULL, FALSE); } @@ -791,6 +803,7 @@ void WebPluginDelegateImpl::WindowlessUpdateGeometry( // We will inform the instance of this change when we call NPP_SetWindow. clip_rect_ = clip_rect; + cutout_rects_.clear(); if (window_rect_ != window_rect) { window_rect_ = window_rect; diff --git a/webkit/glue/plugins/webplugin_delegate_impl.h b/webkit/glue/plugins/webplugin_delegate_impl.h index 7ef9d80..51d0b9b 100644 --- a/webkit/glue/plugins/webplugin_delegate_impl.h +++ b/webkit/glue/plugins/webplugin_delegate_impl.h @@ -41,7 +41,9 @@ class WebPluginDelegateImpl : public WebPluginDelegate { WebPlugin* plugin, bool load_manually); virtual void UpdateGeometry(const gfx::Rect& window_rect, - const gfx::Rect& clip_rect, bool visible); + const gfx::Rect& clip_rect, + const std::vector<gfx::Rect>& cutout_rects, + bool visible); virtual void Paint(HDC hdc, const gfx::Rect& rect); virtual void Print(HDC hdc); virtual void SetFocus(); // only called when windowless @@ -93,6 +95,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate { static void MoveWindow(HWND window, const gfx::Rect& window_rect, const gfx::Rect& clip_rect, + const std::vector<gfx::Rect>& cutout_rects, bool visible); private: @@ -103,7 +106,9 @@ class WebPluginDelegateImpl : public WebPluginDelegate { //-------------------------- // used for windowed plugins void WindowedUpdateGeometry(const gfx::Rect& window_rect, - const gfx::Rect& clip_rect, bool visible); + const gfx::Rect& clip_rect, + const std::vector<gfx::Rect>& cutout_rects, + bool visible); // Create the native window. // Returns true if the window is created (or already exists). // Returns false if unable to create the window. @@ -115,7 +120,9 @@ class WebPluginDelegateImpl : public WebPluginDelegate { // Reposition the native window to be in sync with the given geometry. // Returns true if the native window has moved or been clipped differently. bool WindowedReposition(const gfx::Rect& window_rect, - const gfx::Rect& clip_rect, bool visible); + const gfx::Rect& clip_rect, + const std::vector<gfx::Rect>& cutout_rects, + bool visible); // Tells the plugin about the current state of the window. // See NPAPI NPP_SetWindow for more information. @@ -187,6 +194,7 @@ class WebPluginDelegateImpl : public WebPluginDelegate { NPWindow window_; gfx::Rect window_rect_; gfx::Rect clip_rect_; + std::vector<gfx::Rect> cutout_rects_; int quirks_; // We only move/size the plugin window once after its creation. The diff --git a/webkit/glue/stacking_order_iterator.cc b/webkit/glue/stacking_order_iterator.cc new file mode 100755 index 0000000..b726a8a --- /dev/null +++ b/webkit/glue/stacking_order_iterator.cc @@ -0,0 +1,137 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "config.h" + +#pragma warning(push, 0) +#include "RenderLayer.h" +#include "RenderObject.h" +#pragma warning(pop) +#undef LOG + +#include "webkit/glue/stacking_order_iterator.h" + +// +// RenderLayerIterator +// + +RenderLayerIterator::RenderLayerIterator() { +} + +void RenderLayerIterator::Reset(WebCore::RenderLayer* rl) { + if (rl) { + context_stack_.push_back(Context(rl)); + } +} + +WebCore::RenderLayer* RenderLayerIterator::Next() { + while (context_stack_.size()) { + Context* ctx = &(context_stack_.back()); + if (ctx->HasMoreNeg()) { + context_stack_.push_back(ctx->NextNeg()); + } else if (ctx->HasSelf()) { + // Emit self. + return ctx->NextSelf(); + } else if (ctx->HasMoreOverflow()) { + context_stack_.push_back(ctx->NextOverflow()); + } else if (ctx->HasMorePos()) { + context_stack_.push_back(ctx->NextPos()); + } else { + // Nothing left in this context. Pop. + context_stack_.pop_back(); + } + } + return NULL; +} + +RenderLayerIterator::Context::Context(WebCore::RenderLayer* layer) + : layer_(layer), + next_neg_(0), + next_self_(0), + next_overflow_(0), + next_pos_(0) { + ASSERT(layer_); + layer_->updateZOrderLists(); + layer_->updateOverflowList(); +} + +bool RenderLayerIterator::Context::HasMoreNeg() { + return layer_->negZOrderList() && + next_neg_ < layer_->negZOrderList()->size(); +} + +RenderLayerIterator::Context RenderLayerIterator::Context::NextNeg() { + ASSERT(HasMoreNeg()); + return Context(layer_->negZOrderList()->at(next_neg_++)); +} + +bool RenderLayerIterator::Context::HasSelf() { + return next_self_ < 1; +} + +WebCore::RenderLayer* RenderLayerIterator::Context::NextSelf() { + ASSERT(HasSelf()); + next_self_ = 1; + return layer_; +} + +bool RenderLayerIterator::Context::HasMoreOverflow() { + return layer_->overflowList() && + next_overflow_ >= 0 && + next_overflow_ < layer_->overflowList()->size(); +} + +RenderLayerIterator::Context RenderLayerIterator::Context::NextOverflow() { + ASSERT(HasMoreOverflow()); + return Context(layer_->overflowList()->at(next_overflow_++)); +} + +bool RenderLayerIterator::Context::HasMorePos() { + return layer_->posZOrderList() && + next_pos_ < layer_->posZOrderList()->size(); +} + +RenderLayerIterator::Context RenderLayerIterator::Context::NextPos() { + ASSERT(HasMorePos()); + return Context(layer_->posZOrderList()->at(next_pos_++)); +} + +// +// StackingOrderIterator +// + +StackingOrderIterator::StackingOrderIterator() { + Reset(NULL); +} + +void StackingOrderIterator::Reset(WebCore::RenderLayer* rl) { + layer_iterator_.Reset(rl); + current_object_ = NULL; + current_layer_root_ = NULL; +} + +WebCore::RenderObject* StackingOrderIterator::Next() { + if (current_object_) { + // Get the next object inside the current layer. + current_object_ = current_object_->nextInPreOrder(current_layer_root_); + + // Skip any sub-layers we encounter along the way; they are + // visited (in the correct stacking order) by layer_iterator_. + while (current_object_ && current_object_->hasLayer()) { + current_object_ = current_object_-> + nextInPreOrderAfterChildren(current_layer_root_); + } + } + + if (!current_object_) { + // Start the next layer. + WebCore::RenderLayer* layer = layer_iterator_.Next(); + if (layer) { + current_object_ = layer->renderer(); + current_layer_root_ = current_object_; + } + // No more layers. + } + return current_object_; +} diff --git a/webkit/glue/stacking_order_iterator.h b/webkit/glue/stacking_order_iterator.h new file mode 100755 index 0000000..20dea41 --- /dev/null +++ b/webkit/glue/stacking_order_iterator.h @@ -0,0 +1,73 @@ +// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +// Provides some utilities for iterating over a RenderObject graph in +// stacking order. + +#ifndef WEBKIT_GLUE_STACKING_ORDER_ITERATOR_H__ +#define WEBKIT_GLUE_STACKING_ORDER_ITERATOR_H__ + +#include <vector> + +namespace WebCore { +class RenderLayer; +class RenderObject; +} + +// Iterates over a subtree of RenderLayers in stacking order, back to +// front. Modifying the RenderObject graph invalidates this iterator. +// +// TODO(tulrich): this could go in webkit. +// TODO(tulrich): needs unittests. +class RenderLayerIterator { + public: + RenderLayerIterator(); + + // Sets the RenderLayer subtree to iterate over. + void Reset(WebCore::RenderLayer* rl); + + // Returns the next RenderLayer in stacking order, back to front. + WebCore::RenderLayer* Next(); + private: + class Context { + public: + Context(WebCore::RenderLayer* layer); + + bool HasMoreNeg(); + Context NextNeg(); + bool HasSelf(); + WebCore::RenderLayer* NextSelf(); + bool HasMoreOverflow(); + Context NextOverflow(); + bool HasMorePos(); + Context NextPos(); + + private: + WebCore::RenderLayer* layer_; + size_t next_neg_; + size_t next_self_; + size_t next_overflow_; + size_t next_pos_; + }; + + std::vector<Context> context_stack_; +}; + +// Iterates over a subtree of RenderObjects below a given RenderLayer. +// +// TODO(tulrich): this could go in webkit. +// TODO(tulrich): needs unittests. +class StackingOrderIterator { + public: + StackingOrderIterator(); + void Reset(WebCore::RenderLayer* rl); + WebCore::RenderObject* Next(); + + private: + RenderLayerIterator layer_iterator_; + WebCore::RenderObject* current_object_; + WebCore::RenderObject* current_layer_root_; +}; + +#endif // WEBKIT_GLUE_STACKING_ORDER_ITERATOR_H__ diff --git a/webkit/glue/webcursor.cc b/webkit/glue/webcursor.cc index c00d0d4..cccb3a0 100644 --- a/webkit/glue/webcursor.cc +++ b/webkit/glue/webcursor.cc @@ -6,7 +6,7 @@ #include "webkit/glue/webkit_resources.h" #if PLATFORM(WIN) -#include "base/gfx/bitmap_header.h" +#include "base/gfx/gdi_util.h" #endif WebCursor::WebCursor() diff --git a/webkit/glue/webplugin.h b/webkit/glue/webplugin.h index 5cbf9a9..b704153 100644 --- a/webkit/glue/webplugin.h +++ b/webkit/glue/webplugin.h @@ -56,7 +56,10 @@ struct WebPluginInfo { struct WebPluginGeometry { HWND window; gfx::Rect window_rect; + // Clip rect (include) and cutouts (excludes), relative to + // window_rect origin. gfx::Rect clip_rect; + std::vector<gfx::Rect> cutout_rects; bool visible; }; diff --git a/webkit/glue/webplugin_delegate.h b/webkit/glue/webplugin_delegate.h index 40419bd..df5716a 100644 --- a/webkit/glue/webplugin_delegate.h +++ b/webkit/glue/webplugin_delegate.h @@ -6,6 +6,7 @@ #define WEBKIT_GLUE_WEBPLUGIN_DELEGATE_H__ #include <string> +#include <vector> #include "base/basictypes.h" #include "base/gfx/native_widget_types.h" @@ -42,12 +43,17 @@ class WebPluginDelegate { // methods on the WebPlugin again. virtual void PluginDestroyed() = 0; - // Update the geometry of the plugin. This is a request to move the plugin, - // relative to its containing window, to the coords given by window_rect. - // Its contents should be clipped to the coords given by clip_rect, which are - // relative to the origin of the plugin window. + // Update the geometry of the plugin. This is a request to move the + // plugin, relative to its containing window, to the coords given by + // window_rect. Its contents should be clipped to the coords given + // by clip_rect, which are relative to the origin of the plugin + // window. It's contents should also not overlap the given cutout + // rects. The clip_rect and cutout_rects are in plugin-relative + // coordinates. virtual void UpdateGeometry(const gfx::Rect& window_rect, - const gfx::Rect& clip_rect, bool visible) = 0; + const gfx::Rect& clip_rect, + const std::vector<gfx::Rect>& cutout_rects, + bool visible) = 0; // Tells the plugin to paint the damaged rect. The HDC is only used for // windowless plugins. diff --git a/webkit/glue/webplugin_impl.cc b/webkit/glue/webplugin_impl.cc index 996d6db..b81458c 100644 --- a/webkit/glue/webplugin_impl.cc +++ b/webkit/glue/webplugin_impl.cc @@ -17,7 +17,8 @@ #include "FrameTree.h" #include "FrameView.h" #include "GraphicsContext.h" -#include "HTMLPlugInElement.h" +#include "HTMLNames.h" +#include "HTMLPluginElement.h" #include "IntRect.h" #include "KURL.h" #include "KeyboardEvent.h" @@ -46,6 +47,7 @@ #include "webkit/glue/webplugin_impl.h" #include "webkit/glue/plugins/plugin_host.h" #include "webkit/glue/plugins/plugin_instance.h" +#include "webkit/glue/stacking_order_iterator.h" #include "webkit/glue/webview_impl.h" #include "googleurl/src/gurl.h" #include "webkit/port/platform/Cursor.h" @@ -179,6 +181,11 @@ void WebPluginContainer::detachFromWindow() { hide(); } +void WebPluginContainer::windowCutoutRects(WTF::Vector<WebCore::IntRect>* + cutouts) const { + impl_->windowCutoutRects(cutouts); +} + void WebPluginContainer::didReceiveResponse( const WebCore::ResourceResponse& response) { @@ -530,6 +537,36 @@ WebCore::IntRect WebPluginImpl::windowClipRect() const { return clip_rect; } +void WebPluginImpl::windowCutoutRects( + WTF::Vector<WebCore::IntRect>* cutouts) const { + WebCore::RenderObject* plugin_node = element_->renderer(); + ASSERT(plugin_node); + + // Find all iframes that stack higher than this plugin. + bool higher = false; + StackingOrderIterator iterator; + WebCore::RenderLayer* root = element_->document()->renderer()-> + enclosingLayer(); + iterator.Reset(root); + + while (WebCore::RenderObject* ro = iterator.Next()) { + if (ro == plugin_node) { + // All nodes after this one are higher than plugin. + higher = true; + } else if (higher) { + // Is this a visible iframe? + WebCore::Node* n = ro->node(); + if (n && n->hasTagName(WebCore::HTMLNames::iframeTag)) { + if (!ro->style() || ro->style()->visibility() == WebCore::VISIBLE) { + int x, y; + ro->absolutePosition(x, y); + cutouts->append(WebCore::IntRect(x, y, ro->width(), ro->height())); + } + } + } + } +} + void WebPluginImpl::geometryChanged() const { if (!widget_) return; @@ -538,7 +575,7 @@ void WebPluginImpl::geometryChanged() const { // our parent view was scrolled. const_cast<WebPluginImpl*>(this)->widget_->setFrameGeometry( widget_->frameGeometry()); - } +} void WebPluginImpl::setFrameGeometry(const WebCore::IntRect& rect) { // Compute a new position and clip rect for ourselves relative to the @@ -564,7 +601,8 @@ void WebPluginImpl::setFrameGeometry(const WebCore::IntRect& rect) { WebCore::IntRect window_rect; WebCore::IntRect clip_rect; - CalculateBounds(rect, &window_rect, &clip_rect); + std::vector<gfx::Rect> cutout_rects; + CalculateBounds(rect, &window_rect, &clip_rect, &cutout_rects); if (window_ && received_first_paint_notification_) { // Let the WebViewDelegate know that the plugin window needs to be moved, @@ -573,12 +611,14 @@ void WebPluginImpl::setFrameGeometry(const WebCore::IntRect& rect) { move.window = window_; move.window_rect = gfx::Rect(window_rect); move.clip_rect = gfx::Rect(clip_rect); + move.cutout_rects = cutout_rects; move.visible = visible_; + webview->delegate()->DidMove(webview, move); } delegate_->UpdateGeometry( - gfx::Rect(window_rect), gfx::Rect(clip_rect), + gfx::Rect(window_rect), gfx::Rect(clip_rect), cutout_rects, received_first_paint_notification_? visible_ : false); // delegate_ can go away as a result of above call, so check it first. @@ -613,11 +653,13 @@ void WebPluginImpl::paint(WebCore::GraphicsContext* gc, if (!windowless_) { WebCore::IntRect window_rect; WebCore::IntRect clip_rect; + std::vector<gfx::Rect> cutout_rects; - CalculateBounds(widget_->frameGeometry(), &window_rect, &clip_rect); + CalculateBounds(widget_->frameGeometry(), &window_rect, &clip_rect, + &cutout_rects); delegate_->UpdateGeometry(gfx::Rect(window_rect), gfx::Rect(clip_rect), - visible_); + cutout_rects, visible_); delegate_->FlushGeometryUpdates(); } } @@ -997,7 +1039,8 @@ WebCore::ScrollView* WebPluginImpl::parent() const { void WebPluginImpl::CalculateBounds(const WebCore::IntRect& frame_rect, WebCore::IntRect* window_rect, - WebCore::IntRect* clip_rect) { + WebCore::IntRect* clip_rect, + std::vector<gfx::Rect>* cutout_rects) { DCHECK(parent()->isFrameView()); WebCore::FrameView* view = static_cast<WebCore::FrameView*>(parent()); @@ -1007,6 +1050,16 @@ void WebPluginImpl::CalculateBounds(const WebCore::IntRect& frame_rect, // Calculate a clip-rect so that we don't overlap the scrollbars, etc. *clip_rect = widget_->windowClipRect(); clip_rect->move(-window_rect->x(), -window_rect->y()); + + cutout_rects->clear(); + WTF::Vector<WebCore::IntRect> rects; + widget_->windowCutoutRects(&rects); + // Convert to gfx::Rect and subtract out the plugin position. + for (size_t i = 0; i < rects.size(); i++) { + gfx::Rect r(rects[i]); + r.Offset(-frame_rect.x(), -frame_rect.y()); + cutout_rects->push_back(r); + } } void WebPluginImpl::HandleURLRequest(const char *method, diff --git a/webkit/glue/webplugin_impl.h b/webkit/glue/webplugin_impl.h index b7a4dab..781369e 100644 --- a/webkit/glue/webplugin_impl.h +++ b/webkit/glue/webplugin_impl.h @@ -15,6 +15,7 @@ #include "ResourceHandleClient.h" #include "ResourceRequest.h" #include "Widget.h" +#include "Vector.h" #pragma warning(pop) #include "base/basictypes.h" @@ -64,6 +65,13 @@ class WebPluginContainer : public WebCore::Widget { virtual void attachToWindow(); virtual void detachFromWindow(); + // Returns window-relative rectangles that should clip this widget. + // Use this to implement iframe shim behavior. + // + // TODO(tulrich): add this method to WebCore/platform/Widget.h so it + // can be used by any platform. + void windowCutoutRects(WTF::Vector<WebCore::IntRect>* cutouts) const; + // These methods are invoked from webkit when it has data to be sent to the // plugin. The plugin in this case does not initiate a download for the data. void didReceiveResponse(const WebCore::ResourceResponse& response); @@ -176,6 +184,13 @@ class WebPluginImpl : public WebPlugin, virtual WebCore::IntRect windowClipRect() const; virtual void geometryChanged() const; + // Returns window-relative rectangles that should clip this widget. + // Use this to implement iframe shim behavior. + // + // TODO(tulrich): windowCutoutRects() is not in WebCore::Widgets + // yet; need to add it. + void windowCutoutRects(WTF::Vector<WebCore::IntRect>* rects) const; + // Override for when our window changes size or position. // Used to notify the plugin when the size or position changes. virtual void setFrameGeometry(const WebCore::IntRect& rect); @@ -235,7 +250,8 @@ class WebPluginImpl : public WebPlugin, // Calculates the bounds of the plugin widget based on the frame rect passed in. void CalculateBounds(const WebCore::IntRect& frame_rect, WebCore::IntRect* window_rect, - WebCore::IntRect* clip_rect); + WebCore::IntRect* clip_rect, + std::vector<gfx::Rect>* cutout_rects); void HandleURLRequest(const char *method, bool is_javascript_url, |