mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
334 lines
8.7 KiB
C++
334 lines
8.7 KiB
C++
/* 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 "APZController.h"
|
|
#include "base/message_loop.h"
|
|
#include "mozilla/layers/GeckoContentController.h"
|
|
#include "nsThreadUtils.h"
|
|
#include "MetroUtils.h"
|
|
#include "nsPrintfCString.h"
|
|
#include "mozilla/layers/APZCCallbackHelper.h"
|
|
#include "nsIDocument.h"
|
|
#include "nsPresContext.h"
|
|
#include "nsIDOMElement.h"
|
|
#include "mozilla/dom/Element.h"
|
|
#include "nsIDOMWindowUtils.h"
|
|
#include "nsIInterfaceRequestorUtils.h"
|
|
#include "nsLayoutUtils.h"
|
|
#include "mozilla/TouchEvents.h"
|
|
|
|
//#define DEBUG_CONTROLLER 1
|
|
|
|
#ifdef DEBUG_CONTROLLER
|
|
#include "WinUtils.h"
|
|
using namespace mozilla::widget;
|
|
#endif
|
|
|
|
namespace mozilla {
|
|
namespace widget {
|
|
namespace winrt {
|
|
|
|
nsRefPtr<mozilla::layers::APZCTreeManager> APZController::sAPZC;
|
|
|
|
/*
|
|
* Metro layout specific - test to see if a sub document is a
|
|
* tab.
|
|
*/
|
|
static bool
|
|
IsTab(nsCOMPtr<nsIDocument>& aSubDocument)
|
|
{
|
|
nsRefPtr<nsIDocument> parent = aSubDocument->GetParentDocument();
|
|
if (!parent) {
|
|
NS_WARNING("huh? IsTab should always get a sub document for a parameter");
|
|
return false;
|
|
}
|
|
return parent->IsRootDisplayDocument();
|
|
}
|
|
|
|
/*
|
|
* Returns the sub document associated with the scroll id.
|
|
*/
|
|
static bool
|
|
GetDOMTargets(uint64_t aScrollId,
|
|
nsCOMPtr<nsIDocument>& aSubDocument,
|
|
nsCOMPtr<nsIContent>& aTargetContent)
|
|
{
|
|
// For tabs and subframes this will return the HTML sub document
|
|
aTargetContent = nsLayoutUtils::FindContentFor(aScrollId);
|
|
if (!aTargetContent) {
|
|
return false;
|
|
}
|
|
nsCOMPtr<mozilla::dom::Element> domElement = do_QueryInterface(aTargetContent);
|
|
if (!domElement) {
|
|
return false;
|
|
}
|
|
|
|
aSubDocument = domElement->OwnerDoc();
|
|
|
|
if (!aSubDocument) {
|
|
return false;
|
|
}
|
|
|
|
// If the root element equals domElement, FindElementWithViewId found
|
|
// a document, vs. an element within a document.
|
|
if (aSubDocument->GetRootElement() == domElement && IsTab(aSubDocument)) {
|
|
aTargetContent = nullptr;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
class RequestContentRepaintEvent : public nsRunnable
|
|
{
|
|
typedef mozilla::layers::FrameMetrics FrameMetrics;
|
|
|
|
public:
|
|
RequestContentRepaintEvent(const FrameMetrics& aFrameMetrics) :
|
|
mFrameMetrics(aFrameMetrics)
|
|
{
|
|
}
|
|
|
|
NS_IMETHOD Run() {
|
|
// This must be on the gecko thread since we access the dom
|
|
MOZ_ASSERT(NS_IsMainThread());
|
|
|
|
#ifdef DEBUG_CONTROLLER
|
|
WinUtils::Log("APZController: mScrollOffset: %f %f", mFrameMetrics.mScrollOffset.x,
|
|
mFrameMetrics.mScrollOffset.y);
|
|
#endif
|
|
|
|
nsCOMPtr<nsIDocument> subDocument;
|
|
nsCOMPtr<nsIContent> targetContent;
|
|
if (!GetDOMTargets(mFrameMetrics.GetScrollId(),
|
|
subDocument, targetContent)) {
|
|
return NS_OK;
|
|
}
|
|
|
|
// If we're dealing with a sub frame or content editable element,
|
|
// call UpdateSubFrame.
|
|
if (targetContent) {
|
|
#ifdef DEBUG_CONTROLLER
|
|
WinUtils::Log("APZController: detected subframe or content editable");
|
|
#endif
|
|
mozilla::layers::APZCCallbackHelper::UpdateSubFrame(targetContent, mFrameMetrics);
|
|
return NS_OK;
|
|
}
|
|
|
|
#ifdef DEBUG_CONTROLLER
|
|
WinUtils::Log("APZController: detected tab");
|
|
#endif
|
|
|
|
// We're dealing with a tab, call UpdateRootFrame.
|
|
nsCOMPtr<nsIDOMWindowUtils> utils;
|
|
nsCOMPtr<nsIDOMWindow> window = subDocument->GetDefaultView();
|
|
if (window) {
|
|
utils = do_GetInterface(window);
|
|
if (utils) {
|
|
mozilla::layers::APZCCallbackHelper::UpdateRootFrame(utils, mFrameMetrics);
|
|
|
|
#ifdef DEBUG_CONTROLLER
|
|
WinUtils::Log("APZController: %I64d mDisplayPortMargins: %0.2f %0.2f %0.2f %0.2f",
|
|
mFrameMetrics.GetScrollId(),
|
|
mFrameMetrics.GetDisplayPortMargins().left,
|
|
mFrameMetrics.GetDisplayPortMargins().top,
|
|
mFrameMetrics.GetDisplayPortMargins().right,
|
|
mFrameMetrics.GetDisplayPortMargins().bottom);
|
|
#endif
|
|
}
|
|
}
|
|
return NS_OK;
|
|
}
|
|
protected:
|
|
FrameMetrics mFrameMetrics;
|
|
};
|
|
|
|
void
|
|
APZController::SetPendingResponseFlusher(APZPendingResponseFlusher* aFlusher)
|
|
{
|
|
mFlusher = aFlusher;
|
|
}
|
|
|
|
void
|
|
APZController::ContentReceivedTouch(const ScrollableLayerGuid& aGuid, bool aPreventDefault)
|
|
{
|
|
if (!sAPZC) {
|
|
return;
|
|
}
|
|
sAPZC->ContentReceivedTouch(aGuid, aPreventDefault);
|
|
}
|
|
|
|
bool
|
|
APZController::HitTestAPZC(ScreenIntPoint& aPoint)
|
|
{
|
|
if (!sAPZC) {
|
|
return false;
|
|
}
|
|
return sAPZC->HitTestAPZC(aPoint);
|
|
}
|
|
|
|
void
|
|
APZController::TransformCoordinateToGecko(const ScreenIntPoint& aPoint,
|
|
LayoutDeviceIntPoint* aRefPointOut)
|
|
{
|
|
if (!sAPZC || !aRefPointOut) {
|
|
return;
|
|
}
|
|
sAPZC->TransformCoordinateToGecko(aPoint, aRefPointOut);
|
|
}
|
|
|
|
nsEventStatus
|
|
APZController::ReceiveInputEvent(WidgetInputEvent* aEvent,
|
|
ScrollableLayerGuid* aOutTargetGuid)
|
|
{
|
|
MOZ_ASSERT(aEvent);
|
|
|
|
if (!sAPZC) {
|
|
return nsEventStatus_eIgnore;
|
|
}
|
|
return sAPZC->ReceiveInputEvent(*aEvent->AsInputEvent(), aOutTargetGuid);
|
|
}
|
|
|
|
// APZC sends us this request when we need to update the display port on
|
|
// the scrollable frame the apzc is managing.
|
|
void
|
|
APZController::RequestContentRepaint(const FrameMetrics& aFrameMetrics)
|
|
{
|
|
#ifdef DEBUG_CONTROLLER
|
|
WinUtils::Log("APZController::RequestContentRepaint scrollid=%I64d",
|
|
aFrameMetrics.GetScrollId());
|
|
#endif
|
|
nsCOMPtr<nsIRunnable> r1 = new RequestContentRepaintEvent(aFrameMetrics);
|
|
if (!NS_IsMainThread()) {
|
|
NS_DispatchToMainThread(r1);
|
|
} else {
|
|
r1->Run();
|
|
}
|
|
}
|
|
|
|
void
|
|
APZController::AcknowledgeScrollUpdate(const FrameMetrics::ViewID& aScrollId,
|
|
const uint32_t& aScrollGeneration)
|
|
{
|
|
#ifdef DEBUG_CONTROLLER
|
|
WinUtils::Log("APZController::AcknowledgeScrollUpdate scrollid=%I64d gen=%lu",
|
|
aScrollId, aScrollGeneration);
|
|
#endif
|
|
mozilla::layers::APZCCallbackHelper::AcknowledgeScrollUpdate(aScrollId, aScrollGeneration);
|
|
}
|
|
|
|
void
|
|
APZController::HandleDoubleTap(const CSSPoint& aPoint,
|
|
int32_t aModifiers,
|
|
const ScrollableLayerGuid& aGuid)
|
|
{
|
|
}
|
|
|
|
void
|
|
APZController::HandleSingleTap(const CSSPoint& aPoint,
|
|
int32_t aModifiers,
|
|
const ScrollableLayerGuid& aGuid)
|
|
{
|
|
}
|
|
|
|
void
|
|
APZController::HandleLongTap(const CSSPoint& aPoint,
|
|
int32_t aModifiers,
|
|
const ScrollableLayerGuid& aGuid)
|
|
{
|
|
if (mFlusher) {
|
|
mFlusher->FlushPendingContentResponse();
|
|
}
|
|
ContentReceivedTouch(aGuid, false);
|
|
}
|
|
|
|
void
|
|
APZController::HandleLongTapUp(const CSSPoint& aPoint,
|
|
int32_t aModifiers,
|
|
const ScrollableLayerGuid& aGuid)
|
|
{
|
|
}
|
|
|
|
// requests that we send a mozbrowserasyncscroll domevent. not in use.
|
|
void
|
|
APZController::SendAsyncScrollDOMEvent(bool aIsRoot,
|
|
const CSSRect &aContentRect,
|
|
const CSSSize &aScrollableSize)
|
|
{
|
|
}
|
|
|
|
void
|
|
APZController::PostDelayedTask(Task* aTask, int aDelayMs)
|
|
{
|
|
MessageLoop::current()->PostDelayedTask(FROM_HERE, aTask, aDelayMs);
|
|
}
|
|
|
|
bool
|
|
APZController::GetRootZoomConstraints(ZoomConstraints* aOutConstraints)
|
|
{
|
|
if (aOutConstraints) {
|
|
// Until we support the meta-viewport tag properly allow zooming
|
|
// from 1/4 to 4x by default.
|
|
aOutConstraints->mAllowZoom = true;
|
|
aOutConstraints->mAllowDoubleTapZoom = false;
|
|
aOutConstraints->mMinZoom = CSSToScreenScale(0.25f);
|
|
aOutConstraints->mMaxZoom = CSSToScreenScale(4.0f);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
// apzc notifications
|
|
|
|
class TransformedStartEvent : public nsRunnable
|
|
{
|
|
NS_IMETHOD Run() {
|
|
MetroUtils::FireObserver("apzc-transform-start", L"");
|
|
return NS_OK;
|
|
}
|
|
};
|
|
|
|
class TransformedEndEvent : public nsRunnable
|
|
{
|
|
NS_IMETHOD Run() {
|
|
MetroUtils::FireObserver("apzc-transform-end", L"");
|
|
return NS_OK;
|
|
}
|
|
};
|
|
|
|
void
|
|
APZController::NotifyAPZStateChange(const ScrollableLayerGuid& aGuid,
|
|
APZStateChange aChange,
|
|
int aArg)
|
|
{
|
|
switch (aChange) {
|
|
case APZStateChange::TransformBegin:
|
|
{
|
|
if (NS_IsMainThread()) {
|
|
MetroUtils::FireObserver("apzc-transform-begin", L"");
|
|
return;
|
|
}
|
|
nsCOMPtr<nsIRunnable> runnable = new TransformedStartEvent();
|
|
NS_DispatchToMainThread(runnable);
|
|
break;
|
|
}
|
|
case APZStateChange::TransformEnd:
|
|
{
|
|
if (NS_IsMainThread()) {
|
|
MetroUtils::FireObserver("apzc-transform-end", L"");
|
|
return;
|
|
}
|
|
nsCOMPtr<nsIRunnable> runnable = new TransformedEndEvent();
|
|
NS_DispatchToMainThread(runnable);
|
|
break;
|
|
}
|
|
default:
|
|
{
|
|
// We don't currently care about other state changes.
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
} } }
|