Bug 1379508: Part 1 - Apply the correct client offsets to remote frameloaders in popup widgets. r?kats
On-screen coordinates for points in remote frameloads are calculated relative
to the screen origin of the top-level window, while event coordinates are
calculated relative to the nearest widget. Since popups have their own widgets
separate from the top-level window, their native client offsets have no
particular relation to the origin of the top-level window, and we need to
manually calculate them relative to the origin of the top-level widget
instead.
MozReview-Commit-ID: EDyEyu37XuY
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -729,17 +729,17 @@ TabParent::UpdateDimensions(const nsIntR
if (!widget) {
NS_WARNING("No widget found in TabParent::UpdateDimensions");
return;
}
hal::ScreenConfiguration config;
hal::GetCurrentScreenConfiguration(&config);
ScreenOrientationInternal orientation = config.orientation();
- LayoutDeviceIntPoint clientOffset = widget->GetClientOffset();
+ LayoutDeviceIntPoint clientOffset = GetClientOffset();
LayoutDeviceIntPoint chromeOffset = -GetChildProcessOffset();
if (!mUpdatedDimensions || mOrientation != orientation ||
mDimensions != size || !mRect.IsEqualEdges(rect) ||
clientOffset != mClientOffset ||
chromeOffset != mChromeOffset) {
mUpdatedDimensions = true;
@@ -1987,16 +1987,30 @@ TabParent::GetChildProcessOffset()
nsPoint pt = nsLayoutUtils::GetEventCoordinatesRelativeTo(widget,
LayoutDeviceIntPoint(0, 0),
targetFrame);
return LayoutDeviceIntPoint::FromAppUnitsToNearest(
pt, targetFrame->PresContext()->AppUnitsPerDevPixel());
}
+LayoutDeviceIntPoint
+TabParent::GetClientOffset()
+{
+ nsCOMPtr<nsIWidget> widget = GetWidget();
+ nsCOMPtr<nsIWidget> docWidget = GetDocWidget();
+
+ if (widget == docWidget) {
+ return widget->GetClientOffset();
+ }
+
+ return (docWidget->GetClientOffset() -
+ nsLayoutUtils::WidgetToWidgetOffset(docWidget, widget));
+}
+
mozilla::ipc::IPCResult
TabParent::RecvReplyKeyEvent(const WidgetKeyboardEvent& aEvent)
{
NS_ENSURE_TRUE(mFrameElement, IPC_OK());
WidgetKeyboardEvent localEvent(aEvent);
localEvent.MarkAsHandledInRemoteProcess();
@@ -2563,16 +2577,25 @@ TabParent::GetWidget() const
}
nsCOMPtr<nsIWidget> widget = nsContentUtils::WidgetForContent(mFrameElement);
if (!widget) {
widget = nsContentUtils::WidgetForDocument(mFrameElement->OwnerDoc());
}
return widget.forget();
}
+already_AddRefed<nsIWidget>
+TabParent::GetDocWidget() const
+{
+ if (!mFrameElement) {
+ return nullptr;
+ }
+ return do_AddRef(nsContentUtils::WidgetForDocument(mFrameElement->OwnerDoc()));
+}
+
void
TabParent::ApzAwareEventRoutingToChild(ScrollableLayerGuid* aOutTargetGuid,
uint64_t* aOutInputBlockId,
nsEventStatus* aOutApzResponse)
{
// Let the widget know that the event will be sent to the child process,
// which will (hopefully) send a confirmation notice back to APZ.
// Do this even if APZ is off since we need it for swipe gesture support on
--- a/dom/ipc/TabParent.h
+++ b/dom/ipc/TabParent.h
@@ -533,24 +533,35 @@ public:
nsIContentParent* Manager() const { return mManager; }
/**
* Let managees query if Destroy() is already called so they don't send out
* messages when the PBrowser actor is being destroyed.
*/
bool IsDestroyed() const { return mIsDestroyed; }
+ // Returns the closest widget for our frameloader's content.
already_AddRefed<nsIWidget> GetWidget() const;
+ // Returns the top-level widget for our frameloader's document.
+ already_AddRefed<nsIWidget> GetDocWidget() const;
+
const TabId GetTabId() const
{
return mTabId;
}
LayoutDeviceIntPoint GetChildProcessOffset();
+
+ // Returns the offset from the on-screen origin of our top-level window's
+ // widget (including window decorations) to the origin of our frameloader's
+ // nearest widget. This offset is used to translate coordinates from the
+ // PuppetWidget's origin to absolute screen coordinates in the child.
+ LayoutDeviceIntPoint GetClientOffset();
+
LayoutDevicePoint AdjustTapToChildWidget(const LayoutDevicePoint& aPoint);
/**
* Native widget remoting protocol for use with windowed plugins with e10s.
*/
virtual PPluginWidgetParent* AllocPPluginWidgetParent() override;
virtual bool
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -3090,18 +3090,18 @@ static LayoutDeviceIntPoint GetWidgetOff
LayoutDeviceIntRect bounds = aWidget->GetBounds();
offset += bounds.TopLeft();
aWidget = parent;
}
aRootWidget = aWidget;
return offset;
}
-static LayoutDeviceIntPoint
-WidgetToWidgetOffset(nsIWidget* aFrom, nsIWidget* aTo) {
+LayoutDeviceIntPoint
+nsLayoutUtils::WidgetToWidgetOffset(nsIWidget* aFrom, nsIWidget* aTo) {
nsIWidget* fromRoot;
LayoutDeviceIntPoint fromOffset = GetWidgetOffset(aFrom, fromRoot);
nsIWidget* toRoot;
LayoutDeviceIntPoint toOffset = GetWidgetOffset(aTo, toRoot);
if (fromRoot == toRoot) {
return fromOffset - toOffset;
}
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -780,16 +780,19 @@ public:
* @param aWidget the widget to which returned coordinates are relative
* @return the point in the view's coordinates
*/
static mozilla::LayoutDeviceIntPoint
TranslateViewToWidget(nsPresContext* aPresContext,
nsView* aView, nsPoint aPt,
nsIWidget* aWidget);
+ static mozilla::LayoutDeviceIntPoint
+ WidgetToWidgetOffset(nsIWidget* aFromWidget, nsIWidget* aToWidget);
+
enum FrameForPointFlags {
/**
* When set, paint suppression is ignored, so we'll return non-root page
* elements even if paint suppression is stopping them from painting.
*/
IGNORE_PAINT_SUPPRESSION = 0x01,
/**
* When set, clipping due to the root scroll frame (and any other viewport-