Skip to content

Commit

Permalink
Merge pull request #195 from utmapp/feature/touchscreen-input
Browse files Browse the repository at this point in the history
Support touchscreen input
  • Loading branch information
osy authored Mar 30, 2020
2 parents 2760f2f + 8fd9396 commit 19145d1
Show file tree
Hide file tree
Showing 21 changed files with 388 additions and 180 deletions.
22 changes: 15 additions & 7 deletions CocoaSpice/CSDisplayMetal.m
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,14 @@
(int)display.monitorID, \
## __VA_ARGS__)

@interface CSDisplayMetal ()

@property (nonatomic, readwrite, nullable) SpiceSession *session;
@property (nonatomic, readwrite, assign) NSInteger channelID;
@property (nonatomic, readwrite, assign) NSInteger monitorID;

@end

@implementation CSDisplayMetal {
SpiceDisplayChannel *_display;

Expand Down Expand Up @@ -275,9 +283,9 @@ - (id)initWithSession:(nonnull SpiceSession *)session channelID:(NSInteger)chann
GList *list;
GList *it;

_channelID = channelID;
_monitorID = monitorID;
_session = session;
self.channelID = channelID;
self.monitorID = monitorID;
self.session = session;
_sigsconnected = NO;
g_object_ref(session);

Expand Down Expand Up @@ -306,10 +314,10 @@ - (void)dealloc {
cs_channel_destroy(self.session, SPICE_CHANNEL(_display), (__bridge void *)self);
}
NSLog(@"%s:%d", __FUNCTION__, __LINE__);
g_signal_handlers_disconnect_by_func(_session, G_CALLBACK(cs_channel_new), GLIB_OBJC_RELEASE(self));
g_signal_handlers_disconnect_by_func(_session, G_CALLBACK(cs_channel_destroy), GLIB_OBJC_RELEASE(self));
g_object_unref(_session);
_session = NULL;
g_signal_handlers_disconnect_by_func(self.session, G_CALLBACK(cs_channel_new), GLIB_OBJC_RELEASE(self));
g_signal_handlers_disconnect_by_func(self.session, G_CALLBACK(cs_channel_destroy), GLIB_OBJC_RELEASE(self));
g_object_unref(self.session);
self.session = NULL;
}

- (void)updateVisibleAreaWithRect:(CGRect)rect {
Expand Down
2 changes: 2 additions & 0 deletions CocoaSpice/CSInput.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, assign) BOOL disableInputs;
@property (nonatomic, readonly) CGSize cursorSize;
@property (nonatomic, assign) CGSize displaySize;
@property (nonatomic, assign) BOOL inhibitCursor;

- (void)sendKey:(SendKeyType)type code:(int)scancode;
- (void)sendPause:(SendKeyType)type;
Expand All @@ -59,6 +60,7 @@ NS_ASSUME_NONNULL_BEGIN
- (void)sendMouseScroll:(SendScrollType)type button:(SendButtonType)button dy:(CGFloat)dy;
- (void)sendMouseButton:(SendButtonType)button pressed:(BOOL)pressed point:(CGPoint)point;
- (void)requestMouseMode:(BOOL)server;
- (void)forceCursorPosition:(CGPoint)pos;

- (id)initWithSession:(nonnull SpiceSession *)session channelID:(NSInteger)channelID monitorID:(NSInteger)monitorID;

Expand Down
53 changes: 33 additions & 20 deletions CocoaSpice/CSInput.m
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,17 @@
#import <spice/protocol.h>
#import "UTMShaderTypes.h"

@interface CSInput ()

@property (nonatomic, readwrite, nullable) SpiceSession *session;
@property (nonatomic, readwrite, assign) NSInteger channelID;
@property (nonatomic, readwrite, assign) NSInteger monitorID;
@property (nonatomic, readwrite, assign) BOOL serverModeCursor;
@property (nonatomic, readwrite, assign) BOOL hasCursor;
@property (nonatomic, readwrite) CGSize cursorSize;

@end

