- implements upper screen edge touch detection for absolute touch mode

This commit is contained in:
TrueZhuangjia committed 2024-09-14 16:03:43 +08:00
1 parent b3a64fdf0f
commit 888ecad4d3
2 files changed
+42 -13

No files matched your search

+40 -11
View File
@@ -23,18 +23,32 @@
#define DOUBLE_TAP_DEAD_ZONE_DELTA 0.025f #define DOUBLE_TAP_DEAD_ZONE_DELTA 0.025f
@implementation AbsoluteTouchHandler { @implementation AbsoluteTouchHandler {
StreamView* view; StreamView* streamView;
NSTimer* longPressTimer; NSTimer* longPressTimer;
UITouch* lastTouchDown; UITouch* lastTouchDown;
CGPoint lastTouchDownLocation; CGPoint lastTouchDownLocation;
UITouch* lastTouchUp; UITouch* lastTouchUp;
CGPoint lastTouchUpLocation; CGPoint lastTouchUpLocation;
// upper screen edge check
bool touchPointSpawnedAtUpperScreenEdge;
CGFloat slideGestureVerticalThreshold;
CGFloat screenWidthWithThreshold;
CGFloat EDGE_TOLERANCE;
} }
- (id)initWithView:(StreamView*)view { - (id)initWithView:(StreamView*)view {
self = [self init]; self = [self init];
self->view = view; self->streamView = view;
// upper screen check
EDGE_TOLERANCE = 15.0;
slideGestureVerticalThreshold = CGRectGetHeight([[UIScreen mainScreen] bounds]) * 0.4;
screenWidthWithThreshold = CGRectGetWidth([[UIScreen mainScreen] bounds]) - EDGE_TOLERANCE;
self->touchPointSpawnedAtUpperScreenEdge = false;
return self; return self;
} }
@@ -45,19 +59,28 @@
} }
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint initialPoint = [[touches anyObject] locationInView:streamView];
if(initialPoint.y < slideGestureVerticalThreshold && (initialPoint.x < EDGE_TOLERANCE || initialPoint.x > screenWidthWithThreshold)) {
self->touchPointSpawnedAtUpperScreenEdge = true;
return; // we're done here. this touch event will not be sent to the remote PC.
}
touchPointSpawnedAtUpperScreenEdge = false; // reset this flag immediately if we get a touch event passing the check above, this fixes irresponsive touch after closing the command tool menu.
// Ignore touch down events with more than one finger // Ignore touch down events with more than one finger
if ([[event allTouches] count] > 1) { if ([[event allTouches] count] > 1) {
return; return;
} }
UITouch* touch = [touches anyObject]; UITouch* touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView:view]; CGPoint touchLocation = [touch locationInView:streamView];
// Don't reposition for finger down events within the deadzone. This makes double-clicking easier. // Don't reposition for finger down events within the deadzone. This makes double-clicking easier.
if (touch.timestamp - lastTouchUp.timestamp > DOUBLE_TAP_DEAD_ZONE_DELAY || if (touch.timestamp - lastTouchUp.timestamp > DOUBLE_TAP_DEAD_ZONE_DELAY ||
sqrt(pow((touchLocation.x / view.bounds.size.width) - (lastTouchUpLocation.x / view.bounds.size.width), 2) + sqrt(pow((touchLocation.x / streamView.bounds.size.width) - (lastTouchUpLocation.x / streamView.bounds.size.width), 2) +
pow((touchLocation.y / view.bounds.size.height) - (lastTouchUpLocation.y / view.bounds.size.height), 2)) > DOUBLE_TAP_DEAD_ZONE_DELTA) { pow((touchLocation.y / streamView.bounds.size.height) - (lastTouchUpLocation.y / streamView.bounds.size.height), 2)) > DOUBLE_TAP_DEAD_ZONE_DELTA) {
[view updateCursorLocation:touchLocation isMouse:NO]; [streamView updateCursorLocation:touchLocation isMouse:NO];
} }
// Press the left button down // Press the left button down
@@ -75,25 +98,31 @@
} }
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if(touchPointSpawnedAtUpperScreenEdge) return; // we're done here. this touch event will not be sent to the remote PC.
// Ignore touch move events with more than one finger // Ignore touch move events with more than one finger
if ([[event allTouches] count] > 1) { if ([[event allTouches] count] > 1) {
return; return;
} }
UITouch* touch = [touches anyObject]; UITouch* touch = [touches anyObject];
CGPoint touchLocation = [touch locationInView:view]; CGPoint touchLocation = [touch locationInView:streamView];
if (sqrt(pow((touchLocation.x / view.bounds.size.width) - (lastTouchDownLocation.x / view.bounds.size.width), 2) + if (sqrt(pow((touchLocation.x / streamView.bounds.size.width) - (lastTouchDownLocation.x / streamView.bounds.size.width), 2) +
pow((touchLocation.y / view.bounds.size.height) - (lastTouchDownLocation.y / view.bounds.size.height), 2)) > LONG_PRESS_ACTIVATION_DELTA) { pow((touchLocation.y / streamView.bounds.size.height) - (lastTouchDownLocation.y / streamView.bounds.size.height), 2)) > LONG_PRESS_ACTIVATION_DELTA) {
// Moved too far since touch down. Cancel the long press timer. // Moved too far since touch down. Cancel the long press timer.
[longPressTimer invalidate]; [longPressTimer invalidate];
longPressTimer = nil; longPressTimer = nil;
} }
[view updateCursorLocation:[[touches anyObject] locationInView:view] isMouse:NO]; [streamView updateCursorLocation:[[touches anyObject] locationInView:streamView] isMouse:NO];
} }
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if(touchPointSpawnedAtUpperScreenEdge) return; // we're done here. this touch event will not be sent to the remote PC.
// Only fire this logic if all touches have ended // Only fire this logic if all touches have ended
if ([[event allTouches] count] == [touches count]) { if ([[event allTouches] count] == [touches count]) {
// Cancel the long press timer // Cancel the long press timer
@@ -108,7 +137,7 @@
// Remember this last touch for touch-down deadzoning // Remember this last touch for touch-down deadzoning
lastTouchUp = [touches anyObject]; lastTouchUp = [touches anyObject];
lastTouchUpLocation = [lastTouchUp locationInView:view]; lastTouchUpLocation = [lastTouchUp locationInView:streamView];
} }
} }
+2 -2
View File
@@ -27,7 +27,7 @@ static const float QUICK_TAP_TIME_INTERVAL = 0.2;
BOOL mouseLeftButtonHeldDown; BOOL mouseLeftButtonHeldDown;
BOOL isInMouseWheelScrollingMode; BOOL isInMouseWheelScrollingMode;
// upper screen check // upper screen edge check
bool touchPointSpawnedAtUpperScreenEdge; bool touchPointSpawnedAtUpperScreenEdge;
CGFloat slideGestureVerticalThreshold; CGFloat slideGestureVerticalThreshold;
CGFloat screenWidthWithThreshold; CGFloat screenWidthWithThreshold;
@@ -245,7 +245,7 @@ static const float QUICK_TAP_TIME_INTERVAL = 0.2;
- (void)sendMouseMoveEvent:(UITouch* )touch{ - (void)sendMouseMoveEvent:(UITouch* )touch{
if(touchPointSpawnedAtUpperScreenEdge) return; // we're done here. this touch event will not be sent to the remote PC. and this must be checked after coord selector finishes populating new relative coords, or the app will crash! if(touchPointSpawnedAtUpperScreenEdge) return; // we're done here. this touch event will not be sent to the remote PC.
CGPoint currentLocation = [touch locationInView:streamView]; CGPoint currentLocation = [touch locationInView:streamView];