/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
/* vim: set ts=8 sts=2 et sw=2 tw=80: */
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#include "nsDOMWindowUtils.h"
#include "LayoutConstants.h"
#include "MobileViewportManager.h"
#include "mozilla/layers/CompositorBridgeChild.h"
#include "nsPresContext.h"
#include "nsCaret.h"
#include "nsContentList.h"
#include "nsError.h"
#include "nsQueryContentEventResult.h"
#include "nsGlobalWindowOuter.h"
#include "nsFocusManager.h"
#include "nsFrameManager.h"
#include "nsRefreshDriver.h"
#include "nsStyleUtil.h"
#include "mozilla/Base64.h"
#include "mozilla/dom/Animation.h"
#include "mozilla/dom/BindingDeclarations.h"
#include "mozilla/dom/BlobBinding.h"
#include "mozilla/dom/DocumentInlines.h"
#include "mozilla/dom/DocumentTimeline.h"
#include "mozilla/dom/DOMCollectedFramesBinding.h"
#include "mozilla/dom/Event.h"
#include "mozilla/dom/Touch.h"
#include "mozilla/dom/UserActivation.h"
#include "mozilla/EventStateManager.h"
#include "mozilla/ScrollContainerFrame.h"
#include "mozilla/ServoStyleSet.h"
#include "mozilla/SharedStyleSheetCache.h"
#include "mozilla/dom/SharedScriptCache.h"
#include "mozilla/StaticPrefs_test.h"
#include "mozilla/InputTaskManager.h"
#include "nsIObjectLoadingContent.h"
#include "nsIFrame.h"
#include "mozilla/layers/APZCCallbackHelper.h"
#include "mozilla/layers/PCompositorBridgeTypes.h"
#include "mozilla/layers/TouchActionHelper.h"
#include "mozilla/media/MediaUtils.h"
#include "nsQueryObject.h"
#include "CubebDeviceEnumerator.h"
#include "nsContentUtils.h"
#include "nsIWidget.h"
#include "nsCharsetSource.h"
#include "nsJSEnvironment.h"
#include "nsJSUtils.h"
#include "js/experimental/PCCountProfiling.h" // JS::{Start,Stop}PCCountProfiling, JS::PurgePCCounts, JS::GetPCCountScript{Count,Summary,Contents}
#include "js/Object.h" // JS::GetClass
#include "mozilla/ChaosMode.h"
#include "mozilla/CheckedInt.h"
#include "mozilla/MiscEvents.h"
#include "mozilla/MouseEvents.h"
#include "mozilla/PresShell.h"
#include "mozilla/PresShellInlines.h"
#include "mozilla/Span.h"
#include "mozilla/StaticPrefs_layout.h"
#include "mozilla/TextEvents.h"
#include "mozilla/TextEventDispatcher.h"
#include "mozilla/TouchEvents.h"
#include "nsViewManager.h"
#include "nsLayoutUtils.h"
#include "nsComputedDOMStyle.h"
#include "nsCSSProps.h"
#include "nsIDocShell.h"
#include "mozilla/StyleAnimationValue.h"
#include "mozilla/dom/File.h"
#include "mozilla/dom/FileBinding.h"
#include "mozilla/dom/DOMRect.h"
#include <algorithm>
#if defined (MOZ_WIDGET_GTK)
# include <gdk/gdk.h>
# if defined (MOZ_X11)
# include <gdk/gdkx.h>
# include "X11UndefineNone.h"
# endif
#endif
#include "mozilla/dom/AudioDeviceInfo.h"
#include "mozilla/dom/Element.h"
#include "mozilla/dom/BrowserChild.h"
#include "mozilla/dom/IDBFactoryBinding.h"
#include "mozilla/dom/IndexedDatabaseManager.h"
#include "mozilla/dom/PermissionMessageUtils.h"
#include "mozilla/dom/Text.h"
#include "mozilla/dom/quota/PersistenceType.h"
#include "mozilla/dom/quota/PrincipalUtils.h"
#include "mozilla/dom/ContentChild.h"
#include "mozilla/layers/FrameUniformityData.h"
#include "nsPrintfCString.h"
#include "nsViewportInfo.h"
#include "nsIFormControl.h"
// #include "nsWidgetsCID.h"
#include "nsDisplayList.h"
#include "nsROCSSPrimitiveValue.h"
#include "nsIBaseWindow.h"
#include "nsIDocShellTreeOwner.h"
#include "nsIInterfaceRequestorUtils.h"
#include "mozilla/Preferences.h"
#include "nsContentPermissionHelper.h"
#include "nsCSSPseudoElements.h" // for PseudoStyleType
#include "nsNetUtil.h"
#include "HTMLImageElement.h"
#include "HTMLCanvasElement.h"
#include "mozilla/css/ImageLoader.h"
#include "mozilla/layers/IAPZCTreeManager.h" // for layers::ZoomToRectBehavior
#include "mozilla/dom/Document.h"
#include "mozilla/dom/Promise.h"
#include "mozilla/RDDProcessManager.h"
#include "mozilla/ServoBindings.h"
#include "mozilla/StyleSheetInlines.h"
#include "mozilla/gfx/gfxVars.h"
#include "mozilla/gfx/GPUProcessManager.h"
#include "mozilla/dom/TimeoutManager.h"
#include "mozilla/PreloadedStyleSheet.h"
#include "mozilla/ProfilerLabels.h"
#include "mozilla/ProfilerMarkers.h"
#include "mozilla/layers/WebRenderBridgeChild.h"
#include "mozilla/layers/WebRenderLayerManager.h"
#include "mozilla/DisplayPortUtils.h"
#include "mozilla/ResultExtensions.h"
#include "mozilla/ViewportUtils.h"
#include "mozilla/dom/BrowsingContextGroup.h"
#include "mozilla/IMEStateManager.h"
#include "mozilla/IMEContentObserver.h"
#include "mozilla/WheelHandlingHelper.h"
#include "mozilla/AnimatedPropertyID.h"
#ifdef XP_WIN
# include <direct.h>
#else
# include <sys/stat.h>
#endif
#ifdef XP_WIN
# undef GetClassName
#endif
using namespace mozilla;
using namespace mozilla::dom;
using namespace mozilla::ipc;
using namespace mozilla::layers;
using namespace mozilla::widget;
using namespace mozilla::gfx;
class gfxContext;
class OldWindowSize : public LinkedListElement<OldWindowSize> {
public :
static void Set(nsIWeakReference* aWindowRef, const nsSize& aSize) {
OldWindowSize* item = GetItem(aWindowRef);
if (item) {
item->mSize = aSize;
} else {
item = new OldWindowSize(aWindowRef, aSize);
sList.insertBack(item);
}
}
static nsSize GetAndRemove(nsIWeakReference* aWindowRef) {
nsSize result;
if (OldWindowSize* item = GetItem(aWindowRef)) {
result = item->mSize;
delete item;
}
return result;
}
private :
explicit OldWindowSize(nsIWeakReference* aWindowRef, const nsSize& aSize)
: mWindowRef(aWindowRef), mSize(aSize) {}
~OldWindowSize() = default ;
;
static OldWindowSize* GetItem(nsIWeakReference* aWindowRef) {
OldWindowSize* item = sList.getFirst();
while (item && item->mWindowRef != aWindowRef) {
item = item->getNext();
}
return item;
}
static LinkedList<OldWindowSize> sList;
nsWeakPtr mWindowRef;
nsSize mSize;
};
namespace {
class NativeInputRunnable final : public PrioritizableRunnable {
explicit NativeInputRunnable(already_AddRefed<nsIRunnable>&& aEvent);
~NativeInputRunnable() = default ;
public :
static already_AddRefed<nsIRunnable> Create(
already_AddRefed<nsIRunnable>&& aEvent);
};
NativeInputRunnable::NativeInputRunnable(already_AddRefed<nsIRunnable>&& aEvent)
: PrioritizableRunnable(std::move(aEvent),
nsIRunnablePriority::PRIORITY_INPUT_HIGH) {}
/* static */
already_AddRefed<nsIRunnable> NativeInputRunnable::Create(
already_AddRefed<nsIRunnable>&& aEvent) {
MOZ_ASSERT(NS_IsMainThread());
nsCOMPtr<nsIRunnable> event(new NativeInputRunnable(std::move(aEvent)));
return event.forget();
}
} // unnamed namespace
MOZ_RUNINIT LinkedList<OldWindowSize> OldWindowSize::sList;
NS_INTERFACE_MAP_BEGIN(nsDOMWindowUtils)
NS_INTERFACE_MAP_ENTRY_AMBIGUOUS(nsISupports, nsIDOMWindowUtils)
NS_INTERFACE_MAP_ENTRY(nsIDOMWindowUtils)
NS_INTERFACE_MAP_ENTRY(nsISupportsWeakReference)
NS_INTERFACE_MAP_END
NS_IMPL_ADDREF(nsDOMWindowUtils)
NS_IMPL_RELEASE(nsDOMWindowUtils)
nsDOMWindowUtils::nsDOMWindowUtils(nsGlobalWindowOuter* aWindow) {
nsCOMPtr<nsISupports> supports = do_QueryObject(aWindow);
mWindow = do_GetWeakReference(supports);
}
nsDOMWindowUtils::~nsDOMWindowUtils() { OldWindowSize::GetAndRemove(mWindow); }
nsIDocShell* nsDOMWindowUtils::GetDocShell() {
nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
if (!window) {
return nullptr;
}
return window->GetDocShell();
}
PresShell* nsDOMWindowUtils::GetPresShell() {
nsIDocShell* docShell = GetDocShell();
if (!docShell) {
return nullptr;
}
return docShell->GetPresShell();
}
nsPresContext* nsDOMWindowUtils::GetPresContext() {
nsIDocShell* docShell = GetDocShell();
if (!docShell) {
return nullptr;
}
return docShell->GetPresContext();
}
Document* nsDOMWindowUtils::GetDocument() {
nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
if (!window) {
return nullptr;
}
return window->GetExtantDoc();
}
WebRenderBridgeChild* nsDOMWindowUtils::GetWebRenderBridge() {
if (nsIWidget* widget = GetWidget()) {
if (WindowRenderer* renderer = widget->GetWindowRenderer()) {
if (WebRenderLayerManager* wr = renderer->AsWebRender()) {
return wr->WrBridge();
}
}
}
return nullptr;
}
CompositorBridgeChild* nsDOMWindowUtils::GetCompositorBridge() {
if (nsIWidget* widget = GetWidget()) {
if (WindowRenderer* renderer = widget->GetWindowRenderer()) {
if (CompositorBridgeChild* cbc = renderer->GetCompositorBridgeChild()) {
return cbc;
}
}
}
return nullptr;
}
nsresult nsDOMWindowUtils::GetWidgetOpaqueRegion(
nsTArray<RefPtr<DOMRect>>& aRects) {
nsIWidget* widget = GetWidget();
if (!widget) {
return NS_ERROR_FAILURE;
}
auto AddRect = [&](const LayoutDeviceIntRect& aRect) {
RefPtr rect = new DOMRect(mWindow);
CSSRect cssRect = aRect / widget->GetDefaultScale();
rect->SetRect(cssRect.x, cssRect.y, cssRect.width, cssRect.height);
aRects.AppendElement(std::move(rect));
};
if (widget->GetTransparencyMode() == TransparencyMode::Opaque) {
AddRect(
LayoutDeviceIntRect(LayoutDeviceIntPoint(), widget->GetClientSize()));
return NS_OK;
}
auto region = widget->GetOpaqueRegionForTesting();
for (auto iter = region.RectIter(); !iter.Done(); iter.Next()) {
AddRect(iter.Get());
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetLastOverWindowPointerLocationInCSSPixels(float * aX,
float * aY) {
const PresShell* presShell = GetPresShell();
const nsPresContext* presContext = GetPresContext();
if (!presShell || !presContext) {
return NS_ERROR_FAILURE;
}
const nsPoint& lastOverWindowPointerLocation =
presShell->GetLastOverWindowPointerLocation();
if (lastOverWindowPointerLocation.X() == NS_UNCONSTRAINEDSIZE &&
lastOverWindowPointerLocation.Y() == NS_UNCONSTRAINEDSIZE) {
*aX = 0;
*aY = 0;
} else {
const CSSPoint lastOverWindowPointerLocationInCSSPixels =
CSSPoint::FromAppUnits(lastOverWindowPointerLocation);
*aX = lastOverWindowPointerLocationInCSSPixels.X();
*aY = lastOverWindowPointerLocationInCSSPixels.Y();
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SyncFlushCompositor() {
if (nsIWidget* widget = GetWidget()) {
if (WindowRenderer* renderer = widget->GetWindowRenderer()) {
if (KnowsCompositor* kc = renderer->AsKnowsCompositor()) {
kc->SyncWithCompositor();
}
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetImageAnimationMode(uint16_t* aMode) {
NS_ENSURE_ARG_POINTER(aMode);
*aMode = 0;
nsPresContext* presContext = GetPresContext();
if (presContext) {
*aMode = presContext->ImageAnimationMode();
return NS_OK;
}
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetImageAnimationMode(uint16_t aMode) {
nsPresContext* presContext = GetPresContext();
if (presContext) {
presContext->SetImageAnimationMode(aMode);
return NS_OK;
}
return NS_ERROR_NOT_AVAILABLE;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetDocCharsetIsForced(bool * aIsForced) {
*aIsForced = false ;
Document* doc = GetDocument();
if (doc) {
auto source = doc->GetDocumentCharacterSetSource();
*aIsForced = source == kCharsetFromInitialUserForcedAutoDetection ||
source == kCharsetFromFinalUserForcedAutoDetection;
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetPhysicalMillimeterInCSSPixels(float * aPhysicalMillimeter) {
nsPresContext* presContext = GetPresContext();
if (!presContext) {
return NS_ERROR_NOT_AVAILABLE;
}
*aPhysicalMillimeter = nsPresContext::AppUnitsToFloatCSSPixels(
presContext->PhysicalMillimetersToAppUnits(1));
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetDocumentMetadata(const nsAString& aName,
nsAString& aValue) {
Document* doc = GetDocument();
if (doc) {
RefPtr<nsAtom> name = NS_Atomize(aName);
doc->GetHeaderData(name, aValue);
return NS_OK;
}
aValue.Truncate();
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::UpdateLayerTree() {
if (RefPtr<PresShell> presShell = GetPresShell()) {
// Don't flush throttled animations since it might fire MozAfterPaint event
// (in WebRender it constantly does), thus the reftest harness can't take
// any snapshot until the throttled animations finished.
presShell->FlushPendingNotifications(
ChangesToFlush(FlushType::Layout, false /* flush animations */));
RefPtr<nsViewManager> vm = presShell->GetViewManager();
if (nsView* view = vm->GetRootView()) {
nsAutoScriptBlocker scriptBlocker;
presShell->PaintAndRequestComposite(view,
PaintFlags::PaintSyncDecodeImages);
presShell->GetWindowRenderer()->WaitOnTransactionProcessed();
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetDocumentViewerSize(uint32_t* aDisplayWidth,
uint32_t* aDisplayHeight) {
PresShell* presShell = GetPresShell();
LayoutDeviceIntSize displaySize;
if (!presShell || !nsLayoutUtils::GetDocumentViewerSize(
presShell->GetPresContext(), displaySize)) {
return NS_ERROR_FAILURE;
}
*aDisplayWidth = displaySize.width;
*aDisplayHeight = displaySize.height;
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetViewportInfo(uint32_t aDisplayWidth,
uint32_t aDisplayHeight, double * aDefaultZoom,
bool * aAllowZoom, double * aMinZoom,
double * aMaxZoom, uint32_t* aWidth,
uint32_t* aHeight, bool * aAutoSize) {
Document* doc = GetDocument();
NS_ENSURE_STATE(doc);
nsViewportInfo info =
doc->GetViewportInfo(ScreenIntSize(aDisplayWidth, aDisplayHeight));
*aDefaultZoom = info.GetDefaultZoom().scale;
*aAllowZoom = info.IsZoomAllowed();
*aMinZoom = info.GetMinZoom().scale;
*aMaxZoom = info.GetMaxZoom().scale;
CSSIntSize size = gfx::RoundedToInt(info.GetSize());
*aWidth = size.width;
*aHeight = size.height;
*aAutoSize = info.IsAutoSizeEnabled();
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetViewportFitInfo(nsAString& aViewportFit) {
Document* doc = GetDocument();
NS_ENSURE_STATE(doc);
ViewportMetaData metaData = doc->GetViewportMetaData();
if (metaData.mViewportFit.EqualsLiteral("contain" )) {
aViewportFit.AssignLiteral("contain" );
} else if (metaData.mViewportFit.EqualsLiteral("cover" )) {
aViewportFit.AssignLiteral("cover" );
} else {
aViewportFit.AssignLiteral("auto" );
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetMousewheelAutodir(Element* aElement, bool aEnabled,
bool aHonourRoot) {
aElement->SetProperty(nsGkAtoms::forceMousewheelAutodir,
reinterpret_cast <void *>(aEnabled));
aElement->SetProperty(nsGkAtoms::forceMousewheelAutodirHonourRoot,
reinterpret_cast <void *>(aHonourRoot));
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetDisplayPortForElement(float aXPx, float aYPx,
float aWidthPx, float aHeightPx,
Element* aElement,
uint32_t aPriority) {
PresShell* presShell = GetPresShell();
if (!presShell) {
return NS_ERROR_FAILURE;
}
if (!aElement) {
return NS_ERROR_INVALID_ARG;
}
if (aElement->GetUncomposedDoc() != presShell->GetDocument()) {
return NS_ERROR_INVALID_ARG;
}
bool hadDisplayPort = false ;
bool wasPainted = false ;
nsRect oldDisplayPort;
{
DisplayPortPropertyData* currentData =
static_cast <DisplayPortPropertyData*>(
aElement->GetProperty(nsGkAtoms::DisplayPort));
if (currentData) {
if (currentData->mPriority > aPriority) {
return NS_OK;
}
hadDisplayPort = true ;
oldDisplayPort = currentData->mRect;
wasPainted = currentData->mPainted;
}
}
nsRect displayport(nsPresContext::CSSPixelsToAppUnits(aXPx),
nsPresContext::CSSPixelsToAppUnits(aYPx),
nsPresContext::CSSPixelsToAppUnits(aWidthPx),
nsPresContext::CSSPixelsToAppUnits(aHeightPx));
aElement->RemoveProperty(nsGkAtoms::MinimalDisplayPort);
aElement->SetProperty(
nsGkAtoms::DisplayPort,
new DisplayPortPropertyData(displayport, aPriority, wasPainted),
nsINode::DeleteProperty<DisplayPortPropertyData>);
DisplayPortUtils::InvalidateForDisplayPortChange(aElement, hadDisplayPort,
oldDisplayPort, displayport);
nsIFrame* rootFrame = presShell->GetRootFrame();
if (rootFrame) {
rootFrame->SchedulePaint();
// If we are hiding something that is a display root then send empty paint
// transaction in order to release retained layers because it won't get
// any more paint requests when it is hidden.
if (displayport.IsEmpty() &&
rootFrame == nsLayoutUtils::GetDisplayRootFrame(rootFrame)) {
nsCOMPtr<nsIWidget> widget = GetWidget();
if (widget) {
using PaintFrameFlags = nsLayoutUtils::PaintFrameFlags;
nsLayoutUtils::PaintFrame(
nullptr, rootFrame, nsRegion(), NS_RGB(255, 255, 255),
nsDisplayListBuilderMode::Painting, PaintFrameFlags::WidgetLayers);
}
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetDisplayPortMarginsForElement(
float aLeftMargin, float aTopMargin, float aRightMargin,
float aBottomMargin, Element* aElement, uint32_t aPriority) {
PresShell* presShell = GetPresShell();
if (!presShell) {
return NS_ERROR_FAILURE;
}
if (!aElement) {
return NS_ERROR_INVALID_ARG;
}
if (aElement->GetUncomposedDoc() != presShell->GetDocument()) {
return NS_ERROR_INVALID_ARG;
}
// Note order change of arguments between our function signature and
// ScreenMargin constructor.
ScreenMargin displayportMargins(aTopMargin, aRightMargin, aBottomMargin,
aLeftMargin);
DisplayPortUtils::SetDisplayPortMargins(
aElement, presShell,
DisplayPortMargins::ForContent(aElement, displayportMargins),
DisplayPortUtils::ClearMinimalDisplayPortProperty::Yes, aPriority);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetDisplayPortBaseForElement(int32_t aX, int32_t aY,
int32_t aWidth, int32_t aHeight,
Element* aElement) {
PresShell* presShell = GetPresShell();
if (!presShell) {
return NS_ERROR_FAILURE;
}
if (!aElement) {
return NS_ERROR_INVALID_ARG;
}
if (aElement->GetUncomposedDoc() != presShell->GetDocument()) {
return NS_ERROR_INVALID_ARG;
}
DisplayPortUtils::SetDisplayPortBase(aElement,
nsRect(aX, aY, aWidth, aHeight));
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetScrollbarSizes(Element* aElement,
uint32_t* aOutVerticalScrollbarWidth,
uint32_t* aOutHorizontalScrollbarHeight) {
ScrollContainerFrame* scrollContainerFrame =
nsLayoutUtils::FindScrollContainerFrameFor(aElement);
if (!scrollContainerFrame) {
return NS_ERROR_INVALID_ARG;
}
CSSIntMargin scrollbarSizes = RoundedToInt(
CSSMargin::FromAppUnits(scrollContainerFrame->GetActualScrollbarSizes(
ScrollContainerFrame::ScrollbarSizesOptions::
INCLUDE_VISUAL_VIEWPORT_SCROLLBARS)));
*aOutVerticalScrollbarWidth = scrollbarSizes.LeftRight();
*aOutHorizontalScrollbarHeight = scrollbarSizes.TopBottom();
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetResolutionAndScaleTo(float aResolution) {
PresShell* presShell = GetPresShell();
if (!presShell) {
return NS_ERROR_FAILURE;
}
presShell->SetResolutionAndScaleTo(aResolution, ResolutionChangeOrigin::Test);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetRestoreResolution(float aResolution,
uint32_t aDisplayWidth,
uint32_t aDisplayHeight) {
PresShell* presShell = GetPresShell();
if (!presShell) {
return NS_ERROR_FAILURE;
}
presShell->SetRestoreResolution(
aResolution, LayoutDeviceIntSize(aDisplayWidth, aDisplayHeight));
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetResolution(float * aResolution) {
PresShell* presShell = GetPresShell();
if (!presShell) {
return NS_ERROR_FAILURE;
}
*aResolution = presShell->GetResolution();
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SetIsFirstPaint(bool aIsFirstPaint) {
if (PresShell* presShell = GetPresShell()) {
presShell->SetIsFirstPaint(aIsFirstPaint);
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetIsFirstPaint(bool * aIsFirstPaint) {
if (PresShell* presShell = GetPresShell()) {
*aIsFirstPaint = presShell->GetIsFirstPaint();
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetPresShellId(uint32_t* aPresShellId) {
if (PresShell* presShell = GetPresShell()) {
*aPresShellId = presShell->GetPresShellId();
return NS_OK;
}
return NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsDOMWindowUtils::SendMouseEvent(
const nsAString& aType, float aX, float aY, int32_t aButton,
int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame,
float aPressure, unsigned short aInputSourceArg,
bool aIsDOMEventSynthesized, bool aIsWidgetEventSynthesized,
int32_t aButtons, uint32_t aIdentifier, uint8_t aOptionalArgCount,
bool * aPreventDefault) {
return SendMouseEventCommon(
aType, aX, aY, aButton, aClickCount, aModifiers, aIgnoreRootScrollFrame,
aPressure, aInputSourceArg,
aOptionalArgCount >= 7 ? aIdentifier : DEFAULT_MOUSE_POINTER_ID, false ,
aPreventDefault, aOptionalArgCount >= 4 ? aIsDOMEventSynthesized : true ,
aOptionalArgCount >= 5 ? aIsWidgetEventSynthesized : false ,
aOptionalArgCount >= 6 ? aButtons : MOUSE_BUTTONS_NOT_SPECIFIED);
}
NS_IMETHODIMP
nsDOMWindowUtils::SendMouseEventToWindow(
const nsAString& aType, float aX, float aY, int32_t aButton,
int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame,
float aPressure, unsigned short aInputSourceArg,
bool aIsDOMEventSynthesized, bool aIsWidgetEventSynthesized,
int32_t aButtons, uint32_t aIdentifier, uint8_t aOptionalArgCount) {
AUTO_PROFILER_LABEL("nsDOMWindowUtils::SendMouseEventToWindow" , OTHER);
return SendMouseEventCommon(
aType, aX, aY, aButton, aClickCount, aModifiers, aIgnoreRootScrollFrame,
aPressure, aInputSourceArg,
aOptionalArgCount >= 7 ? aIdentifier : DEFAULT_MOUSE_POINTER_ID, true ,
nullptr, aOptionalArgCount >= 4 ? aIsDOMEventSynthesized : true ,
aOptionalArgCount >= 5 ? aIsWidgetEventSynthesized : false ,
aOptionalArgCount >= 6 ? aButtons : MOUSE_BUTTONS_NOT_SPECIFIED);
}
NS_IMETHODIMP
nsDOMWindowUtils::SendMouseEventCommon(
const nsAString& aType, float aX, float aY, int32_t aButton,
int32_t aClickCount, int32_t aModifiers, bool aIgnoreRootScrollFrame,
float aPressure, unsigned short aInputSourceArg, uint32_t aPointerId,
bool aToWindow, bool * aPreventDefault, bool aIsDOMEventSynthesized,
bool aIsWidgetEventSynthesized, int32_t aButtons) {
RefPtr<PresShell> presShell = GetPresShell();
return nsContentUtils::SendMouseEvent(
presShell, aType, aX, aY, aButton, aButtons, aClickCount, aModifiers,
aIgnoreRootScrollFrame, aPressure, aInputSourceArg, aPointerId, aToWindow,
aPreventDefault, aIsDOMEventSynthesized, aIsWidgetEventSynthesized);
}
NS_IMETHODIMP
nsDOMWindowUtils::IsCORSSafelistedRequestHeader(const nsACString& aName,
const nsACString& aValue,
bool * aRetVal) {
NS_ENSURE_ARG_POINTER(aRetVal);
*aRetVal = nsContentUtils::IsCORSSafelistedRequestHeader(aName, aValue);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SendWheelEvent(float aX, float aY, double aDeltaX,
double aDeltaY, double aDeltaZ,
uint32_t aDeltaMode, int32_t aModifiers,
int32_t aLineOrPageDeltaX,
int32_t aLineOrPageDeltaY, uint32_t aOptions) {
// get the widget to send the event to
nsPoint offset;
nsCOMPtr<nsIWidget> widget = GetWidget(&offset);
if (!widget) {
return NS_ERROR_NULL_POINTER;
}
WidgetWheelEvent wheelEvent(true , eWheel, widget);
wheelEvent.mModifiers = nsContentUtils::GetWidgetModifiers(aModifiers);
wheelEvent.mDeltaX = aDeltaX;
wheelEvent.mDeltaY = aDeltaY;
wheelEvent.mDeltaZ = aDeltaZ;
wheelEvent.mDeltaMode = aDeltaMode;
wheelEvent.mIsMomentum = (aOptions & WHEEL_EVENT_CAUSED_BY_MOMENTUM) != 0;
wheelEvent.mIsNoLineOrPageDelta =
(aOptions & WHEEL_EVENT_CAUSED_BY_NO_LINE_OR_PAGE_DELTA_DEVICE) != 0;
wheelEvent.mCustomizedByUserPrefs =
(aOptions & WHEEL_EVENT_CUSTOMIZED_BY_USER_PREFS) != 0;
wheelEvent.mLineOrPageDeltaX = aLineOrPageDeltaX;
wheelEvent.mLineOrPageDeltaY = aLineOrPageDeltaY;
nsPresContext* presContext = GetPresContext();
NS_ENSURE_TRUE(presContext, NS_ERROR_FAILURE);
wheelEvent.mRefPoint =
nsContentUtils::ToWidgetPoint(CSSPoint(aX, aY), offset, presContext);
if (StaticPrefs::test_events_async_enabled()) {
widget->DispatchInputEvent(&wheelEvent);
} else {
nsEventStatus status = nsEventStatus_eIgnore;
nsresult rv = widget->DispatchEvent(&wheelEvent, status);
NS_ENSURE_SUCCESS(rv, rv);
}
if (widget->AsyncPanZoomEnabled()) {
// Computing overflow deltas is not compatible with APZ, so if APZ is
// enabled, we skip testing it.
return NS_OK;
}
bool failedX = false ;
if ((aOptions & WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_X_ZERO) &&
wheelEvent.mOverflowDeltaX != 0) {
failedX = true ;
}
if ((aOptions & WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_X_POSITIVE) &&
wheelEvent.mOverflowDeltaX <= 0) {
failedX = true ;
}
if ((aOptions & WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_X_NEGATIVE) &&
wheelEvent.mOverflowDeltaX >= 0) {
failedX = true ;
}
bool failedY = false ;
if ((aOptions & WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_Y_ZERO) &&
wheelEvent.mOverflowDeltaY != 0) {
failedY = true ;
}
if ((aOptions & WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_Y_POSITIVE) &&
wheelEvent.mOverflowDeltaY <= 0) {
failedY = true ;
}
if ((aOptions & WHEEL_EVENT_EXPECTED_OVERFLOW_DELTA_Y_NEGATIVE) &&
wheelEvent.mOverflowDeltaY >= 0) {
failedY = true ;
}
#ifdef DEBUG
if (failedX) {
nsPrintfCString debugMsg("SendWheelEvent(): unexpected mOverflowDeltaX: %f" ,
wheelEvent.mOverflowDeltaX);
NS_WARNING(debugMsg.get());
}
if (failedY) {
nsPrintfCString debugMsg("SendWheelEvent(): unexpected mOverflowDeltaY: %f" ,
wheelEvent.mOverflowDeltaY);
NS_WARNING(debugMsg.get());
}
#endif
return (!failedX && !failedY) ? NS_OK : NS_ERROR_FAILURE;
}
NS_IMETHODIMP
nsDOMWindowUtils::SendTouchEvent(
const nsAString& aType, const nsTArray<uint32_t>& aIdentifiers,
const nsTArray<int32_t>& aXs, const nsTArray<int32_t>& aYs,
const nsTArray<uint32_t>& aRxs, const nsTArray<uint32_t>& aRys,
const nsTArray<float >& aRotationAngles, const nsTArray<float >& aForces,
const nsTArray<int32_t>& aTiltXs, const nsTArray<int32_t>& aTiltYs,
const nsTArray<int32_t>& aTwists, int32_t aModifiers,
bool aIgnoreRootScrollFrame, bool * aPreventDefault) {
return SendTouchEventCommon(aType, aIdentifiers, aXs, aYs, aRxs, aRys,
aRotationAngles, aForces, aTiltXs, aTiltYs,
aTwists, aModifiers, aIgnoreRootScrollFrame,
/* aIsPen */ false,
/* aToWindow */ false, aPreventDefault);
}
NS_IMETHODIMP
nsDOMWindowUtils::SendTouchEventAsPen(
const nsAString& aType, uint32_t aIdentifier, int32_t aX, int32_t aY,
uint32_t aRx, uint32_t aRy, float aRotationAngle, float aForce,
int32_t aTiltX, int32_t aTiltY, int32_t aTwist, int32_t aModifier,
bool aIgnoreRootScrollFrame, bool * aPreventDefault) {
return SendTouchEventCommon(
aType, nsTArray{aIdentifier}, nsTArray{aX}, nsTArray{aY}, nsTArray{aRx},
nsTArray{aRy}, nsTArray{aRotationAngle}, nsTArray{aForce},
nsTArray{aTiltX}, nsTArray{aTiltY}, nsTArray{aTwist}, aModifier,
aIgnoreRootScrollFrame,
/* aIsPen */ true,
/* aToWindow */ false, aPreventDefault);
}
NS_IMETHODIMP
nsDOMWindowUtils::SendTouchEventToWindow(
const nsAString& aType, const nsTArray<uint32_t>& aIdentifiers,
const nsTArray<int32_t>& aXs, const nsTArray<int32_t>& aYs,
const nsTArray<uint32_t>& aRxs, const nsTArray<uint32_t>& aRys,
const nsTArray<float >& aRotationAngles, const nsTArray<float >& aForces,
const nsTArray<int32_t>& aTiltXs, const nsTArray<int32_t>& aTiltYs,
const nsTArray<int32_t>& aTwists, int32_t aModifiers,
bool aIgnoreRootScrollFrame, bool * aPreventDefault) {
return SendTouchEventCommon(aType, aIdentifiers, aXs, aYs, aRxs, aRys,
aRotationAngles, aForces, aTiltXs, aTiltYs,
aTwists, aModifiers, aIgnoreRootScrollFrame,
/* aIsPen */ false,
/* aToWindow */ true, aPreventDefault);
}
nsresult nsDOMWindowUtils::SendTouchEventCommon(
const nsAString& aType, const nsTArray<uint32_t>& aIdentifiers,
const nsTArray<int32_t>& aXs, const nsTArray<int32_t>& aYs,
const nsTArray<uint32_t>& aRxs, const nsTArray<uint32_t>& aRys,
const nsTArray<float >& aRotationAngles, const nsTArray<float >& aForces,
const nsTArray<int32_t>& aTiltXs, const nsTArray<int32_t>& aTiltYs,
const nsTArray<int32_t>& aTwists, int32_t aModifiers,
bool aIgnoreRootScrollFrame, bool aIsPen, bool aToWindow,
bool * aPreventDefault) {
// get the widget to send the event to
nsPoint offset;
nsCOMPtr<nsIWidget> widget = GetWidget(&offset);
if (!widget) {
return NS_ERROR_NULL_POINTER;
}
EventMessage msg;
if (aType.EqualsLiteral("touchstart" )) {
msg = eTouchStart;
} else if (aType.EqualsLiteral("touchmove" )) {
msg = eTouchMove;
} else if (aType.EqualsLiteral("touchend" )) {
msg = eTouchEnd;
} else if (aType.EqualsLiteral("touchcancel" )) {
msg = eTouchCancel;
} else {
return NS_ERROR_UNEXPECTED;
}
WidgetTouchEvent event(true , msg, widget);
event.mFlags.mIsSynthesizedForTests = true ;
event.mModifiers = nsContentUtils::GetWidgetModifiers(aModifiers);
if (aIsPen) {
event.mInputSource = MouseEvent_Binding::MOZ_SOURCE_PEN;
}
nsPresContext* presContext = GetPresContext();
if (!presContext) {
return NS_ERROR_FAILURE;
}
uint32_t count = aIdentifiers.Length();
if (aXs.Length() != count || aYs.Length() != count ||
aRxs.Length() != count || aRys.Length() != count ||
aRotationAngles.Length() != count || aForces.Length() != count) {
return NS_ERROR_INVALID_ARG;
}
event.mTouches.SetCapacity(count);
for (uint32_t i = 0; i < count; ++i) {
LayoutDeviceIntPoint pt = nsContentUtils::ToWidgetPoint(
CSSPoint(aXs[i], aYs[i]), offset, presContext);
LayoutDeviceIntPoint radius = LayoutDeviceIntPoint::FromAppUnitsRounded(
CSSPoint::ToAppUnits(CSSPoint(aRxs[i], aRys[i])),
presContext->AppUnitsPerDevPixel());
RefPtr<Touch> t = new Touch(aIdentifiers[i], pt, radius, aRotationAngles[i],
aForces[i], aTiltXs[i], aTiltYs[i], aTwists[i]);
event.mTouches.AppendElement(t);
}
nsEventStatus status = nsEventStatus_eIgnore;
if (aToWindow) {
RefPtr<PresShell> presShell;
nsView* view = nsContentUtils::GetViewToDispatchEvent(
presContext, getter_AddRefs(presShell));
if (!presShell || !view) {
return NS_ERROR_FAILURE;
}
*aPreventDefault = (status == nsEventStatus_eConsumeNoDefault);
return presShell->HandleEvent(view->GetFrame(), &event, false , &status);
}
if (StaticPrefs::test_events_async_enabled()) {
status = widget->DispatchInputEvent(&event).mContentStatus;
} else {
nsresult rv = widget->DispatchEvent(&event, status);
NS_ENSURE_SUCCESS(rv, rv);
}
if (aPreventDefault) {
*aPreventDefault = (status == nsEventStatus_eConsumeNoDefault);
}
return NS_OK;
}
static_assert(
static_cast <uint32_t>(nsIWidget::Modifiers::CAPS_LOCK) ==
static_cast <uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_CAPS_LOCK),
"Need to sync CapsLock value between nsIWidget::Modifiers and "
"nsIDOMWindowUtils" );
static_assert(
static_cast <uint32_t>(nsIWidget::Modifiers::NUM_LOCK) ==
static_cast <uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_NUM_LOCK),
"Need to sync NumLock value between nsIWidget::Modifiers and "
"nsIDOMWindowUtils" );
static_assert(
static_cast <uint32_t>(nsIWidget::Modifiers::SHIFT_L) ==
static_cast <uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_SHIFT_LEFT),
"Need to sync ShiftLeft value between nsIWidget::Modifiers and "
"nsIDOMWindowUtils" );
static_assert(
static_cast <uint32_t>(nsIWidget::Modifiers::SHIFT_R) ==
static_cast <uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_SHIFT_RIGHT),
"Need to sync ShiftRight value between nsIWidget::Modifiers and "
"nsIDOMWindowUtils" );
static_assert(
static_cast <uint32_t>(nsIWidget::Modifiers::CTRL_L) ==
static_cast <uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_CONTROL_LEFT),
"Need to sync ControlLeft value between nsIWidget::Modifiers and "
"nsIDOMWindowUtils" );
static_assert(
static_cast <uint32_t>(nsIWidget::Modifiers::CTRL_R) ==
static_cast <uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_CONTROL_RIGHT),
"Need to sync ControlRight value between nsIWidget::Modifiers "
"and nsIDOMWindowUtils" );
static_assert(
static_cast <uint32_t>(nsIWidget::Modifiers::ALT_L) ==
static_cast <uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_ALT_LEFT),
"Need to sync AltLeft value between nsIWidget::Modifiers and "
"nsIDOMWindowUtils" );
static_assert(
static_cast <uint32_t>(nsIWidget::Modifiers::ALT_R) ==
static_cast <uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_ALT_RIGHT),
"Need to sync AltRight value between nsIWidget::Modifiers and "
"nsIDOMWindowUtils" );
static_assert(
static_cast <uint32_t>(nsIWidget::Modifiers::COMMAND_L) ==
static_cast <uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_COMMAND_LEFT),
"Need to sync CommandLeft value between nsIWidget::Modifiers and "
"nsIDOMWindowUtils" );
static_assert(
static_cast <uint32_t>(nsIWidget::Modifiers::COMMAND_R) ==
static_cast <uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_COMMAND_RIGHT),
"Need to sync CommandRight value between nsIWidget::Modifiers "
"and nsIDOMWindowUtils" );
static_assert(
static_cast <uint32_t>(nsIWidget::Modifiers::HELP) ==
static_cast <uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_HELP),
"Need to sync Help value between nsIWidget::Modifiers and "
"nsIDOMWindowUtils" );
static_assert(
static_cast <uint32_t>(nsIWidget::Modifiers::ALTGRAPH) ==
static_cast <uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_ALT_GRAPH),
"Need to sync AltGraph value between nsIWidget::Modifiers and "
"nsIDOMWindowUtils" );
static_assert(
static_cast <uint32_t>(nsIWidget::Modifiers::FUNCTION) ==
static_cast <uint32_t>(nsIDOMWindowUtils::NATIVE_MODIFIER_FUNCTION),
"Need to sync Function value between nsIWidget::Modifiers and "
"nsIDOMWindowUtils" );
static_assert(static_cast <uint32_t>(nsIWidget::Modifiers::NUMERIC_KEY_PAD) ==
static_cast <uint32_t>(
nsIDOMWindowUtils::NATIVE_MODIFIER_NUMERIC_KEY_PAD),
"Need to sync NumericKeyPad value between nsIWidget::Modifiers "
"and nsIDOMWindowUtils" );
static nsIWidget::Modifiers GetWidgetModifiers(uint32_t aNativeModifiers) {
nsIWidget::Modifiers widgetModifiers = static_cast <nsIWidget::Modifiers>(
aNativeModifiers &
(nsIWidget::Modifiers::CAPS_LOCK | nsIWidget::Modifiers::NUM_LOCK |
nsIWidget::Modifiers::SHIFT_L | nsIWidget::Modifiers::SHIFT_R |
nsIWidget::Modifiers::CTRL_L | nsIWidget::Modifiers::CTRL_R |
nsIWidget::Modifiers::ALT_L | nsIWidget::Modifiers::ALT_R |
nsIWidget::Modifiers::COMMAND_L | nsIWidget::Modifiers::COMMAND_R |
nsIWidget::Modifiers::HELP | nsIWidget::Modifiers::ALTGRAPH |
nsIWidget::Modifiers::FUNCTION | nsIWidget::Modifiers::NUMERIC_KEY_PAD));
NS_ASSERTION(static_cast <uint32_t>(widgetModifiers) == aNativeModifiers,
"Invalid value is specified to the native modifiers" );
return widgetModifiers;
}
NS_IMETHODIMP
nsDOMWindowUtils::SendNativeKeyEvent(int32_t aNativeKeyboardLayout,
int32_t aNativeKeyCode,
uint32_t aModifiers,
const nsAString& aCharacters,
const nsAString& aUnmodifiedCharacters,
nsIObserver* aObserver) {
// get the widget to send the event to
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) return NS_ERROR_FAILURE;
NS_DispatchToMainThread(NativeInputRunnable::Create(
NewRunnableMethod<int32_t, int32_t, uint32_t, nsString, nsString,
nsIObserver*>(
"nsIWidget::SynthesizeNativeKeyEvent" , widget,
&nsIWidget::SynthesizeNativeKeyEvent, aNativeKeyboardLayout,
aNativeKeyCode, static_cast <uint32_t>(GetWidgetModifiers(aModifiers)),
aCharacters, aUnmodifiedCharacters, aObserver)));
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SendNativeMouseEvent(int32_t aScreenX, int32_t aScreenY,
uint32_t aNativeMessage, int16_t aButton,
uint32_t aModifierFlags,
Element* aElementOnWidget,
nsIObserver* aObserver) {
// get the widget to send the event to
nsCOMPtr<nsIWidget> widget = GetWidgetForElement(aElementOnWidget);
if (!widget) {
return NS_ERROR_FAILURE;
}
nsIWidget::NativeMouseMessage message;
switch (aNativeMessage) {
case NATIVE_MOUSE_MESSAGE_BUTTON_DOWN:
message = nsIWidget::NativeMouseMessage::ButtonDown;
break ;
case NATIVE_MOUSE_MESSAGE_BUTTON_UP:
message = nsIWidget::NativeMouseMessage::ButtonUp;
break ;
case NATIVE_MOUSE_MESSAGE_MOVE:
message = nsIWidget::NativeMouseMessage::Move;
break ;
case NATIVE_MOUSE_MESSAGE_ENTER_WINDOW:
message = nsIWidget::NativeMouseMessage::EnterWindow;
break ;
case NATIVE_MOUSE_MESSAGE_LEAVE_WINDOW:
message = nsIWidget::NativeMouseMessage::LeaveWindow;
break ;
default :
return NS_ERROR_INVALID_ARG;
}
NS_DispatchToMainThread(NativeInputRunnable::Create(
NewRunnableMethod<LayoutDeviceIntPoint, nsIWidget::NativeMouseMessage,
MouseButton, nsIWidget::Modifiers, nsIObserver*>(
"nsIWidget::SynthesizeNativeMouseEvent" , widget,
&nsIWidget::SynthesizeNativeMouseEvent,
LayoutDeviceIntPoint(aScreenX, aScreenY), message,
static_cast <MouseButton>(aButton), GetWidgetModifiers(aModifierFlags),
aObserver)));
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SendNativeMouseScrollEvent(
int32_t aScreenX, int32_t aScreenY, uint32_t aNativeMessage, double aDeltaX,
double aDeltaY, double aDeltaZ, uint32_t aModifierFlags,
uint32_t aAdditionalFlags, Element* aElement, nsIObserver* aObserver) {
// get the widget to send the event to
nsCOMPtr<nsIWidget> widget = GetWidgetForElement(aElement);
if (!widget) {
return NS_ERROR_FAILURE;
}
NS_DispatchToMainThread(NativeInputRunnable::Create(
NewRunnableMethod<mozilla::LayoutDeviceIntPoint, uint32_t, double , double ,
double , uint32_t, uint32_t, nsIObserver*>(
"nsIWidget::SynthesizeNativeMouseScrollEvent" , widget,
&nsIWidget::SynthesizeNativeMouseScrollEvent,
LayoutDeviceIntPoint(aScreenX, aScreenY), aNativeMessage, aDeltaX,
aDeltaY, aDeltaZ, aModifierFlags, aAdditionalFlags, aObserver)));
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SendNativeTouchPoint(uint32_t aPointerId,
uint32_t aTouchState, int32_t aScreenX,
int32_t aScreenY, double aPressure,
uint32_t aOrientation,
nsIObserver* aObserver,
Element* aElement) {
// FYI: This was designed for automated tests, but currently, this is used by
// DevTools to emulate touch events from mouse events in the responsive
// design mode.
nsCOMPtr<nsIWidget> widget = GetWidgetForElement(aElement);
if (!widget) {
return NS_ERROR_FAILURE;
}
if (aPressure < 0 || aPressure > 1 || aOrientation > 359) {
return NS_ERROR_INVALID_ARG;
}
NS_DispatchToMainThread(NativeInputRunnable::Create(
NewRunnableMethod<uint32_t, nsIWidget::TouchPointerState,
LayoutDeviceIntPoint, double , uint32_t, nsIObserver*>(
"nsIWidget::SynthesizeNativeTouchPoint" , widget,
&nsIWidget::SynthesizeNativeTouchPoint, aPointerId,
(nsIWidget::TouchPointerState)aTouchState,
LayoutDeviceIntPoint(aScreenX, aScreenY), aPressure, aOrientation,
aObserver)));
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SendNativeTouchpadPinch(uint32_t aEventPhase, float aScale,
int32_t aScreenX, int32_t aScreenY,
int32_t aModifierFlags) {
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
return NS_ERROR_FAILURE;
}
NS_DispatchToMainThread(NativeInputRunnable::Create(
NewRunnableMethod<nsIWidget::TouchpadGesturePhase, float ,
LayoutDeviceIntPoint, int32_t>(
"nsIWidget::SynthesizeNativeTouchPadPinch" , widget,
&nsIWidget::SynthesizeNativeTouchPadPinch,
(nsIWidget::TouchpadGesturePhase)aEventPhase, aScale,
LayoutDeviceIntPoint(aScreenX, aScreenY), aModifierFlags)));
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SendNativeTouchTap(int32_t aScreenX, int32_t aScreenY,
bool aLongTap, nsIObserver* aObserver) {
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
return NS_ERROR_FAILURE;
}
NS_DispatchToMainThread(NativeInputRunnable::Create(
NewRunnableMethod<LayoutDeviceIntPoint, bool , nsIObserver*>(
"nsIWidget::SynthesizeNativeTouchTap" , widget,
&nsIWidget::SynthesizeNativeTouchTap,
LayoutDeviceIntPoint(aScreenX, aScreenY), aLongTap, aObserver)));
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SendNativePenInput(uint32_t aPointerId,
uint32_t aPointerState, int32_t aScreenX,
int32_t aScreenY, double aPressure,
uint32_t aRotation, int32_t aTiltX,
int32_t aTiltY, int32_t aButton,
nsIObserver* aObserver,
Element* aElement) {
nsCOMPtr<nsIWidget> widget = GetWidgetForElement(aElement);
if (!widget) {
return NS_ERROR_FAILURE;
}
if (aPressure < 0 || aPressure > 1 || aRotation > 359 || aTiltX < -90 ||
aTiltX > 90 || aTiltY < -90 || aTiltY > 90) {
return NS_ERROR_INVALID_ARG;
}
NS_DispatchToMainThread(NativeInputRunnable::Create(
NewRunnableMethod<uint32_t, nsIWidget::TouchPointerState,
LayoutDeviceIntPoint, double , uint32_t, int32_t,
int32_t, int32_t, nsIObserver*>(
"nsIWidget::SynthesizeNativePenInput" , widget,
&nsIWidget::SynthesizeNativePenInput, aPointerId,
(nsIWidget::TouchPointerState)aPointerState,
LayoutDeviceIntPoint(aScreenX, aScreenY), aPressure, aRotation,
aTiltX, aTiltY, aButton, aObserver)));
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SendNativeTouchpadDoubleTap(int32_t aScreenX,
int32_t aScreenY,
int32_t aModifierFlags) {
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(aModifierFlags >= 0);
NS_DispatchToMainThread(NativeInputRunnable::Create(
NewRunnableMethod<LayoutDeviceIntPoint, uint32_t>(
"nsIWidget::SynthesizeNativeTouchpadDoubleTap" , widget,
&nsIWidget::SynthesizeNativeTouchpadDoubleTap,
LayoutDeviceIntPoint(aScreenX, aScreenY), aModifierFlags)));
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SendNativeTouchpadPan(uint32_t aEventPhase, int32_t aScreenX,
int32_t aScreenY, double aDeltaX,
double aDeltaY, int32_t aModifierFlags,
nsIObserver* aObserver) {
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
return NS_ERROR_FAILURE;
}
MOZ_ASSERT(aModifierFlags >= 0);
NS_DispatchToMainThread(NativeInputRunnable::Create(
NewRunnableMethod<nsIWidget::TouchpadGesturePhase, LayoutDeviceIntPoint,
double , double , uint32_t, nsIObserver*>(
"nsIWidget::SynthesizeNativeTouchpadPan" , widget,
&nsIWidget::SynthesizeNativeTouchpadPan,
(nsIWidget::TouchpadGesturePhase)aEventPhase,
LayoutDeviceIntPoint(aScreenX, aScreenY), aDeltaX, aDeltaY,
aModifierFlags, aObserver)));
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SuppressAnimation(bool aSuppress) {
nsIWidget* widget = GetWidget();
if (widget) {
widget->SuppressAnimation(aSuppress);
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::ClearSharedStyleSheetCache() {
SharedStyleSheetCache::Clear();
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::ClearSharedScriptCache() {
SharedScriptCache::Clear();
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetParsedStyleSheets(uint32_t* aSheets) {
RefPtr<Document> doc = GetDocument();
if (!doc) {
return NS_ERROR_UNEXPECTED;
}
*aSheets = doc->CSSLoader()->ParsedSheetCount();
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::ClearNativeTouchSequence(nsIObserver* aObserver) {
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
return NS_ERROR_FAILURE;
}
NS_DispatchToMainThread(
NativeInputRunnable::Create(NewRunnableMethod<nsIObserver*>(
"nsIWidget::ClearNativeTouchSequence" , widget,
&nsIWidget::ClearNativeTouchSequence, aObserver)));
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::ActivateNativeMenuItemAt(const nsAString& indexString) {
// get the widget to send the event to
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) return NS_ERROR_FAILURE;
return widget->ActivateNativeMenuItemAt(indexString);
}
NS_IMETHODIMP
nsDOMWindowUtils::ForceUpdateNativeMenuAt(const nsAString& indexString) {
// get the widget to send the event to
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) return NS_ERROR_FAILURE;
return widget->ForceUpdateNativeMenuAt(indexString);
}
NS_IMETHODIMP
nsDOMWindowUtils::GetSelectionAsPlaintext(nsAString& aResult) {
// Get the widget to send the event to.
nsCOMPtr<nsIWidget> widget = GetWidget();
if (!widget) {
return NS_ERROR_FAILURE;
}
return widget->GetSelectionAsPlaintext(aResult);
}
nsIWidget* nsDOMWindowUtils::GetWidget(nsPoint* aOffset) {
nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
if (window) {
nsIDocShell* docShell = window->GetDocShell();
if (docShell) {
return nsContentUtils::GetWidget(docShell->GetPresShell(), aOffset);
}
}
return nullptr;
}
nsIWidget* nsDOMWindowUtils::GetWidgetForElement(Element* aElement) {
if (!aElement) {
return GetWidget();
}
if (Document* doc = aElement->GetUncomposedDoc()) {
if (PresShell* presShell = doc->GetPresShell()) {
nsIFrame* frame = aElement->GetPrimaryFrame();
if (!frame) {
frame = presShell->GetRootFrame();
}
if (frame) {
return frame->GetNearestWidget();
}
}
}
return nullptr;
}
NS_IMETHODIMP
nsDOMWindowUtils::GarbageCollect(nsICycleCollectorListener* aListener) {
AUTO_PROFILER_LABEL("nsDOMWindowUtils::GarbageCollect" , GCCC);
nsJSContext::GarbageCollectNow(JS::GCReason::DOM_UTILS);
nsJSContext::CycleCollectNow(CCReason::API, aListener);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::CycleCollect(nsICycleCollectorListener* aListener) {
nsJSContext::CycleCollectNow(CCReason::API, aListener);
return NS_OK;
}
static bool ParseGCReason(const nsACString& aStr, JS::GCReason* aReason,
JS::GCReason aDefault) {
if (aStr.IsEmpty()) {
*aReason = aDefault;
return true ;
}
#define CHECK_REASON(name, _) \
if (aStr.EqualsIgnoreCase(#name )) { \
*aReason = JS::GCReason::name; \
return true ; \
}
GCREASONS(CHECK_REASON);
return false ;
}
NS_IMETHODIMP
nsDOMWindowUtils::RunNextCollectorTimer(const nsACString& aReason) {
JS::GCReason reason;
if (!ParseGCReason(aReason, &reason, JS::GCReason::DOM_WINDOW_UTILS)) {
return NS_ERROR_INVALID_ARG;
}
nsJSContext::RunNextCollectorTimer(reason);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::PokeGC(const nsACString& aReason) {
JS::GCReason reason;
if (!ParseGCReason(aReason, &reason, JS::GCReason::DOM_WINDOW_UTILS)) {
return NS_ERROR_INVALID_ARG;
}
nsJSContext::PokeGC(reason, nullptr);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SendSimpleGestureEvent(const nsAString& aType, float aX,
float aY, uint32_t aDirection,
double aDelta, int32_t aModifiers,
uint32_t aClickCount) {
// get the widget to send the event to
nsPoint offset;
nsCOMPtr<nsIWidget> widget = GetWidget(&offset);
if (!widget) return NS_ERROR_FAILURE;
EventMessage msg;
if (aType.EqualsLiteral("MozSwipeGestureMayStart" )) {
msg = eSwipeGestureMayStart;
} else if (aType.EqualsLiteral("MozSwipeGestureStart" )) {
msg = eSwipeGestureStart;
} else if (aType.EqualsLiteral("MozSwipeGestureUpdate" )) {
msg = eSwipeGestureUpdate;
} else if (aType.EqualsLiteral("MozSwipeGestureEnd" )) {
msg = eSwipeGestureEnd;
} else if (aType.EqualsLiteral("MozSwipeGesture" )) {
msg = eSwipeGesture;
} else if (aType.EqualsLiteral("MozMagnifyGestureStart" )) {
msg = eMagnifyGestureStart;
} else if (aType.EqualsLiteral("MozMagnifyGestureUpdate" )) {
msg = eMagnifyGestureUpdate;
} else if (aType.EqualsLiteral("MozMagnifyGesture" )) {
msg = eMagnifyGesture;
} else if (aType.EqualsLiteral("MozRotateGestureStart" )) {
msg = eRotateGestureStart;
} else if (aType.EqualsLiteral("MozRotateGestureUpdate" )) {
msg = eRotateGestureUpdate;
} else if (aType.EqualsLiteral("MozRotateGesture" )) {
msg = eRotateGesture;
} else if (aType.EqualsLiteral("MozTapGesture" )) {
msg = eTapGesture;
} else if (aType.EqualsLiteral("MozPressTapGesture" )) {
msg = ePressTapGesture;
} else if (aType.EqualsLiteral("MozEdgeUIStarted" )) {
msg = eEdgeUIStarted;
} else if (aType.EqualsLiteral("MozEdgeUICanceled" )) {
msg = eEdgeUICanceled;
} else if (aType.EqualsLiteral("MozEdgeUICompleted" )) {
msg = eEdgeUICompleted;
} else {
return NS_ERROR_FAILURE;
}
WidgetSimpleGestureEvent event(true , msg, widget);
event.mModifiers = nsContentUtils::GetWidgetModifiers(aModifiers);
event.mDirection = aDirection;
event.mDelta = aDelta;
event.mClickCount = aClickCount;
nsPresContext* presContext = GetPresContext();
if (!presContext) return NS_ERROR_FAILURE;
event.mRefPoint =
nsContentUtils::ToWidgetPoint(CSSPoint(aX, aY), offset, presContext);
nsEventStatus status;
return widget->DispatchEvent(&event, status);
}
NS_IMETHODIMP
nsDOMWindowUtils::ElementFromPoint(float aX, float aY,
bool aIgnoreRootScrollFrame,
bool aFlushLayout, Element** aReturn) {
nsCOMPtr<Document> doc = GetDocument();
NS_ENSURE_STATE(doc);
RefPtr<Element> el = doc->ElementFromPointHelper(
aX, aY, aIgnoreRootScrollFrame, aFlushLayout, ViewportType::Layout);
el.forget(aReturn);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::NodesFromRect(float aX, float aY, float aTopSize,
float aRightSize, float aBottomSize,
float aLeftSize, bool aIgnoreRootScrollFrame,
bool aFlushLayout, bool aOnlyVisible,
float aVisibleThreshold,
nsINodeList** aReturn) {
RefPtr<Document> doc = GetDocument();
NS_ENSURE_STATE(doc);
auto list = MakeRefPtr<nsSimpleContentList>(doc);
// The visible threshold was omitted or given a zero value (which makes no
// sense), so give a reasonable default.
if (aVisibleThreshold == 0.0f) {
aVisibleThreshold = 1.0f;
}
AutoTArray<RefPtr<nsINode>, 8> nodes;
doc->NodesFromRect(aX, aY, aTopSize, aRightSize, aBottomSize, aLeftSize,
aIgnoreRootScrollFrame, aFlushLayout, aOnlyVisible,
aVisibleThreshold, nodes);
list->SetCapacity(nodes.Length());
for (auto & node : nodes) {
list->AppendElement(node->AsContent());
}
list.forget(aReturn);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetTranslationNodes(nsINode* aRoot,
nsITranslationNodeList** aRetVal) {
NS_ENSURE_ARG_POINTER(aRetVal);
nsCOMPtr<nsIContent> root = do_QueryInterface(aRoot);
NS_ENSURE_STATE(root);
nsCOMPtr<Document> doc = GetDocument();
NS_ENSURE_STATE(doc);
if (root->OwnerDoc() != doc) {
return NS_ERROR_DOM_WRONG_DOCUMENT_ERR;
}
nsTHashSet<nsIContent*> translationNodesHash(500);
RefPtr<nsTranslationNodeList> list = new nsTranslationNodeList;
uint32_t limit = 15000;
// We begin iteration with content->GetNextNode because we want to explicitly
// skip the root tag from being a translation node.
nsIContent* content = root;
while ((limit > 0) && (content = content->GetNextNode(root))) {
if (!content->IsHTMLElement()) {
continue ;
}
// Skip elements that usually contain non-translatable text content.
if (content->IsAnyOfHTMLElements(nsGkAtoms::script, nsGkAtoms::iframe,
nsGkAtoms::frameset, nsGkAtoms::frame,
nsGkAtoms::code, nsGkAtoms::noscript,
nsGkAtoms::style)) {
continue ;
}
// An element is a translation node if it contains
// at least one text node that has meaningful data
// for translation
for (nsIContent* child = content->GetFirstChild(); child;
child = child->GetNextSibling()) {
if (child->IsText() && child->GetAsText()->HasTextForTranslation()) {
translationNodesHash.Insert(content);
nsIFrame* frame = content->GetPrimaryFrame();
bool isTranslationRoot = frame && frame->IsBlockFrameOrSubclass();
if (!isTranslationRoot) {
// If an element is not a block element, it still
// can be considered a translation root if the parent
// of this element didn't make into the list of nodes
// to be translated.
bool parentInList = false ;
nsIContent* parent = content->GetParent();
if (parent) {
parentInList = translationNodesHash.Contains(parent);
}
isTranslationRoot = !parentInList;
}
list->AppendElement(content, isTranslationRoot);
--limit;
break ;
}
}
}
*aRetVal = list.forget().take();
return NS_OK;
}
static already_AddRefed<DataSourceSurface> CanvasToDataSourceSurface(
HTMLCanvasElement* aCanvas) {
MOZ_ASSERT(aCanvas);
SurfaceFromElementResult result = nsLayoutUtils::SurfaceFromElement(aCanvas);
MOZ_ASSERT(result.GetSourceSurface());
return result.GetSourceSurface()->GetDataSurface();
}
NS_IMETHODIMP
nsDOMWindowUtils::CompareCanvases(nsISupports* aCanvas1, nsISupports* aCanvas2,
uint32_t* aMaxDifference, uint32_t* retVal) {
nsCOMPtr<nsIContent> contentCanvas1 = do_QueryInterface(aCanvas1);
nsCOMPtr<nsIContent> contentCanvas2 = do_QueryInterface(aCanvas2);
auto * canvas1 = HTMLCanvasElement::FromNodeOrNull(contentCanvas1);
auto * canvas2 = HTMLCanvasElement::FromNodeOrNull(contentCanvas2);
if (NS_WARN_IF(!canvas1) || NS_WARN_IF(!canvas2)) {
return NS_ERROR_FAILURE;
}
RefPtr<DataSourceSurface> img1 = CanvasToDataSourceSurface(canvas1);
RefPtr<DataSourceSurface> img2 = CanvasToDataSourceSurface(canvas2);
if (NS_WARN_IF(!img1) || NS_WARN_IF(!img2) ||
NS_WARN_IF(img1->GetSize() != img2->GetSize())) {
return NS_ERROR_FAILURE;
}
if (img1->Equals(img2)) {
// They point to the same underlying content.
return NS_OK;
}
DataSourceSurface::ScopedMap map1(img1, DataSourceSurface::READ);
DataSourceSurface::ScopedMap map2(img2, DataSourceSurface::READ);
if (NS_WARN_IF(!map1.IsMapped()) || NS_WARN_IF(!map2.IsMapped())) {
return NS_ERROR_FAILURE;
}
int v;
IntSize size = img1->GetSize();
int32_t stride1 = map1.GetStride();
int32_t stride2 = map2.GetStride();
// we can optimize for the common all-pass case
if (stride1 == stride2 && stride1 == size.width * 4) {
v = memcmp(map1.GetData(), map2.GetData(), size.width * size.height * 4);
if (v == 0) {
if (aMaxDifference) *aMaxDifference = 0;
*retVal = 0;
return NS_OK;
}
}
uint32_t dc = 0;
uint32_t different = 0;
for (int j = 0; j < size.height; j++) {
unsigned char * p1 = map1.GetData() + j * stride1;
unsigned char * p2 = map2.GetData() + j * stride2;
v = memcmp(p1, p2, size.width * 4);
if (v) {
for (int i = 0; i < size.width; i++) {
if (*(uint32_t*)p1 != *(uint32_t*)p2) {
different++;
dc = std::max((uint32_t)abs(p1[0] - p2[0]), dc);
dc = std::max((uint32_t)abs(p1[1] - p2[1]), dc);
dc = std::max((uint32_t)abs(p1[2] - p2[2]), dc);
dc = std::max((uint32_t)abs(p1[3] - p2[3]), dc);
}
p1 += 4;
p2 += 4;
}
}
}
if (aMaxDifference) *aMaxDifference = dc;
*retVal = different;
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetIsMozAfterPaintPending(bool * aResult) {
NS_ENSURE_ARG_POINTER(aResult);
*aResult = false ;
nsPresContext* presContext = GetPresContext();
if (!presContext) return NS_OK;
*aResult = presContext->IsDOMPaintEventPending();
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetIsWindowFullyOccluded(bool * aResult) {
NS_ENSURE_ARG_POINTER(aResult);
*aResult = false ;
if (nsIWidget* widget = GetWidget()) {
*aResult = widget->IsFullyOccluded();
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetIsCompositorPaused(bool * aResult) {
NS_ENSURE_ARG_POINTER(aResult);
*aResult = false ;
CompositorBridgeChild* cbc = GetCompositorBridge();
if (cbc) {
*aResult = cbc->IsPaused();
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetIsInputTaskManagerSuspended(bool * aResult) {
*aResult = InputTaskManager::Get()->IsSuspended();
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::DisableNonTestMouseEvents(bool aDisable) {
nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
NS_ENSURE_TRUE(window, NS_ERROR_FAILURE);
nsIDocShell* docShell = window->GetDocShell();
NS_ENSURE_TRUE(docShell, NS_ERROR_FAILURE);
PresShell* presShell = docShell->GetPresShell();
NS_ENSURE_TRUE(presShell, NS_ERROR_FAILURE);
presShell->DisableNonTestMouseEvents(aDisable);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::SuppressEventHandling(bool aSuppress) {
nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
NS_ENSURE_STATE(window);
if (aSuppress) {
window->SuppressEventHandling();
} else {
window->UnsuppressEventHandling();
}
return NS_OK;
}
static nsresult getScrollXYAppUnits(const nsWeakPtr& aWindow, bool aFlushLayout,
nsPoint& aScrollPos) {
nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(aWindow);
nsCOMPtr<Document> doc = window ? window->GetExtantDoc() : nullptr;
NS_ENSURE_STATE(doc);
if (aFlushLayout) {
doc->FlushPendingNotifications(FlushType::Layout);
}
if (PresShell* presShell = doc->GetPresShell()) {
ScrollContainerFrame* sf = presShell->GetRootScrollContainerFrame();
if (sf) {
aScrollPos = sf->GetScrollPosition();
}
}
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetScrollXY(bool aFlushLayout, int32_t* aScrollX,
int32_t* aScrollY) {
nsPoint scrollPos(0, 0);
nsresult rv = getScrollXYAppUnits(mWindow, aFlushLayout, scrollPos);
NS_ENSURE_SUCCESS(rv, rv);
*aScrollX = nsPresContext::AppUnitsToIntCSSPixels(scrollPos.x);
*aScrollY = nsPresContext::AppUnitsToIntCSSPixels(scrollPos.y);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetScrollXYFloat(bool aFlushLayout, float * aScrollX,
float * aScrollY) {
nsPoint scrollPos(0, 0);
nsresult rv = getScrollXYAppUnits(mWindow, aFlushLayout, scrollPos);
NS_ENSURE_SUCCESS(rv, rv);
*aScrollX = nsPresContext::AppUnitsToFloatCSSPixels(scrollPos.x);
*aScrollY = nsPresContext::AppUnitsToFloatCSSPixels(scrollPos.y);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::ScrollToVisual(float aOffsetX, float aOffsetY,
int32_t aUpdateType, int32_t aScrollMode) {
nsCOMPtr<Document> doc = GetDocument();
NS_ENSURE_STATE(doc);
nsPresContext* presContext = doc->GetPresContext();
NS_ENSURE_TRUE(presContext, NS_ERROR_NOT_AVAILABLE);
// This should only be called on the root content document.
NS_ENSURE_TRUE(presContext->IsRootContentDocumentCrossProcess(),
NS_ERROR_INVALID_ARG);
FrameMetrics::ScrollOffsetUpdateType updateType;
switch (aUpdateType) {
case UPDATE_TYPE_RESTORE:
updateType = FrameMetrics::eRestore;
break ;
case UPDATE_TYPE_MAIN_THREAD:
updateType = FrameMetrics::eMainThread;
break ;
default :
return NS_ERROR_INVALID_ARG;
}
ScrollMode scrollMode;
switch (aScrollMode) {
case SCROLL_MODE_INSTANT:
scrollMode = ScrollMode::Instant;
break ;
case SCROLL_MODE_SMOOTH:
scrollMode = ScrollMode::SmoothMsd;
break ;
default :
return NS_ERROR_INVALID_ARG;
}
presContext->PresShell()->ScrollToVisual(
CSSPoint::ToAppUnits(CSSPoint(aOffsetX, aOffsetY)), updateType,
scrollMode);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetVisualViewportOffsetRelativeToLayoutViewport(
float * aOffsetX, float * aOffsetY) {
*aOffsetX = 0;
*aOffsetY = 0;
nsCOMPtr<Document> doc = GetDocument();
NS_ENSURE_STATE(doc);
PresShell* presShell = doc->GetPresShell();
NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_AVAILABLE);
nsPoint offset = presShell->GetVisualViewportOffsetRelativeToLayoutViewport();
*aOffsetX = nsPresContext::AppUnitsToFloatCSSPixels(offset.x);
*aOffsetY = nsPresContext::AppUnitsToFloatCSSPixels(offset.y);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetVisualViewportOffset(int32_t* aOffsetX,
int32_t* aOffsetY) {
*aOffsetX = 0;
*aOffsetY = 0;
nsCOMPtr<Document> doc = GetDocument();
NS_ENSURE_STATE(doc);
PresShell* presShell = doc->GetPresShell();
NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_AVAILABLE);
nsPoint offset = presShell->GetVisualViewportOffset();
*aOffsetX = nsPresContext::AppUnitsToIntCSSPixels(offset.x);
*aOffsetY = nsPresContext::AppUnitsToIntCSSPixels(offset.y);
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::TransformRectLayoutToVisual(float aX, float aY, float aWidth,
float aHeight,
DOMRect** aResult) {
nsCOMPtr<nsPIDOMWindowOuter> window = do_QueryReferent(mWindow);
NS_ENSURE_STATE(window);
PresShell* presShell = GetPresShell();
NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_AVAILABLE);
--> --------------------
--> maximum size reached
--> --------------------
quality 98%
¤ Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.0.74Bemerkung:
Wie Sie bei der Firma Beratungs- und Dienstleistungen beauftragen können
¤
*Bot Zugriff