Blame server/shadow/Mac/mac_shadow.c

Packit 1fb8d4
/**
Packit 1fb8d4
 * FreeRDP: A Remote Desktop Protocol Implementation
Packit 1fb8d4
 *
Packit 1fb8d4
 * Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
Packit 1fb8d4
 *
Packit 1fb8d4
 * Licensed under the Apache License, Version 2.0 (the "License");
Packit 1fb8d4
 * you may not use this file except in compliance with the License.
Packit 1fb8d4
 * You may obtain a copy of the License at
Packit 1fb8d4
 *
Packit 1fb8d4
 *     http://www.apache.org/licenses/LICENSE-2.0
Packit 1fb8d4
 *
Packit 1fb8d4
 * Unless required by applicable law or agreed to in writing, software
Packit 1fb8d4
 * distributed under the License is distributed on an "AS IS" BASIS,
Packit 1fb8d4
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Packit 1fb8d4
 * See the License for the specific language governing permissions and
Packit 1fb8d4
 * limitations under the License.
Packit 1fb8d4
 */
Packit 1fb8d4
Packit 1fb8d4
#include <winpr/crt.h>
Packit 1fb8d4
#include <winpr/synch.h>
Packit 1fb8d4
#include <winpr/input.h>
Packit 1fb8d4
#include <winpr/sysinfo.h>
Packit 1fb8d4
Packit 1fb8d4
#include <freerdp/codec/color.h>
Packit 1fb8d4
#include <freerdp/codec/region.h>
Packit 1fb8d4
#include <freerdp/log.h>
Packit 1fb8d4
Packit 1fb8d4
#include "mac_shadow.h"
Packit 1fb8d4
Packit 1fb8d4
#define TAG SERVER_TAG("shadow.mac")
Packit 1fb8d4
Packit 1fb8d4
static macShadowSubsystem* g_Subsystem = NULL;
Packit 1fb8d4
Packit 1fb8d4
static BOOL mac_shadow_input_synchronize_event(rdpShadowSubsystem* subsystem,
Packit Service 5a9772
                                               rdpShadowClient* client, UINT32 flags)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!subsystem || !client)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL mac_shadow_input_keyboard_event(rdpShadowSubsystem* subsystem, rdpShadowClient* client,
Packit Service 5a9772
                                            UINT16 flags, UINT16 code)
Packit 1fb8d4
{
Packit 1fb8d4
	DWORD vkcode;
Packit 1fb8d4
	DWORD keycode;
Packit 1fb8d4
	BOOL extended;
Packit 1fb8d4
	CGEventRef kbdEvent;
Packit 1fb8d4
	CGEventSourceRef source;
Packit 1fb8d4
	extended = (flags & KBD_FLAGS_EXTENDED) ? TRUE : FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (!subsystem || !client)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (extended)
Packit 1fb8d4
		code |= KBDEXT;
Packit 1fb8d4
Packit 1fb8d4
	vkcode = GetVirtualKeyCodeFromVirtualScanCode(code, 4);
Packit 1fb8d4
Packit 1fb8d4
	if (extended)
Packit 1fb8d4
		vkcode |= KBDEXT;
Packit 1fb8d4
Packit 1fb8d4
	keycode = GetKeycodeFromVirtualKeyCode(vkcode, KEYCODE_TYPE_APPLE);
Packit 1fb8d4
Packit 1fb8d4
	if (keycode < 8)
Packit 1fb8d4
		return TRUE;
Packit 1fb8d4
Packit 1fb8d4
	keycode -= 8;
Packit 1fb8d4
	source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
Packit 1fb8d4
Packit 1fb8d4
	if (flags & KBD_FLAGS_DOWN)
Packit 1fb8d4
	{
Packit Service 5a9772
		kbdEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode)keycode, TRUE);
Packit 1fb8d4
		CGEventPost(kCGHIDEventTap, kbdEvent);
Packit 1fb8d4
		CFRelease(kbdEvent);
Packit 1fb8d4
	}
Packit 1fb8d4
	else if (flags & KBD_FLAGS_RELEASE)
Packit 1fb8d4
	{
Packit Service 5a9772
		kbdEvent = CGEventCreateKeyboardEvent(source, (CGKeyCode)keycode, FALSE);
Packit 1fb8d4
		CGEventPost(kCGHIDEventTap, kbdEvent);
Packit 1fb8d4
		CFRelease(kbdEvent);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	CFRelease(source);
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL mac_shadow_input_unicode_keyboard_event(rdpShadowSubsystem* subsystem,
Packit Service 5a9772
                                                    rdpShadowClient* client, UINT16 flags,
Packit Service 5a9772
                                                    UINT16 code)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!subsystem || !client)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static BOOL mac_shadow_input_mouse_event(rdpShadowSubsystem* subsystem, rdpShadowClient* client,
Packit Service 5a9772
                                         UINT16 flags, UINT16 x, UINT16 y)
