summaryrefslogtreecommitdiffstats
path: root/webkit
diff options
context:
space:
mode:
authorojan@google.com <ojan@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-09 21:58:05 +0000
committerojan@google.com <ojan@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2008-10-09 21:58:05 +0000
commit8a2820a90f85f91c500a9d382f8e8ba870fb621c (patch)
tree8d8bd23228cd1e6455e64b0de46e961947459382 /webkit
parent283f76091ad757bdc17c6d9090209eade4211075 (diff)
downloadchromium_src-8a2820a90f85f91c500a9d382f8e8ba870fb621c.zip
chromium_src-8a2820a90f85f91c500a9d382f8e8ba870fb621c.tar.gz
chromium_src-8a2820a90f85f91c500a9d382f8e8ba870fb621c.tar.bz2
Patch by Thatcher Ulrich <tulrich@google.com>.
Implement "iframe shim" behavior for windowed plugins. In FF and IE on windows, iframes are implemented as native HWNDs. This has the side effect that iframes display on top of windowed plugins. This side effect has long been known as a workaround for allowing HTML elements to appear above plugin content. BUG=1788 Review URL: http://codereview.chromium.org/7032 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@3137 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'webkit')
-rw-r--r--webkit/build/glue/glue.vcproj8
-rwxr-xr-xwebkit/data/layout_tests/pending/plugins/iframe-shims-expected.txt6
-rwxr-xr-xwebkit/data/layout_tests/pending/plugins/iframe-shims.html144
-rw-r--r--webkit/data/layout_tests/pending/plugins/simple_blank.swfbin0 -> 37 bytes
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl.cc45
-rw-r--r--webkit/glue/plugins/webplugin_delegate_impl.h14
-rwxr-xr-xwebkit/glue/stacking_order_iterator.cc137
-rwxr-xr-xwebkit/glue/stacking_order_iterator.h73
-rw-r--r--webkit/glue/webcursor.cc2
-rw-r--r--webkit/glue/webplugin.h3
-rw-r--r--webkit/glue/webplugin_delegate.h16
-rw-r--r--webkit/glue/webplugin_impl.cc67
-rw-r--r--webkit/glue/webplugin_impl.h18
-rw-r--r--webkit/port/platform/graphics/ImageSkia.cpp2
-rw-r--r--webkit/port/platform/graphics/SkiaUtils.cpp2
-rw-r--r--webkit/tools/test_shell/test_webview_delegate.cc3
16 files changed, 504 insertions, 36 deletions
diff --git a/webkit/build/glue/glue.vcproj b/webkit/build/glue/glue.vcproj
index bd7c70c..aab75ce 100644
--- a/webkit/build/glue/glue.vcproj
+++ b/webkit/build/glue/glue.vcproj
@@ -481,6 +481,14 @@
>
</File>
<File
+ RelativePath="..\..\glue\stacking_order_iterator.cc"
+ >
+ </File>
+ <File
+ RelativePath="..\..\glue\stacking_order_iterator.h"
+ >
+ </File>
+ <File
RelativePath="..\..\glue\webcursor.cc"
>
</File>
diff --git a/webkit/data/layout_tests/pending/plugins/iframe-shims-expected.txt b/webkit/data/layout_tests/pending/plugins/iframe-shims-expected.txt
new file mode 100755
index 0000000..d1cde7e
--- /dev/null
+++ b/webkit/data/layout_tests/pending/plugins/iframe-shims-expected.txt
@@ -0,0 +1,6 @@
+Test that iframe shims can be used to overlay HTML above a windowed plugin. The red squares should be hidden by the blue flash plugin, and the green squares should appear over it. To test interactively, click over the buttons on the squares. You should not be able to reach the red squares' buttons.
+
+Prints "SUCCESS" on success, "FAILURE" on failure.
+
+SUCCESS
+
diff --git a/webkit/data/layout_tests/pending/plugins/iframe-shims.html b/webkit/data/layout_tests/pending/plugins/iframe-shims.html
new file mode 100755
index 0000000..28d7f25
--- /dev/null
+++ b/webkit/data/layout_tests/pending/plugins/iframe-shims.html
@@ -0,0 +1,144 @@
+<html><head>
+<script>
+ function noop(x) {
+ }
+
+ var red1_clicks = 0;
+ var green1_clicks = 0;
+ var red2_clicks = 0;
+ var green2_clicks = 0;
+
+ function red1Clicked() {
+ red1_clicks++;
+ checkResult();
+ }
+
+ function green1Clicked() {
+ green1_clicks++;
+ checkResult();
+ }
+
+ function red2Clicked() {
+ red2_clicks++;
+ checkResult();
+ }
+
+ function green2Clicked() {
+ green2_clicks++;
+ checkResult();
+ }
+
+ function checkResult() {
+ var output = document.getElementById("output");
+ var success = green1_clicks > 0 && green2_clicks > 0 &&
+ red1_clicks == 0 && red2_clicks == 0;
+ output.innerHTML = success ? "SUCCESS" : "FAILURE";
+ document.title = output.innerHTML;
+ }
+
+ function moveMouseOver(elem_name) {
+ var elem = document.getElementById(elem_name);
+ var x = elem.offsetLeft + elem.scrollWidth / 2;
+ var y = elem.offsetTop + elem.scrollHeight / 2;
+ var offsetParent = elem.offsetParent;
+ while (offsetParent) {
+ x += offsetParent.offsetLeft;
+ y += offsetParent.offsetTop;
+ offsetParent = offsetParent.offsetParent;
+ }
+ eventSender.mouseMoveTo(x, y);
+ }
+
+ function runTest() {
+ if (window.layoutTestController && window.eventSender) {
+ layoutTestController.waitUntilDone();
+ layoutTestController.dumpAsText();
+ setTimeout(doClickRed1, 0);
+ }
+ }
+
+ function doClickRed1() {
+ moveMouseOver("red_square1");
+ eventSender.mouseDown();
+ setTimeout(doClickGreen1, 0);
+ }
+
+ function doClickGreen1() {
+ eventSender.mouseUp();
+ moveMouseOver("green_square1");
+ eventSender.mouseDown();
+ setTimeout(doClickRed2, 0);
+ }
+
+ function doClickRed2() {
+ eventSender.mouseUp();
+ moveMouseOver("red_square2");
+ eventSender.mouseDown();
+ setTimeout(doClickGreen2, 0);
+ }
+
+ function doClickGreen2() {
+ eventSender.mouseUp();
+ moveMouseOver("green_square2");
+ eventSender.mouseDown();
+ setTimeout(finishTest, 0);
+ }
+
+ function finishTest() {
+ eventSender.mouseUp();
+ layoutTestController.notifyDone();
+ }
+</script>
+</head>
+<body onload="runTest()">
+
+<p>Test that iframe shims can be used to overlay HTML above a windowed
+plugin. The red squares should be hidden by the blue flash plugin, and
+the green squares should appear over it. To test interactively, click
+over the buttons on the squares. You should not be able to reach the
+red squares' buttons.</p>
+
+<p>Prints "SUCCESS" on success, "FAILURE" on failure.</p>
+
+<div id=output>NONE</div>
+
+<div style="position: relative;">
+
+ <!-- div with a lower stacking order than the plugin, appearing earlier in the document -->
+ <div id="red_square1"
+ style="z-index: 50; background-color: #FF0000; position: absolute; top: -10; left: 50; width: 100px; height: 100px; overflow: hidden;">
+ <input type="button" onclick="red1Clicked()" value="red" style="position: absolute; top: 10; left: 10; width: 80px; height: 80px;"/>
+ <iframe src="javascript:void(0);" frameborder=0 style="z-index: -1; position: absolute; left: 0px; top: 0px; width: 100%; height: 100%;"></iframe>
+ </div>
+
+ <!-- div with a higher stacking order than the plugin, appearing earlier in the document -->
+ <div id="green_square1"
+ style="z-index: 150; background-color: #00FF00; position: absolute; top: -10; left: 250; width: 100px; height: 100px; overflow: hidden;">
+ <input type="button" onclick="green1Clicked()" value="green" style="position: absolute; top: 10; left: 10; width: 80px; height: 80px;"/>
+ <iframe src="javascript:void(0);" frameborder=0 style="z-index: -1; position: absolute; left: 0px; top: 0px; width: 100%; height: 100%;"></iframe>
+ </div>
+
+ <div id="embed_parent" style="position: absolute; z-index: 100"
+ <embed width="400" height="200" wmode="window" loop="false" quality="high" src="simple_blank.swf" type="application/x-shockwave-flash" />
+ </div>
+
+ <!-- div with a lower stacking order than the plugin, appearing later in the document -->
+ <div id="red_square2"
+ style="z-index: 50; background-color: #FF0000; position: absolute; top: 110; left: 50; width: 100px; height: 100px; overflow: hidden;">
+ <input type="button" onclick="red2Clicked()" value="red" style="position: absolute; top: 10; left: 10; width: 80px; height: 80px;"/>
+ <iframe src="javascript:void(0);" frameborder=0 style="z-index: -1; position: absolute; left: 0px; top: 0px; width: 100%; height: 100%;"></iframe>
+ </div>
+
+ <!-- div with a higher stacking order than the plugin, appearing later in the document -->
+ <div id="green_square2"
+ style="z-index: 150; background-color: #00FF00; position: absolute; top: 110; left: 250; width: 100px; height: 100px; overflow: hidden;">
+ <input type="button" onclick="green2Clicked()" value="green" style="position: absolute; top: 10; left: 10; width: 80px; height: 80px;"/>
+ <iframe src="javascript:void(0);" frameborder=0 style="z-index: -1; position: absolute; left: 0px; top: 0px; width: 100%; height: 100%;"></iframe>
+ </div>
+
+
+
+</div>
+
+</body>
+</html> \ No newline at end of file
diff --git a/webkit/data/layout_tests/pending/plugins/simple_blank.swf b/webkit/data/layout_tests/pending/plugins/simple_blank.swf
new file mode 100644
index 0000000..b846387
--- /dev/null
+++ b/webkit/data/layout_tests/pending/plugins/simple_blank.swf
Binary files differ
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,
diff --git a/webkit/port/platform/graphics/ImageSkia.cpp b/webkit/port/platform/graphics/ImageSkia.cpp
index 1989eba8..2c5911c 100644
--- a/webkit/port/platform/graphics/ImageSkia.cpp
+++ b/webkit/port/platform/graphics/ImageSkia.cpp
@@ -44,7 +44,7 @@
#include "SkiaUtils.h"
#include "SkShader.h"
-#include "base/gfx/bitmap_header.h"
+#include "base/gfx/gdi_util.h"
#include "base/gfx/image_operations.h"
#include "base/gfx/native_theme.h"
#include "base/gfx/platform_canvas_win.h"
diff --git a/webkit/port/platform/graphics/SkiaUtils.cpp b/webkit/port/platform/graphics/SkiaUtils.cpp
index 4e1e5b5..422f24a 100644
--- a/webkit/port/platform/graphics/SkiaUtils.cpp
+++ b/webkit/port/platform/graphics/SkiaUtils.cpp
@@ -39,7 +39,7 @@
#include "base/basictypes.h"
#if defined(OS_WIN)
-#include "base/gfx/bitmap_header.h"
+#include "base/gfx/gdi_util.h"
#endif
void WebCorePointToSkiaPoint(const WebCore::FloatPoint& src, SkPoint* dst)
diff --git a/webkit/tools/test_shell/test_webview_delegate.cc b/webkit/tools/test_shell/test_webview_delegate.cc
index f7cc828..844182e 100644
--- a/webkit/tools/test_shell/test_webview_delegate.cc
+++ b/webkit/tools/test_shell/test_webview_delegate.cc
@@ -759,7 +759,8 @@ void TestWebViewDelegate::GetRootWindowRect(WebWidget* webwidget,
void TestWebViewDelegate::DidMove(WebWidget* webwidget,
const WebPluginGeometry& move) {
WebPluginDelegateImpl::MoveWindow(
- move.window, move.window_rect, move.clip_rect, move.visible);
+ move.window, move.window_rect, move.clip_rect, move.cutout_rects,
+ move.visible);
}
void TestWebViewDelegate::RunModal(WebWidget* webwidget) {