Attachment #8542238: Part 2 - Send touch inputs through APZ before sending them through gecko for bug #920036

View | Details | Raw Unified | Return to bug 920036
Collapse All | Expand All

(-)a/dom/ipc/TabParent.cpp (-1 / +5 lines)
Line     Link Here 
 Lines 2134-2150   TabParent::UseAsyncPanZoom() Link Here 
2134
          GetScrollingBehavior() == ASYNC_PAN_ZOOM);
2134
          GetScrollingBehavior() == ASYNC_PAN_ZOOM);
2135
}
2135
}
2136
2136
2137
nsEventStatus
2137
nsEventStatus
2138
TabParent::MaybeForwardEventToRenderFrame(WidgetInputEvent& aEvent,
2138
TabParent::MaybeForwardEventToRenderFrame(WidgetInputEvent& aEvent,
2139
                                          ScrollableLayerGuid* aOutTargetGuid,
2139
                                          ScrollableLayerGuid* aOutTargetGuid,
2140
                                          uint64_t* aOutInputBlockId)
2140
                                          uint64_t* aOutInputBlockId)
2141
{
2141
{
2142
  if (aEvent.mClass == eWheelEventClass) {
2142
  if (aEvent.mClass == eWheelEventClass
2143
#ifdef MOZ_WIDGET_GONK
2144
      || aEvent.mClass == eTouchEventClass
2145
#endif
2146
     ) {
2143
    // Wheel events must be sent to APZ directly from the widget. New APZ-
2147
    // Wheel events must be sent to APZ directly from the widget. New APZ-
2144
    // aware events should follow suit and move there as well. However, we
2148
    // aware events should follow suit and move there as well. However, we
2145
    // do need to inform the child process of the correct target and block
2149
    // do need to inform the child process of the correct target and block
2146
    // id.
2150
    // id.
2147
    if (aOutTargetGuid) {
2151
    if (aOutTargetGuid) {
2148
      *aOutTargetGuid = InputAPZContext::GetTargetLayerGuid();
2152
      *aOutTargetGuid = InputAPZContext::GetTargetLayerGuid();
2149
    }
2153
    }
2150
    if (aOutInputBlockId) {
2154
    if (aOutInputBlockId) {
(-)a/widget/gonk/GeckoTouchDispatcher.cpp (-24 / +1 lines)
Line     Link Here 
 Lines 19-35    Link Here 
19
#include "GeckoProfiler.h"
19
#include "GeckoProfiler.h"
20
#include "GeckoTouchDispatcher.h"
20
#include "GeckoTouchDispatcher.h"
21
#include "InputData.h"
21
#include "InputData.h"
22
#include "ProfilerMarkers.h"
22
#include "ProfilerMarkers.h"
23
#include "base/basictypes.h"
23
#include "base/basictypes.h"
24
#include "gfxPrefs.h"
24
#include "gfxPrefs.h"
25
#include "libui/Input.h"
25
#include "libui/Input.h"
26
#include "mozilla/ClearOnShutdown.h"
26
#include "mozilla/ClearOnShutdown.h"
27
#include "mozilla/MouseEvents.h"
28
#include "mozilla/Mutex.h"
27
#include "mozilla/Mutex.h"
29
#include "mozilla/TimeStamp.h"
28
#include "mozilla/TimeStamp.h"
30
#include "mozilla/TouchEvents.h"
29
#include "mozilla/TouchEvents.h"
31
#include "mozilla/dom/Touch.h"
30
#include "mozilla/dom/Touch.h"
32
#include "mozilla/layers/CompositorParent.h"
31
#include "mozilla/layers/CompositorParent.h"
33
#include "nsAppShell.h"
32
#include "nsAppShell.h"
34
#include "nsDebug.h"
33
#include "nsDebug.h"
35
#include "nsThreadUtils.h"
34
#include "nsThreadUtils.h"
 Lines 328-358   GeckoTouchDispatcher::ResampleTouchMoves(MultiTouchInput& aOutTouch, TimeStamp a Link Here 
328
327
329
  // Both mTimeStamp and mTime are being updated to sampleTime here.
328
  // Both mTimeStamp and mTime are being updated to sampleTime here.
330
  // mTime needs to be updated using a delta since TimeStamp doesn't
329
  // mTime needs to be updated using a delta since TimeStamp doesn't
331
  // provide a way to obtain a raw value.
330
  // provide a way to obtain a raw value.
332
  aOutTouch.mTime += (sampleTime - aOutTouch.mTimeStamp).ToMilliseconds();
331
  aOutTouch.mTime += (sampleTime - aOutTouch.mTimeStamp).ToMilliseconds();
333
  aOutTouch.mTimeStamp = sampleTime;
332
  aOutTouch.mTimeStamp = sampleTime;
334
}
333
}
335
334
336
// Some touch events get sent as mouse events. If APZ doesn't capture the event
337
// and if a touch only has 1 touch input, we can send a mouse event.
338
void
339
GeckoTouchDispatcher::DispatchMouseEvent(MultiTouchInput& aMultiTouch,
340
                                         bool aForwardToChildren)
341
{
342
  WidgetMouseEvent mouseEvent = aMultiTouch.ToWidgetMouseEvent(nullptr);
343
  if (mouseEvent.message == NS_EVENT_NULL) {
344
    return;
345
  }
346
347
  mouseEvent.mFlags.mNoCrossProcessBoundaryForwarding = !aForwardToChildren;
348
  nsWindow::DispatchInputEvent(mouseEvent);
349
}
350
351
static bool
335
static bool
352
IsExpired(const MultiTouchInput& aTouch)
336
IsExpired(const MultiTouchInput& aTouch)
353
{
337
{
354
  // No pending events, the filter state can be updated.
338
  // No pending events, the filter state can be updated.
355
  uint64_t timeNowMs = systemTime(SYSTEM_TIME_MONOTONIC) / 1000000;
339
  uint64_t timeNowMs = systemTime(SYSTEM_TIME_MONOTONIC) / 1000000;
356
  return (timeNowMs - aTouch.mTime) > kInputExpirationThresholdMs;
340
  return (timeNowMs - aTouch.mTime) > kInputExpirationThresholdMs;
357
}
341
}
358
void
342
void
 Lines 367-385   GeckoTouchDispatcher::DispatchTouchEvent(MultiTouchInput& aMultiTouch) Link Here 
367
             aMultiTouch.mTouches.Length() == 1) {
351
             aMultiTouch.mTouches.Length() == 1) {
368
    mTouchEventsFiltered = IsExpired(aMultiTouch);
352
    mTouchEventsFiltered = IsExpired(aMultiTouch);
369
  }
353
  }
370
354
371
  if (mTouchEventsFiltered) {
355
  if (mTouchEventsFiltered) {
372
    return;
356
    return;
373
  }
357
  }
374
358
375
  bool captured = false;
359
  nsWindow::DispatchTouchInput(aMultiTouch);
376
  WidgetTouchEvent event = aMultiTouch.ToWidgetTouchEvent(nullptr);
377
  nsEventStatus status = nsWindow::DispatchInputEvent(event, &captured);
378
360
379
  if (mEnabledUniformityInfo && profiler_is_active()) {
361
  if (mEnabledUniformityInfo && profiler_is_active()) {
380
    const char* touchAction = "Invalid";
362
    const char* touchAction = "Invalid";
381
    switch (aMultiTouch.mType) {
363
    switch (aMultiTouch.mType) {
382
      case MultiTouchInput::MULTITOUCH_START:
364
      case MultiTouchInput::MULTITOUCH_START:
383
        touchAction = "Touch_Event_Down";
365
        touchAction = "Touch_Event_Down";
384
        break;
366
        break;
385
      case MultiTouchInput::MULTITOUCH_MOVE:
367
      case MultiTouchInput::MULTITOUCH_MOVE:
 Lines 390-405   GeckoTouchDispatcher::DispatchTouchEvent(MultiTouchInput& aMultiTouch) Link Here 
390
        touchAction = "Touch_Event_Up";
372
        touchAction = "Touch_Event_Up";
391
        break;
373
        break;
392
    }
374
    }
393
375
394
    const ScreenIntPoint& touchPoint = aMultiTouch.mTouches[0].mScreenPoint;
376
    const ScreenIntPoint& touchPoint = aMultiTouch.mTouches[0].mScreenPoint;
395
    TouchDataPayload* payload = new TouchDataPayload(touchPoint);
377
    TouchDataPayload* payload = new TouchDataPayload(touchPoint);
396
    PROFILER_MARKER_PAYLOAD(touchAction, payload);
378
    PROFILER_MARKER_PAYLOAD(touchAction, payload);
397
  }
379
  }
398
399
  if (!captured && (aMultiTouch.mTouches.Length() == 1)) {
400
    bool forwardToChildren = status != nsEventStatus_eConsumeNoDefault;
401
    DispatchMouseEvent(aMultiTouch, forwardToChildren);
402
  }
403
}
380
}
404
381
405
} // namespace mozilla
382
} // namespace mozilla
(-)a/widget/gonk/nsWindow.cpp (-14 / +71 lines)
Line     Link Here 
 Lines 42-57    Link Here 
