From 24253ba6434548eb754edc4aff6f97dd1aad26bd Mon Sep 17 00:00:00 2001 From: Chinmay Garde Date: Wed, 3 Oct 2018 18:48:39 -0700 Subject: [PATCH] Remove touch mapper and respect the UITouch phase when calculating the pointer data change type. The touch mapper was a relic of a time when the pointer IDs had to be less than 16. Not respecting the touch phase is getting in the way of clients that fake their own touches. Turns out the AppDelegate also like to fake touches to simulate status bar events. Now, except in cases where there is a specific override in place, the UI touch phase is respected. --- ci/licenses_golden/licenses_flutter | 2 - shell/platform/darwin/ios/BUILD.gn | 2 - .../framework/Source/FlutterViewController.mm | 77 +++++++------------ .../framework/Source/flutter_touch_mapper.h | 40 ---------- .../framework/Source/flutter_touch_mapper.mm | 31 -------- 5 files changed, 29 insertions(+), 123 deletions(-) delete mode 100644 shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.h delete mode 100644 shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.mm diff --git a/ci/licenses_golden/licenses_flutter b/ci/licenses_golden/licenses_flutter index 09f307de62a57..d3cf0bf9c8179 100644 --- a/ci/licenses_golden/licenses_flutter +++ b/ci/licenses_golden/licenses_flutter @@ -396,8 +396,6 @@ FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterView.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/accessibility_bridge.mm -FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.h -FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.mm FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_router.h FILE: ../../../flutter/shell/platform/darwin/ios/framework/Source/platform_message_router.mm FILE: ../../../flutter/shell/platform/darwin/ios/platform_view_ios.h diff --git a/shell/platform/darwin/ios/BUILD.gn b/shell/platform/darwin/ios/BUILD.gn index 3de4e258a7d75..d93fe00a7d8c3 100644 --- a/shell/platform/darwin/ios/BUILD.gn +++ b/shell/platform/darwin/ios/BUILD.gn @@ -69,8 +69,6 @@ shared_library("create_flutter_framework_dylib") { "framework/Source/accessibility_bridge.mm", "framework/Source/accessibility_text_entry.h", "framework/Source/accessibility_text_entry.mm", - "framework/Source/flutter_touch_mapper.h", - "framework/Source/flutter_touch_mapper.mm", "framework/Source/platform_message_response_darwin.h", "framework/Source/platform_message_response_darwin.mm", "framework/Source/platform_message_router.h", diff --git a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm index 2c42c14911e57..d9da2160d9cc9 100644 --- a/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm +++ b/shell/platform/darwin/ios/framework/Source/FlutterViewController.mm @@ -18,7 +18,6 @@ #include "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputDelegate.h" #include "flutter/shell/platform/darwin/ios/framework/Source/FlutterTextInputPlugin.h" #include "flutter/shell/platform/darwin/ios/framework/Source/FlutterView.h" -#include "flutter/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.h" #include "flutter/shell/platform/darwin/ios/framework/Source/platform_message_response_darwin.h" #include "flutter/shell/platform/darwin/ios/platform_view_ios.h" @@ -55,7 +54,6 @@ @implementation FlutterViewController { UIInterfaceOrientationMask _orientationPreferences; UIStatusBarStyle _statusBarStyle; blink::ViewportMetrics _viewportMetrics; - shell::TouchMapper _touchMapper; int64_t _nextTextureId; BOOL _initialized; } @@ -543,32 +541,25 @@ - (void)applicationWillEnterForeground:(NSNotification*)notification { #pragma mark - Touch event handling -enum MapperPhase { - Accessed, - Added, - Removed, -}; - -using PointerChangeMapperPhase = std::pair; -static inline PointerChangeMapperPhase PointerChangePhaseFromUITouchPhase(UITouchPhase phase) { +static blink::PointerData::Change PointerDataChangeFromUITouchPhase(UITouchPhase phase) { switch (phase) { case UITouchPhaseBegan: - return PointerChangeMapperPhase(blink::PointerData::Change::kDown, MapperPhase::Added); + return blink::PointerData::Change::kDown; case UITouchPhaseMoved: case UITouchPhaseStationary: // There is no EVENT_TYPE_POINTER_STATIONARY. So we just pass a move type // with the same coordinates - return PointerChangeMapperPhase(blink::PointerData::Change::kMove, MapperPhase::Accessed); + return blink::PointerData::Change::kMove; case UITouchPhaseEnded: - return PointerChangeMapperPhase(blink::PointerData::Change::kUp, MapperPhase::Removed); + return blink::PointerData::Change::kUp; case UITouchPhaseCancelled: - return PointerChangeMapperPhase(blink::PointerData::Change::kCancel, MapperPhase::Removed); + return blink::PointerData::Change::kCancel; } - return PointerChangeMapperPhase(blink::PointerData::Change::kCancel, MapperPhase::Accessed); + return blink::PointerData::Change::kCancel; } -static inline blink::PointerData::DeviceKind DeviceKindFromTouchType(UITouch* touch) { +static blink::PointerData::DeviceKind DeviceKindFromTouchType(UITouch* touch) { if (@available(iOS 9, *)) { switch (touch.type) { case UITouchTypeDirect: @@ -584,33 +575,18 @@ static inline PointerChangeMapperPhase PointerChangePhaseFromUITouchPhase(UITouc return blink::PointerData::DeviceKind::kTouch; } -- (void)dispatchTouches:(NSSet*)touches phase:(UITouchPhase)phase { - // Note: we cannot rely on touch.phase, since in some cases, e.g., - // handleStatusBarTouches, we synthesize touches from existing events. - // - // TODO(cbracken) consider creating out own class with the touch fields we - // need. - auto eventTypePhase = PointerChangePhaseFromUITouchPhase(phase); +// Dispatches the UITouches to the engine. Usually, the type of change of the touch is determined +// from the UITouch's phase. However, FlutterAppDelegate fakes touches to ensure that touch events +// in the status bar area are available to framework code. The change type (optional) of the faked +// touch is specified in the second argument. +- (void)dispatchTouches:(NSSet*)touches + pointerDataChangeOverride:(blink::PointerData::Change*)overridden_change { const CGFloat scale = [UIScreen mainScreen].scale; auto packet = std::make_unique(touches.count); - int i = 0; - for (UITouch* touch in touches) { - int device_id = 0; - - switch (eventTypePhase.second) { - case Accessed: - device_id = _touchMapper.identifierOf(touch); - break; - case Added: - device_id = _touchMapper.registerTouch(touch); - break; - case Removed: - device_id = _touchMapper.unregisterTouch(touch); - break; - } + size_t pointer_index = 0; - FML_DCHECK(device_id != 0); + for (UITouch* touch in touches) { CGPoint windowCoordinates = [touch locationInView:self.view]; blink::PointerData pointer_data; @@ -619,11 +595,13 @@ - (void)dispatchTouches:(NSSet*)touches phase:(UITouchPhase)phase { constexpr int kMicrosecondsPerSecond = 1000 * 1000; pointer_data.time_stamp = touch.timestamp * kMicrosecondsPerSecond; - pointer_data.change = eventTypePhase.first; + pointer_data.change = overridden_change != nullptr + ? *overridden_change + : PointerDataChangeFromUITouchPhase(touch.phase); pointer_data.kind = DeviceKindFromTouchType(touch); - pointer_data.device = device_id; + pointer_data.device = reinterpret_cast(touch); pointer_data.physical_x = windowCoordinates.x * scale; pointer_data.physical_y = windowCoordinates.y * scale; @@ -681,7 +659,7 @@ - (void)dispatchTouches:(NSSet*)touches phase:(UITouchPhase)phase { pointer_data.orientation = [touch azimuthAngleInView:nil] - M_PI_2; } - packet->SetPointerData(i++, pointer_data); + packet->SetPointerData(pointer_index++, pointer_data); } _shell->GetTaskRunners().GetUITaskRunner()->PostTask( @@ -693,19 +671,19 @@ - (void)dispatchTouches:(NSSet*)touches phase:(UITouchPhase)phase { } - (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event { - [self dispatchTouches:touches phase:UITouchPhaseBegan]; + [self dispatchTouches:touches pointerDataChangeOverride:nullptr]; } - (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event { - [self dispatchTouches:touches phase:UITouchPhaseMoved]; + [self dispatchTouches:touches pointerDataChangeOverride:nullptr]; } - (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event { - [self dispatchTouches:touches phase:UITouchPhaseEnded]; + [self dispatchTouches:touches pointerDataChangeOverride:nullptr]; } - (void)touchesCancelled:(NSSet*)touches withEvent:(UIEvent*)event { - [self dispatchTouches:touches phase:UITouchPhaseCancelled]; + [self dispatchTouches:touches pointerDataChangeOverride:nullptr]; } #pragma mark - Handle view resizing @@ -1024,8 +1002,11 @@ - (void)handleStatusBarTouches:(UIEvent*)event { CGPoint screenLoc = [touch.window convertPoint:windowLoc toWindow:nil]; if (CGRectContainsPoint(statusBarFrame, screenLoc)) { NSSet* statusbarTouches = [NSSet setWithObject:touch]; - [self dispatchTouches:statusbarTouches phase:UITouchPhaseBegan]; - [self dispatchTouches:statusbarTouches phase:UITouchPhaseEnded]; + + blink::PointerData::Change change = blink::PointerData::Change::kDown; + [self dispatchTouches:statusbarTouches pointerDataChangeOverride:&change]; + change = blink::PointerData::Change::kUp; + [self dispatchTouches:statusbarTouches pointerDataChangeOverride:&change]; return; } } diff --git a/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.h b/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.h deleted file mode 100644 index e88b35d4ed5ad..0000000000000 --- a/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.h +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_TOUCH_MAPPER_H_ -#define SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_TOUCH_MAPPER_H_ - -#include - -#include "flutter/fml/macros.h" - -#include - -namespace shell { - -/// UITouch pointers cannot be used as touch ids (even though they remain -/// constant throughout the multitouch sequence) because internal components -/// assume that ids are < 16. This class maps touch pointers to ids -class TouchMapper { - public: - TouchMapper(); - ~TouchMapper(); - - int registerTouch(UITouch* touch); - - int unregisterTouch(UITouch* touch); - - int identifierOf(UITouch* touch) const; - - private: - using BitSet = long long int; - BitSet free_spots_; - std::map touch_map_; - - FML_DISALLOW_COPY_AND_ASSIGN(TouchMapper); -}; - -} // namespace shell - -#endif // SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_TOUCH_MAPPER_H_ diff --git a/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.mm b/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.mm deleted file mode 100644 index b0a69b03acd47..0000000000000 --- a/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.mm +++ /dev/null @@ -1,31 +0,0 @@ -// Copyright 2016 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "flutter/shell/platform/darwin/ios/framework/Source/flutter_touch_mapper.h" - -namespace shell { - -TouchMapper::TouchMapper() : free_spots_(~0) {} - -TouchMapper::~TouchMapper() = default; - -int TouchMapper::registerTouch(UITouch* touch) { - int freeSpot = ffsll(free_spots_); - touch_map_[touch] = freeSpot; - free_spots_ &= ~(1 << (freeSpot - 1)); - return freeSpot; -} - -int TouchMapper::unregisterTouch(UITouch* touch) { - auto index = touch_map_[touch]; - free_spots_ |= 1 << (index - 1); - touch_map_.erase(touch); - return index; -} - -int TouchMapper::identifierOf(UITouch* touch) const { - return touch_map_.at(touch); -} - -} // namespace shell