mirror of
https://github.com/moonlight-stream/moonlight-ios.git
synced 2026-06-17 14:11:35 +00:00
Refactor relative touch handling into a separate class
This commit is contained in:
@@ -0,0 +1,19 @@
|
|||||||
|
//
|
||||||
|
// RelativeTouchHandler.h
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Cameron Gutman on 11/1/20.
|
||||||
|
// Copyright © 2020 Moonlight Game Streaming Project. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface RelativeTouchHandler : UIResponder
|
||||||
|
|
||||||
|
-(id)initWithView:(UIView*)view;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
||||||
@@ -0,0 +1,196 @@
|
|||||||
|
//
|
||||||
|
// RelativeTouchHandler.m
|
||||||
|
// Moonlight
|
||||||
|
//
|
||||||
|
// Created by Cameron Gutman on 11/1/20.
|
||||||
|
// Copyright © 2020 Moonlight Game Streaming Project. All rights reserved.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "RelativeTouchHandler.h"
|
||||||
|
|
||||||
|
#include <Limelight.h>
|
||||||
|
|
||||||
|
static const int REFERENCE_WIDTH = 1280;
|
||||||
|
static const int REFERENCE_HEIGHT = 720;
|
||||||
|
|
||||||
|
@implementation RelativeTouchHandler {
|
||||||
|
CGPoint touchLocation, originalLocation;
|
||||||
|
BOOL touchMoved;
|
||||||
|
BOOL isDragging;
|
||||||
|
NSTimer* dragTimer;
|
||||||
|
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
UIGestureRecognizer* remotePressRecognizer;
|
||||||
|
UIGestureRecognizer* remoteLongPressRecognizer;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
UIView* view;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (id)initWithView:(UIView*)view {
|
||||||
|
self = [self init];
|
||||||
|
self->view = view;
|
||||||
|
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
remotePressRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(remoteButtonPressed:)];
|
||||||
|
remotePressRecognizer.allowedPressTypes = @[@(UIPressTypeSelect)];
|
||||||
|
|
||||||
|
remoteLongPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(remoteButtonLongPressed:)];
|
||||||
|
remoteLongPressRecognizer.allowedPressTypes = @[@(UIPressTypeSelect)];
|
||||||
|
|
||||||
|
[self->view addGestureRecognizer:remotePressRecognizer];
|
||||||
|
[self->view addGestureRecognizer:remoteLongPressRecognizer];
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (BOOL)isConfirmedMove:(CGPoint)currentPoint from:(CGPoint)originalPoint {
|
||||||
|
// Movements of greater than 5 pixels are considered confirmed
|
||||||
|
return hypotf(originalPoint.x - currentPoint.x, originalPoint.y - currentPoint.y) >= 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)onDragStart:(NSTimer*)timer {
|
||||||
|
if (!touchMoved && !isDragging){
|
||||||
|
isDragging = true;
|
||||||
|
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||||
|
UITouch *touch = [[event allTouches] anyObject];
|
||||||
|
originalLocation = touchLocation = [touch locationInView:view];
|
||||||
|
touchMoved = false;
|
||||||
|
if ([[event allTouches] count] == 1 && !isDragging) {
|
||||||
|
dragTimer = [NSTimer scheduledTimerWithTimeInterval:0.650
|
||||||
|
target:self
|
||||||
|
selector:@selector(onDragStart:)
|
||||||
|
userInfo:nil
|
||||||
|
repeats:NO];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||||
|
if ([[event allTouches] count] == 1) {
|
||||||
|
UITouch *touch = [[event allTouches] anyObject];
|
||||||
|
CGPoint currentLocation = [touch locationInView:view];
|
||||||
|
|
||||||
|
if (touchLocation.x != currentLocation.x ||
|
||||||
|
touchLocation.y != currentLocation.y)
|
||||||
|
{
|
||||||
|
int deltaX = (currentLocation.x - touchLocation.x) * (REFERENCE_WIDTH / view.bounds.size.width);
|
||||||
|
int deltaY = (currentLocation.y - touchLocation.y) * (REFERENCE_HEIGHT / view.bounds.size.height);
|
||||||
|
|
||||||
|
if (deltaX != 0 || deltaY != 0) {
|
||||||
|
LiSendMouseMoveEvent(deltaX, deltaY);
|
||||||
|
touchLocation = currentLocation;
|
||||||
|
|
||||||
|
// If we've moved far enough to confirm this wasn't just human/machine error,
|
||||||
|
// mark it as such.
|
||||||
|
if ([self isConfirmedMove:touchLocation from:originalLocation]) {
|
||||||
|
touchMoved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if ([[event allTouches] count] == 2) {
|
||||||
|
CGPoint firstLocation = [[[[event allTouches] allObjects] objectAtIndex:0] locationInView:view];
|
||||||
|
CGPoint secondLocation = [[[[event allTouches] allObjects] objectAtIndex:1] locationInView:view];
|
||||||
|
|
||||||
|
CGPoint avgLocation = CGPointMake((firstLocation.x + secondLocation.x) / 2, (firstLocation.y + secondLocation.y) / 2);
|
||||||
|
if (touchLocation.y != avgLocation.y) {
|
||||||
|
LiSendScrollEvent(avgLocation.y - touchLocation.y);
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we've moved far enough to confirm this wasn't just human/machine error,
|
||||||
|
// mark it as such.
|
||||||
|
if ([self isConfirmedMove:firstLocation from:originalLocation]) {
|
||||||
|
touchMoved = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
touchLocation = avgLocation;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||||
|
[dragTimer invalidate];
|
||||||
|
dragTimer = nil;
|
||||||
|
if (isDragging) {
|
||||||
|
isDragging = false;
|
||||||
|
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
||||||
|
} else if (!touchMoved) {
|
||||||
|
if ([[event allTouches] count] == 2) {
|
||||||
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
||||||
|
Log(LOG_D, @"Sending right mouse button press");
|
||||||
|
|
||||||
|
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT);
|
||||||
|
|
||||||
|
// Wait 100 ms to simulate a real button press
|
||||||
|
usleep(100 * 1000);
|
||||||
|
|
||||||
|
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT);
|
||||||
|
});
|
||||||
|
} else if ([[event allTouches] count] == 1) {
|
||||||
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
||||||
|
if (!self->isDragging){
|
||||||
|
Log(LOG_D, @"Sending left mouse button press");
|
||||||
|
|
||||||
|
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
|
||||||
|
|
||||||
|
// Wait 100 ms to simulate a real button press
|
||||||
|
usleep(100 * 1000);
|
||||||
|
}
|
||||||
|
self->isDragging = false;
|
||||||
|
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// We we're moving from 2+ touches to 1. Synchronize the current position
|
||||||
|
// of the active finger so we don't jump unexpectedly on the next touchesMoved
|
||||||
|
// callback when finger 1 switches on us.
|
||||||
|
if ([[event allTouches] count] - [touches count] == 1) {
|
||||||
|
NSMutableSet *activeSet = [[NSMutableSet alloc] initWithCapacity:[[event allTouches] count]];
|
||||||
|
[activeSet unionSet:[event allTouches]];
|
||||||
|
[activeSet minusSet:touches];
|
||||||
|
touchLocation = [[activeSet anyObject] locationInView:view];
|
||||||
|
|
||||||
|
// Mark this touch as moved so we don't send a left mouse click if the user
|
||||||
|
// right clicks without moving their other finger.
|
||||||
|
touchMoved = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||||
|
[dragTimer invalidate];
|
||||||
|
dragTimer = nil;
|
||||||
|
if (isDragging) {
|
||||||
|
isDragging = false;
|
||||||
|
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#if TARGET_OS_TV
|
||||||
|
- (void)remoteButtonPressed:(id)sender {
|
||||||
|
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
||||||
|
Log(LOG_D, @"Sending left mouse button press");
|
||||||
|
|
||||||
|
// Mark this as touchMoved to avoid a duplicate press on touch up
|
||||||
|
self->touchMoved = true;
|
||||||
|
|
||||||
|
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
|
||||||
|
|
||||||
|
// Wait 100 ms to simulate a real button press
|
||||||
|
usleep(100 * 1000);
|
||||||
|
|
||||||
|
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
- (void)remoteButtonLongPressed:(id)sender {
|
||||||
|
Log(LOG_D, @"Holding left mouse button");
|
||||||
|
|
||||||
|
isDragging = true;
|
||||||
|
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
@end
|
||||||
+30
-174
@@ -11,20 +11,14 @@
|
|||||||
#import "DataManager.h"
|
#import "DataManager.h"
|
||||||
#import "ControllerSupport.h"
|
#import "ControllerSupport.h"
|
||||||
#import "KeyboardSupport.h"
|
#import "KeyboardSupport.h"
|
||||||
|
#import "RelativeTouchHandler.h"
|
||||||
|
|
||||||
static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
||||||
|
|
||||||
static const int REFERENCE_WIDTH = 1280;
|
|
||||||
static const int REFERENCE_HEIGHT = 720;
|
|
||||||
|
|
||||||
@implementation StreamView {
|
@implementation StreamView {
|
||||||
CGPoint touchLocation, originalLocation;
|
|
||||||
BOOL touchMoved;
|
|
||||||
OnScreenControls* onScreenControls;
|
OnScreenControls* onScreenControls;
|
||||||
|
|
||||||
BOOL isInputingText;
|
BOOL isInputingText;
|
||||||
BOOL isDragging;
|
|
||||||
NSTimer* dragTimer;
|
|
||||||
|
|
||||||
float streamAspectRatio;
|
float streamAspectRatio;
|
||||||
|
|
||||||
@@ -38,10 +32,7 @@ static const int REFERENCE_HEIGHT = 720;
|
|||||||
double accumulatedMouseDeltaX;
|
double accumulatedMouseDeltaX;
|
||||||
double accumulatedMouseDeltaY;
|
double accumulatedMouseDeltaY;
|
||||||
|
|
||||||
#if TARGET_OS_TV
|
RelativeTouchHandler* touchHandler;
|
||||||
UIGestureRecognizer* remotePressRecognizer;
|
|
||||||
UIGestureRecognizer* remoteLongPressRecognizer;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
id<UserInteractionDelegate> interactionDelegate;
|
id<UserInteractionDelegate> interactionDelegate;
|
||||||
NSTimer* interactionTimer;
|
NSTimer* interactionTimer;
|
||||||
@@ -57,18 +48,11 @@ static const int REFERENCE_HEIGHT = 720;
|
|||||||
self->interactionDelegate = interactionDelegate;
|
self->interactionDelegate = interactionDelegate;
|
||||||
self->streamAspectRatio = (float)streamConfig.width / (float)streamConfig.height;
|
self->streamAspectRatio = (float)streamConfig.width / (float)streamConfig.height;
|
||||||
|
|
||||||
|
self->touchHandler = [[RelativeTouchHandler alloc] initWithView:self];
|
||||||
|
|
||||||
TemporarySettings* settings = [[[DataManager alloc] init] getSettings];
|
TemporarySettings* settings = [[[DataManager alloc] init] getSettings];
|
||||||
|
|
||||||
#if TARGET_OS_TV
|
#if !TARGET_OS_TV
|
||||||
remotePressRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(remoteButtonPressed:)];
|
|
||||||
remotePressRecognizer.allowedPressTypes = @[@(UIPressTypeSelect)];
|
|
||||||
|
|
||||||
remoteLongPressRecognizer = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(remoteButtonLongPressed:)];
|
|
||||||
remoteLongPressRecognizer.allowedPressTypes = @[@(UIPressTypeSelect)];
|
|
||||||
|
|
||||||
[self addGestureRecognizer:remotePressRecognizer];
|
|
||||||
[self addGestureRecognizer:remoteLongPressRecognizer];
|
|
||||||
#else
|
|
||||||
onScreenControls = [[OnScreenControls alloc] initWithView:self controllerSup:controllerSupport swipeDelegate:swipeDelegate];
|
onScreenControls = [[OnScreenControls alloc] initWithView:self controllerSup:controllerSupport swipeDelegate:swipeDelegate];
|
||||||
OnScreenControlsLevel level = (OnScreenControlsLevel)[settings.onscreenControls integerValue];
|
OnScreenControlsLevel level = (OnScreenControlsLevel)[settings.onscreenControls integerValue];
|
||||||
if (level == OnScreenControlsLevelAuto) {
|
if (level == OnScreenControlsLevelAuto) {
|
||||||
@@ -149,11 +133,6 @@ static const int REFERENCE_HEIGHT = 720;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (BOOL)isConfirmedMove:(CGPoint)currentPoint from:(CGPoint)originalPoint {
|
|
||||||
// Movements of greater than 5 pixels are considered confirmed
|
|
||||||
return hypotf(originalPoint.x - currentPoint.x, originalPoint.y - currentPoint.y) >= 5;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
|
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||||
if ([self handleMouseButtonEvent:BUTTON_ACTION_PRESS
|
if ([self handleMouseButtonEvent:BUTTON_ACTION_PRESS
|
||||||
forTouches:touches
|
forTouches:touches
|
||||||
@@ -168,23 +147,28 @@ static const int REFERENCE_HEIGHT = 720;
|
|||||||
[self startInteractionTimer];
|
[self startInteractionTimer];
|
||||||
|
|
||||||
if (![onScreenControls handleTouchDownEvent:touches]) {
|
if (![onScreenControls handleTouchDownEvent:touches]) {
|
||||||
UITouch *touch = [[event allTouches] anyObject];
|
if ([[event allTouches] count] == 3) {
|
||||||
originalLocation = touchLocation = [touch locationInView:self];
|
if (isInputingText) {
|
||||||
touchMoved = false;
|
Log(LOG_D, @"Closing the keyboard");
|
||||||
if ([[event allTouches] count] == 1 && !isDragging) {
|
[_keyInputField resignFirstResponder];
|
||||||
dragTimer = [NSTimer scheduledTimerWithTimeInterval:0.650
|
isInputingText = false;
|
||||||
target:self
|
} else {
|
||||||
selector:@selector(onDragStart:)
|
Log(LOG_D, @"Opening the keyboard");
|
||||||
userInfo:nil
|
// Prepare the textbox used to capture keyboard events.
|
||||||
repeats:NO];
|
_keyInputField.delegate = self;
|
||||||
|
_keyInputField.text = @"0";
|
||||||
|
[_keyInputField becomeFirstResponder];
|
||||||
|
[_keyInputField addTarget:self action:@selector(onKeyboardPressed:) forControlEvents:UIControlEventEditingChanged];
|
||||||
|
|
||||||
|
// Undo causes issues for our state management, so turn it off
|
||||||
|
[_keyInputField.undoManager disableUndoRegistration];
|
||||||
|
|
||||||
|
isInputingText = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
[touchHandler touchesBegan:touches withEvent:event];
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)onDragStart:(NSTimer*)timer {
|
|
||||||
if (!touchMoved && !isDragging){
|
|
||||||
isDragging = true;
|
|
||||||
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -276,46 +260,8 @@ static const int REFERENCE_HEIGHT = 720;
|
|||||||
hasUserInteracted = YES;
|
hasUserInteracted = YES;
|
||||||
|
|
||||||
if (![onScreenControls handleTouchMovedEvent:touches]) {
|
if (![onScreenControls handleTouchMovedEvent:touches]) {
|
||||||
if ([[event allTouches] count] == 1) {
|
[touchHandler touchesMoved:touches withEvent:event];
|
||||||
UITouch *touch = [[event allTouches] anyObject];
|
|
||||||
CGPoint currentLocation = [touch locationInView:self];
|
|
||||||
|
|
||||||
if (touchLocation.x != currentLocation.x ||
|
|
||||||
touchLocation.y != currentLocation.y)
|
|
||||||
{
|
|
||||||
int deltaX = (currentLocation.x - touchLocation.x) * (REFERENCE_WIDTH / self.bounds.size.width);
|
|
||||||
int deltaY = (currentLocation.y - touchLocation.y) * (REFERENCE_HEIGHT / self.bounds.size.height);
|
|
||||||
|
|
||||||
if (deltaX != 0 || deltaY != 0) {
|
|
||||||
LiSendMouseMoveEvent(deltaX, deltaY);
|
|
||||||
touchLocation = currentLocation;
|
|
||||||
|
|
||||||
// If we've moved far enough to confirm this wasn't just human/machine error,
|
|
||||||
// mark it as such.
|
|
||||||
if ([self isConfirmedMove:touchLocation from:originalLocation]) {
|
|
||||||
touchMoved = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if ([[event allTouches] count] == 2) {
|
|
||||||
CGPoint firstLocation = [[[[event allTouches] allObjects] objectAtIndex:0] locationInView:self];
|
|
||||||
CGPoint secondLocation = [[[[event allTouches] allObjects] objectAtIndex:1] locationInView:self];
|
|
||||||
|
|
||||||
CGPoint avgLocation = CGPointMake((firstLocation.x + secondLocation.x) / 2, (firstLocation.y + secondLocation.y) / 2);
|
|
||||||
if (touchLocation.y != avgLocation.y) {
|
|
||||||
LiSendScrollEvent(avgLocation.y - touchLocation.y);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we've moved far enough to confirm this wasn't just human/machine error,
|
|
||||||
// mark it as such.
|
|
||||||
if ([self isConfirmedMove:firstLocation from:originalLocation]) {
|
|
||||||
touchMoved = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
touchLocation = avgLocation;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
|
- (void)pressesBegan:(NSSet<UIPress *> *)presses withEvent:(UIPressesEvent *)event {
|
||||||
@@ -369,108 +315,18 @@ static const int REFERENCE_HEIGHT = 720;
|
|||||||
hasUserInteracted = YES;
|
hasUserInteracted = YES;
|
||||||
|
|
||||||
if (![onScreenControls handleTouchUpEvent:touches]) {
|
if (![onScreenControls handleTouchUpEvent:touches]) {
|
||||||
[dragTimer invalidate];
|
[touchHandler touchesEnded:touches withEvent:event];
|
||||||
dragTimer = nil;
|
|
||||||
if (isDragging) {
|
|
||||||
isDragging = false;
|
|
||||||
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
|
||||||
} else if (!touchMoved) {
|
|
||||||
if ([[event allTouches] count] == 3) {
|
|
||||||
if (isInputingText) {
|
|
||||||
Log(LOG_D, @"Closing the keyboard");
|
|
||||||
[_keyInputField resignFirstResponder];
|
|
||||||
isInputingText = false;
|
|
||||||
} else {
|
|
||||||
Log(LOG_D, @"Opening the keyboard");
|
|
||||||
// Prepare the textbox used to capture keyboard events.
|
|
||||||
_keyInputField.delegate = self;
|
|
||||||
_keyInputField.text = @"0";
|
|
||||||
[_keyInputField becomeFirstResponder];
|
|
||||||
[_keyInputField addTarget:self action:@selector(onKeyboardPressed:) forControlEvents:UIControlEventEditingChanged];
|
|
||||||
|
|
||||||
// Undo causes issues for our state management, so turn it off
|
|
||||||
[_keyInputField.undoManager disableUndoRegistration];
|
|
||||||
|
|
||||||
isInputingText = true;
|
|
||||||
}
|
|
||||||
} else if ([[event allTouches] count] == 2) {
|
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
|
||||||
Log(LOG_D, @"Sending right mouse button press");
|
|
||||||
|
|
||||||
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_RIGHT);
|
|
||||||
|
|
||||||
// Wait 100 ms to simulate a real button press
|
|
||||||
usleep(100 * 1000);
|
|
||||||
|
|
||||||
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_RIGHT);
|
|
||||||
});
|
|
||||||
} else if ([[event allTouches] count] == 1) {
|
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
|
||||||
if (!self->isDragging){
|
|
||||||
Log(LOG_D, @"Sending left mouse button press");
|
|
||||||
|
|
||||||
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
|
|
||||||
|
|
||||||
// Wait 100 ms to simulate a real button press
|
|
||||||
usleep(100 * 1000);
|
|
||||||
}
|
|
||||||
self->isDragging = false;
|
|
||||||
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// We we're moving from 2+ touches to 1. Synchronize the current position
|
|
||||||
// of the active finger so we don't jump unexpectedly on the next touchesMoved
|
|
||||||
// callback when finger 1 switches on us.
|
|
||||||
if ([[event allTouches] count] - [touches count] == 1) {
|
|
||||||
NSMutableSet *activeSet = [[NSMutableSet alloc] initWithCapacity:[[event allTouches] count]];
|
|
||||||
[activeSet unionSet:[event allTouches]];
|
|
||||||
[activeSet minusSet:touches];
|
|
||||||
touchLocation = [[activeSet anyObject] locationInView:self];
|
|
||||||
|
|
||||||
// Mark this touch as moved so we don't send a left mouse click if the user
|
|
||||||
// right clicks without moving their other finger.
|
|
||||||
touchMoved = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
|
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||||
[dragTimer invalidate];
|
[touchHandler touchesCancelled:touches withEvent:event];
|
||||||
dragTimer = nil;
|
|
||||||
if (isDragging) {
|
|
||||||
isDragging = false;
|
|
||||||
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
|
||||||
}
|
|
||||||
[self handleMouseButtonEvent:BUTTON_ACTION_RELEASE
|
[self handleMouseButtonEvent:BUTTON_ACTION_RELEASE
|
||||||
forTouches:touches
|
forTouches:touches
|
||||||
withEvent:event];
|
withEvent:event];
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_OS_TV
|
#if !TARGET_OS_TV
|
||||||
- (void)remoteButtonPressed:(id)sender {
|
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
|
|
||||||
Log(LOG_D, @"Sending left mouse button press");
|
|
||||||
|
|
||||||
// Mark this as touchMoved to avoid a duplicate press on touch up
|
|
||||||
self->touchMoved = true;
|
|
||||||
|
|
||||||
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
|
|
||||||
|
|
||||||
// Wait 100 ms to simulate a real button press
|
|
||||||
usleep(100 * 1000);
|
|
||||||
|
|
||||||
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
- (void)remoteButtonLongPressed:(id)sender {
|
|
||||||
Log(LOG_D, @"Holding left mouse button");
|
|
||||||
|
|
||||||
isDragging = true;
|
|
||||||
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
- (void) updateCursorLocation:(CGPoint)location {
|
- (void) updateCursorLocation:(CGPoint)location {
|
||||||
// These are now relative to the StreamView, however we need to scale them
|
// These are now relative to the StreamView, however we need to scale them
|
||||||
// further to make them relative to the actual video portion.
|
// further to make them relative to the actual video portion.
|
||||||
|
|||||||
@@ -8,6 +8,8 @@
|
|||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
693B3A9B218638CD00982F7B /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 693B3A9A218638CD00982F7B /* Settings.bundle */; };
|
693B3A9B218638CD00982F7B /* Settings.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 693B3A9A218638CD00982F7B /* Settings.bundle */; };
|
||||||
|
9819CC14254F107A008A7C8E /* RelativeTouchHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 9819CC13254F107A008A7C8E /* RelativeTouchHandler.m */; };
|
||||||
|
9819CC1D254F1730008A7C8E /* RelativeTouchHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = 9819CC13254F107A008A7C8E /* RelativeTouchHandler.m */; };
|
||||||
9827E7A32514366900F25707 /* HapticContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 9827E7A22514366900F25707 /* HapticContext.m */; };
|
9827E7A32514366900F25707 /* HapticContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 9827E7A22514366900F25707 /* HapticContext.m */; };
|
||||||
9827E7A42514366900F25707 /* HapticContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 9827E7A22514366900F25707 /* HapticContext.m */; };
|
9827E7A42514366900F25707 /* HapticContext.m in Sources */ = {isa = PBXBuildFile; fileRef = 9827E7A22514366900F25707 /* HapticContext.m */; };
|
||||||
9832D1361BBCD5C50036EF48 /* TemporaryApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 9832D1351BBCD5C50036EF48 /* TemporaryApp.m */; };
|
9832D1361BBCD5C50036EF48 /* TemporaryApp.m in Sources */ = {isa = PBXBuildFile; fileRef = 9832D1351BBCD5C50036EF48 /* TemporaryApp.m */; };
|
||||||
@@ -159,6 +161,8 @@
|
|||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
693B3A9A218638CD00982F7B /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; };
|
693B3A9A218638CD00982F7B /* Settings.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; path = Settings.bundle; sourceTree = "<group>"; };
|
||||||
98132E8C20BC9A62007A053F /* Moonlight v1.1.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Moonlight v1.1.xcdatamodel"; sourceTree = "<group>"; };
|
98132E8C20BC9A62007A053F /* Moonlight v1.1.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "Moonlight v1.1.xcdatamodel"; sourceTree = "<group>"; };
|
||||||
|
9819CC12254F107A008A7C8E /* RelativeTouchHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = RelativeTouchHandler.h; sourceTree = "<group>"; };
|
||||||
|
9819CC13254F107A008A7C8E /* RelativeTouchHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = RelativeTouchHandler.m; sourceTree = "<group>"; };
|
||||||
9827E7A22514366900F25707 /* HapticContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HapticContext.m; sourceTree = "<group>"; };
|
9827E7A22514366900F25707 /* HapticContext.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HapticContext.m; sourceTree = "<group>"; };
|
||||||
9827E7A7251436EA00F25707 /* HapticContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HapticContext.h; sourceTree = "<group>"; };
|
9827E7A7251436EA00F25707 /* HapticContext.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HapticContext.h; sourceTree = "<group>"; };
|
||||||
9832D1341BBCD5C50036EF48 /* TemporaryApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TemporaryApp.h; path = Database/TemporaryApp.h; sourceTree = "<group>"; };
|
9832D1341BBCD5C50036EF48 /* TemporaryApp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = TemporaryApp.h; path = Database/TemporaryApp.h; sourceTree = "<group>"; };
|
||||||
@@ -539,6 +543,8 @@
|
|||||||
9897B6A32212610800966419 /* Controller.h */,
|
9897B6A32212610800966419 /* Controller.h */,
|
||||||
9827E7A22514366900F25707 /* HapticContext.m */,
|
9827E7A22514366900F25707 /* HapticContext.m */,
|
||||||
9827E7A7251436EA00F25707 /* HapticContext.h */,
|
9827E7A7251436EA00F25707 /* HapticContext.h */,
|
||||||
|
9819CC12254F107A008A7C8E /* RelativeTouchHandler.h */,
|
||||||
|
9819CC13254F107A008A7C8E /* RelativeTouchHandler.m */,
|
||||||
);
|
);
|
||||||
path = Input;
|
path = Input;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -988,6 +994,7 @@
|
|||||||
FB1A67B7213245D500507771 /* ServerInfoResponse.m in Sources */,
|
FB1A67B7213245D500507771 /* ServerInfoResponse.m in Sources */,
|
||||||
FB1A67B9213245D500507771 /* AppAssetResponse.m in Sources */,
|
FB1A67B9213245D500507771 /* AppAssetResponse.m in Sources */,
|
||||||
FB1A67BB213245D500507771 /* AppListResponse.m in Sources */,
|
FB1A67BB213245D500507771 /* AppListResponse.m in Sources */,
|
||||||
|
9819CC1D254F1730008A7C8E /* RelativeTouchHandler.m in Sources */,
|
||||||
FB1A67AB213245C500507771 /* CryptoManager.m in Sources */,
|
FB1A67AB213245C500507771 /* CryptoManager.m in Sources */,
|
||||||
FB1A67AF213245C500507771 /* IdManager.m in Sources */,
|
FB1A67AF213245C500507771 /* IdManager.m in Sources */,
|
||||||
FB1A67A3213245BD00507771 /* Connection.m in Sources */,
|
FB1A67A3213245BD00507771 /* Connection.m in Sources */,
|
||||||
@@ -1003,6 +1010,7 @@
|
|||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
FB290D0719B2C406004C83CF /* Limelight.xcdatamodeld in Sources */,
|
FB290D0719B2C406004C83CF /* Limelight.xcdatamodeld in Sources */,
|
||||||
|
9819CC14254F107A008A7C8E /* RelativeTouchHandler.m in Sources */,
|
||||||
FB1A674D2131E65900507771 /* KeyboardSupport.m in Sources */,
|
FB1A674D2131E65900507771 /* KeyboardSupport.m in Sources */,
|
||||||
FB89463219F646E200339C8A /* VideoDecoderRenderer.m in Sources */,
|
FB89463219F646E200339C8A /* VideoDecoderRenderer.m in Sources */,
|
||||||
FB290D0419B2C406004C83CF /* AppDelegate.m in Sources */,
|
FB290D0419B2C406004C83CF /* AppDelegate.m in Sources */,
|
||||||
|
|||||||
Reference in New Issue
Block a user