42
#include "ClientLayerManager.h"
42
#include "ClientLayerManager.h"
43
#include "BasicLayers.h"
43
#include "BasicLayers.h"
44
#include "libdisplay/GonkDisplay.h"
44
#include "libdisplay/GonkDisplay.h"
45
#include "pixelflinger/format.h"
45
#include "pixelflinger/format.h"
46
#include "mozilla/BasicEvents.h"
46
#include "mozilla/BasicEvents.h"
47
#include "mozilla/gfx/2D.h"
47
#include "mozilla/gfx/2D.h"
48
#include "mozilla/layers/APZCTreeManager.h"
48
#include "mozilla/layers/APZCTreeManager.h"
49
#include "mozilla/layers/CompositorParent.h"
49
#include "mozilla/layers/CompositorParent.h"
50
#include "mozilla/layers/InputAPZContext.h"
51
#include "mozilla/MouseEvents.h"
52
#include "mozilla/TouchEvents.h"
50
#include "ParentProcessController.h"
53
#include "ParentProcessController.h"
51
#include "nsThreadUtils.h"
54
#include "nsThreadUtils.h"
52
#include "HwcComposer2D.h"
55
#include "HwcComposer2D.h"
53
56
54
#define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
57
#define LOG(args...)  __android_log_print(ANDROID_LOG_INFO, "Gonk" , ## args)
55
#define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "Gonk", ## args)
58
#define LOGW(args...) __android_log_print(ANDROID_LOG_WARN, "Gonk", ## args)
56
#define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "Gonk", ## args)
59
#define LOGE(args...) __android_log_print(ANDROID_LOG_ERROR, "Gonk", ## args)
57
60
 Lines 223-265   nsWindow::NotifyVsync(TimeStamp aVsyncTimestamp) Link Here 
