# HG changeset patch # User Kartikaya Gupta Send touch events through APZ in the widget code diff --git a/dom/ipc/TabParent.cpp b/dom/ipc/TabParent.cpp index 8de59af..1100fde 100644 --- a/dom/ipc/TabParent.cpp +++ b/dom/ipc/TabParent.cpp @@ -14,16 +14,17 @@ #include "mozilla/dom/ContentParent.h" #include "mozilla/dom/PContentPermissionRequestParent.h" #include "mozilla/dom/indexedDB/ActorsParent.h" #include "mozilla/plugins/PluginWidgetParent.h" #include "mozilla/EventStateManager.h" #include "mozilla/Hal.h" #include "mozilla/ipc/DocumentRendererParent.h" #include "mozilla/layers/CompositorParent.h" +#include "mozilla/layers/InputEventContext.h" #include "mozilla/layout/RenderFrameParent.h" #include "mozilla/MouseEvents.h" #include "mozilla/net/NeckoChild.h" #include "mozilla/Preferences.h" #include "mozilla/TextEvents.h" #include "mozilla/TouchEvents.h" #include "mozilla/unused.h" #include "nsCOMPtr.h" @@ -1123,18 +1124,18 @@ bool TabParent::SendProcessJumpingTouchEvent(WidgetTouchEvent& event) } } return SendRealTouchEvent(event); } bool TabParent::SendRealTouchEvent(WidgetTouchEvent& event) { - ScrollableLayerGuid guid; - uint64_t blockId; + ScrollableLayerGuid guid = InputEventContext::GetTargetLayerGuid(); + uint64_t blockId = InputEventContext::GetInputBlockId(); nsEventStatus status = MaybeForwardEventToRenderFrame(event, &guid, &blockId); if (status == nsEventStatus_eConsumeNoDefault || mIsDestroyed) { return false; } MapEventCoordinatesForChildProcess(mChildProcessOffsetAtTouchStart, &event); @@ -2111,16 +2112,25 @@ TabParent::UseAsyncPanZoom() GetScrollingBehavior() == ASYNC_PAN_ZOOM); } nsEventStatus TabParent::MaybeForwardEventToRenderFrame(WidgetInputEvent& aEvent, ScrollableLayerGuid* aOutTargetGuid, uint64_t* aOutInputBlockId) { +#ifdef MOZ_WIDGET_GONK + if (aEvent.mClass == eTouchEventClass) { + // Stole this idea from :dvander's patch on bug 1109985. As we finish the + // event rerouting work to make all platforms route their events through + // the APZ code in widget, this function should basically become a no-op + // everywhere and can be removed. + return nsEventStatus_eIgnore; + } +#endif if (RenderFrameParent* rfp = GetRenderFrame()) { return rfp->NotifyInputEvent(aEvent, aOutTargetGuid, aOutInputBlockId); } return nsEventStatus_eIgnore; } bool TabParent::RecvBrowserFrameOpenWindow(PBrowserParent* aOpener, diff --git a/gfx/layers/apz/src/APZCTreeManager.cpp b/gfx/layers/apz/src/APZCTreeManager.cpp index cba095a..faf5588 100644 --- a/gfx/layers/apz/src/APZCTreeManager.cpp +++ b/gfx/layers/apz/src/APZCTreeManager.cpp @@ -436,31 +436,31 @@ APZCTreeManager::UpdatePanZoomControllerTree(TreeBuildingState& aState, Matrix4x4 ancestorTransform = transform; if (!apzc) { ancestorTransform = ancestorTransform * aAncestorTransform; } uint64_t childLayersId = (aLayer.AsRefLayer() ? aLayer.AsRefLayer()->GetReferentId() : aLayersId); nsIntRegion obscured; - if (aLayersId == childLayersId) { + //if (aLayersId == childLayersId) { // If the child layer is in the same process, transform // aObscured from aLayer's ParentLayerPixels to aLayer's LayerPixels, // which are the children layers' ParentLayerPixels. // If we cross a process boundary, we assume that we can start with // an empty obscured region because nothing in the parent process will // obscure the child process. This may be false. However, not doing this // definitely runs into a problematic case where the B2G notification // bar and the keyboard get merged into a single layer that obscures // all child processes, even though visually they do not. We'd probably // have to check for mask layers and so on in order to properly handle // that case. obscured = aObscured; obscured.Transform(To3DMatrix(transform).Inverse()); - } + //} // If there's no APZC at this level, any APZCs for our child layers will // have our siblings as their siblings, and our parent as their parent. AsyncPanZoomController* next = aNextSibling; if (apzc) { // Otherwise, use this APZC as the parent going downwards, and start off // with its first child as the next sibling aParent = apzc; diff --git a/widget/gonk/GeckoTouchDispatcher.cpp b/widget/gonk/GeckoTouchDispatcher.cpp index ae9728a..3f0eaa9 100644 --- a/widget/gonk/GeckoTouchDispatcher.cpp +++ b/widget/gonk/GeckoTouchDispatcher.cpp @@ -19,17 +19,16 @@ #include "GeckoProfiler.h" #include "GeckoTouchDispatcher.h" #include "InputData.h" #include "ProfilerMarkers.h" #include "base/basictypes.h" #include "gfxPrefs.h" #include "libui/Input.h" #include "mozilla/ClearOnShutdown.h" -#include "mozilla/MouseEvents.h" #include "mozilla/Mutex.h" #include "mozilla/TimeStamp.h" #include "mozilla/TouchEvents.h" #include "mozilla/dom/Touch.h" #include "nsAppShell.h" #include "nsDebug.h" #include "nsThreadUtils.h" #include "nsWindow.h" @@ -311,31 +310,16 @@ GeckoTouchDispatcher::ResampleTouchMoves(MultiTouchInput& aOutTouch, TimeStamp a // Both mTimeStamp and mTime are being updated to sampleTime here. // mTime needs to be updated using a delta since TimeStamp doesn't // provide a way to obtain a raw value. aOutTouch.mTime += (sampleTime - aOutTouch.mTimeStamp).ToMilliseconds(); aOutTouch.mTimeStamp = sampleTime; } -// Some touch events get sent as mouse events. If APZ doesn't capture the event -// and if a touch only has 1 touch input, we can send a mouse event. -void -GeckoTouchDispatcher::DispatchMouseEvent(MultiTouchInput& aMultiTouch, - bool aForwardToChildren) -{ - WidgetMouseEvent mouseEvent = ToWidgetMouseEvent(aMultiTouch, nullptr); - if (mouseEvent.message == NS_EVENT_NULL) { - return; - } - - mouseEvent.mFlags.mNoCrossProcessBoundaryForwarding = !aForwardToChildren; - nsWindow::DispatchInputEvent(mouseEvent); -} - static bool IsExpired(const MultiTouchInput& aTouch) { // No pending events, the filter state can be updated. uint64_t timeNowMs = systemTime(SYSTEM_TIME_MONOTONIC) / 1000000; return (timeNowMs - aTouch.mTime) > kInputExpirationThresholdMs; } void @@ -350,19 +334,17 @@ GeckoTouchDispatcher::DispatchTouchEvent(MultiTouchInput& aMultiTouch) aMultiTouch.mTouches.Length() == 1) { mTouchEventsFiltered = IsExpired(aMultiTouch); } if (mTouchEventsFiltered) { return; } - bool captured = false; - WidgetTouchEvent event = aMultiTouch.ToWidgetTouchEvent(nullptr); - nsEventStatus status = nsWindow::DispatchInputEvent(event, &captured); + nsWindow::DispatchTouchEvent(aMultiTouch); if (mEnabledUniformityInfo && profiler_is_active()) { const char* touchAction = "Invalid"; switch (aMultiTouch.mType) { case MultiTouchInput::MULTITOUCH_START: touchAction = "Touch_Event_Down"; break; case MultiTouchInput::MULTITOUCH_MOVE: @@ -373,16 +355,11 @@ GeckoTouchDispatcher::DispatchTouchEvent(MultiTouchInput& aMultiTouch) touchAction = "Touch_Event_Up"; break; } const ScreenIntPoint& touchPoint = aMultiTouch.mTouches[0].mScreenPoint; TouchDataPayload* payload = new TouchDataPayload(touchPoint); PROFILER_MARKER_PAYLOAD(touchAction, payload); } - - if (!captured && (aMultiTouch.mTouches.Length() == 1)) { - bool forwardToChildren = status != nsEventStatus_eConsumeNoDefault; - DispatchMouseEvent(aMultiTouch, forwardToChildren); - } } } // namespace mozilla diff --git a/widget/gonk/nsWindow.cpp b/widget/gonk/nsWindow.cpp index 31cd75d..e8bdcc2 100644 --- a/widget/gonk/nsWindow.cpp +++ b/widget/gonk/nsWindow.cpp @@ -42,16 +42,19 @@ #include "ClientLayerManager.h" #include "BasicLayers.h" #include "libdisplay/GonkDisplay.h" #include "pixelflinger/format.h" #include "mozilla/BasicEvents.h" #include "mozilla/gfx/2D.h" #include "mozilla/layers/APZCTreeManager.h" #include "mozilla/layers/CompositorParent.h" +#include "mozilla/layers/InputEventContext.h" +#include "mozilla/MouseEvents.h" +#include "mozilla/TouchEvents.h" #include "ParentProcessController.h" #include "nsThreadUtils.h" #include "HwcComposer2D.h" #define LOG(args...) __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args) #define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "Gonk", ## args) #define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "Gonk", ## args) @@ -208,16 +211,68 @@ nsWindow::DoDraw(void) } listener = targetWindow->GetWidgetListener(); if (listener) { listener->DidPaintWindow(); } } +void +nsWindow::DispatchTouchEvent(MultiTouchInput& aInput) +{ + if (!gFocusedWindow) { + return; + } + + nsRefPtr apz = gFocusedWindow->mAPZC; + if (!apz) { + return; + } + + mozilla::layers::ScrollableLayerGuid guid; + uint64_t inputBlockId; + nsEventStatus rv = apz->ReceiveInputEvent(aInput, &guid, &inputBlockId); + if (rv == nsEventStatus_eConsumeNoDefault) { + return; + } + + WidgetTouchEvent event = aInput.ToWidgetTouchEvent(gFocusedWindow); + InputEventContext context(guid, inputBlockId); + + TabParent* childProc = TabParent::GetTabParentFromLayersId(guid.mLayersId); + + if (childProc) { + // Send the touch event directly to the child process + childProc->SendRealTouchEvent(event); + return; + } + + // Touch event needs to go through the root process (and may still end up + // going to a child process). + bool captured = false; + rv = DispatchInputEvent(event, &captured); + + // TODO: all the stuff from TabChild::RecvRealTouchEvent will need to be + // done here as well. Refactor and reuse! + // For now we're just doing the blind dispatch of mouse events because we + // need this for click events to work in the chrome process. This can be + // removed once we have APZ and ChromeProcessController::HandleSingleTap + // working/implemented for the root process. + + if (captured || (event.touches.Length() != 1)) { + return; + } + WidgetMouseEvent mouseEvent = aInput.ToWidgetMouseEvent(gFocusedWindow); + if (mouseEvent.message != NS_EVENT_NULL) { + mouseEvent.mFlags.mNoCrossProcessBoundaryForwarding = (rv == nsEventStatus_eConsumeNoDefault); + DispatchInputEvent(mouseEvent); + } +} + nsEventStatus nsWindow::DispatchInputEvent(WidgetGUIEvent& aEvent, bool* aWasCaptured) { if (aWasCaptured) { *aWasCaptured = false; } if (!gFocusedWindow) { return nsEventStatus_eIgnore; diff --git a/widget/gonk/nsWindow.h b/widget/gonk/nsWindow.h index 128b533..e4a4fc8 100644 --- a/widget/gonk/nsWindow.h +++ b/widget/gonk/nsWindow.h @@ -11,16 +11,17 @@ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef nsWindow_h #define nsWindow_h +#include "InputData.h" #include "nsBaseWidget.h" #include "nsRegion.h" #include "nsIIdleServiceInternal.h" #include "Units.h" extern nsIntRect gScreenBounds; namespace mozilla { @@ -45,16 +46,17 @@ struct InputContextAction; class nsWindow : public nsBaseWidget { public: nsWindow(); virtual ~nsWindow(); static void DoDraw(void); + static void DispatchTouchEvent(mozilla::MultiTouchInput& aInput); static nsEventStatus DispatchInputEvent(mozilla::WidgetGUIEvent& aEvent, bool* aWasCaptured = nullptr); NS_IMETHOD Create(nsIWidget *aParent, void *aNativeParent, const nsIntRect &aRect, nsDeviceContext *aContext, nsWidgetInitData *aInitData);