mirror of
https://github.com/moonlight-stream/moonlight-ios.git
synced 2026-06-17 14:11:35 +00:00
@@ -23,7 +23,11 @@
|
|||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
#if TARGET_OS_TV
|
||||||
@interface StreamView : OSView <X1KitMouseDelegate>
|
@interface StreamView : OSView <X1KitMouseDelegate>
|
||||||
|
#else
|
||||||
|
@interface StreamView : OSView <X1KitMouseDelegate, UIPointerInteractionDelegate>
|
||||||
|
#endif
|
||||||
|
|
||||||
@property (nonatomic, retain) IBOutlet UITextField* keyInputField;
|
@property (nonatomic, retain) IBOutlet UITextField* keyInputField;
|
||||||
|
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
float yDeltaFactor;
|
float yDeltaFactor;
|
||||||
float screenFactor;
|
float screenFactor;
|
||||||
|
|
||||||
|
NSInteger lastMouseButtonMask;
|
||||||
double mouseX;
|
double mouseX;
|
||||||
double mouseY;
|
double mouseY;
|
||||||
|
|
||||||
@@ -81,6 +82,15 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
Log(LOG_I, @"Setting manual on-screen controls level: %d", (int)level);
|
Log(LOG_I, @"Setting manual on-screen controls level: %d", (int)level);
|
||||||
[onScreenControls setLevel:level];
|
[onScreenControls setLevel:level];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (@available(iOS 13.4, *)) {
|
||||||
|
[self addInteraction:[[UIPointerInteraction alloc] initWithDelegate:self]];
|
||||||
|
|
||||||
|
UIPanGestureRecognizer *mouseWheelRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(mouseWheelMoved:)];
|
||||||
|
mouseWheelRecognizer.allowedScrollTypesMask = UIScrollTypeMaskDiscrete;
|
||||||
|
mouseWheelRecognizer.allowedTouchTypes = @[@(UITouchTypeIndirectPointer)];
|
||||||
|
[self addGestureRecognizer:mouseWheelRecognizer];
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
textFieldDelegate = [[TextFieldKeyboardDelegate alloc] initWithTextField:_keyInputField];
|
textFieldDelegate = [[TextFieldKeyboardDelegate alloc] initWithTextField:_keyInputField];
|
||||||
@@ -147,6 +157,13 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
|
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||||
|
if ([self handleMouseButtonEvent:BUTTON_ACTION_PRESS
|
||||||
|
forTouches:touches
|
||||||
|
withEvent:event]) {
|
||||||
|
// If it's a mouse event, we're done
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Log(LOG_D, @"Touch down");
|
Log(LOG_D, @"Touch down");
|
||||||
|
|
||||||
// Notify of user interaction and start expiration timer
|
// Notify of user interaction and start expiration timer
|
||||||
@@ -173,7 +190,57 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (BOOL)handleMouseButtonEvent:(int)buttonAction forTouches:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
if (@available(iOS 13.4, *)) {
|
||||||
|
UITouch* touch = [touches anyObject];
|
||||||
|
if (touch.type == UITouchTypeIndirectPointer) {
|
||||||
|
UIEventButtonMask changedButtons = lastMouseButtonMask ^ event.buttonMask;
|
||||||
|
|
||||||
|
for (int i = BUTTON_LEFT; i <= BUTTON_X2; i++) {
|
||||||
|
UIEventButtonMask buttonFlag;
|
||||||
|
|
||||||
|
switch (i) {
|
||||||
|
// Right and Middle are reversed from what iOS uses
|
||||||
|
case BUTTON_RIGHT:
|
||||||
|
buttonFlag = UIEventButtonMaskForButtonNumber(2);
|
||||||
|
break;
|
||||||
|
case BUTTON_MIDDLE:
|
||||||
|
buttonFlag = UIEventButtonMaskForButtonNumber(3);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
buttonFlag = UIEventButtonMaskForButtonNumber(i);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (changedButtons & buttonFlag) {
|
||||||
|
LiSendMouseButtonEvent(buttonAction, i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lastMouseButtonMask = event.buttonMask;
|
||||||
|
return YES;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
|
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||||
|
#if !TARGET_OS_TV
|
||||||
|
if (@available(iOS 13.4, *)) {
|
||||||
|
UITouch *touch = [touches anyObject];
|
||||||
|
if (touch.type == UITouchTypeIndirectPointer) {
|
||||||
|
// Ignore move events from mice. These only happen while the
|
||||||
|
// mouse button is pressed and conflict with our positional
|
||||||
|
// mouse input handling.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
hasUserInteracted = YES;
|
hasUserInteracted = YES;
|
||||||
|
|
||||||
if (![onScreenControls handleTouchMovedEvent:touches]) {
|
if (![onScreenControls handleTouchMovedEvent:touches]) {
|
||||||
@@ -261,6 +328,13 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
|
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
|
||||||
|
if ([self handleMouseButtonEvent:BUTTON_ACTION_RELEASE
|
||||||
|
forTouches:touches
|
||||||
|
withEvent:event]) {
|
||||||
|
// If it's a mouse event, we're done
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
Log(LOG_D, @"Touch up");
|
Log(LOG_D, @"Touch up");
|
||||||
|
|
||||||
hasUserInteracted = YES;
|
hasUserInteracted = YES;
|
||||||
@@ -338,6 +412,9 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
isDragging = false;
|
isDragging = false;
|
||||||
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
LiSendMouseButtonEvent(BUTTON_ACTION_RELEASE, BUTTON_LEFT);
|
||||||
}
|
}
|
||||||
|
[self handleMouseButtonEvent:BUTTON_ACTION_RELEASE
|
||||||
|
forTouches:touches
|
||||||
|
withEvent:event];
|
||||||
}
|
}
|
||||||
|
|
||||||
#if TARGET_OS_TV
|
#if TARGET_OS_TV
|
||||||
@@ -362,6 +439,42 @@ static const double X1_MOUSE_SPEED_DIVISOR = 2.5;
|
|||||||
isDragging = true;
|
isDragging = true;
|
||||||
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
|
LiSendMouseButtonEvent(BUTTON_ACTION_PRESS, BUTTON_LEFT);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
- (UIPointerRegion *)pointerInteraction:(UIPointerInteraction *)interaction
|
||||||
|
regionForRequest:(UIPointerRegionRequest *)request
|
||||||
|
defaultRegion:(UIPointerRegion *)defaultRegion API_AVAILABLE(ios(13.4)) {
|
||||||
|
// Send coordinates normalized to our view
|
||||||
|
LiSendMousePositionEvent(request.location.x - self.bounds.origin.x,
|
||||||
|
request.location.y - self.bounds.origin.y,
|
||||||
|
self.bounds.size.width, self.bounds.size.height);
|
||||||
|
|
||||||
|
// The pointer interaction should cover the entire view
|
||||||
|
return [UIPointerRegion regionWithRect:self.bounds identifier:nil];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIPointerStyle *)pointerInteraction:(UIPointerInteraction *)interaction styleForRegion:(UIPointerRegion *)region API_AVAILABLE(ios(13.4)) {
|
||||||
|
// Always hide the mouse cursor over our stream view
|
||||||
|
return [UIPointerStyle hiddenPointerStyle];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)mouseWheelMoved:(UIPanGestureRecognizer *)gesture {
|
||||||
|
switch (gesture.state) {
|
||||||
|
case UIGestureRecognizerStateBegan:
|
||||||
|
case UIGestureRecognizerStateChanged:
|
||||||
|
case UIGestureRecognizerStateEnded:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
// Ignore recognition failure and other states
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CGPoint velocity = [gesture velocityInView:self];
|
||||||
|
if ((short)velocity.y != 0) {
|
||||||
|
LiSendHighResScrollEvent((short)velocity.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
|
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
|
||||||
|
|||||||
@@ -2,10 +2,6 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>NSBluetoothPeripheralUsageDescription</key>
|
|
||||||
<string>Bluetooth access allows Moonlight to connect to Citrix X1 mice.</string>
|
|
||||||
<key>NSBluetoothAlwaysUsageDescription</key>
|
|
||||||
<string>Bluetooth access allows Moonlight to connect to Citrix X1 mice.</string>
|
|
||||||
<key>CADisableMinimumFrameDuration</key>
|
<key>CADisableMinimumFrameDuration</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
@@ -50,6 +46,12 @@
|
|||||||
<key>NSAllowsArbitraryLoads</key>
|
<key>NSAllowsArbitraryLoads</key>
|
||||||
<true/>
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
|
<key>NSBluetoothAlwaysUsageDescription</key>
|
||||||
|
<string>Bluetooth access allows Moonlight to connect to Citrix X1 mice.</string>
|
||||||
|
<key>NSBluetoothPeripheralUsageDescription</key>
|
||||||
|
<string>Bluetooth access allows Moonlight to connect to Citrix X1 mice.</string>
|
||||||
|
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||||
|
<true/>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>UILaunchStoryboardName</key>
|
||||||
<string>Launch Screen</string>
|
<string>Launch Screen</string>
|
||||||
<key>UIMainStoryboardFile</key>
|
<key>UIMainStoryboardFile</key>
|
||||||
|
|||||||
Reference in New Issue
Block a user