223
    CompositorVsyncDispatcher* vsyncDispatcher = gFocusedWindow->GetCompositorVsyncDispatcher();
226
    CompositorVsyncDispatcher* vsyncDispatcher = gFocusedWindow->GetCompositorVsyncDispatcher();
224
    // During bootup, there is a delay between when the nsWindow is created
227
    // During bootup, there is a delay between when the nsWindow is created
225
    // and when the Compositor is created, but vsync is already turned on
228
    // and when the Compositor is created, but vsync is already turned on
226
    if (vsyncDispatcher) {
229
    if (vsyncDispatcher) {
227
      vsyncDispatcher->NotifyVsync(aVsyncTimestamp);
230
      vsyncDispatcher->NotifyVsync(aVsyncTimestamp);
228
    }
231
    }
229
}
232
}
230
233
231
nsEventStatus
234
/*static*/ nsEventStatus
232
nsWindow::DispatchInputEvent(WidgetGUIEvent& aEvent, bool* aWasCaptured)
235
nsWindow::DispatchInputEvent(WidgetGUIEvent& aEvent)
233
{
236
{
234
    if (aWasCaptured) {
235
        *aWasCaptured = false;
236
    }
237
    if (!gFocusedWindow) {
237
    if (!gFocusedWindow) {
238
        return nsEventStatus_eIgnore;
238
        return nsEventStatus_eIgnore;
239
    }
239
    }
240
240
241
    gFocusedWindow->UserActivity();
241
    gFocusedWindow->UserActivity();
242
242
243
    nsEventStatus status;
243
    aEvent.widget = gFocusedWindow;
244
    aEvent.widget = gFocusedWindow;
245
    gFocusedWindow->DispatchEvent(&aEvent, status);
246
    return status;
247
}
248
249
/*static*/ void
250
nsWindow::DispatchTouchInput(MultiTouchInput& aInput)
251
{
252
    if (!gFocusedWindow) {
253
        return;
254
    }
255
256
    gFocusedWindow->UserActivity();
257
    gFocusedWindow->DispatchTouchInputViaAPZ(aInput);
258
}
259
260
void
261
nsWindow::DispatchTouchInputViaAPZ(MultiTouchInput& aInput)
262
{
263
    if (!mAPZC) {
264
        return;
265
    }
266
267
    // First send it through the APZ code
268
    mozilla::layers::ScrollableLayerGuid guid;
269
    uint64_t inputBlockId;
270
    nsEventStatus rv = mAPZC->ReceiveInputEvent(aInput, &guid, &inputBlockId);
271
    // If the APZ says to drop it, then we drop it
272
    if (rv == nsEventStatus_eConsumeNoDefault) {
273
        return;
274
    }
244
275
276
    // Convert it to an event we can send to Gecko
277
    WidgetTouchEvent event = aInput.ToWidgetTouchEvent(this);
278
279
    // If there is an event capturing child process, send it directly there.
280
    // This happens if we already sent a touchstart event through the root
281
    // process hit test and it ended up going to a child process. The event
282
    // capturing process should get all subsequent touch events in the same
283
    // event block. In this case the TryCapture call below will return true,
284
    // and the child process will take care of responding to the event as needed
285
    // so we don't need to do anything else here.
245
    if (TabParent* capturer = TabParent::GetEventCapturer()) {
286
    if (TabParent* capturer = TabParent::GetEventCapturer()) {
246
        bool captured = capturer->TryCapture(aEvent);
287
        InputAPZContext context(guid, inputBlockId);
247
        if (aWasCaptured) {
288
        if (capturer->TryCapture(event)) {
248
            *aWasCaptured = captured;
289
            return;
249
        }
250
        if (captured) {
251
            return nsEventStatus_eConsumeNoDefault;
252
        }
290
        }
253
    }
291
    }
254
292
255
    nsEventStatus status;
293
    // If it didn't get captured, dispatch the event into the gecko root process
256
    gFocusedWindow->DispatchEvent(&aEvent, status);
294
    // for "normal" flow. The event might get sent to the child process still,
257
    return status;
295
    // but if it doesn't we need to notify the APZ of various things. All of
296
    // that happens in DispatchEventForAPZ
297
    rv = DispatchEventForAPZ(&event, guid, inputBlockId);
298
299
    // Finally, if the touch event had only one touch point, generate a mouse
300
    // event for it and send it through the gecko root process.
301
    // Technically we should not need to do this if the touch event was routed
302
    // to the child process, but that seems to expose a bug in B2G where the
303
    // keyboard doesn't go away in some cases.
304
    // Also for now we're dispatching mouse events from all touch events because
305
    // we need this for click events to work in the chrome process. Once we have
306
    // APZ and ChromeProcessController::HandleSingleTap working for the chrome
307
    // process we shouldn't need to do this at all.
308
    if (event.touches.Length() == 1) {
309
        WidgetMouseEvent mouseEvent = aInput.ToWidgetMouseEvent(this);
310
        if (mouseEvent.message != NS_EVENT_NULL) {
311
            mouseEvent.mFlags.mNoCrossProcessBoundaryForwarding = (rv == nsEventStatus_eConsumeNoDefault);
312
            DispatchEvent(&mouseEvent, rv);
313
        }
314
    }
258
}
315
}
259
316
260
NS_IMETHODIMP
317
NS_IMETHODIMP
261
nsWindow::Create(nsIWidget *aParent,
318
nsWindow::Create(nsIWidget *aParent,
262
                 void *aNativeParent,
319
                 void *aNativeParent,
263
                 const nsIntRect &aRect,
320
                 const nsIntRect &aRect,
264
                 nsDeviceContext *aContext,
321
                 nsDeviceContext *aContext,
265
                 nsWidgetInitData *aInitData)
322
                 nsWidgetInitData *aInitData)