Packit 1fb8d4
{
Packit 1fb8d4
	macShadowSubsystem* mac = (macShadowSubsystem*)subsystem;
Packit 1fb8d4
	UINT32 scrollX = 0;
Packit 1fb8d4
	UINT32 scrollY = 0;
Packit 1fb8d4
	CGWheelCount wheelCount = 2;
Packit 1fb8d4
Packit 1fb8d4
	if (!subsystem || !client)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (flags & PTR_FLAGS_WHEEL)
Packit 1fb8d4
	{
Packit 1fb8d4
		scrollY = flags & WheelRotationMask;
Packit 1fb8d4
Packit 1fb8d4
		if (flags & PTR_FLAGS_WHEEL_NEGATIVE)
Packit 1fb8d4
		{
Packit 1fb8d4
			scrollY = -(flags & WheelRotationMask) / 392;
Packit 1fb8d4
		}
Packit 1fb8d4
		else
Packit 1fb8d4
		{
Packit 1fb8d4
			scrollY = (flags & WheelRotationMask) / 120;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit Service 5a9772
		CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
Packit Service 5a9772
		CGEventRef scroll = CGEventCreateScrollWheelEvent(source, kCGScrollEventUnitLine,
Packit Service 5a9772
		                                                  wheelCount, scrollY, scrollX);
Packit 1fb8d4
		CGEventPost(kCGHIDEventTap, scroll);
Packit 1fb8d4
		CFRelease(scroll);
Packit 1fb8d4
		CFRelease(source);
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit Service 5a9772
		CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
Packit 1fb8d4
		CGEventType mouseType = kCGEventNull;
Packit 1fb8d4
		CGMouseButton mouseButton = kCGMouseButtonLeft;
Packit 1fb8d4
Packit 1fb8d4
		if (flags & PTR_FLAGS_MOVE)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (mac->mouseDownLeft)
Packit 1fb8d4
				mouseType = kCGEventLeftMouseDragged;
Packit 1fb8d4
			else if (mac->mouseDownRight)
Packit 1fb8d4
				mouseType = kCGEventRightMouseDragged;
Packit 1fb8d4
			else if (mac->mouseDownOther)
Packit 1fb8d4
				mouseType = kCGEventOtherMouseDragged;
Packit 1fb8d4
			else
Packit 1fb8d4
				mouseType = kCGEventMouseMoved;
Packit 1fb8d4
Packit Service 5a9772
			CGEventRef move =
Packit Service 5a9772
			    CGEventCreateMouseEvent(source, mouseType, CGPointMake(x, y), mouseButton);
Packit 1fb8d4
			CGEventPost(kCGHIDEventTap, move);
Packit 1fb8d4
			CFRelease(move);
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if (flags & PTR_FLAGS_BUTTON1)
Packit 1fb8d4
		{
Packit 1fb8d4
			mouseButton = kCGMouseButtonLeft;
Packit 1fb8d4
Packit 1fb8d4
			if (flags & PTR_FLAGS_DOWN)
Packit 1fb8d4
			{
Packit 1fb8d4
				mouseType = kCGEventLeftMouseDown;
Packit 1fb8d4
				mac->mouseDownLeft = TRUE;
Packit 1fb8d4
			}
Packit 1fb8d4
			else
Packit 1fb8d4
			{
Packit 1fb8d4
				mouseType = kCGEventLeftMouseUp;
Packit 1fb8d4
				mac->mouseDownLeft = FALSE;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (flags & PTR_FLAGS_BUTTON2)
Packit 1fb8d4
		{
Packit 1fb8d4
			mouseButton = kCGMouseButtonRight;
Packit 1fb8d4
Packit 1fb8d4
			if (flags & PTR_FLAGS_DOWN)
Packit 1fb8d4
			{
Packit 1fb8d4
				mouseType = kCGEventRightMouseDown;
Packit 1fb8d4
				mac->mouseDownRight = TRUE;
Packit 1fb8d4
			}
Packit 1fb8d4
			else
Packit 1fb8d4
			{
Packit 1fb8d4
				mouseType = kCGEventRightMouseUp;
Packit 1fb8d4
				mac->mouseDownRight = FALSE;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
		else if (flags & PTR_FLAGS_BUTTON3)
Packit 1fb8d4
		{
Packit 1fb8d4
			mouseButton = kCGMouseButtonCenter;
Packit 1fb8d4
Packit 1fb8d4
			if (flags & PTR_FLAGS_DOWN)
Packit 1fb8d4
			{
Packit 1fb8d4
				mouseType = kCGEventOtherMouseDown;
Packit 1fb8d4
				mac->mouseDownOther = TRUE;
Packit 1fb8d4
			}
Packit 1fb8d4
			else
Packit 1fb8d4
			{
Packit 1fb8d4
				mouseType = kCGEventOtherMouseUp;
Packit 1fb8d4
				mac->mouseDownOther = FALSE;
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit Service 5a9772
		CGEventRef mouseEvent =
Packit Service 5a9772
		    CGEventCreateMouseEvent(source, mouseType, CGPointMake(x, y), mouseButton);
Packit 1fb8d4
		CGEventPost(kCGHIDEventTap, mouseEvent);
Packit 1fb8d4
		CFRelease(mouseEvent);
Packit 1fb8d4
		CFRelease(source);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static BOOL mac_shadow_input_extended_mouse_event(rdpShadowSubsystem* subsystem,
Packit Service 5a9772
                                                  rdpShadowClient* client, UINT16 flags, UINT16 x,
Packit Service 5a9772
                                                  UINT16 y)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!subsystem || !client)
Packit 1fb8d4
		return FALSE;
Packit 1fb8d4
Packit 1fb8d4
	return TRUE;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int mac_shadow_detect_monitors(macShadowSubsystem* subsystem)
Packit 1fb8d4
{
Packit 1fb8d4
	size_t wide, high;
Packit 1fb8d4
	MONITOR_DEF* monitor;
Packit 1fb8d4
	CGDirectDisplayID displayId;
Packit 1fb8d4
	displayId = CGMainDisplayID();
Packit 1fb8d4
	CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayId);
Packit 1fb8d4
	subsystem->pixelWidth = CGDisplayModeGetPixelWidth(mode);
Packit 1fb8d4
	subsystem->pixelHeight = CGDisplayModeGetPixelHeight(mode);
Packit 1fb8d4
	wide = CGDisplayPixelsWide(displayId);
Packit 1fb8d4
	high = CGDisplayPixelsHigh(displayId);
Packit 1fb8d4
	CGDisplayModeRelease(mode);
Packit 1fb8d4
	subsystem->retina = ((subsystem->pixelWidth / wide) == 2) ? TRUE : FALSE;
Packit 1fb8d4
Packit 1fb8d4
	if (subsystem->retina)
Packit 1fb8d4
	{
Packit 1fb8d4
		subsystem->width = wide;
Packit 1fb8d4
		subsystem->height = high;
Packit 1fb8d4
	}
Packit 1fb8d4
	else
Packit 1fb8d4
	{
Packit 1fb8d4
		subsystem->width = subsystem->pixelWidth;
Packit 1fb8d4
		subsystem->height = subsystem->pixelHeight;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	subsystem->common.numMonitors = 1;
Packit 1fb8d4
	monitor = &(subsystem->common.monitors[0]);
Packit 1fb8d4
	monitor->left = 0;
Packit 1fb8d4
	monitor->top = 0;
Packit 1fb8d4
	monitor->right = subsystem->width;
Packit 1fb8d4
	monitor->bottom = subsystem->height;
Packit 1fb8d4
	monitor->flags = 1;
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int mac_shadow_capture_start(macShadowSubsystem* subsystem)
Packit 1fb8d4
{
Packit 1fb8d4
	CGError err;
Packit 1fb8d4
	err = CGDisplayStreamStart(subsystem->stream);
Packit 1fb8d4
Packit 1fb8d4
	if (err != kCGErrorSuccess)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int mac_shadow_capture_stop(macShadowSubsystem* subsystem)
Packit 1fb8d4
{
Packit 1fb8d4
	CGError err;
Packit 1fb8d4
	err = CGDisplayStreamStop(subsystem->stream);
Packit 1fb8d4
Packit 1fb8d4
	if (err != kCGErrorSuccess)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int mac_shadow_capture_get_dirty_region(macShadowSubsystem* subsystem)
Packit 1fb8d4
{
Packit 1fb8d4
	size_t index;
Packit 1fb8d4
	size_t numRects;
Packit 1fb8d4
	const CGRect* rects;
Packit 1fb8d4
	RECTANGLE_16 invalidRect;
Packit 1fb8d4
	rdpShadowSurface* surface = subsystem->common.server->surface;
Packit Service 5a9772
	rects = CGDisplayStreamUpdateGetRects(subsystem->lastUpdate, kCGDisplayStreamUpdateDirtyRects,
Packit Service 5a9772
	                                      &numRects);
Packit 1fb8d4
Packit 1fb8d4
	if (!numRects)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	for (index = 0; index < numRects; index++)
Packit 1fb8d4
	{
Packit Service 5a9772
		invalidRect.left = (UINT16)rects[index].origin.x;
Packit Service 5a9772
		invalidRect.top = (UINT16)rects[index].origin.y;
Packit Service 5a9772
		invalidRect.right = invalidRect.left + (UINT16)rects[index].size.width;
Packit Service 5a9772
		invalidRect.bottom = invalidRect.top + (UINT16)rects[index].size.height;
Packit 1fb8d4
Packit 1fb8d4
		if (subsystem->retina)
Packit 1fb8d4
		{
Packit 1fb8d4
			/* scale invalid rect */
Packit 1fb8d4
			invalidRect.left /= 2;
Packit 1fb8d4
			invalidRect.top /= 2;
Packit 1fb8d4
			invalidRect.right /= 2;
Packit 1fb8d4
			invalidRect.bottom /= 2;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit Service 5a9772
		region16_union_rect(&(surface->invalidRegion), &(surface->invalidRegion), &invalidRect);
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static int freerdp_image_copy_from_retina(BYTE* pDstData, DWORD DstFormat, int nDstStep, int nXDst,
Packit Service 5a9772
                                          int nYDst, int nWidth, int nHeight, BYTE* pSrcData,
Packit Service 5a9772
                                          int nSrcStep, int nXSrc, int nYSrc)
Packit 1fb8d4
{
Packit 1fb8d4
	BYTE* pSrcPixel;
Packit 1fb8d4
	BYTE* pDstPixel;
Packit 1fb8d4
	int x, y;
Packit 1fb8d4
	int nSrcPad;
Packit 1fb8d4
	int nDstPad;
Packit 1fb8d4
	int srcBitsPerPixel;
Packit 1fb8d4
	int srcBytesPerPixel;
Packit 1fb8d4
	int dstBitsPerPixel;
Packit 1fb8d4
	int dstBytesPerPixel;
Packit 1fb8d4
	srcBitsPerPixel = 24;
Packit 1fb8d4
	srcBytesPerPixel = 8;
Packit 1fb8d4
Packit 1fb8d4
	if (nSrcStep < 0)
Packit 1fb8d4
		nSrcStep = srcBytesPerPixel * nWidth;
Packit 1fb8d4
Packit 1fb8d4
	dstBitsPerPixel = GetBitsPerPixel(DstFormat);
Packit 1fb8d4
	dstBytesPerPixel = GetBytesPerPixel(DstFormat);
Packit 1fb8d4
Packit 1fb8d4
	if (nDstStep < 0)
Packit 1fb8d4
		nDstStep = dstBytesPerPixel * nWidth;
Packit 1fb8d4
Packit 1fb8d4
	nSrcPad = (nSrcStep - (nWidth * srcBytesPerPixel));
Packit 1fb8d4
	nDstPad = (nDstStep - (nWidth * dstBytesPerPixel));
Packit 1fb8d4
	pSrcPixel = &pSrcData[(nYSrc * nSrcStep) + (nXSrc * 4)];
Packit 1fb8d4
	pDstPixel = &pDstData[(nYDst * nDstStep) + (nXDst * 4)];
Packit 1fb8d4
Packit 1fb8d4
	for (y = 0; y < nHeight; y++)
Packit 1fb8d4
	{
Packit 1fb8d4
		for (x = 0; x < nWidth; x++)
Packit 1fb8d4
		{
Packit 1fb8d4
			UINT32 R, G, B;
Packit 1fb8d4
			UINT32 color;
Packit 1fb8d4
			/* simple box filter scaling, could be improved with better algorithm */
Packit Service 5a9772
			B = pSrcPixel[0] + pSrcPixel[4] + pSrcPixel[nSrcStep + 0] + pSrcPixel[nSrcStep + 4];
Packit Service 5a9772
			G = pSrcPixel[1] + pSrcPixel[5] + pSrcPixel[nSrcStep + 1] + pSrcPixel[nSrcStep + 5];
Packit Service 5a9772
			R = pSrcPixel[2] + pSrcPixel[6] + pSrcPixel[nSrcStep + 2] + pSrcPixel[nSrcStep + 6];
Packit 1fb8d4
			pSrcPixel += 8;
Packit 1fb8d4
			color = FreeRDPGetColor(DstFormat, R >> 2, G >> 2, B >> 2, 0xFF);
Packit 1fb8d4
			WriteColor(pDstPixel, DstFormat, color);
Packit 1fb8d4
			pDstPixel += dstBytesPerPixel;
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		pSrcPixel = &pSrcPixel[nSrcPad + nSrcStep];
Packit 1fb8d4
		pDstPixel = &pDstPixel[nDstPad];
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static void (^mac_capture_stream_handler)(
Packit Service 5a9772
    CGDisplayStreamFrameStatus, uint64_t, IOSurfaceRef,
Packit Service 5a9772
    CGDisplayStreamUpdateRef) = ^(CGDisplayStreamFrameStatus status, uint64_t displayTime,
Packit Service 5a9772
                                  IOSurfaceRef frameSurface, CGDisplayStreamUpdateRef updateRef) {
Packit Service 5a9772
  int x, y;
Packit Service 5a9772
  int count;
Packit Service 5a9772
  int width;
Packit Service 5a9772
  int height;
Packit Service 5a9772
  int nSrcStep;
Packit Service 5a9772
  BYTE* pSrcData;
Packit Service 5a9772
  RECTANGLE_16 surfaceRect;
Packit Service 5a9772
  const RECTANGLE_16* extents;
Packit Service 5a9772
  macShadowSubsystem* subsystem = g_Subsystem;
Packit Service 5a9772
  rdpShadowServer* server = subsystem->common.server;
Packit Service 5a9772
  rdpShadowSurface* surface = server->surface;
Packit Service 5a9772
  count = ArrayList_Count(server->clients);
Packit Service 5a9772
Packit Service 5a9772
  if (count < 1)
Packit Service 5a9772
	  return;
Packit Service 5a9772
Packit Service 5a9772
  mac_shadow_capture_get_dirty_region(subsystem);
Packit Service 5a9772
  surfaceRect.left = 0;
Packit Service 5a9772
  surfaceRect.top = 0;
Packit Service 5a9772
  surfaceRect.right = surface->width;
Packit Service 5a9772
  surfaceRect.bottom = surface->height;
Packit Service 5a9772
  region16_intersect_rect(&(surface->invalidRegion), &(surface->invalidRegion), &surfaceRect);
Packit Service 5a9772
Packit Service 5a9772
  if (!region16_is_empty(&(surface->invalidRegion)))
Packit Service 5a9772
  {
Packit Service 5a9772
	  extents = region16_extents(&(surface->invalidRegion));
Packit Service 5a9772
	  x = extents->left;
Packit Service 5a9772
	  y = extents->top;
Packit Service 5a9772
	  width = extents->right - extents->left;
Packit Service 5a9772
	  height = extents->bottom - extents->top;
Packit Service 5a9772
	  IOSurfaceLock(frameSurface, kIOSurfaceLockReadOnly, NULL);
Packit Service 5a9772
	  pSrcData = (BYTE*)IOSurfaceGetBaseAddress(frameSurface);
Packit Service 5a9772
	  nSrcStep = (int)IOSurfaceGetBytesPerRow(frameSurface);
Packit Service 5a9772
Packit Service 5a9772
	  if (subsystem->retina)
Packit Service 5a9772
	  {
Packit Service 5a9772
		  freerdp_image_copy_from_retina(surface->data, surface->format, surface->scanline, x, y,
Packit Service 5a9772
			                             width, height, pSrcData, nSrcStep, x, y);
Packit Service 5a9772
	  }
Packit Service 5a9772
	  else
Packit Service 5a9772
	  {
Packit Service 5a9772
		  freerdp_image_copy(surface->data, surface->format, surface->scanline, x, y, width, height,
Packit Service 5a9772
			                 pSrcData, PIXEL_FORMAT_BGRX32, nSrcStep, x, y, NULL,
Packit Service 5a9772
			                 FREERDP_FLIP_NONE);
Packit Service 5a9772
	  }
Packit Service 5a9772
Packit Service 5a9772
	  IOSurfaceUnlock(frameSurface, kIOSurfaceLockReadOnly, NULL);
Packit Service 5a9772
	  ArrayList_Lock(server->clients);
Packit Service 5a9772
	  count = ArrayList_Count(server->clients);
Packit Service 5a9772
	  EnterCriticalSection(&(surface->lock));
Packit Service 5a9772
	  shadow_subsystem_frame_update(&subsystem->common);
Packit Service 5a9772
	  LeaveCriticalSection(&(surface->lock));
Packit Service 5a9772
Packit Service 5a9772
	  if (count == 1)
Packit Service 5a9772
	  {
Packit Service 5a9772
		  rdpShadowClient* client;
Packit Service 5a9772
		  client = (rdpShadowClient*)ArrayList_GetItem(server->clients, 0);
Packit Service 5a9772
Packit Service 5a9772
		  if (client)
Packit Service 5a9772
		  {
Packit Service 5a9772
			  subsystem->common.captureFrameRate = shadow_encoder_preferred_fps(client->encoder);
Packit Service 5a9772
		  }
Packit Service 5a9772
	  }
Packit Service 5a9772
Packit Service 5a9772
	  ArrayList_Unlock(server->clients);
Packit Service 5a9772
	  region16_clear(&(surface->invalidRegion));
Packit Service 5a9772
  }
Packit Service 5a9772
Packit Service 5a9772
  if (status != kCGDisplayStreamFrameStatusFrameComplete)
Packit Service 5a9772
  {
Packit Service 5a9772
	  switch (status)
Packit Service 5a9772
	  {
Packit Service 5a9772
		  case kCGDisplayStreamFrameStatusFrameIdle:
Packit Service 5a9772
			  break;
Packit Service 5a9772
Packit Service 5a9772
		  case kCGDisplayStreamFrameStatusStopped:
Packit Service 5a9772
			  break;
Packit Service 5a9772
Packit Service 5a9772
		  case kCGDisplayStreamFrameStatusFrameBlank:
Packit Service 5a9772
			  break;
Packit Service 5a9772
Packit Service 5a9772
		  default:
Packit Service 5a9772
			  break;
Packit Service 5a9772
	  }
Packit Service 5a9772
  }
Packit Service 5a9772
  else if (!subsystem->lastUpdate)
Packit Service 5a9772
  {
Packit Service 5a9772
	  CFRetain(updateRef);
Packit Service 5a9772
	  subsystem->lastUpdate = updateRef;
Packit Service 5a9772
  }
Packit Service 5a9772
  else
Packit Service 5a9772
  {
Packit Service 5a9772
	  CGDisplayStreamUpdateRef tmpRef = subsystem->lastUpdate;
Packit Service 5a9772
	  subsystem->lastUpdate = CGDisplayStreamUpdateCreateMergedUpdate(tmpRef, updateRef);
Packit Service 5a9772
	  CFRelease(tmpRef);
Packit Service 5a9772
  }
Packit 1fb8d4
};
Packit 1fb8d4
Packit 1fb8d4
static int mac_shadow_capture_init(macShadowSubsystem* subsystem)
Packit 1fb8d4
{
Packit 1fb8d4
	void* keys[2];
Packit 1fb8d4
	void* values[2];
Packit 1fb8d4
	CFDictionaryRef opts;
Packit 1fb8d4
	CGDirectDisplayID displayId;
Packit 1fb8d4
	displayId = CGMainDisplayID();
Packit 1fb8d4
	subsystem->captureQueue = dispatch_queue_create("mac.shadow.capture", NULL);
Packit Service 5a9772
	keys[0] = (void*)kCGDisplayStreamShowCursor;
Packit Service 5a9772
	values[0] = (void*)kCFBooleanFalse;
Packit Service 5a9772
	opts = CFDictionaryCreate(kCFAllocatorDefault, (const void**)keys, (const void**)values, 1,
Packit Service 5a9772
	                          NULL, NULL);
Packit Service 5a9772
	subsystem->stream = CGDisplayStreamCreateWithDispatchQueue(
Packit Service 5a9772
	    displayId, subsystem->pixelWidth, subsystem->pixelHeight, 'BGRA', opts,
Packit Service 5a9772
	    subsystem->captureQueue, mac_capture_stream_handler);
Packit 1fb8d4
	CFRelease(opts);
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int mac_shadow_screen_grab(macShadowSubsystem* subsystem)
Packit 1fb8d4
{
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit Service 5a9772
static int mac_shadow_subsystem_process_message(macShadowSubsystem* subsystem, wMessage* message)
Packit 1fb8d4
{
Packit 1fb8d4
	rdpShadowServer* server = subsystem->common.server;
Packit 1fb8d4
	rdpShadowSurface* surface = server->surface;
Packit 1fb8d4
Packit 1fb8d4
	switch (message->id)
Packit 1fb8d4
	{
Packit 1fb8d4
		case SHADOW_MSG_IN_REFRESH_REQUEST_ID:
Packit 1fb8d4
			EnterCriticalSection(&(surface->lock));
Packit 1fb8d4
			shadow_subsystem_frame_update((rdpShadowSubsystem*)subsystem);
Packit 1fb8d4
			LeaveCriticalSection(&(surface->lock));
Packit 1fb8d4
			break;
Packit 1fb8d4
Packit 1fb8d4
		default:
Packit Service 5a9772
			WLog_ERR(TAG, "Unknown message id: %" PRIu32 "", message->id);
Packit 1fb8d4
			break;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	if (message->Free)
Packit 1fb8d4
		message->Free(message);
Packit 1fb8d4
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static DWORD WINAPI mac_shadow_subsystem_thread(LPVOID arg)
Packit 1fb8d4
{
Packit 1fb8d4
	macShadowSubsystem* subsystem = (macShadowSubsystem*)arg;
Packit 1fb8d4
	DWORD status;
Packit 1fb8d4
	DWORD nCount;
Packit 1fb8d4
	UINT64 cTime;
Packit 1fb8d4
	DWORD dwTimeout;
Packit 1fb8d4
	DWORD dwInterval;
Packit 1fb8d4
	UINT64 frameTime;
Packit 1fb8d4
	HANDLE events[32];
Packit 1fb8d4
	wMessage message;
Packit 1fb8d4
	wMessagePipe* MsgPipe;
Packit 1fb8d4
	MsgPipe = subsystem->common.MsgPipe;
Packit 1fb8d4
	nCount = 0;
Packit 1fb8d4
	events[nCount++] = MessageQueue_Event(MsgPipe->In);
Packit 1fb8d4
	subsystem->common.captureFrameRate = 16;
Packit 1fb8d4
	dwInterval = 1000 / subsystem->common.captureFrameRate;
Packit 1fb8d4
	frameTime = GetTickCount64() + dwInterval;
Packit 1fb8d4
Packit 1fb8d4
	while (1)
Packit 1fb8d4
	{
Packit 1fb8d4
		cTime = GetTickCount64();
Packit 1fb8d4
		dwTimeout = (cTime > frameTime) ? 0 : frameTime - cTime;
Packit 1fb8d4
		status = WaitForMultipleObjects(nCount, events, FALSE, dwTimeout);
Packit 1fb8d4
Packit 1fb8d4
		if (WaitForSingleObject(MessageQueue_Event(MsgPipe->In), 0) == WAIT_OBJECT_0)
Packit 1fb8d4
		{
Packit 1fb8d4
			if (MessageQueue_Peek(MsgPipe->In, &message, TRUE))
Packit 1fb8d4
			{
Packit 1fb8d4
				if (message.id == WMQ_QUIT)
Packit 1fb8d4
					break;
Packit 1fb8d4
Packit 1fb8d4
				mac_shadow_subsystem_process_message(subsystem, &message);
Packit 1fb8d4
			}
Packit 1fb8d4
		}
Packit 1fb8d4
Packit 1fb8d4
		if ((status == WAIT_TIMEOUT) || (GetTickCount64() > frameTime))
Packit 1fb8d4
		{
Packit 1fb8d4
			mac_shadow_screen_grab(subsystem);
Packit 1fb8d4
			dwInterval = 1000 / subsystem->common.captureFrameRate;
Packit 1fb8d4
			frameTime += dwInterval;
Packit 1fb8d4
		}
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	ExitThread(0);
Packit 1fb8d4
	return 0;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int mac_shadow_enum_monitors(MONITOR_DEF* monitors, int maxMonitors)
Packit 1fb8d4
{
Packit 1fb8d4
	int index;
Packit 1fb8d4
	size_t wide, high;
Packit 1fb8d4
	int numMonitors = 0;
Packit 1fb8d4
	MONITOR_DEF* monitor;
Packit 1fb8d4
	CGDirectDisplayID displayId;
Packit 1fb8d4
	displayId = CGMainDisplayID();
Packit 1fb8d4
	CGDisplayModeRef mode = CGDisplayCopyDisplayMode(displayId);
Packit 1fb8d4
	wide = CGDisplayPixelsWide(displayId);
Packit 1fb8d4
	high = CGDisplayPixelsHigh(displayId);
Packit 1fb8d4
	CGDisplayModeRelease(mode);
Packit 1fb8d4
	index = 0;
Packit 1fb8d4
	numMonitors = 1;
Packit 1fb8d4
	monitor = &monitors[index];
Packit 1fb8d4
	monitor->left = 0;
Packit 1fb8d4
	monitor->top = 0;
Packit Service 5a9772
	monitor->right = (int)wide;
Packit Service 5a9772
	monitor->bottom = (int)high;
Packit 1fb8d4
	monitor->flags = 1;
Packit 1fb8d4
	return numMonitors;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int mac_shadow_subsystem_init(macShadowSubsystem* subsystem)
Packit 1fb8d4
{
Packit 1fb8d4
	g_Subsystem = subsystem;
Packit 1fb8d4
	mac_shadow_detect_monitors(subsystem);
Packit 1fb8d4
	mac_shadow_capture_init(subsystem);
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int mac_shadow_subsystem_uninit(macShadowSubsystem* subsystem)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!subsystem)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	if (subsystem->lastUpdate)
Packit 1fb8d4
	{
Packit 1fb8d4
		CFRelease(subsystem->lastUpdate);
Packit 1fb8d4
		subsystem->lastUpdate = NULL;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int mac_shadow_subsystem_start(macShadowSubsystem* subsystem)
Packit 1fb8d4
{
Packit 1fb8d4
	HANDLE thread;
Packit 1fb8d4
Packit 1fb8d4
	if (!subsystem)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	mac_shadow_capture_start(subsystem);
Packit 1fb8d4
Packit Service 5a9772
	if (!(thread = CreateThread(NULL, 0, mac_shadow_subsystem_thread, (void*)subsystem, 0, NULL)))
Packit 1fb8d4
	{
Packit 1fb8d4
		WLog_ERR(TAG, "Failed to create thread");
Packit 1fb8d4
		return -1;
Packit 1fb8d4
	}
Packit 1fb8d4
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static int mac_shadow_subsystem_stop(macShadowSubsystem* subsystem)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!subsystem)
Packit 1fb8d4
		return -1;
Packit 1fb8d4
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static void mac_shadow_subsystem_free(macShadowSubsystem* subsystem)
Packit 1fb8d4
{
Packit 1fb8d4
	if (!subsystem)
Packit 1fb8d4
		return;
Packit 1fb8d4
Packit 1fb8d4
	mac_shadow_subsystem_uninit(subsystem);
Packit 1fb8d4
	free(subsystem);
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
static macShadowSubsystem* mac_shadow_subsystem_new(void)
Packit 1fb8d4
{
Packit 1fb8d4
	macShadowSubsystem* subsystem;
Packit Service 5a9772
	subsystem = (macShadowSubsystem*)calloc(1, sizeof(macShadowSubsystem));
Packit 1fb8d4
Packit 1fb8d4
	if (!subsystem)
Packit 1fb8d4
		return NULL;
Packit 1fb8d4
Packit 1fb8d4
	subsystem->common.SynchronizeEvent = mac_shadow_input_synchronize_event;
Packit 1fb8d4
	subsystem->common.KeyboardEvent = mac_shadow_input_keyboard_event;
Packit 1fb8d4
	subsystem->common.UnicodeKeyboardEvent = mac_shadow_input_unicode_keyboard_event;
Packit 1fb8d4
	subsystem->common.MouseEvent = mac_shadow_input_mouse_event;
Packit 1fb8d4
	subsystem->common.ExtendedMouseEvent = mac_shadow_input_extended_mouse_event;
Packit 1fb8d4
	return subsystem;
Packit 1fb8d4
}
Packit 1fb8d4
Packit 1fb8d4
FREERDP_API int Mac_ShadowSubsystemEntry(RDP_SHADOW_ENTRY_POINTS* pEntryPoints)
Packit 1fb8d4
{
Packit Service 5a9772
	pEntryPoints->New = (pfnShadowSubsystemNew)mac_shadow_subsystem_new;
Packit Service 5a9772
	pEntryPoints->Free = (pfnShadowSubsystemFree)mac_shadow_subsystem_free;
Packit Service 5a9772
	pEntryPoints->Init = (pfnShadowSubsystemInit)mac_shadow_subsystem_init;
Packit Service 5a9772
	pEntryPoints->Uninit = (pfnShadowSubsystemInit)mac_shadow_subsystem_uninit;
Packit Service 5a9772
	pEntryPoints->Start = (pfnShadowSubsystemStart)mac_shadow_subsystem_start;
Packit Service 5a9772
	pEntryPoints->Stop = (pfnShadowSubsystemStop)mac_shadow_subsystem_stop;
Packit Service 5a9772
	pEntryPoints->EnumMonitors = (pfnShadowEnumMonitors)mac_shadow_enum_monitors;
Packit 1fb8d4
	return 1;
Packit 1fb8d4
}