未验证 提交 45c5fe56 编写于 作者: C Chinmay Garde 提交者: GitHub

Remove touch mapper and respect the UITouch phase when calculating the pointer...

Remove touch mapper and respect the UITouch phase when calculating the pointer data change type. (#6430)

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.
上级 23473680
......@@ -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
......
......@@ -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",
......
......@@ -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 @@
UIInterfaceOrientationMask _orientationPreferences;
UIStatusBarStyle _statusBarStyle;
blink::ViewportMetrics _viewportMetrics;
shell::TouchMapper _touchMapper;
int64_t _nextTextureId;
BOOL _initialized;
}
......@@ -543,32 +541,25 @@
#pragma mark - Touch event handling
enum MapperPhase {
Accessed,
Added,
Removed,
};
using PointerChangeMapperPhase = std::pair<blink::PointerData::Change, MapperPhase>;
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 blink::PointerData::DeviceKind DeviceKindFromTouchType(UITouch* to
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<blink::PointerDataPacket>(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 @@ static inline blink::PointerData::DeviceKind DeviceKindFromTouchType(UITouch* to
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<int64_t>(touch);
pointer_data.physical_x = windowCoordinates.x * scale;
pointer_data.physical_y = windowCoordinates.y * scale;
......@@ -681,7 +659,7 @@ static inline blink::PointerData::DeviceKind DeviceKindFromTouchType(UITouch* to
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 @@ static inline blink::PointerData::DeviceKind DeviceKindFromTouchType(UITouch* to
}
- (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 @@ constexpr CGFloat kStandardStatusBarHeight = 20.0;
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;
}
}
......
// 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 <UIKit/UIKit.h>
#include "flutter/fml/macros.h"
#include <map>
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<UITouch*, int> touch_map_;
FML_DISALLOW_COPY_AND_ASSIGN(TouchMapper);
};
} // namespace shell
#endif // SHELL_PLATFORM_IOS_FRAMEWORK_SOURCE_TOUCH_MAPPER_H_
// 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
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册