(-)a/widget/gonk/nsWindow.h (-2 / +4 lines)
Line     Link Here 
 Lines 11-26    Link Here 
11
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
 * See the License for the specific language governing permissions and
12
 * See the License for the specific language governing permissions and
13
 * limitations under the License.
13
 * limitations under the License.
14
 */
14
 */
15
15
16
#ifndef nsWindow_h
16
#ifndef nsWindow_h
17
#define nsWindow_h
17
#define nsWindow_h
18
18
19
#include "InputData.h"
19
#include "nsBaseWidget.h"
20
#include "nsBaseWidget.h"
20
#include "nsRegion.h"
21
#include "nsRegion.h"
21
#include "nsIIdleServiceInternal.h"
22
#include "nsIIdleServiceInternal.h"
22
#include "Units.h"
23
#include "Units.h"
23
24
24
extern nsIntRect gScreenBounds;
25
extern nsIntRect gScreenBounds;
25
26
26
namespace mozilla {
27
namespace mozilla {
 Lines 46-63   struct InputContextAction; Link Here 
46
class nsWindow : public nsBaseWidget
47
class nsWindow : public nsBaseWidget
47
{
48
{
48
public:
49
public:
49
    nsWindow();
50
    nsWindow();
50
    virtual ~nsWindow();
51
    virtual ~nsWindow();
51
52
52
    static void NotifyVsync(mozilla::TimeStamp aVsyncTimestamp);
53
    static void NotifyVsync(mozilla::TimeStamp aVsyncTimestamp);
53
    static void DoDraw(void);
54
    static void DoDraw(void);
54
    static nsEventStatus DispatchInputEvent(mozilla::WidgetGUIEvent& aEvent,
55
    static nsEventStatus DispatchInputEvent(mozilla::WidgetGUIEvent& aEvent);
55
                                            bool* aWasCaptured = nullptr);
56
    static void DispatchTouchInput(mozilla::MultiTouchInput& aInput);
56
57
57
    NS_IMETHOD Create(nsIWidget *aParent,
58
    NS_IMETHOD Create(nsIWidget *aParent,
58
                      void *aNativeParent,
59
                      void *aNativeParent,
59
                      const nsIntRect &aRect,
60
                      const nsIntRect &aRect,
60
                      nsDeviceContext *aContext,
61
                      nsDeviceContext *aContext,
61
                      nsWidgetInitData *aInitData);
62
                      nsWidgetInitData *aInitData);
62
    NS_IMETHOD Destroy(void);
63
    NS_IMETHOD Destroy(void);
63
64
 Lines 82-97   public: Link Here 
82
    NS_IMETHOD ConfigureChildren(const nsTArray<nsIWidget::Configuration>&);
83
    NS_IMETHOD ConfigureChildren(const nsTArray<nsIWidget::Configuration>&);
83
    NS_IMETHOD Invalidate(const nsIntRect &aRect);
84
    NS_IMETHOD Invalidate(const nsIntRect &aRect);
84
    virtual void* GetNativeData(uint32_t aDataType);
85
    virtual void* GetNativeData(uint32_t aDataType);
85
    NS_IMETHOD SetTitle(const nsAString& aTitle)
86
    NS_IMETHOD SetTitle(const nsAString& aTitle)
86
    {
87
    {
87
        return NS_OK;
88
        return NS_OK;
88
    }
89
    }
89
    virtual nsIntPoint WidgetToScreenOffset();
90
    virtual nsIntPoint WidgetToScreenOffset();
91
    void DispatchTouchInputViaAPZ(mozilla::MultiTouchInput& aInput);
90
    NS_IMETHOD DispatchEvent(mozilla::WidgetGUIEvent* aEvent,
92
    NS_IMETHOD DispatchEvent(mozilla::WidgetGUIEvent* aEvent,
91
                             nsEventStatus& aStatus);
93
                             nsEventStatus& aStatus);
92
    NS_IMETHOD CaptureRollupEvents(nsIRollupListener *aListener,
94
    NS_IMETHOD CaptureRollupEvents(nsIRollupListener *aListener,
93
                                   bool aDoCapture)
95
                                   bool aDoCapture)
94
    {
96
    {
95
        return NS_ERROR_NOT_IMPLEMENTED;
97
        return NS_ERROR_NOT_IMPLEMENTED;
96
    }
98
    }
97
    NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent);
99
    NS_IMETHOD ReparentNativeWidget(nsIWidget* aNewParent);

Return to bug 920036