mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 915213 - Transform all gecko input through the apzc via widget to compensate for zoom. r=bbondy
This commit is contained in:
parent
17fa48d08b
commit
a774def610
@ -203,6 +203,7 @@ namespace winrt {
|
||||
MetroInput::MetroInput(MetroWidget* aWidget,
|
||||
UI::Core::ICoreWindow* aWindow)
|
||||
: mWidget(aWidget),
|
||||
mChromeHitTestCacheForTouch(false),
|
||||
mWindow(aWindow)
|
||||
{
|
||||
LogFunction();
|
||||
@ -644,6 +645,43 @@ MetroInput::OnPointerReleased(UI::Core::ICoreWindow* aSender,
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
// Tests for chrome vs. content target so we know whether input coordinates need
|
||||
// to be transformed through the apz. Eventually this hit testing should move
|
||||
// into the apz (bug 918288).
|
||||
bool
|
||||
MetroInput::HitTestChrome(const LayoutDeviceIntPoint& pt)
|
||||
{
|
||||
// Confirm this event targets content. We pick this up in browser's input.js.
|
||||
nsMouseEvent hittest(true, NS_MOUSE_MOZHITTEST, mWidget.Get(), nsMouseEvent::eReal, nsMouseEvent::eNormal);
|
||||
hittest.refPoint = pt;
|
||||
nsEventStatus status;
|
||||
mWidget->DispatchEvent(&hittest, status);
|
||||
return (status == nsEventStatus_eConsumeNoDefault);
|
||||
}
|
||||
|
||||
void
|
||||
MetroInput::TransformRefPoint(const Foundation::Point& aPosition, LayoutDeviceIntPoint& aRefPointOut)
|
||||
{
|
||||
// If this event is destined for content we need to transform our ref point through
|
||||
// the apz so that zoom can be accounted for.
|
||||
LayoutDeviceIntPoint pt = LayoutDeviceIntPoint::FromUntyped(MetroUtils::LogToPhys(aPosition));
|
||||
aRefPointOut = pt;
|
||||
// This is currently a general contained rect hit test, it may produce a false positive for
|
||||
// overlay chrome elements.
|
||||
bool apzIntersect = mWidget->HitTestAPZC(mozilla::ScreenPoint(pt.x, pt.y));
|
||||
if (apzIntersect && HitTestChrome(pt)) {
|
||||
return;
|
||||
}
|
||||
nsMouseEvent event(true,
|
||||
NS_MOUSE_MOVE,
|
||||
mWidget.Get(),
|
||||
nsMouseEvent::eReal,
|
||||
nsMouseEvent::eNormal);
|
||||
event.refPoint = aRefPointOut;
|
||||
mWidget->ApzReceiveInputEvent(&event);
|
||||
aRefPointOut = event.refPoint;
|
||||
}
|
||||
|
||||
void
|
||||
MetroInput::InitGeckoMouseEventFromPointerPoint(
|
||||
nsMouseEvent* aEvent,
|
||||
@ -667,7 +705,7 @@ MetroInput::InitGeckoMouseEventFromPointerPoint(
|
||||
props->get_Pressure(&pressure);
|
||||
mGestureRecognizer->CanBeDoubleTap(aPointerPoint, &canBeDoubleTap);
|
||||
|
||||
aEvent->refPoint = LayoutDeviceIntPoint::FromUntyped(MetroUtils::LogToPhys(position));
|
||||
TransformRefPoint(position, aEvent->refPoint);
|
||||
|
||||
if (!canBeDoubleTap) {
|
||||
aEvent->clickCount = 1;
|
||||
@ -965,8 +1003,7 @@ MetroInput::OnTapped(UI::Input::IGestureRecognizer* aSender,
|
||||
|
||||
Foundation::Point position;
|
||||
aArgs->get_Position(&position);
|
||||
HandleSingleTap(
|
||||
LayoutDeviceIntPoint::FromUntyped(MetroUtils::LogToPhys(position)));
|
||||
HandleSingleTap(position);
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
@ -987,18 +1024,20 @@ MetroInput::OnRightTapped(UI::Input::IGestureRecognizer* aSender,
|
||||
|
||||
Foundation::Point position;
|
||||
aArgs->get_Position(&position);
|
||||
HandleLongTap(
|
||||
LayoutDeviceIntPoint::FromUntyped(MetroUtils::LogToPhys(position)));
|
||||
HandleLongTap(position);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
void
|
||||
MetroInput::HandleSingleTap(const LayoutDeviceIntPoint& aPoint)
|
||||
MetroInput::HandleSingleTap(const Foundation::Point& aPoint)
|
||||
{
|
||||
#ifdef DEBUG_INPUT
|
||||
LogFunction();
|
||||
#endif
|
||||
|
||||
LayoutDeviceIntPoint refPoint;
|
||||
TransformRefPoint(aPoint, refPoint);
|
||||
|
||||
// send mousemove
|
||||
nsMouseEvent* mouseEvent = new nsMouseEvent(true,
|
||||
@ -1006,7 +1045,7 @@ MetroInput::HandleSingleTap(const LayoutDeviceIntPoint& aPoint)
|
||||
mWidget.Get(),
|
||||
nsMouseEvent::eReal,
|
||||
nsMouseEvent::eNormal);
|
||||
mouseEvent->refPoint = aPoint;
|
||||
mouseEvent->refPoint = refPoint;
|
||||
mouseEvent->clickCount = 1;
|
||||
mouseEvent->inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||
DispatchAsyncEventIgnoreStatus(mouseEvent);
|
||||
@ -1017,7 +1056,7 @@ MetroInput::HandleSingleTap(const LayoutDeviceIntPoint& aPoint)
|
||||
mWidget.Get(),
|
||||
nsMouseEvent::eReal,
|
||||
nsMouseEvent::eNormal);
|
||||
mouseEvent->refPoint = aPoint;
|
||||
mouseEvent->refPoint = refPoint;
|
||||
mouseEvent->clickCount = 1;
|
||||
mouseEvent->inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||
mouseEvent->button = nsMouseEvent::buttonType::eLeftButton;
|
||||
@ -1028,7 +1067,7 @@ MetroInput::HandleSingleTap(const LayoutDeviceIntPoint& aPoint)
|
||||
mWidget.Get(),
|
||||
nsMouseEvent::eReal,
|
||||
nsMouseEvent::eNormal);
|
||||
mouseEvent->refPoint = aPoint;
|
||||
mouseEvent->refPoint = refPoint;
|
||||
mouseEvent->clickCount = 1;
|
||||
mouseEvent->inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||
mouseEvent->button = nsMouseEvent::buttonType::eLeftButton;
|
||||
@ -1055,18 +1094,20 @@ MetroInput::HandleSingleTap(const LayoutDeviceIntPoint& aPoint)
|
||||
}
|
||||
|
||||
void
|
||||
MetroInput::HandleLongTap(const LayoutDeviceIntPoint& aPoint)
|
||||
MetroInput::HandleLongTap(const Foundation::Point& aPoint)
|
||||
{
|
||||
#ifdef DEBUG_INPUT
|
||||
LogFunction();
|
||||
#endif
|
||||
LayoutDeviceIntPoint refPoint;
|
||||
TransformRefPoint(aPoint, refPoint);
|
||||
|
||||
nsMouseEvent* contextEvent = new nsMouseEvent(true,
|
||||
NS_CONTEXTMENU,
|
||||
mWidget.Get(),
|
||||
nsMouseEvent::eReal,
|
||||
nsMouseEvent::eNormal);
|
||||
contextEvent->refPoint = aPoint;
|
||||
contextEvent->refPoint = refPoint;
|
||||
contextEvent->inputSource = nsIDOMMouseEvent::MOZ_SOURCE_TOUCH;
|
||||
DispatchAsyncEventIgnoreStatus(contextEvent);
|
||||
}
|
||||
@ -1128,7 +1169,7 @@ MetroInput::DeliverNextQueuedTouchEvent()
|
||||
* (ignoring return result) and to content and return the content event
|
||||
* status result to our caller.
|
||||
* 2) mTouchStartDefaultPrevented or mTouchMoveDefaultPrevented are true
|
||||
* Deliver touch directly to content and bypass the apz. Our callers
|
||||
* Deliver touch to content after transforming through the apz. Our callers
|
||||
* handle calling cancel for the touch sequence on the apz.
|
||||
* 3) mTouchStartDefaultPrevented and mTouchMoveDefaultPrevented are false
|
||||
* Deliver events to the apz. If the apz returns eConsumeNoDefault dispatch
|
||||
@ -1137,17 +1178,33 @@ MetroInput::DeliverNextQueuedTouchEvent()
|
||||
* the overhead of delivering dom events.)
|
||||
*/
|
||||
|
||||
// Test for chrome vs. content target. To do this we only use the first touch
|
||||
// point since that will be the input batch target. Cache this for touch events
|
||||
// since HitTestChrome has to send a dom event.
|
||||
if (event->message == NS_TOUCH_START) {
|
||||
nsRefPtr<Touch> touch = event->touches[0];
|
||||
LayoutDeviceIntPoint pt = LayoutDeviceIntPoint::FromUntyped(touch->mRefPoint);
|
||||
bool apzIntersect = mWidget->HitTestAPZC(mozilla::ScreenPoint(pt.x, pt.y));
|
||||
mChromeHitTestCacheForTouch = (apzIntersect && HitTestChrome(pt));
|
||||
}
|
||||
|
||||
// Check if content called preventDefault on touchstart or first touchmove. If so
|
||||
// send directly to content, do not forward to the apz.
|
||||
// and the event is destined for chrome, send the event. If destined for content,
|
||||
// translate coordinates through the apz then send.
|
||||
if (mTouchStartDefaultPrevented || mTouchMoveDefaultPrevented) {
|
||||
// continue delivering events to content
|
||||
if (!mChromeHitTestCacheForTouch) {
|
||||
// ContentReceivedTouch has already been called so this shouldn't cause
|
||||
// the apz to react. We still need to transform our coordinates though.
|
||||
mWidget->ApzReceiveInputEvent(event);
|
||||
}
|
||||
mWidget->DispatchEvent(event, status);
|
||||
return status;
|
||||
}
|
||||
|
||||
// Forward event data to apz. If the apz consumes the event, don't forward to
|
||||
// content if this is not a cancelable event.
|
||||
status = mWidget->ApzReceiveInputEvent(event);
|
||||
nsTouchEvent transformedEvent(*event);
|
||||
status = mWidget->ApzReceiveInputEvent(event, &transformedEvent);
|
||||
if (!mCancelable && status == nsEventStatus_eConsumeNoDefault) {
|
||||
if (!mTouchCancelSent) {
|
||||
mTouchCancelSent = true;
|
||||
@ -1156,8 +1213,9 @@ MetroInput::DeliverNextQueuedTouchEvent()
|
||||
return status;
|
||||
}
|
||||
|
||||
// Deliver event to content
|
||||
mWidget->DispatchEvent(event, status);
|
||||
// Deliver event. If this is destined for chrome, use the untransformed event
|
||||
// data, if it's destined for content, use the transformed event.
|
||||
mWidget->DispatchEvent(!mChromeHitTestCacheForTouch ? &transformedEvent : event, status);
|
||||
return status;
|
||||
}
|
||||
|
||||
|
@ -145,8 +145,8 @@ public:
|
||||
HRESULT OnRightTapped(IGestureRecognizer* aSender,
|
||||
IRightTappedEventArgs* aArgs);
|
||||
|
||||
void HandleSingleTap(const mozilla::LayoutDeviceIntPoint& aPoint);
|
||||
void HandleLongTap(const mozilla::LayoutDeviceIntPoint& aPoint);
|
||||
void HandleSingleTap(const Point& aPoint);
|
||||
void HandleLongTap(const Point& aPoint);
|
||||
|
||||
private:
|
||||
Microsoft::WRL::ComPtr<ICoreWindow> mWindow;
|
||||
@ -159,7 +159,13 @@ private:
|
||||
void RegisterInputEvents();
|
||||
void UnregisterInputEvents();
|
||||
|
||||
// Hit testing for chrome content
|
||||
bool mChromeHitTestCacheForTouch;
|
||||
bool HitTestChrome(const LayoutDeviceIntPoint& pt);
|
||||
|
||||
// Event processing helpers. See function definitions for more info.
|
||||
void TransformRefPoint(const Point& aPosition,
|
||||
LayoutDeviceIntPoint& aRefPointOut);
|
||||
void OnPointerNonTouch(IPointerPoint* aPoint);
|
||||
void InitGeckoMouseEventFromPointerPoint(nsMouseEvent* aEvent,
|
||||
IPointerPoint* aPoint);
|
||||
|
@ -999,17 +999,38 @@ MetroWidget::ApzContentIgnoringTouch()
|
||||
MetroWidget::sAPZC->ContentReceivedTouch(mRootLayerTreeId, false);
|
||||
}
|
||||
|
||||
bool
|
||||
MetroWidget::HitTestAPZC(ScreenPoint& pt)
|
||||
{
|
||||
if (!MetroWidget::sAPZC) {
|
||||
return false;
|
||||
}
|
||||
return MetroWidget::sAPZC->HitTestAPZC(pt);
|
||||
}
|
||||
|
||||
nsEventStatus
|
||||
MetroWidget::ApzReceiveInputEvent(nsTouchEvent* aEvent)
|
||||
MetroWidget::ApzReceiveInputEvent(nsInputEvent* aEvent)
|
||||
{
|
||||
MOZ_ASSERT(aEvent);
|
||||
|
||||
if (!MetroWidget::sAPZC) {
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
nsInputEvent& event = static_cast<nsInputEvent&>(*aEvent);
|
||||
return MetroWidget::sAPZC->ReceiveInputEvent(event);
|
||||
}
|
||||
|
||||
MultiTouchInput inputData(*aEvent);
|
||||
return MetroWidget::sAPZC->ReceiveInputEvent(inputData);
|
||||
nsEventStatus
|
||||
MetroWidget::ApzReceiveInputEvent(nsInputEvent* aInEvent, nsInputEvent* aOutEvent)
|
||||
{
|
||||
MOZ_ASSERT(aInEvent);
|
||||
MOZ_ASSERT(aOutEvent);
|
||||
|
||||
if (!MetroWidget::sAPZC) {
|
||||
return nsEventStatus_eIgnore;
|
||||
}
|
||||
nsInputEvent& event = static_cast<nsInputEvent&>(*aInEvent);
|
||||
return MetroWidget::sAPZC->ReceiveInputEvent(event, aOutEvent);
|
||||
}
|
||||
|
||||
LayerManager*
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "mozilla/layers/CompositorParent.h"
|
||||
#include "mozilla/layers/APZCTreeManager.h"
|
||||
#include "mozilla/layers/LayerManagerComposite.h"
|
||||
#include "Units.h"
|
||||
#include "nsDeque.h"
|
||||
#include "APZController.h"
|
||||
|
||||
@ -199,7 +198,9 @@ public:
|
||||
// APZ related apis
|
||||
void ApzContentConsumingTouch();
|
||||
void ApzContentIgnoringTouch();
|
||||
nsEventStatus ApzReceiveInputEvent(nsTouchEvent* aEvent);
|
||||
nsEventStatus ApzReceiveInputEvent(nsInputEvent* aEvent);
|
||||
nsEventStatus ApzReceiveInputEvent(nsInputEvent* aInEvent, nsInputEvent* aOutEvent);
|
||||
bool HitTestAPZC(mozilla::ScreenPoint& pt);
|
||||
nsresult RequestContentScroll();
|
||||
void RequestContentRepaintImplMainThread();
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user