@implementation CSInput {
SpiceMainChannel *_main;
SpiceCursorChannel *_cursor;
Expand All @@ -37,7 +48,6 @@ @implementation CSInput {
id<MTLBuffer> _vertices;
NSUInteger _numVertices;
dispatch_semaphore_t _drawLock;
CGSize _cursorSize;
BOOL _cursorHidden;
}

Expand All @@ -51,7 +61,7 @@ static void cs_update_mouse_mode(SpiceChannel *channel, gpointer data)
g_object_get(channel, "mouse-mode", &mouse_mode, NULL);
DISPLAY_DEBUG(self, "mouse mode %u", mouse_mode);

self->_serverModeCursor = (mouse_mode == SPICE_MOUSE_MODE_SERVER);
self.serverModeCursor = (mouse_mode == SPICE_MOUSE_MODE_SERVER);

if (self.serverModeCursor) {
self->_mouse_guest.x = -1;
Expand Down Expand Up @@ -83,7 +93,7 @@ static void cs_cursor_set(SpiceCursorChannel *channel,

CGPoint hotspot = CGPointMake(cursor_shape->hot_spot_x, cursor_shape->hot_spot_y);
CGSize newSize = CGSizeMake(cursor_shape->width, cursor_shape->height);
if (!CGSizeEqualToSize(newSize, self->_cursorSize)) {
if (!CGSizeEqualToSize(newSize, self.cursorSize)) {
[self rebuildTexture:newSize center:hotspot];
}
[self drawCursor:cursor_shape->data];
Expand Down Expand Up @@ -141,7 +151,7 @@ static void cs_channel_new(SpiceSession *s, SpiceChannel *channel, gpointer data

if (SPICE_IS_CURSOR_CHANNEL(channel)) {
gpointer cursor_shape;
if (chid != self->_channelID)
if (chid != self.channelID)
return;
self->_cursor = SPICE_CURSOR_CHANNEL(channel);
g_signal_connect(channel, "notify::cursor",
Expand Down Expand Up @@ -186,7 +196,7 @@ static void cs_channel_destroy(SpiceSession *s, SpiceChannel *channel, gpointer
}

if (SPICE_IS_CURSOR_CHANNEL(channel)) {
if (chid != self->_channelID)
if (chid != self.channelID)
return;
self->_cursor = NULL;
g_signal_handlers_disconnect_by_func(channel, G_CALLBACK(cs_cursor_set), GLIB_OBJC_RELEASE(self));
Expand Down Expand Up @@ -393,6 +403,10 @@ - (void)requestMouseMode:(BOOL)server {
}
}

- (void)forceCursorPosition:(CGPoint)pos {
_mouse_guest = pos;
}

#pragma mark - Initializers

- (id)init {
Expand All @@ -411,9 +425,9 @@ - (id)initWithSession:(nonnull SpiceSession *)session channelID:(NSInteger)chann
GList *list;
GList *it;

_channelID = channelID;
_monitorID = monitorID;
_session = session;
self.channelID = channelID;
self.monitorID = monitorID;
self.session = session;
g_object_ref(session);

NSLog(@"%s:%d", __FUNCTION__, __LINE__);
Expand All @@ -440,15 +454,14 @@ - (void)dealloc {
cs_channel_destroy(self.session, SPICE_CHANNEL(_main), (__bridge void *)self);
}
NSLog(@"%s:%d", __FUNCTION__, __LINE__);
g_signal_handlers_disconnect_by_func(_session, G_CALLBACK(cs_channel_new), GLIB_OBJC_RELEASE(self));
g_signal_handlers_disconnect_by_func(_session, G_CALLBACK(cs_channel_destroy), GLIB_OBJC_RELEASE(self));
g_object_unref(_session);
_session = NULL;
g_signal_handlers_disconnect_by_func(self.session, G_CALLBACK(cs_channel_new), GLIB_OBJC_RELEASE(self));
g_signal_handlers_disconnect_by_func(self.session, G_CALLBACK(cs_channel_destroy), GLIB_OBJC_RELEASE(self));
g_object_unref(self.session);
self.session = NULL;
}

#pragma mark - Drawing Cursor

@synthesize cursorSize = _cursorSize;
@synthesize device = _device;
@synthesize drawLock = _drawLock;
@synthesize texture = _texture;
Expand Down Expand Up @@ -491,8 +504,8 @@ - (void)rebuildTexture:(CGSize)size center:(CGPoint)hotspot {

// Calculate the number of vertices by dividing the byte length by the size of each vertex
_numVertices = sizeof(quadVertices) / sizeof(UTMVertex);
_cursorSize = size;
_hasCursor = YES;
self.cursorSize = size;
self.hasCursor = YES;
dispatch_semaphore_signal(_drawLock);
}

Expand All @@ -501,27 +514,27 @@ - (void)destroyTexture {
_numVertices = 0;
_vertices = nil;
_texture = nil;
_cursorSize = CGSizeZero;
_hasCursor = NO;
self.cursorSize = CGSizeZero;
self.hasCursor = NO;
dispatch_semaphore_signal(_drawLock);
}

- (void)drawCursor:(const void *)buffer {
const NSInteger pixelSize = 4;
MTLRegion region = {
{ 0, 0 }, // MTLOrigin
{ _cursorSize.width, _cursorSize.height, 1} // MTLSize
{ self.cursorSize.width, self.cursorSize.height, 1} // MTLSize
};
dispatch_semaphore_wait(_drawLock, DISPATCH_TIME_FOREVER);
[_texture replaceRegion:region
mipmapLevel:0
withBytes:buffer
bytesPerRow:_cursorSize.width*pixelSize];
bytesPerRow:self.cursorSize.width*pixelSize];
dispatch_semaphore_signal(_drawLock);
}

- (BOOL)visible {
return self.hasCursor && !_cursorHidden;
return !self.inhibitCursor && self.hasCursor && !_cursorHidden;
}

- (CGPoint)viewportOrigin {
Expand Down
12 changes: 9 additions & 3 deletions CocoaSpice/CSMain.m
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@
#import <pthread.h>
#import "gst_ios_init.h"

@interface CSMain ()

@property (nonatomic, readwrite) BOOL running;

@end

@implementation CSMain {
GMainContext *_main_context;
GMainLoop *_main_loop;
Expand Down Expand Up @@ -100,15 +106,15 @@ - (void)dealloc {

- (void)spiceSetDebug:(BOOL)enabled {
spice_util_set_debug(enabled);
g_log_set_default_handler(logHandler, NULL);
g_log_set_handler(NULL, G_LOG_LEVEL_MASK, logHandler, NULL);
}

- (BOOL)spiceStart {
if (!self.running) {
if (pthread_create(&_spice_thread, NULL, &spice_main_loop, (__bridge_retained void *)self) != 0) {
return NO;
}
_running = YES;
self.running = YES;
}
return YES;
}
Expand All @@ -118,7 +124,7 @@ - (void)spiceStop {
void *status;
g_main_loop_quit(_main_loop);
pthread_join(_spice_thread, &status);
_running = NO;
self.running = NO;
}
}

Expand Down
3 changes: 1 addition & 2 deletions Configuration/UTMConfiguration.h
Original file line number Diff line number Diff line change
Expand Up @@ -67,8 +67,7 @@ NS_ASSUME_NONNULL_BEGIN
@property (nonatomic, assign) BOOL displayZoomScale;
@property (nonatomic, assign) BOOL displayZoomLetterBox;

@property (nonatomic, assign) BOOL inputTouchscreenMode;
@property (nonatomic, assign) BOOL inputDirect;
@property (nonatomic, assign) BOOL inputLegacy;

@property (nonatomic, assign) BOOL networkEnabled;
@property (nonatomic, assign) BOOL networkLocalhostOnly;
Expand Down
23 changes: 11 additions & 12 deletions Configuration/UTMConfiguration.m
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@

const NSString *const kUTMConfigTouchscreenModeKey = @"TouchscreenMode";
const NSString *const kUTMConfigDirectInputKey = @"DirectInput";
const NSString *const kUTMConfigInputLegacyKey = @"InputLegacy";

const NSString *const kUTMConfigNetworkEnabledKey = @"NetworkEnabled";
const NSString *const kUTMConfigLocalhostOnlyKey = @"LocalhostOnly";
Expand Down Expand Up @@ -1362,6 +1363,12 @@ - (void)migrateConfigurationIfNecessary {
[obj removeObjectForKey:kUTMConfigCdromKey];
}
}];
// Migrate input settings
[_rootDict[kUTMConfigInputKey] removeObjectForKey:kUTMConfigTouchscreenModeKey];
[_rootDict[kUTMConfigInputKey] removeObjectForKey:kUTMConfigDirectInputKey];
if (!_rootDict[kUTMConfigInputKey][kUTMConfigInputLegacyKey]) {
self.inputLegacy = NO;
}
}

#pragma mark - Initialization
Expand Down Expand Up @@ -1563,20 +1570,12 @@ - (BOOL)displayZoomLetterBox {
return [_rootDict[kUTMConfigDisplayKey][kUTMConfigZoomLetterboxKey] boolValue];
}

- (void)setInputTouchscreenMode:(BOOL)inputTouchscreenMode {
_rootDict[kUTMConfigInputKey][kUTMConfigTouchscreenModeKey] = @(inputTouchscreenMode);
}

- (BOOL)inputTouchscreenMode {
return [_rootDict[kUTMConfigInputKey][kUTMConfigTouchscreenModeKey] boolValue];
}

- (void)setInputDirect:(BOOL)inputDirect {
_rootDict[kUTMConfigInputKey][kUTMConfigDirectInputKey] = @(inputDirect);
- (void)setInputLegacy:(BOOL)inputDirect {
_rootDict[kUTMConfigInputKey][kUTMConfigInputLegacyKey] = @(inputDirect);
}

- (BOOL)inputDirect {
return [_rootDict[kUTMConfigInputKey][kUTMConfigDirectInputKey] boolValue];
- (BOOL)inputLegacy {
return [_rootDict[kUTMConfigInputKey][kUTMConfigInputLegacyKey] boolValue];
}

- (void)setNetworkEnabled:(BOOL)networkEnabled {
Expand Down
9 changes: 3 additions & 6 deletions ConfigurationViews/VMConfigInputViewController.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,10 @@ NS_ASSUME_NONNULL_BEGIN

@interface VMConfigInputViewController : VMConfigViewController

@property (weak, nonatomic) IBOutlet UITableViewCell *pointerStyleTouchscreenCell;
@property (weak, nonatomic) IBOutlet UITableViewCell *pointerStyleTrackpadCell;
@property (weak, nonatomic) IBOutlet UITableViewCell *inputReceiverDirectCell;
@property (weak, nonatomic) IBOutlet UITableViewCell *inputReceiverServerCell;
@property (weak, nonatomic) IBOutlet UITableViewCell *openSettingsCell;
@property (weak, nonatomic) IBOutlet UISwitch *legacyModeSwitch;

@property (nonatomic, assign) BOOL inputTouchscreenMode;
@property (nonatomic, assign) BOOL inputDirect;
- (IBAction)legacyModeChanged:(UISwitch *)sender;

@end

Expand Down
59 changes: 11 additions & 48 deletions ConfigurationViews/VMConfigInputViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -23,63 +23,26 @@ @interface VMConfigInputViewController ()

@implementation VMConfigInputViewController

- (void)viewDidLoad {
[super viewDidLoad];
// FIXME: remove this warning
[self showUnimplementedAlert];
}

- (void)refreshViewFromConfiguration {
[super refreshViewFromConfiguration];
self.inputTouchscreenMode = self.configuration.inputTouchscreenMode;
self.inputDirect = self.configuration.inputDirect;
self.legacyModeSwitch.on = self.configuration.inputLegacy;
}

#pragma mark - Properties
#pragma mark - Table delegate

- (void)setInputTouchscreenMode:(BOOL)inputTouchscreenMode {
_inputTouchscreenMode = inputTouchscreenMode;
self.configuration.inputTouchscreenMode = inputTouchscreenMode;
if (inputTouchscreenMode) {
[self.pointerStyleTouchscreenCell setAccessoryType:UITableViewCellAccessoryCheckmark];
[self.pointerStyleTrackpadCell setAccessoryType:UITableViewCellAccessoryNone];
[self.pointerStyleTouchscreenCell setSelected:NO animated:YES];
} else {
[self.pointerStyleTouchscreenCell setAccessoryType:UITableViewCellAccessoryNone];
[self.pointerStyleTrackpadCell setAccessoryType:UITableViewCellAccessoryCheckmark];
[self.pointerStyleTrackpadCell setSelected:NO animated:YES];
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if ([tableView cellForRowAtIndexPath:indexPath] == self.openSettingsCell) {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]
options:@{}
completionHandler:nil];
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
}

- (void)setInputDirect:(BOOL)inputDirect {
_inputDirect = inputDirect;
self.configuration.inputDirect = inputDirect;
if (inputDirect) {
[self.inputReceiverDirectCell setAccessoryType:UITableViewCellAccessoryCheckmark];
[self.inputReceiverServerCell setAccessoryType:UITableViewCellAccessoryNone];
[self.inputReceiverDirectCell setSelected:NO animated:YES];
} else {
[self.inputReceiverDirectCell setAccessoryType:UITableViewCellAccessoryNone];
[self.inputReceiverServerCell setAccessoryType:UITableViewCellAccessoryCheckmark];
[self.inputReceiverServerCell setSelected:NO animated:YES];
}
}
#pragma mark - Event handlers

#pragma mark - Table delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if ([tableView cellForRowAtIndexPath:indexPath] == self.pointerStyleTouchscreenCell) {
self.inputTouchscreenMode = YES;
}
if ([tableView cellForRowAtIndexPath:indexPath] == self.pointerStyleTrackpadCell) {
self.inputTouchscreenMode = NO;
}
if ([tableView cellForRowAtIndexPath:indexPath] == self.inputReceiverDirectCell) {
self.inputDirect = YES;
}
if ([tableView cellForRowAtIndexPath:indexPath] == self.inputReceiverServerCell) {
self.inputDirect = NO;
}
- (IBAction)legacyModeChanged:(UISwitch *)sender {
self.configuration.inputLegacy = sender.on;
}

@end
Loading

0 comments on commit 19145d1

Please sign in to comment.