FreeRDP/server/shadow/Mac/mac_shadow.c
2014-09-13 13:21:34 -04:00

336 lines
8.0 KiB
C

/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/sysinfo.h>
#include <freerdp/codec/color.h>
#include <freerdp/codec/region.h>
#include "../shadow_screen.h"
#include "../shadow_surface.h"
#include "mac_shadow.h"
void mac_shadow_input_synchronize_event(macShadowSubsystem* subsystem, UINT32 flags)
{
}
void mac_shadow_input_keyboard_event(macShadowSubsystem* subsystem, UINT16 flags, UINT16 code)
{
}
void mac_shadow_input_unicode_keyboard_event(macShadowSubsystem* subsystem, UINT16 flags, UINT16 code)
{
}
void mac_shadow_input_mouse_event(macShadowSubsystem* subsystem, UINT16 flags, UINT16 x, UINT16 y)
{
UINT32 scrollX = 0;
UINT32 scrollY = 0;
CGWheelCount wheelCount = 2;
if (flags & PTR_FLAGS_WHEEL)
{
scrollY = flags & WheelRotationMask;
if (flags & PTR_FLAGS_WHEEL_NEGATIVE)
{
scrollY = -(flags & WheelRotationMask) / 392;
}
else
{
scrollY = (flags & WheelRotationMask) / 120;
}
CGEventSourceRef source = CGEventSourceCreate (kCGEventSourceStateHIDSystemState);
CGEventRef scroll = CGEventCreateScrollWheelEvent(source, kCGScrollEventUnitLine,
wheelCount, scrollY, scrollX);
CGEventPost(kCGHIDEventTap, scroll);
CFRelease(scroll);
CFRelease(source);
}
else
{
CGEventSourceRef source = CGEventSourceCreate (kCGEventSourceStateHIDSystemState);
CGEventType mouseType = kCGEventNull;
CGMouseButton mouseButton = kCGMouseButtonLeft;
if (flags & PTR_FLAGS_MOVE)
{
if (subsystem->mouseDownLeft)
mouseType = kCGEventLeftMouseDragged;
else if (subsystem->mouseDownRight)
mouseType = kCGEventRightMouseDragged;
else if (subsystem->mouseDownOther)
mouseType = kCGEventOtherMouseDragged;
else
mouseType = kCGEventMouseMoved;
CGEventRef move = CGEventCreateMouseEvent(source, mouseType, CGPointMake(x, y), mouseButton);
CGEventPost(kCGHIDEventTap, move);
CFRelease(move);
}
if (flags & PTR_FLAGS_BUTTON1)
{
mouseButton = kCGMouseButtonLeft;
if (flags & PTR_FLAGS_DOWN)
{
mouseType = kCGEventLeftMouseDown;
subsystem->mouseDownLeft = TRUE;
}
else
{
mouseType = kCGEventLeftMouseUp;
subsystem->mouseDownLeft = FALSE;
}
}
else if (flags & PTR_FLAGS_BUTTON2)
{
mouseButton = kCGMouseButtonRight;
if (flags & PTR_FLAGS_DOWN)
{
mouseType = kCGEventRightMouseDown;
subsystem->mouseDownRight = TRUE;
}
else
{
mouseType = kCGEventRightMouseUp;
subsystem->mouseDownRight = FALSE;
}
}
else if (flags & PTR_FLAGS_BUTTON3)
{
mouseButton = kCGMouseButtonCenter;
if (flags & PTR_FLAGS_DOWN)
{
mouseType = kCGEventOtherMouseDown;
subsystem->mouseDownOther = TRUE;
}
else
{
mouseType = kCGEventOtherMouseUp;
subsystem->mouseDownOther = FALSE;
}
}
CGEventRef mouseEvent = CGEventCreateMouseEvent(source, mouseType, CGPointMake(x, y), mouseButton);
CGEventPost(kCGHIDEventTap, mouseEvent);
CFRelease(mouseEvent);
CFRelease(source);
}
}
void mac_shadow_input_extended_mouse_event(macShadowSubsystem* subsystem, UINT16 flags, UINT16 x, UINT16 y)
{
}
void* mac_shadow_subsystem_thread(macShadowSubsystem* subsystem)
{
DWORD status;
DWORD nCount;
HANDLE events[32];
HANDLE StopEvent;
StopEvent = subsystem->server->StopEvent;
nCount = 0;
events[nCount++] = StopEvent;
while (1)
{
status = WaitForMultipleObjects(nCount, events, FALSE, INFINITE);
if (WaitForSingleObject(StopEvent, 0) == WAIT_OBJECT_0)
{
break;
}
}
ExitThread(0);
return NULL;
}
int mac_shadow_detect_monitors(macShadowSubsystem* subsystem)
{
size_t wide, high;
MONITOR_DEF* monitor;
CGDirectDisplayID displayId;
displayId = CGMainDisplayID();
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayId);
subsystem->pixelWidth = CGDisplayModeGetPixelWidth(mode);
subsystem->pixelHeight = CGDisplayModeGetPixelHeight(mode);
wide = CGDisplayPixelsWide(displayId);
high = CGDisplayPixelsHigh(displayId);
CGDisplayModeRelease(mode);
subsystem->retina = ((subsystem->pixelWidth / wide) == 2) ? TRUE : FALSE;
if (subsystem->retina)
{
subsystem->width = wide;
subsystem->height = high;
}
else
{
subsystem->width = subsystem->pixelWidth;
subsystem->height = subsystem->pixelHeight;
}
subsystem->monitorCount = 1;
monitor = &(subsystem->monitors[0]);
monitor->left = 0;
monitor->top = 0;
monitor->right = subsystem->width;
monitor->bottom = subsystem->height;
monitor->flags = 1;
return 1;
}
void (^streamHandler)(CGDisplayStreamFrameStatus, uint64_t, IOSurfaceRef, CGDisplayStreamUpdateRef) = ^(CGDisplayStreamFrameStatus status, uint64_t displayTime, IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef)
{
};
int mac_shadow_capture_init(macShadowSubsystem* subsystem)
{
void* keys[2];
void* values[2];
CFDictionaryRef opts;
CGDirectDisplayID displayId;
displayId = CGMainDisplayID();
subsystem->captureQueue = dispatch_queue_create("mac.shadow.capture", NULL);
keys[0] = (void*) kCGDisplayStreamShowCursor;
values[0] = (void*) kCFBooleanFalse;
opts = CFDictionaryCreate(kCFAllocatorDefault, (const void**) keys, (const void**) values, 1, NULL, NULL);
subsystem->stream = CGDisplayStreamCreateWithDispatchQueue(displayId,
subsystem->pixelWidth, subsystem->pixelHeight,
'BGRA', opts, subsystem->captureQueue, streamHandler);
CFRelease(opts);
return 1;
}
int mac_shadow_subsystem_init(macShadowSubsystem* subsystem)
{
mac_shadow_detect_monitors(subsystem);
return 1;
}
int mac_shadow_subsystem_uninit(macShadowSubsystem* subsystem)
{
if (!subsystem)
return -1;
return 1;
}
int mac_shadow_subsystem_start(macShadowSubsystem* subsystem)
{
HANDLE thread;
if (!subsystem)
return -1;
thread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE) mac_shadow_subsystem_thread,
(void*) subsystem, 0, NULL);
return 1;
}
int mac_shadow_subsystem_stop(macShadowSubsystem* subsystem)
{
if (!subsystem)
return -1;
return 1;
}
void mac_shadow_subsystem_free(macShadowSubsystem* subsystem)
{
if (!subsystem)
return;
mac_shadow_subsystem_uninit(subsystem);
free(subsystem);
}
macShadowSubsystem* mac_shadow_subsystem_new(rdpShadowServer* server)
{
macShadowSubsystem* subsystem;
subsystem = (macShadowSubsystem*) calloc(1, sizeof(macShadowSubsystem));
if (!subsystem)
return NULL;
subsystem->server = server;
subsystem->updateEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
region16_init(&(subsystem->invalidRegion));
subsystem->Init = (pfnShadowSubsystemInit) mac_shadow_subsystem_init;
subsystem->Uninit = (pfnShadowSubsystemInit) mac_shadow_subsystem_uninit;
subsystem->Start = (pfnShadowSubsystemStart) mac_shadow_subsystem_start;
subsystem->Stop = (pfnShadowSubsystemStop) mac_shadow_subsystem_stop;
subsystem->Free = (pfnShadowSubsystemFree) mac_shadow_subsystem_free;
subsystem->SynchronizeEvent = (pfnShadowSynchronizeEvent) mac_shadow_input_synchronize_event;
subsystem->KeyboardEvent = (pfnShadowKeyboardEvent) mac_shadow_input_keyboard_event;
subsystem->UnicodeKeyboardEvent = (pfnShadowUnicodeKeyboardEvent) mac_shadow_input_unicode_keyboard_event;
subsystem->MouseEvent = (pfnShadowMouseEvent) mac_shadow_input_mouse_event;
subsystem->ExtendedMouseEvent = (pfnShadowExtendedMouseEvent) mac_shadow_input_extended_mouse_event;
return subsystem;
}
rdpShadowSubsystem* Mac_ShadowCreateSubsystem(rdpShadowServer* server)
{
return (rdpShadowSubsystem*) mac_shadow_subsystem_new(server);
}