Milestone 5: deliver embedded RDP sessions and lifecycle hardening

This commit is contained in:
Keith Smith
2026-03-03 18:59:26 -07:00
parent 230a401386
commit 36006bd4aa
2941 changed files with 724359 additions and 77 deletions

View File

@@ -0,0 +1,89 @@
cmake_minimum_required(VERSION 3.13)
if(NOT FREERDP_DEFAULT_PROJECT_VERSION)
set(FREERDP_DEFAULT_PROJECT_VERSION "1.0.0.0")
endif()
project(MacFreeRDP-library VERSION ${FREERDP_DEFAULT_PROJECT_VERSION})
message("project ${PROJECT_NAME} is using version ${PROJECT_VERSION}")
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../cmake/)
include(CommonConfigOptions)
find_library(FOUNDATION_LIBRARY Foundation REQUIRED)
find_library(COCOA_LIBRARY Cocoa REQUIRED)
find_library(APPKIT_LIBRARY AppKit REQUIRED)
find_library(IOKIT_LIBRARY IOKit REQUIRED)
find_library(COREGRAPHICS_LIBRARY CoreGraphics REQUIRED)
set(EXTRA_LIBS ${COCOA_LIBRARY} ${FOUNDATION_LIBRARY} ${APPKIT_LIBRARY} ${IOKIT_LIBRARY})
set(XIBS CertificateDialog.xib PasswordDialog.xib)
set(SOURCES "")
set(OBJECTIVE_SOURCES
main.m
mf_client.m
MRDPCursor.m
MRDPView.m
Keyboard.m
Clipboard.m
CertificateDialog.m
PasswordDialog.m
)
list(APPEND SOURCES ${OBJECTIVE_SOURCES})
set(HEADERS
mfreerdp.h
mf_client.h
MRDPCursor.h
MRDPView.h
Keyboard.h
Clipboard.h
CertificateDialog.h
PasswordDialog.h
)
set(RESOURCES "en.lproj/InfoPlist.strings")
# Include XIB file in Xcode resources.
if("${CMAKE_GENERATOR}" MATCHES "Xcode")
message(STATUS "Adding Xcode XIB resources for ${MODULE_NAME}")
list(APPEND RESOURCES ${XIBS})
set(IS_XCODE ON)
endif()
add_library(${PROJECT_NAME} ../common/client.c ${SOURCES} ${HEADERS} ${RESOURCES})
set(LIBS ${EXTRA_LIBS} freerdp-client)
target_link_libraries(${PROJECT_NAME} PUBLIC ${LIBS})
set_target_properties(${PROJECT_NAME} PROPERTIES RESOURCE "${RESOURCES}")
if(NOT IS_XCODE)
find_program(IBTOOL ibtool REQUIRED HINTS "/usr/bin" "${OSX_DEVELOPER_ROOT}/usr/bin")
# Compile the .xib files using the 'ibtool' program with the destination being the app package
foreach(xib ${XIBS})
get_filename_component(XIB_WE ${xib} NAME_WE)
set(NIB ${CMAKE_CURRENT_BINARY_DIR}/${XIB_WE}.nib)
list(APPEND NIBS ${NIB})
add_custom_command(
TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${IBTOOL} --errors --warnings --notices --output-format
human-readable-text --compile ${NIB} ${CMAKE_CURRENT_SOURCE_DIR}/${xib}
COMMENT "Compiling ${xib}"
)
endforeach()
install(FILES ${NIBS} DESTINATION ${CMAKE_INSTALL_DATADIR})
endif()
install(TARGETS ${PROJECT_NAME} COMPONENT client RESOURCE DESTINATION ${CMAKE_INSTALL_DATADIR})
include_directories(${CMAKE_CURRENT_SOURCE_DIR})
add_subdirectory(cli)

View File

@@ -0,0 +1,60 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* MacFreeRDP
*
* Copyright 2018 Armin Novak <armin.novak@thincast.com>
* Copyright 2018 Thicast Technologies GmbH
*
* 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.
*/
#import <Cocoa/Cocoa.h>
@interface CertificateDialog : NSWindowController
{
@public
NSTextField *textCommonName;
NSTextField *textSubject;
NSTextField *textIssuer;
NSTextField *textFingerprint;
NSTextField *textMismatch;
NSTextField *messageLabel;
NSString *serverHostname;
BOOL hostMismatch;
BOOL changed;
int result;
}
@property(retain) IBOutlet NSTextField *textCommonName;
@property(retain) IBOutlet NSTextField *textSubject;
@property(retain) IBOutlet NSTextField *textIssuer;
@property(retain) IBOutlet NSTextField *textFingerprint;
@property(retain) IBOutlet NSTextField *textMismatch;
@property(retain) IBOutlet NSTextField *messageLabel;
- (IBAction)onAccept:(NSObject *)sender;
- (IBAction)onTemporary:(NSObject *)sender;
- (IBAction)onCancel:(NSObject *)sender;
@property(retain) NSString *serverHostname;
@property(retain) NSString *commonName;
@property(retain) NSString *subject;
@property(retain) NSString *issuer;
@property(retain) NSString *fingerprint;
@property BOOL hostMismatch;
@property BOOL changed;
@property(readonly) int result;
- (int)runModal:(NSWindow *)mainWindow;
@end

View File

@@ -0,0 +1,135 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* MacFreeRDP
*
* Copyright 2018 Armin Novak <armin.novak@thincast.com>
* Copyright 2018 Thicast Technologies GmbH
*
* 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.
*/
#import "CertificateDialog.h"
#import <freerdp/client/cmdline.h>
#import <CoreGraphics/CoreGraphics.h>
@interface CertificateDialog ()
@property int result;
@end
@implementation CertificateDialog
@synthesize textCommonName;
@synthesize textFingerprint;
@synthesize textIssuer;
@synthesize textSubject;
@synthesize textMismatch;
@synthesize messageLabel;
@synthesize serverHostname;
@synthesize commonName;
@synthesize fingerprint;
@synthesize issuer;
@synthesize subject;
@synthesize hostMismatch;
@synthesize changed;
@synthesize result;
- (id)init
{
return [self initWithWindowNibName:@"CertificateDialog"];
}
- (void)windowDidLoad
{
[super windowDidLoad];
// Implement this method to handle any initialization after your window controller's window has
// been loaded from its nib file.
[self.window setTitle:self.serverHostname];
if (self.changed)
[self.messageLabel setStringValue:[NSString stringWithFormat:@"Changed certificate for %@",
self.serverHostname]];
else
[self.messageLabel setStringValue:[NSString stringWithFormat:@"New Certificate for %@",
self.serverHostname]];
if (!self.hostMismatch)
[self.textMismatch
setStringValue:[NSString stringWithFormat:
@"NOTE: The server name matches the certificate, good."]];
else
[self.textMismatch
setStringValue:[NSString
stringWithFormat:
@"ATTENTION: The common name does not match the server name!"]];
[self.textCommonName setStringValue:self.commonName];
[self.textFingerprint setStringValue:self.fingerprint];
[self.textIssuer setStringValue:self.issuer];
[self.textSubject setStringValue:self.subject];
}
- (IBAction)onAccept:(NSObject *)sender
{
[NSApp stopModalWithCode:1];
}
- (IBAction)onTemporary:(NSObject *)sender
{
[NSApp stopModalWithCode:2];
}
- (IBAction)onCancel:(NSObject *)sender
{
[NSApp stopModalWithCode:0];
}
- (int)runModal:(NSWindow *)mainWindow
{
if ([mainWindow respondsToSelector:@selector(beginSheet:completionHandler:)])
{
[mainWindow beginSheet:self.window completionHandler:nil];
self.result = [NSApp runModalForWindow:self.window];
[mainWindow endSheet:self.window];
}
else
{
[NSApp beginSheet:self.window
modalForWindow:mainWindow
modalDelegate:nil
didEndSelector:nil
contextInfo:nil];
self.result = [NSApp runModalForWindow:self.window];
[NSApp endSheet:self.window];
}
[self.window orderOut:nil];
return self.result;
}
- (void)dealloc
{
[textCommonName release];
[textFingerprint release];
[textIssuer release];
[textSubject release];
[messageLabel release];
[serverHostname release];
[commonName release];
[fingerprint release];
[issuer release];
[subject release];
[super dealloc];
}
@end

View File

@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="CertificateDialog">
<connections>
<outlet property="messageLabel" destination="7" id="50"/>
<outlet property="textCommonName" destination="2HW-of-a4n" id="4442"/>
<outlet property="textFingerprint" destination="cLB-ZO-jvx" id="4445"/>
<outlet property="textIssuer" destination="kHA-F4-dxw" id="4444"/>
<outlet property="textMismatch" destination="LgQ-ni-jXv" id="5550"/>
<outlet property="textSubject" destination="R9r-82-XAH" id="4443"/>
<outlet property="window" destination="1" id="3"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application" customClass="NSObject"/>
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" visibleAtLaunch="NO" animationBehavior="default" id="1">
<windowStyleMask key="styleMask" titled="YES" texturedBackground="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="641" height="338"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<view key="contentView" id="2">
<rect key="frame" x="0.0" y="0.0" width="641" height="338"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField verticalHuggingPriority="750" id="7">
<rect key="frame" x="47" y="274" width="344" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" sendsActionOnEndEditing="YES" title="Certificate for SERVER_NAME" placeholderString="" id="20">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" id="8">
<rect key="frame" x="545" y="13" width="82" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="18">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent" base64-UTF8="YES">
Gw
</string>
</buttonCell>
<connections>
<action selector="onCancel:" target="-2" id="52"/>
</connections>
</button>
<button verticalHuggingPriority="750" id="9">
<rect key="frame" x="463" y="13" width="82" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="OK" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="17">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent" base64-UTF8="YES">
DQ
</string>
</buttonCell>
<connections>
<accessibilityConnection property="link" destination="8" id="cks-Lf-tCO"/>
<action selector="onAccept:" target="-2" id="522"/>
</connections>
</button>
<button verticalHuggingPriority="750" id="7I5-a2-h65">
<rect key="frame" x="358" y="13" width="105" height="32"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<buttonCell key="cell" type="push" title="Temporary" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="i6y-0u-COa">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
</buttonCell>
<connections>
<accessibilityConnection property="link" destination="9" id="5nn-SX-Rqq"/>
<action selector="onTemporary:" target="-2" id="BWk-o1-tug"/>
</connections>
</button>
<textField verticalHuggingPriority="750" id="LgQ-ni-jXv">
<rect key="frame" x="47" y="236" width="582" height="36"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="ATTENTION: The common name does not match the server name!" id="94f-Om-tJh">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" id="5">
<rect key="frame" x="47" y="186" width="89" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="Subject" id="22">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" id="vA4-qf-QuW">
<rect key="frame" x="47" y="161" width="89" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="Issuer" id="tAl-Qh-OR9">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" id="10">
<rect key="frame" x="47" y="211" width="89" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="Common" id="15">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" id="2HW-of-a4n">
<rect key="frame" x="140" y="211" width="305" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="COMMON NAME" id="N48-2i-W6H">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" id="R9r-82-XAH">
<rect key="frame" x="140" y="186" width="305" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="SUBJECT" id="iGw-oh-i3p">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" id="kHA-F4-dxw">
<rect key="frame" x="140" y="161" width="305" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="ISSUER" id="daP-a0-hI1">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" id="cLB-ZO-jvx">
<rect key="frame" x="140" y="117" width="483" height="36"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="FINGERPRINT" id="VqU-vO-noG">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" id="VLG-f9-Gcl">
<rect key="frame" x="47" y="136" width="89" height="17"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" alignment="left" title="Fingerprint" id="49l-Xk-MUH">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
</view>
<connections>
<outlet property="delegate" destination="-2" id="4"/>
</connections>
<point key="canvasLocation" x="228.5" y="102"/>
</window>
</objects>
</document>

View File

@@ -0,0 +1,31 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.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.
*/
#import "mfreerdp.h"
#import "mf_client.h"
#import "freerdp/freerdp.h"
#import "freerdp/channels/channels.h"
#import "freerdp/client/cliprdr.h"
int mac_cliprdr_send_client_format_list(CliprdrClientContext* cliprdr);
void mac_cliprdr_init(mfContext* mfc, CliprdrClientContext* cliprdr);
void mac_cliprdr_uninit(mfContext* mfc, CliprdrClientContext* cliprdr);

View File

@@ -0,0 +1,433 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
*
* Copyright 2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
* Copyright 2015 Thincast Technologies GmbH
* Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.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.
*/
#import "Clipboard.h"
#import "MRDPView.h"
int mac_cliprdr_send_client_format_list(CliprdrClientContext *cliprdr)
{
UINT32 formatId;
UINT32 numFormats;
UINT32 *pFormatIds;
const char *formatName;
CLIPRDR_FORMAT *formats;
CLIPRDR_FORMAT_LIST formatList = WINPR_C_ARRAY_INIT;
WINPR_ASSERT(cliprdr);
mfContext *mfc = (mfContext *)cliprdr->custom;
WINPR_ASSERT(mfc);
pFormatIds = nullptr;
numFormats = ClipboardGetFormatIds(mfc->clipboard, &pFormatIds);
formats = (CLIPRDR_FORMAT *)calloc(numFormats, sizeof(CLIPRDR_FORMAT));
if (!formats)
return -1;
for (UINT32 index = 0; index < numFormats; index++)
{
formatId = pFormatIds[index];
formatName = ClipboardGetFormatName(mfc->clipboard, formatId);
formats[index].formatId = formatId;
formats[index].formatName = nullptr;
if ((formatId > CF_MAX) && formatName)
formats[index].formatName = _strdup(formatName);
}
formatList.common.msgFlags = 0;
formatList.numFormats = numFormats;
formatList.formats = formats;
formatList.common.msgType = CB_FORMAT_LIST;
mfc->cliprdr->ClientFormatList(mfc->cliprdr, &formatList);
for (UINT32 index = 0; index < numFormats; index++)
{
free(formats[index].formatName);
}
free(pFormatIds);
free(formats);
return 1;
}
static int mac_cliprdr_send_client_format_list_response(CliprdrClientContext *cliprdr, BOOL status)
{
CLIPRDR_FORMAT_LIST_RESPONSE formatListResponse;
formatListResponse.common.msgType = CB_FORMAT_LIST_RESPONSE;
formatListResponse.common.msgFlags = status ? CB_RESPONSE_OK : CB_RESPONSE_FAIL;
formatListResponse.common.dataLen = 0;
cliprdr->ClientFormatListResponse(cliprdr, &formatListResponse);
return 1;
}
static UINT mac_cliprdr_send_client_format_data_request(CliprdrClientContext *cliprdr,
UINT32 formatId)
{
CLIPRDR_FORMAT_DATA_REQUEST formatDataRequest = WINPR_C_ARRAY_INIT;
WINPR_ASSERT(cliprdr);
if (formatId == 0)
return CHANNEL_RC_OK;
mfContext *mfc = (mfContext *)cliprdr->custom;
WINPR_ASSERT(mfc);
formatDataRequest.common.msgType = CB_FORMAT_DATA_REQUEST;
formatDataRequest.common.msgFlags = 0;
formatDataRequest.requestedFormatId = formatId;
mfc->requestedFormatId = formatId;
(void)ResetEvent(mfc->clipboardRequestEvent);
return cliprdr->ClientFormatDataRequest(cliprdr, &formatDataRequest);
}
static int mac_cliprdr_send_client_capabilities(CliprdrClientContext *cliprdr)
{
CLIPRDR_CAPABILITIES capabilities;
CLIPRDR_GENERAL_CAPABILITY_SET generalCapabilitySet;
capabilities.cCapabilitiesSets = 1;
capabilities.capabilitySets = (CLIPRDR_CAPABILITY_SET *)&(generalCapabilitySet);
generalCapabilitySet.capabilitySetType = CB_CAPSTYPE_GENERAL;
generalCapabilitySet.capabilitySetLength = 12;
generalCapabilitySet.version = CB_CAPS_VERSION_2;
generalCapabilitySet.generalFlags = CB_USE_LONG_FORMAT_NAMES;
cliprdr->ClientCapabilities(cliprdr, &capabilities);
return 1;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT mac_cliprdr_monitor_ready(CliprdrClientContext *cliprdr,
const CLIPRDR_MONITOR_READY *monitorReady)
{
mfContext *mfc = (mfContext *)cliprdr->custom;
mfc->clipboardSync = TRUE;
mac_cliprdr_send_client_capabilities(cliprdr);
mac_cliprdr_send_client_format_list(cliprdr);
return CHANNEL_RC_OK;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT mac_cliprdr_server_capabilities(CliprdrClientContext *cliprdr,
const CLIPRDR_CAPABILITIES *capabilities)
{
CLIPRDR_CAPABILITY_SET *capabilitySet;
mfContext *mfc = (mfContext *)cliprdr->custom;
for (UINT32 index = 0; index < capabilities->cCapabilitiesSets; index++)
{
capabilitySet = &(capabilities->capabilitySets[index]);
if ((capabilitySet->capabilitySetType == CB_CAPSTYPE_GENERAL) &&
(capabilitySet->capabilitySetLength >= CB_CAPSTYPE_GENERAL_LEN))
{
CLIPRDR_GENERAL_CAPABILITY_SET *generalCapabilitySet =
(CLIPRDR_GENERAL_CAPABILITY_SET *)capabilitySet;
mfc->clipboardCapabilities = generalCapabilitySet->generalFlags;
break;
}
}
return CHANNEL_RC_OK;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT mac_cliprdr_server_format_list(CliprdrClientContext *cliprdr,
const CLIPRDR_FORMAT_LIST *formatList)
{
WINPR_ASSERT(cliprdr);
mfContext *mfc = (mfContext *)cliprdr->custom;
WINPR_ASSERT(mfc);
if (mfc->serverFormats)
{
for (UINT32 index = 0; index < mfc->numServerFormats; index++)
{
free(mfc->serverFormats[index].formatName);
}
free(mfc->serverFormats);
mfc->serverFormats = nullptr;
mfc->numServerFormats = 0;
}
if (formatList->numFormats < 1)
return CHANNEL_RC_OK;
mfc->numServerFormats = formatList->numFormats;
mfc->serverFormats = (CLIPRDR_FORMAT *)calloc(mfc->numServerFormats, sizeof(CLIPRDR_FORMAT));
if (!mfc->serverFormats)
return CHANNEL_RC_NO_MEMORY;
for (UINT32 index = 0; index < mfc->numServerFormats; index++)
{
mfc->serverFormats[index].formatId = formatList->formats[index].formatId;
mfc->serverFormats[index].formatName = nullptr;
if (formatList->formats[index].formatName)
mfc->serverFormats[index].formatName = _strdup(formatList->formats[index].formatName);
}
mac_cliprdr_send_client_format_list_response(cliprdr, TRUE);
uint32_t formatId = 0;
for (UINT32 index = 0; index < mfc->numServerFormats; index++)
{
const CLIPRDR_FORMAT *format = &(mfc->serverFormats[index]);
if (format->formatId == CF_UNICODETEXT)
formatId = format->formatId;
else if (format->formatId == CF_OEMTEXT)
{
if (formatId == 0)
formatId == CF_OEMTEXT;
}
else if (format->formatId == CF_TEXT)
{
if (formatId == 0)
formatId == CF_TEXT;
}
}
return mac_cliprdr_send_client_format_data_request(cliprdr, formatId);
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT
mac_cliprdr_server_format_list_response(CliprdrClientContext *cliprdr,
const CLIPRDR_FORMAT_LIST_RESPONSE *formatListResponse)
{
return CHANNEL_RC_OK;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT
mac_cliprdr_server_lock_clipboard_data(CliprdrClientContext *cliprdr,
const CLIPRDR_LOCK_CLIPBOARD_DATA *lockClipboardData)
{
return CHANNEL_RC_OK;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT
mac_cliprdr_server_unlock_clipboard_data(CliprdrClientContext *cliprdr,
const CLIPRDR_UNLOCK_CLIPBOARD_DATA *unlockClipboardData)
{
return CHANNEL_RC_OK;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT
mac_cliprdr_server_format_data_request(CliprdrClientContext *cliprdr,
const CLIPRDR_FORMAT_DATA_REQUEST *formatDataRequest)
{
BYTE *data;
UINT32 size;
UINT32 formatId;
CLIPRDR_FORMAT_DATA_RESPONSE response = WINPR_C_ARRAY_INIT;
WINPR_ASSERT(cliprdr);
mfContext *mfc = (mfContext *)cliprdr->custom;
WINPR_ASSERT(mfc);
formatId = formatDataRequest->requestedFormatId;
data = (BYTE *)ClipboardGetData(mfc->clipboard, formatId, &size);
response.common.msgFlags = CB_RESPONSE_OK;
response.common.dataLen = size;
response.requestedFormatData = data;
if (!data)
{
response.common.msgFlags = CB_RESPONSE_FAIL;
response.common.dataLen = 0;
response.requestedFormatData = nullptr;
}
cliprdr->ClientFormatDataResponse(cliprdr, &response);
free(data);
return CHANNEL_RC_OK;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT
mac_cliprdr_server_format_data_response(CliprdrClientContext *cliprdr,
const CLIPRDR_FORMAT_DATA_RESPONSE *formatDataResponse)
{
UINT32 formatId;
CLIPRDR_FORMAT *format = nullptr;
mfContext *mfc = (mfContext *)cliprdr->custom;
MRDPView *view = (MRDPView *)mfc->view;
if (formatDataResponse->common.msgFlags & CB_RESPONSE_FAIL)
{
(void)SetEvent(mfc->clipboardRequestEvent);
return ERROR_INTERNAL_ERROR;
}
for (UINT32 index = 0; index < mfc->numServerFormats; index++)
{
if (mfc->requestedFormatId == mfc->serverFormats[index].formatId)
format = &(mfc->serverFormats[index]);
}
if (!format)
{
(void)SetEvent(mfc->clipboardRequestEvent);
return ERROR_INTERNAL_ERROR;
}
if (format->formatName)
formatId = ClipboardRegisterFormat(mfc->clipboard, format->formatName);
else
formatId = format->formatId;
const size_t size = formatDataResponse->common.dataLen;
ClipboardSetData(mfc->clipboard, formatId, formatDataResponse->requestedFormatData, size);
(void)SetEvent(mfc->clipboardRequestEvent);
if ((formatId == CF_TEXT) || (formatId == CF_OEMTEXT) || (formatId == CF_UNICODETEXT))
{
formatId = ClipboardRegisterFormat(mfc->clipboard, "text/plain");
UINT32 dstSize = 0;
char *data = ClipboardGetData(mfc->clipboard, formatId, &dstSize);
dstSize = strnlen(data, dstSize); /* we need the size without the null terminator */
NSString *str = [[NSString alloc] initWithBytes:(void *)data
length:dstSize
encoding:NSUTF8StringEncoding];
free(data);
NSArray *types = [[NSArray alloc] initWithObjects:NSPasteboardTypeString, nil];
[view->pasteboard_wr declareTypes:types owner:view];
[view->pasteboard_wr setString:str forType:NSPasteboardTypeString];
}
return CHANNEL_RC_OK;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT
mac_cliprdr_server_file_contents_request(CliprdrClientContext *cliprdr,
const CLIPRDR_FILE_CONTENTS_REQUEST *fileContentsRequest)
{
return CHANNEL_RC_OK;
}
/**
* Function description
*
* @return 0 on success, otherwise a Win32 error code
*/
static UINT mac_cliprdr_server_file_contents_response(
CliprdrClientContext *cliprdr, const CLIPRDR_FILE_CONTENTS_RESPONSE *fileContentsResponse)
{
return CHANNEL_RC_OK;
}
void mac_cliprdr_init(mfContext *mfc, CliprdrClientContext *cliprdr)
{
cliprdr->custom = (void *)mfc;
mfc->cliprdr = cliprdr;
mfc->clipboard = ClipboardCreate();
mfc->clipboardRequestEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
cliprdr->MonitorReady = mac_cliprdr_monitor_ready;
cliprdr->ServerCapabilities = mac_cliprdr_server_capabilities;
cliprdr->ServerFormatList = mac_cliprdr_server_format_list;
cliprdr->ServerFormatListResponse = mac_cliprdr_server_format_list_response;
cliprdr->ServerLockClipboardData = mac_cliprdr_server_lock_clipboard_data;
cliprdr->ServerUnlockClipboardData = mac_cliprdr_server_unlock_clipboard_data;
cliprdr->ServerFormatDataRequest = mac_cliprdr_server_format_data_request;
cliprdr->ServerFormatDataResponse = mac_cliprdr_server_format_data_response;
cliprdr->ServerFileContentsRequest = mac_cliprdr_server_file_contents_request;
cliprdr->ServerFileContentsResponse = mac_cliprdr_server_file_contents_response;
}
void mac_cliprdr_uninit(mfContext *mfc, CliprdrClientContext *cliprdr)
{
cliprdr->custom = nullptr;
mfc->cliprdr = nullptr;
ClipboardDestroy(mfc->clipboard);
(void)CloseHandle(mfc->clipboardRequestEvent);
}

View File

@@ -0,0 +1,21 @@
{\rtf1\ansi\ansicpg1252\cocoartf1138\cocoasubrtf320
{\fonttbl\f0\fswiss\fcharset0 Helvetica;}
{\colortbl;\red255\green255\blue255;}
\vieww9600\viewh8400\viewkind0
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720
\f0\b\fs24 \cf0 Engineering:
\b0 \
Jay sorg\
Marc-Andre Moreau\
Vic Lee\
Otvaio Salvador \
Laxmikant Rashinkar\
and others\
\
\b Human Interface Design:
\b0 \
Laxmikant Rashinkar\
Jay Sorg\
}

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSCameraUsageDescription</key>
<string>This application requires camera access to redirect it to the remote host</string>
<key>NSMicrophoneUsageDescription</key>
<string>This application requires microphone access to redirect it to the remote host</string>
<key>CFBundleDevelopmentRegion</key>
<string>English</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>FreeRDP.Mac</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string></string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>

View File

@@ -0,0 +1,27 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* MacFreeRDP
*
* Copyright 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.
*/
enum APPLE_KEYBOARD_TYPE
{
APPLE_KEYBOARD_TYPE_ANSI,
APPLE_KEYBOARD_TYPE_ISO,
APPLE_KEYBOARD_TYPE_JIS
};
enum APPLE_KEYBOARD_TYPE mac_detect_keyboard_type(void);

View File

@@ -0,0 +1,240 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* MacFreeRDP
*
* Copyright 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.
*/
#import "Keyboard.h"
#include <CoreFoundation/CoreFoundation.h>
#include <IOKit/IOKitLib.h>
#include <IOKit/hid/IOHIDManager.h>
typedef struct
{
uint32_t ProductId;
enum APPLE_KEYBOARD_TYPE Type;
} APPLE_KEYBOARD_DESC;
/* VendorID: 0x05AC (Apple, Inc.) */
static const APPLE_KEYBOARD_DESC APPLE_KEYBOARDS[] = {
{ 0x200, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x201, APPLE_KEYBOARD_TYPE_ANSI }, /* USB Keyboard [Alps or Logitech, M2452] */
{ 0x202, APPLE_KEYBOARD_TYPE_ANSI }, /* Keyboard [ALPS] */
{ 0x203, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x204, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x205, APPLE_KEYBOARD_TYPE_ANSI }, /* Extended Keyboard [Mitsumi] */
{ 0x206, APPLE_KEYBOARD_TYPE_ANSI }, /* Extended Keyboard [Mitsumi] */
{ 0x207, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x208, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x209, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x20A, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x20B, APPLE_KEYBOARD_TYPE_ANSI }, /* Pro Keyboard [Mitsumi, A1048/US layout] */
{ 0x20C, APPLE_KEYBOARD_TYPE_ANSI }, /* Extended Keyboard [Mitsumi] */
{ 0x20D, APPLE_KEYBOARD_TYPE_ANSI }, /* Pro Keyboard [Mitsumi, A1048/JIS layout] */
{ 0x20E, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */
{ 0x20F, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */
{ 0x210, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x211, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x212, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x213, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x214, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */
{ 0x215, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */
{ 0x216, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */
{ 0x217, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */
{ 0x218, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */
{ 0x219, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */
{ 0x21A, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */
{ 0x21B, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */
{ 0x21C, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */
{ 0x21D, APPLE_KEYBOARD_TYPE_ANSI }, /* Aluminum Mini Keyboard (ANSI) */
{ 0x21E, APPLE_KEYBOARD_TYPE_ISO }, /* Aluminum Mini Keyboard (ISO) */
{ 0x21F, APPLE_KEYBOARD_TYPE_JIS }, /* Aluminum Mini Keyboard (JIS) */
{ 0x220, APPLE_KEYBOARD_TYPE_ANSI }, /* Aluminum Keyboard (ANSI) */
{ 0x221, APPLE_KEYBOARD_TYPE_JIS }, /* Aluminum Keyboard (JIS) */
{ 0x222, APPLE_KEYBOARD_TYPE_JIS }, /* Aluminum Keyboard (JIS) */
{ 0x223, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */
{ 0x224, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */
{ 0x225, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */
{ 0x226, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x227, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x228, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x229, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (MacBook Pro) (ANSI) */
{ 0x22A, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (MacBook Pro) (ISO) */
{ 0x22B, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (MacBook Pro) (JIS) */
{ 0x22C, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x22D, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x22E, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x22F, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x230, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (MacBook Pro 4,1) (ANSI) */
{ 0x231, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (MacBook Pro 4,1) (ISO) */
{ 0x232, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (MacBook Pro 4,1) (JIS) */
{ 0x233, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x234, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x235, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x236, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */
{ 0x237, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */
{ 0x238, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */
{ 0x239, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x23A, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x23B, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x23C, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x23D, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x23E, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x23F, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */
{ 0x240, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */
{ 0x241, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */
{ 0x242, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */
{ 0x243, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */
{ 0x244, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */
{ 0x245, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */
{ 0x246, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */
{ 0x247, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */
{ 0x248, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x249, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x24A, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (MacBook Air) (ISO) */
{ 0x24B, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x24C, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x24D, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (MacBook Air) (ISO) */
{ 0x24E, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x24F, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x250, APPLE_KEYBOARD_TYPE_ISO }, /* Aluminium Keyboard (ISO) */
{ 0x251, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x252, APPLE_KEYBOARD_TYPE_ANSI }, /* Internal Keyboard/Trackpad (ANSI) */
{ 0x253, APPLE_KEYBOARD_TYPE_ISO }, /* Internal Keyboard/Trackpad (ISO) */
{ 0x254, APPLE_KEYBOARD_TYPE_JIS }, /* Internal Keyboard/Trackpad (JIS) */
{ 0x255, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x256, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x257, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x258, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x259, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x25A, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x25B, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x25C, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x25D, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x25E, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x25F, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x260, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x261, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x262, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x263, APPLE_KEYBOARD_TYPE_ANSI }, /* Apple Internal Keyboard / Trackpad (MacBook Retina) */
{ 0x264, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x265, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x266, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x267, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x268, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x269, APPLE_KEYBOARD_TYPE_ANSI },
{ 0x26A, APPLE_KEYBOARD_TYPE_ANSI }
};
static enum APPLE_KEYBOARD_TYPE mac_identify_keyboard_type(uint32_t vendorID, uint32_t productID)
{
enum APPLE_KEYBOARD_TYPE type = APPLE_KEYBOARD_TYPE_ANSI;
if (vendorID != 0x05AC) /* Apple, Inc. */
return type;
if ((productID < 0x200) || (productID > 0x26A))
return type;
type = APPLE_KEYBOARDS[productID - 0x200].Type;
return type;
}
enum APPLE_KEYBOARD_TYPE mac_detect_keyboard_type(void)
{
CFSetRef deviceCFSetRef = nullptr;
IOHIDDeviceRef inIOHIDDeviceRef = nullptr;
IOHIDManagerRef tIOHIDManagerRef = nullptr;
IOHIDDeviceRef *tIOHIDDeviceRefs = nil;
enum APPLE_KEYBOARD_TYPE type = APPLE_KEYBOARD_TYPE_ANSI;
tIOHIDManagerRef = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
if (!tIOHIDManagerRef)
return type;
IOHIDManagerSetDeviceMatching(tIOHIDManagerRef, nullptr);
IOReturn tIOReturn = IOHIDManagerOpen(tIOHIDManagerRef, kIOHIDOptionsTypeNone);
if (noErr != tIOReturn)
return type;
deviceCFSetRef = IOHIDManagerCopyDevices(tIOHIDManagerRef);
if (!deviceCFSetRef)
return type;
CFIndex deviceIndex, deviceCount = CFSetGetCount(deviceCFSetRef);
tIOHIDDeviceRefs = malloc(sizeof(IOHIDDeviceRef) * deviceCount);
if (!tIOHIDDeviceRefs)
return type;
CFSetGetValues(deviceCFSetRef, (const void **)tIOHIDDeviceRefs);
CFRelease(deviceCFSetRef);
deviceCFSetRef = nullptr;
for (deviceIndex = 0; deviceIndex < deviceCount; deviceIndex++)
{
CFTypeRef tCFTypeRef;
uint32_t vendorID = 0;
uint32_t productID = 0;
uint32_t countryCode = 0;
enum APPLE_KEYBOARD_TYPE ltype;
if (!tIOHIDDeviceRefs[deviceIndex])
continue;
inIOHIDDeviceRef = tIOHIDDeviceRefs[deviceIndex];
tCFTypeRef = IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDVendorIDKey));
if (tCFTypeRef)
CFNumberGetValue((CFNumberRef)tCFTypeRef, kCFNumberSInt32Type, &vendorID);
tCFTypeRef = IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDProductIDKey));
if (tCFTypeRef)
CFNumberGetValue((CFNumberRef)tCFTypeRef, kCFNumberSInt32Type, &productID);
tCFTypeRef = IOHIDDeviceGetProperty(inIOHIDDeviceRef, CFSTR(kIOHIDCountryCodeKey));
if (tCFTypeRef)
CFNumberGetValue((CFNumberRef)tCFTypeRef, kCFNumberSInt32Type, &countryCode);
ltype = mac_identify_keyboard_type(vendorID, productID);
if (ltype != APPLE_KEYBOARD_TYPE_ANSI)
{
type = ltype;
break;
}
}
free(tIOHIDDeviceRefs);
if (deviceCFSetRef)
{
CFRelease(deviceCFSetRef);
deviceCFSetRef = nullptr;
}
if (tIOHIDManagerRef)
CFRelease(tIOHIDManagerRef);
return type;
}

View File

@@ -0,0 +1,34 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* MacFreeRDP
*
* Copyright 2012 Thomas Goddard
*
* 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.
*/
#import <Cocoa/Cocoa.h>
#include "freerdp/graphics.h"
@interface MRDPCursor : NSObject
{
@public
rdpPointer *pointer;
BYTE *cursor_data;
NSBitmapImageRep *bmiRep;
NSCursor *nsCursor;
NSImage *nsImage;
}
@end

View File

@@ -0,0 +1,24 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* MacFreeRDP
*
* Copyright 2012 Thomas Goddard
*
* 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.
*/
#import "MRDPCursor.h"
@implementation MRDPCursor
@end

View File

@@ -0,0 +1,91 @@
#ifndef FREERDP_CLIENT_MAC_MRDPVIEW_H
#define FREERDP_CLIENT_MAC_MRDPVIEW_H
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* MacFreeRDP
*
* Copyright 2012 Thomas Goddard
*
* 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.
*/
#import <Cocoa/Cocoa.h>
#import "mfreerdp.h"
#import "mf_client.h"
#import "Keyboard.h"
#import <CoreGraphics/CoreGraphics.h>
@interface MRDPView : NSView
{
mfContext *mfc;
NSBitmapImageRep *bmiRep;
NSMutableArray *cursors;
NSMutableArray *windows;
NSTimer *pasteboard_timer;
NSCursor *currentCursor;
NSRect prevWinPosition;
freerdp *instance;
rdpContext *context;
CGContextRef bitmap_context;
char *pixel_data;
int argc;
char **argv;
DWORD kbdModFlags;
BOOL initialized;
NSPoint savedDragLocation;
BOOL firstCreateWindow;
BOOL isMoveSizeInProgress;
BOOL skipResizeOnce;
BOOL saveInitialDragLoc;
BOOL skipMoveWindowOnce;
@public
NSPasteboard *pasteboard_rd;
NSPasteboard *pasteboard_wr;
int pasteboard_changecount;
int pasteboard_format;
int is_connected;
}
- (int)rdpStart:(rdpContext *)rdp_context;
- (void)setCursor:(NSCursor *)cursor;
- (void)setScrollOffset:(int)xOffset y:(int)yOffset w:(int)width h:(int)height;
- (void)onPasteboardTimerFired:(NSTimer *)timer;
- (void)pause;
- (void)resume;
- (void)releaseResources;
@property(assign) int is_connected;
@end
BOOL mac_pre_connect(freerdp *instance);
BOOL mac_post_connect(freerdp *instance);
void mac_post_disconnect(freerdp *instance);
BOOL mac_authenticate_ex(freerdp *instance, char **username, char **password, char **domain,
rdp_auth_reason reason);
DWORD mac_verify_certificate_ex(freerdp *instance, const char *host, UINT16 port,
const char *common_name, const char *subject, const char *issuer,
const char *fingerprint, DWORD flags);
DWORD mac_verify_changed_certificate_ex(freerdp *instance, const char *host, UINT16 port,
const char *common_name, const char *subject,
const char *issuer, const char *fingerprint,
const char *old_subject, const char *old_issuer,
const char *old_fingerprint, DWORD flags);
int mac_logon_error_info(freerdp *instance, UINT32 data, UINT32 type);
#endif /* FREERDP_CLIENT_MAC_MRDPVIEW_H */

1542
third_party/FreeRDP/client/Mac/MRDPView.m vendored Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,3 @@
set(FREERDP_CLIENT_NAME "mfreerdp")
set(FREERDP_CLIENT_PLATFORM "MacOSX")
set(FREERDP_CLIENT_VENDOR "FreeRDP")

View File

@@ -0,0 +1,49 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* MacFreeRDP
*
* Copyright 2013 Christian Hofstaedtler
*
* 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.
*/
#import <Cocoa/Cocoa.h>
@interface PasswordDialog : NSWindowController
{
@public
NSTextField *usernameText;
NSTextField *passwordText;
NSTextField *messageLabel;
NSString *serverHostname;
NSString *username;
NSString *password;
NSString *domain;
BOOL modalCode;
}
@property(retain) IBOutlet NSTextField *usernameText;
@property(retain) IBOutlet NSTextField *passwordText;
@property(retain) IBOutlet NSTextField *messageLabel;
- (IBAction)onOK:(NSObject *)sender;
- (IBAction)onCancel:(NSObject *)sender;
@property(retain) NSString *serverHostname;
@property(retain) NSString *username;
@property(retain) NSString *password;
@property(retain) NSString *domain;
@property(readonly) BOOL modalCode;
- (BOOL)runModal:(NSWindow *)mainWindow;
@end

View File

@@ -0,0 +1,140 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* MacFreeRDP
*
* Copyright 2013 Christian Hofstaedtler
*
* 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.
*/
#import "PasswordDialog.h"
#import <freerdp/client/cmdline.h>
#import <CoreGraphics/CoreGraphics.h>
@interface PasswordDialog ()
@property BOOL modalCode;
@end
@implementation PasswordDialog
@synthesize usernameText;
@synthesize passwordText;
@synthesize messageLabel;
@synthesize serverHostname;
@synthesize username;
@synthesize password;
@synthesize domain;
@synthesize modalCode;
- (id)init
{
return [self initWithWindowNibName:@"PasswordDialog"];
}
- (void)windowDidLoad
{
[super windowDidLoad];
// Implement this method to handle any initialization after your window controller's window has
// been loaded from its nib file.
[self.window setTitle:self.serverHostname];
[self.messageLabel
setStringValue:[NSString stringWithFormat:@"Authenticate to %@", self.serverHostname]];
NSMutableString *domainUser = [[NSMutableString alloc] initWithString:@""];
if (self.domain != nil &&
[[self.domain stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]
length] > 0)
{
[domainUser appendFormat:@"%@\\", self.domain];
}
if (self.username != nil)
{
[domainUser appendString:self.username];
[self.window makeFirstResponder:self.passwordText];
}
[self.usernameText setStringValue:domainUser];
}
- (IBAction)onOK:(NSObject *)sender
{
char *submittedUser = nullptr;
char *submittedDomain = nullptr;
if (freerdp_parse_username(
[self.usernameText.stringValue cStringUsingEncoding:NSUTF8StringEncoding],
&submittedUser, &submittedDomain))
{
if (submittedUser)
self.username = [NSString stringWithCString:submittedUser
encoding:NSUTF8StringEncoding];
if (submittedDomain)
self.domain = [NSString stringWithCString:submittedDomain
encoding:NSUTF8StringEncoding];
}
else
{
self.username = self.usernameText.stringValue;
}
self.password = self.passwordText.stringValue;
free(submittedUser);
free(submittedDomain);
[NSApp stopModalWithCode:TRUE];
}
- (IBAction)onCancel:(NSObject *)sender
{
[NSApp stopModalWithCode:FALSE];
}
- (BOOL)runModal:(NSWindow *)mainWindow
{
if ([mainWindow respondsToSelector:@selector(beginSheet:completionHandler:)])
{
[mainWindow beginSheet:self.window completionHandler:nil];
self.modalCode = [NSApp runModalForWindow:self.window];
[mainWindow endSheet:self.window];
}
else
{
[NSApp beginSheet:self.window
modalForWindow:mainWindow
modalDelegate:nil
didEndSelector:nil
contextInfo:nil];
self.modalCode = [NSApp runModalForWindow:self.window];
[NSApp endSheet:self.window];
}
[self.window orderOut:nil];
return self.modalCode;
}
- (void)dealloc
{
[usernameText release];
[passwordText release];
[messageLabel release];
[serverHostname release];
[username release];
[password release];
[domain release];
[super dealloc];
}
@end

View File

@@ -0,0 +1,132 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="11201" systemVersion="16A323" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="11201"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="PasswordDialog">
<connections>
<outlet property="messageLabel" destination="7" id="50"/>
<outlet property="passwordText" destination="6" id="48"/>
<outlet property="usernameText" destination="11" id="49"/>
<outlet property="window" destination="1" id="3"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application"/>
<window title="Window" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" oneShot="NO" visibleAtLaunch="NO" animationBehavior="default" id="1">
<windowStyleMask key="styleMask" titled="YES" texturedBackground="YES"/>
<windowPositionMask key="initialPositionMask" leftStrut="YES" rightStrut="YES" topStrut="YES" bottomStrut="YES"/>
<rect key="contentRect" x="196" y="240" width="480" height="270"/>
<rect key="screenRect" x="0.0" y="0.0" width="1440" height="877"/>
<view key="contentView" id="2">
<rect key="frame" x="0.0" y="0.0" width="480" height="270"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="5">
<rect key="frame" x="47" y="127" width="106" height="17"/>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Password:" id="22">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<secureTextField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="6">
<rect key="frame" x="159" y="124" width="233" height="22"/>
<secureTextFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" borderStyle="bezel" placeholderString="Password" drawsBackground="YES" usesSingleLineMode="YES" id="21">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
<allowedInputSourceLocales>
<string>NSAllRomanInputSourcesLocaleIdentifier</string>
</allowedInputSourceLocales>
</secureTextFieldCell>
</secureTextField>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="7">
<rect key="frame" x="47" y="206" width="344" height="17"/>
<constraints>
<constraint firstAttribute="width" constant="340" id="19"/>
</constraints>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Connect to SERVER_NAME" placeholderString="" id="20">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="8">
<rect key="frame" x="384" y="13" width="82" height="32"/>
<buttonCell key="cell" type="push" title="Cancel" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="18">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent" base64-UTF8="YES">
Gw
</string>
</buttonCell>
<connections>
<action selector="onCancel:" target="-2" id="52"/>
</connections>
</button>
<button verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="9">
<rect key="frame" x="302" y="13" width="82" height="32"/>
<constraints>
<constraint firstAttribute="width" constant="70" id="16"/>
</constraints>
<buttonCell key="cell" type="push" title="OK" bezelStyle="rounded" alignment="center" borderStyle="border" imageScaling="proportionallyDown" inset="2" id="17">
<behavior key="behavior" pushIn="YES" lightByBackground="YES" lightByGray="YES"/>
<font key="font" metaFont="system"/>
<string key="keyEquivalent" base64-UTF8="YES">
DQ
</string>
</buttonCell>
<connections>
<action selector="onOK:" target="-2" id="51"/>
</connections>
</button>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="10">
<rect key="frame" x="47" y="159" width="106" height="17"/>
<constraints>
<constraint firstAttribute="width" constant="102" id="14"/>
</constraints>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" sendsActionOnEndEditing="YES" title="Username:" id="15">
<font key="font" metaFont="system"/>
<color key="textColor" name="controlTextColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="controlColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
<textField verticalHuggingPriority="750" translatesAutoresizingMaskIntoConstraints="NO" id="11">
<rect key="frame" x="159" y="156" width="233" height="22"/>
<constraints>
<constraint firstAttribute="width" constant="233" id="12"/>
</constraints>
<textFieldCell key="cell" scrollable="YES" lineBreakMode="clipping" selectable="YES" editable="YES" sendsActionOnEndEditing="YES" state="on" borderStyle="bezel" placeholderString="username@domain" drawsBackground="YES" id="13">
<font key="font" metaFont="system"/>
<color key="textColor" name="textColor" catalog="System" colorSpace="catalog"/>
<color key="backgroundColor" name="textBackgroundColor" catalog="System" colorSpace="catalog"/>
</textFieldCell>
</textField>
</subviews>
<constraints>
<constraint firstItem="6" firstAttribute="leading" secondItem="11" secondAttribute="leading" id="25"/>
<constraint firstItem="5" firstAttribute="centerY" secondItem="6" secondAttribute="centerY" id="27"/>
<constraint firstItem="6" firstAttribute="leading" secondItem="5" secondAttribute="trailing" constant="8" symbolic="YES" id="28"/>
<constraint firstItem="6" firstAttribute="trailing" secondItem="11" secondAttribute="trailing" id="30"/>
<constraint firstItem="11" firstAttribute="leading" secondItem="10" secondAttribute="trailing" constant="8" symbolic="YES" id="31"/>
<constraint firstItem="8" firstAttribute="leading" secondItem="9" secondAttribute="trailing" constant="12" symbolic="YES" id="32"/>
<constraint firstItem="10" firstAttribute="leading" secondItem="5" secondAttribute="leading" id="34"/>
<constraint firstItem="10" firstAttribute="leading" secondItem="7" secondAttribute="leading" id="37"/>
<constraint firstAttribute="bottom" secondItem="9" secondAttribute="bottom" constant="20" symbolic="YES" id="39"/>
<constraint firstItem="5" firstAttribute="centerY" secondItem="2" secondAttribute="centerY" id="41"/>
<constraint firstAttribute="bottom" secondItem="8" secondAttribute="bottom" constant="20" symbolic="YES" id="42"/>
<constraint firstAttribute="trailing" secondItem="8" secondAttribute="trailing" constant="20" symbolic="YES" id="43"/>
<constraint firstItem="7" firstAttribute="leading" secondItem="2" secondAttribute="leading" constant="49" id="44"/>
<constraint firstItem="7" firstAttribute="top" secondItem="2" secondAttribute="top" constant="47" id="45"/>
<constraint firstItem="6" firstAttribute="top" secondItem="11" secondAttribute="bottom" constant="10" symbolic="YES" id="46"/>
<constraint firstItem="10" firstAttribute="baseline" secondItem="11" secondAttribute="baseline" id="47"/>
</constraints>
</view>
<connections>
<outlet property="delegate" destination="-2" id="4"/>
</connections>
</window>
</objects>
</document>

View File

@@ -0,0 +1,26 @@
//
// AppDelegate.h
// MacClient2
//
// Created by Benoît et Kathy on 2013-05-08.
//
//
#import <Cocoa/Cocoa.h>
#import <MRDPView.h>
#import <mfreerdp.h>
@interface AppDelegate : NSObject <NSApplicationDelegate>
{
@public
NSWindow *window;
rdpContext *context;
MRDPView *mrdpView;
}
- (void)rdpConnectError:(NSString *)customMessage;
@property(assign) IBOutlet NSWindow *window;
@property(assign) rdpContext *context;
@end

View File

@@ -0,0 +1,325 @@
//
// AppDelegate.m
// MacClient2
//
// Created by Benoît et Kathy on 2013-05-08.
//
//
#import "AppDelegate.h"
#import <mfreerdp.h>
#import <mf_client.h>
#import <MRDPView.h>
#import <winpr/assert.h>
#import <freerdp/client/cmdline.h>
static AppDelegate *_singleDelegate = nil;
void AppDelegate_ConnectionResultEventHandler(void *context, const ConnectionResultEventArgs *e);
void AppDelegate_ErrorInfoEventHandler(void *ctx, const ErrorInfoEventArgs *e);
void AppDelegate_EmbedWindowEventHandler(void *context, const EmbedWindowEventArgs *e);
void AppDelegate_ResizeWindowEventHandler(void *context, const ResizeWindowEventArgs *e);
void mac_set_view_size(rdpContext *context, MRDPView *view);
@implementation AppDelegate
- (void)dealloc
{
[super dealloc];
}
@synthesize window = window;
@synthesize context = context;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
int status;
mfContext *mfc;
_singleDelegate = self;
[self CreateContext];
status = [self ParseCommandLineArguments];
mfc = (mfContext *)context;
WINPR_ASSERT(mfc);
mfc->view = (void *)mrdpView;
if (status == 0)
{
NSScreen *screen = [[NSScreen screens] objectAtIndex:0];
NSRect screenFrame = [screen frame];
rdpSettings *settings = context->settings;
WINPR_ASSERT(settings);
if (freerdp_settings_get_bool(settings, FreeRDP_Fullscreen))
{
(void)freerdp_settings_set_uint32(settings, FreeRDP_DesktopWidth,
screenFrame.size.width);
(void)freerdp_settings_set_uint32(settings, FreeRDP_DesktopHeight,
screenFrame.size.height);
}
PubSub_SubscribeConnectionResult(context->pubSub, AppDelegate_ConnectionResultEventHandler);
PubSub_SubscribeErrorInfo(context->pubSub, AppDelegate_ErrorInfoEventHandler);
PubSub_SubscribeEmbedWindow(context->pubSub, AppDelegate_EmbedWindowEventHandler);
PubSub_SubscribeResizeWindow(context->pubSub, AppDelegate_ResizeWindowEventHandler);
freerdp_client_start(context);
NSString *winTitle;
const char *WindowTitle = freerdp_settings_get_string(settings, FreeRDP_WindowTitle);
if (WindowTitle && WindowTitle[0])
{
winTitle = [[NSString alloc]
initWithFormat:@"%@", [NSString stringWithCString:WindowTitle
encoding:NSUTF8StringEncoding]];
}
else
{
const char *name = freerdp_settings_get_string(settings, FreeRDP_ServerHostname);
const UINT32 port = freerdp_settings_get_uint32(settings, FreeRDP_ServerPort);
winTitle = [[NSString alloc]
initWithFormat:@"%@:%u",
[NSString stringWithCString:name encoding:NSUTF8StringEncoding],
port];
}
[window setTitle:winTitle];
}
else
{
[NSApp terminate:self];
}
}
- (void)applicationWillBecomeActive:(NSNotification *)notification
{
[mrdpView resume];
}
- (void)applicationWillResignActive:(NSNotification *)notification
{
[mrdpView pause];
}
- (void)applicationWillTerminate:(NSNotification *)notification
{
NSLog(@"Stopping...\n");
freerdp_client_stop(context);
[mrdpView releaseResources];
_singleDelegate = nil;
NSLog(@"Stopped.\n");
[NSApp terminate:self];
}
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender
{
return YES;
}
- (BOOL)applicationSupportsSecureRestorableState:(NSApplication *)app
{
return YES;
}
- (int)ParseCommandLineArguments
{
int i;
int length;
int status;
char *cptr;
NSArray *args = [[NSProcessInfo processInfo] arguments];
context->argc = (int)[args count];
context->argv = malloc(sizeof(char *) * context->argc);
i = 0;
for (NSString *str in args)
{
/* filter out some arguments added by XCode */
if ([str isEqualToString:@"YES"])
continue;
if ([str isEqualToString:@"-NSDocumentRevisionsDebugMode"])
continue;
length = (int)([str lengthOfBytesUsingEncoding:NSUTF8StringEncoding] + 1);
cptr = (char *)malloc(length);
sprintf_s(cptr, length, "%s", [str UTF8String]);
context->argv[i++] = cptr;
}
context->argc = i;
status = freerdp_client_settings_parse_command_line(context->settings, context->argc,
context->argv, FALSE);
freerdp_client_settings_command_line_status_print(context->settings, status, context->argc,
context->argv);
return status;
}
- (void)CreateContext
{
RDP_CLIENT_ENTRY_POINTS clientEntryPoints = WINPR_C_ARRAY_INIT;
clientEntryPoints.Size = sizeof(RDP_CLIENT_ENTRY_POINTS);
clientEntryPoints.Version = RDP_CLIENT_INTERFACE_VERSION;
RdpClientEntry(&clientEntryPoints);
context = freerdp_client_context_new(&clientEntryPoints);
}
- (void)ReleaseContext
{
mfContext *mfc;
MRDPView *view;
mfc = (mfContext *)context;
view = (MRDPView *)mfc->view;
[view exitFullScreenModeWithOptions:nil];
[view releaseResources];
[view release];
mfc->view = nil;
freerdp_client_context_free(context);
context = nil;
}
/** *********************************************************************
* called when we fail to connect to a RDP server - Make sure this is called from the main thread.
***********************************************************************/
- (void)rdpConnectError:(NSString *)withMessage
{
mfContext *mfc;
MRDPView *view;
mfc = (mfContext *)context;
view = (MRDPView *)mfc->view;
[view exitFullScreenModeWithOptions:nil];
NSString *message = withMessage ? withMessage : @"Error connecting to server";
NSAlert *alert = [[NSAlert alloc] init];
[alert setMessageText:message];
[alert beginSheetModalForWindow:[self window]
modalDelegate:self
didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:)
contextInfo:nil];
}
/** *********************************************************************
* just a terminate selector for above call
***********************************************************************/
- (void)alertDidEnd:(NSAlert *)a returnCode:(NSInteger)rc contextInfo:(void *)ci
{
[NSApp terminate:nil];
}
@end
/** *********************************************************************
* On connection error, display message and quit application
***********************************************************************/
void AppDelegate_ConnectionResultEventHandler(void *ctx, const ConnectionResultEventArgs *e)
{
rdpContext *context = (rdpContext *)ctx;
NSLog(@"ConnectionResult event result:%d\n", e->result);
if (_singleDelegate)
{
if (e->result != 0)
{
NSString *message = nil;
DWORD code = freerdp_get_last_error(context);
switch (code)
{
case FREERDP_ERROR_AUTHENTICATION_FAILED:
message = [NSString
stringWithFormat:@"%@", @"Authentication failure, check credentials."];
break;
default:
break;
}
// Making sure this should be invoked on the main UI thread.
[_singleDelegate performSelectorOnMainThread:@selector(rdpConnectError:)
withObject:message
waitUntilDone:FALSE];
}
}
}
void AppDelegate_ErrorInfoEventHandler(void *ctx, const ErrorInfoEventArgs *e)
{
NSLog(@"ErrorInfo event code:%d\n", e->code);
if (_singleDelegate)
{
// Retrieve error message associated with error code
NSString *message = nil;
if (e->code != ERRINFO_NONE)
{
const char *errorMessage = freerdp_get_error_info_string(e->code);
message = [[NSString alloc] initWithUTF8String:errorMessage];
}
// Making sure this should be invoked on the main UI thread.
[_singleDelegate performSelectorOnMainThread:@selector(rdpConnectError:)
withObject:message
waitUntilDone:TRUE];
[message release];
}
}
void AppDelegate_EmbedWindowEventHandler(void *ctx, const EmbedWindowEventArgs *e)
{
rdpContext *context = (rdpContext *)ctx;
if (_singleDelegate)
{
mfContext *mfc = (mfContext *)context;
_singleDelegate->mrdpView = mfc->view;
if (_singleDelegate->window)
{
[[_singleDelegate->window contentView] addSubview:mfc->view];
}
dispatch_async(dispatch_get_main_queue(), ^{
mac_set_view_size(context, mfc->view);
});
}
}
void AppDelegate_ResizeWindowEventHandler(void *ctx, const ResizeWindowEventArgs *e)
{
rdpContext *context = (rdpContext *)ctx;
(void)fprintf(stderr, "ResizeWindowEventHandler: %d %d\n", e->width, e->height);
if (_singleDelegate)
{
mfContext *mfc = (mfContext *)context;
dispatch_async(dispatch_get_main_queue(), ^{
mac_set_view_size(context, mfc->view);
});
}
}
void mac_set_view_size(rdpContext *context, MRDPView *view)
{
// set client area to specified dimensions
NSRect innerRect;
innerRect.origin.x = 0;
innerRect.origin.y = 0;
innerRect.size.width = freerdp_settings_get_uint32(context->settings, FreeRDP_DesktopWidth);
innerRect.size.height = freerdp_settings_get_uint32(context->settings, FreeRDP_DesktopHeight);
[view setFrame:innerRect];
// calculate window of same size, but keep position
NSRect outerRect = [[view window] frame];
outerRect.size = [[view window] frameRectForContentRect:innerRect].size;
// we are not in RemoteApp mode, disable larger than resolution
[[view window] setContentMaxSize:innerRect.size];
// set window to given area
[[view window] setFrame:outerRect display:YES];
// set window to front
[NSApp activateIgnoringOtherApps:YES];
if (freerdp_settings_get_bool(context->settings, FreeRDP_Fullscreen))
[[view window] toggleFullScreen:nil];
}

View File

@@ -0,0 +1,88 @@
cmake_minimum_required(VERSION 3.13)
if(NOT FREERDP_DEFAULT_PROJECT_VERSION)
set(FREERDP_DEFAULT_PROJECT_VERSION "1.0.0.0")
endif()
project(MacFreeRDP VERSION ${FREERDP_DEFAULT_PROJECT_VERSION})
message("project ${PROJECT_NAME} is using version ${PROJECT_VERSION}")
list(APPEND CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/../../../cmake/)
include(CommonConfigOptions)
# Import libraries
find_library(FOUNDATION_LIBRARY Foundation REQUIRED)
find_library(COCOA_LIBRARY Cocoa REQUIRED)
find_library(APPKIT_LIBRARY AppKit REQUIRED)
string(TIMESTAMP VERSION_YEAR "%Y")
set(MACOSX_BUNDLE_INFO_STRING "MacFreeRDP")
set(MACOSX_BUNDLE_ICON_FILE "FreeRDP.icns")
set(MACOSX_BUNDLE_GUI_IDENTIFIER "com.freerdp.mac")
set(MACOSX_BUNDLE_BUNDLE_IDENTIFIER "FreeRDP-client.Mac")
set(MACOSX_BUNDLE_LONG_VERSION_STRING "MacFreeRDP Client Version ${FREERDP_VERSION}")
set(MACOSX_BUNDLE_BUNDLE_NAME "MacFreeRDP")
set(MACOSX_BUNDLE_SHORT_VERSION_STRING ${FREERDP_VERSION})
set(MACOSX_BUNDLE_BUNDLE_VERSION ${FREERDP_VERSION})
set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2013-${VERSION_YEAR}. All Rights Reserved.")
set(MACOSX_BUNDLE_NSMAIN_NIB_FILE "MainMenu")
set(MACOSX_BUNDLE_NSPRINCIPAL_CLASS "NSApplication")
set(XIBS MainMenu.xib)
set(SOURCES "")
set(OBJECTIVE_SOURCES main.m AppDelegate.m)
list(APPEND SOURCES ${OBJECTIVE_SOURCES})
set(HEADERS AppDelegate.h)
set(RESOURCES "en.lproj/InfoPlist.strings" ${MACOSX_BUNDLE_ICON_FILE})
# Include XIB file in Xcode resources.
if("${CMAKE_GENERATOR}" MATCHES "Xcode")
message(STATUS "Adding Xcode XIB resources for ${MODULE_NAME}")
list(APPEND RESOURCES ${XIBS})
set(IS_XCODE ON)
endif()
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in ${CMAKE_CURRENT_BINARY_DIR}/Info.plist @ONLY)
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/PkgInfo.in ${CMAKE_CURRENT_BINARY_DIR}/PkgInfo @ONLY)
add_executable(${PROJECT_NAME} ${HEADERS} ${SOURCES} ${RESOURCES})
if(WITH_BINARY_VERSIONING)
set_target_properties(${PROJECT_NAME} PROPERTIES OUTPUT_NAME "${PROJECT_NAME}${PROJECT_VERSION_MAJOR}")
endif()
set_target_properties(${PROJECT_NAME} PROPERTIES RESOURCE "${RESOURCES}")
set_target_properties(${PROJECT_NAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist)
target_link_libraries(
${PROJECT_NAME} PRIVATE ${COCOA_LIBRARY} ${FOUNDATION_LIBRARY} ${APPKIT_LIBRARY} MacFreeRDP-library
)
if(NOT IS_XCODE)
find_program(IBTOOL ibtool REQUIRED HINTS "/usr/bin" "${OSX_DEVELOPER_ROOT}/usr/bin")
# Compile the .xib files using the 'ibtool' program with the destination being the app package
foreach(xib ${XIBS})
get_filename_component(XIB_WE ${xib} NAME_WE)
set(NIB ${CMAKE_CURRENT_BINARY_DIR}/${XIB_WE}.nib)
list(APPEND NIBS ${NIB})
add_custom_command(
TARGET ${PROJECT_NAME} POST_BUILD COMMAND ${IBTOOL} --errors --warnings --notices --output-format
human-readable-text --compile ${NIB} ${CMAKE_CURRENT_SOURCE_DIR}/${xib}
COMMENT "Compiling ${xib}"
)
endforeach()
install(FILES ${NIBS} DESTINATION ${CMAKE_INSTALL_DATADIR})
endif()
install(TARGETS ${PROJECT_NAME} COMPONENT client RESOURCE DESTINATION ${CMAKE_INSTALL_DATADIR})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/Info.plist DESTINATION ${CMAKE_INSTALL_PREFIX})
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/PkgInfo DESTINATION ${CMAKE_INSTALL_PREFIX})

Binary file not shown.

View File

@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSCameraUsageDescription</key>
<string>This application requires camera access to redirect it to the remote host</string>
<key>NSMicrophoneUsageDescription</key>
<string>This application requires microphone access to redirect it to the remote host</string>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string></string>
<key>CFBundleIconFile</key>
<string>FreeRDP</string>
<key>CFBundleIdentifier</key>
<string>FreeRDP.Mac</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string></string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string></string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2012 __MyCompanyName__. All rights reserved.</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIconFile</key>
<string></string>
<key>CFBundleIdentifier</key>
<string>awakecoding.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSMinimumSystemVersion</key>
<string>${MACOSX_DEPLOYMENT_TARGET}</string>
<key>NSMainNibFile</key>
<string>MainMenu</string>
<key>NSPrincipalClass</key>
<string>NSApplication</string>
</dict>
</plist>

View File

@@ -0,0 +1,7 @@
//
// Prefix header for all source files of the 'MacClient2' target in the 'MacClient2' project
//
#ifdef __OBJC__
#import <Cocoa/Cocoa.h>
#endif

View File

@@ -0,0 +1,120 @@
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="14460.31" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
<dependencies>
<deployment identifier="macosx"/>
<plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="14460.31"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<objects>
<customObject id="-2" userLabel="File's Owner" customClass="NSApplication">
<connections>
<outlet property="delegate" destination="494" id="568"/>
</connections>
</customObject>
<customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
<customObject id="-3" userLabel="Application"/>
<menu title="AMainMenu" systemMenu="main" id="29">
<items>
<menuItem title="FreeRDP" id="56">
<menu key="submenu" title="FreeRDP" systemMenu="apple" id="57">
<items>
<menuItem title="About FreeRDP" id="58">
<modifierMask key="keyEquivalentModifierMask"/>
<connections>
<action selector="orderFrontStandardAboutPanel:" target="-2" id="142"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="236">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Hide FreeRDP" keyEquivalent="h" id="134">
<connections>
<action selector="hide:" target="-1" id="367"/>
</connections>
</menuItem>
<menuItem title="Hide Others" keyEquivalent="h" id="145">
<modifierMask key="keyEquivalentModifierMask" option="YES" command="YES"/>
<connections>
<action selector="hideOtherApplications:" target="-1" id="368"/>
</connections>
</menuItem>
<menuItem title="Show All" id="150">
<connections>
<action selector="unhideAllApplications:" target="-1" id="370"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="149">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Quit FreeRDP" keyEquivalent="q" id="136">
<connections>
<action selector="terminate:" target="-3" id="449"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="File" id="83"/>
<menuItem title="Edit" id="217"/>
<menuItem title="Format" id="375">
<modifierMask key="keyEquivalentModifierMask"/>
</menuItem>
<menuItem title="View" id="295"/>
<menuItem title="Window" id="19">
<menu key="submenu" title="Window" systemMenu="window" id="24">
<items>
<menuItem title="Minimize" keyEquivalent="m" id="23">
<connections>
<action selector="performMiniaturize:" target="-1" id="37"/>
</connections>
</menuItem>
<menuItem title="Zoom" id="239">
<connections>
<action selector="performZoom:" target="-1" id="240"/>
</connections>
</menuItem>
<menuItem isSeparatorItem="YES" id="92">
<modifierMask key="keyEquivalentModifierMask" command="YES"/>
</menuItem>
<menuItem title="Bring All to Front" id="5">
<connections>
<action selector="arrangeInFront:" target="-1" id="39"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
<menuItem title="Help" id="490">
<modifierMask key="keyEquivalentModifierMask"/>
<menu key="submenu" title="Help" systemMenu="help" id="491">
<items>
<menuItem title="Mac Help" keyEquivalent="?" id="492">
<connections>
<action selector="showHelp:" target="-1" id="493"/>
</connections>
</menuItem>
</items>
</menu>
</menuItem>
</items>
</menu>
<window title="FreeRDP" allowsToolTipsWhenApplicationIsInactive="NO" autorecalculatesKeyViewLoop="NO" releasedWhenClosed="NO" animationBehavior="default" id="371">
<windowStyleMask key="styleMask" titled="YES" closable="YES" miniaturizable="YES" resizable="YES"/>
<windowCollectionBehavior key="collectionBehavior" fullScreenPrimary="YES"/>
<rect key="contentRect" x="163" y="10" width="1024" height="768"/>
<rect key="screenRect" x="0.0" y="0.0" width="2560" height="1417"/>
<value key="minSize" type="size" width="1024" height="768"/>
<value key="maxSize" type="size" width="1024" height="768"/>
<view key="contentView" id="372">
<rect key="frame" x="0.0" y="0.0" width="1024" height="768"/>
<autoresizingMask key="autoresizingMask"/>
</view>
</window>
<customObject id="494" customClass="AppDelegate">
<connections>
<outlet property="window" destination="371" id="570"/>
</connections>
</customObject>
<customObject id="420" customClass="NSFontManager"/>
</objects>
</document>

View File

@@ -0,0 +1 @@
APPL????

View File

@@ -0,0 +1,29 @@
{\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;}
{\colortbl;\red255\green255\blue255;}
\paperw9840\paperh8400
\pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural
\f0\b\fs24 \cf0 Engineering:
\b0 \
Some people\
\
\b Human Interface Design:
\b0 \
Some other people\
\
\b Testing:
\b0 \
Hopefully not nobody\
\
\b Documentation:
\b0 \
Whoever\
\
\b With special thanks to:
\b0 \
Mom\
}

View File

@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,26 @@
//
// main.m
// MacClient2
//
// Created by Benoît et Kathy on 2013-05-08.
//
//
#import <Cocoa/Cocoa.h>
#include <freerdp/client/cmdline.h>
int main(int argc, char *argv[])
{
freerdp_client_warn_deprecated(argc, argv);
for (int i = 0; i < argc; i++)
{
char *ctemp = argv[i];
if (memcmp(ctemp, "/p:", 3) == 0 || memcmp(ctemp, "-p:", 3) == 0)
{
memset(ctemp + 3, '*', strlen(ctemp) - 3);
}
}
const char **cargv = (const char **)argv;
return NSApplicationMain(argc, cargv);
}

View File

@@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */

25
third_party/FreeRDP/client/Mac/main.m vendored Normal file
View File

@@ -0,0 +1,25 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* MacFreeRDP
*
* Copyright 2012 Thomas Goddard
*
* 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.
*/
#import <Cocoa/Cocoa.h>
int main(int argc, char *argv[])
{
return NSApplicationMain(argc, (const char *const *)argv);
}

View File

@@ -0,0 +1,46 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* Windows Client
*
* Copyright 2009-2011 Jay Sorg
* Copyright 2010-2011 Vic Lee
* Copyright 2010-2011 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.
*/
#ifndef FREERDP_CLIENT_MAC_CLIENT_H
#define FREERDP_CLIENT_MAC_CLIENT_H
#include <freerdp/client.h>
#ifdef __cplusplus
extern "C"
{
#endif
FREERDP_API void mf_press_mouse_button(void* context, int button, int x, int y, BOOL down);
FREERDP_API void mf_scale_mouse_event(void* context, UINT16 flags, UINT16 x, UINT16 y);
FREERDP_API void mf_scale_mouse_event_ex(void* context, UINT16 flags, UINT16 x, UINT16 y);
/**
* Client Interface
*/
FREERDP_API int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS* pEntryPoints);
#ifdef __cplusplus
}
#endif
#endif /* FREERDP_CLIENT_MAC_CLIENT_H */

View File

@@ -0,0 +1,220 @@
/**
* FreeRDP: A Remote Desktop Protocol Implementation
* X11 Client Interface
*
* Copyright 2013 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 <freerdp/config.h>
#include "mfreerdp.h"
#include <winpr/assert.h>
#include <freerdp/constants.h>
#include <freerdp/utils/signal.h>
#include <freerdp/client/cmdline.h>
#include "MRDPView.h"
/**
* Client Interface
*/
static BOOL mfreerdp_client_global_init(void)
{
freerdp_handle_signals();
return TRUE;
}
static void mfreerdp_client_global_uninit(void)
{
}
static int mfreerdp_client_start(rdpContext *context)
{
MRDPView *view;
mfContext *mfc = (mfContext *)context;
if (mfc->view == nullptr)
{
// view not specified beforehand. Create view dynamically
mfc->view = [[MRDPView alloc]
initWithFrame:NSMakeRect(
0, 0,
freerdp_settings_get_uint32(context->settings, FreeRDP_DesktopWidth),
freerdp_settings_get_uint32(context->settings,
FreeRDP_DesktopHeight))];
mfc->view_ownership = TRUE;
}
view = (MRDPView *)mfc->view;
return [view rdpStart:context];
}
static int mfreerdp_client_stop(rdpContext *context)
{
mfContext *mfc = (mfContext *)context;
freerdp_client_common_stop(context);
if (mfc->view_ownership)
{
MRDPView *view = (MRDPView *)mfc->view;
[view releaseResources];
[view release];
mfc->view = nil;
}
return 0;
}
static BOOL mfreerdp_client_new(freerdp *instance, rdpContext *context)
{
mfContext *mfc;
WINPR_ASSERT(instance);
mfc = (mfContext *)instance->context;
WINPR_ASSERT(mfc);
mfc->stopEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr);
if (!mfc->stopEvent)
return FALSE;
context->instance->PreConnect = mac_pre_connect;
context->instance->PostConnect = mac_post_connect;
context->instance->PostDisconnect = mac_post_disconnect;
context->instance->AuthenticateEx = mac_authenticate_ex;
context->instance->VerifyCertificateEx = mac_verify_certificate_ex;
context->instance->VerifyChangedCertificateEx = mac_verify_changed_certificate_ex;
context->instance->LogonErrorInfo = mac_logon_error_info;
return TRUE;
}
static void mfreerdp_client_free(freerdp *instance, rdpContext *context)
{
mfContext *mfc;
if (!instance || !context)
return;
mfc = (mfContext *)instance->context;
(void)CloseHandle(mfc->stopEvent);
}
static void mf_scale_mouse_coordinates(mfContext *mfc, UINT16 *px, UINT16 *py)
{
UINT16 x = *px;
UINT16 y = *py;
UINT32 ww = mfc->client_width;
UINT32 wh = mfc->client_height;
UINT32 dw = freerdp_settings_get_uint32(mfc->common.context.settings, FreeRDP_DesktopWidth);
UINT32 dh = freerdp_settings_get_uint32(mfc->common.context.settings, FreeRDP_DesktopHeight);
if (!freerdp_settings_get_bool(mfc->common.context.settings, FreeRDP_SmartSizing) ||
((ww == dw) && (wh == dh)))
{
y = y + mfc->yCurrentScroll;
x = x + mfc->xCurrentScroll;
y -= (dh - wh);
x -= (dw - ww);
}
else
{
y = y * dh / wh + mfc->yCurrentScroll;
x = x * dw / ww + mfc->xCurrentScroll;
}
*px = x;
*py = y;
}
void mf_scale_mouse_event(void *context, UINT16 flags, UINT16 x, UINT16 y)
{
mfContext *mfc = (mfContext *)context;
MRDPView *view = (MRDPView *)mfc->view;
// Convert to windows coordinates
y = [view frame].size.height - y;
if ((flags & (PTR_FLAGS_WHEEL | PTR_FLAGS_HWHEEL)) == 0)
mf_scale_mouse_coordinates(mfc, &x, &y);
freerdp_client_send_button_event(&mfc->common, FALSE, flags, x, y);
}
void mf_scale_mouse_event_ex(void *context, UINT16 flags, UINT16 x, UINT16 y)
{
mfContext *mfc = (mfContext *)context;
MRDPView *view = (MRDPView *)mfc->view;
// Convert to windows coordinates
y = [view frame].size.height - y;
mf_scale_mouse_coordinates(mfc, &x, &y);
freerdp_client_send_extended_button_event(&mfc->common, FALSE, flags, x, y);
}
void mf_press_mouse_button(void *context, int button, int x, int y, BOOL down)
{
UINT16 flags = 0;
UINT16 xflags = 0;
if (down)
{
flags |= PTR_FLAGS_DOWN;
xflags |= PTR_XFLAGS_DOWN;
}
switch (button)
{
case 0:
mf_scale_mouse_event(context, flags | PTR_FLAGS_BUTTON1, x, y);
break;
case 1:
mf_scale_mouse_event(context, flags | PTR_FLAGS_BUTTON2, x, y);
break;
case 2:
mf_scale_mouse_event(context, flags | PTR_FLAGS_BUTTON3, x, y);
break;
case 3:
mf_scale_mouse_event_ex(context, xflags | PTR_XFLAGS_BUTTON1, x, y);
break;
case 4:
mf_scale_mouse_event_ex(context, xflags | PTR_XFLAGS_BUTTON2, x, y);
break;
default:
break;
}
}
int RdpClientEntry(RDP_CLIENT_ENTRY_POINTS *pEntryPoints)
{
WINPR_ASSERT(pEntryPoints);
pEntryPoints->Version = 1;
pEntryPoints->Size = sizeof(RDP_CLIENT_ENTRY_POINTS_V1);
pEntryPoints->GlobalInit = mfreerdp_client_global_init;
pEntryPoints->GlobalUninit = mfreerdp_client_global_uninit;
pEntryPoints->ContextSize = sizeof(mfContext);
pEntryPoints->ClientNew = mfreerdp_client_new;
pEntryPoints->ClientFree = mfreerdp_client_free;
pEntryPoints->ClientStart = mfreerdp_client_start;
pEntryPoints->ClientStop = mfreerdp_client_stop;
return 0;
}

View File

@@ -0,0 +1,86 @@
#ifndef FREERDP_CLIENT_MAC_FREERDP_H
#define FREERDP_CLIENT_MAC_FREERDP_H
#include <freerdp/freerdp.h>
#include <freerdp/client/file.h>
#include <freerdp/api.h>
#include <freerdp/freerdp.h>
#include <freerdp/gdi/gdi.h>
#include <freerdp/gdi/dc.h>
#include <freerdp/gdi/gfx.h>
#include <freerdp/gdi/region.h>
#include <freerdp/channels/channels.h>
#include <freerdp/client/channels.h>
#include <freerdp/client/rdpei.h>
#include <freerdp/client/rdpgfx.h>
#include <freerdp/client/cliprdr.h>
#include <freerdp/client/encomsp.h>
#include <winpr/crt.h>
#include <winpr/synch.h>
#include <winpr/thread.h>
#include <winpr/clipboard.h>
#include "Keyboard.h"
#include <CoreGraphics/CoreGraphics.h>
typedef struct
{
rdpClientContext common;
void* view;
BOOL view_ownership;
int width;
int height;
int offset_x;
int offset_y;
int fs_toggle;
int fullscreen;
int percentscreen;
char window_title[64];
int client_x;
int client_y;
int client_width;
int client_height;
HANDLE stopEvent;
HANDLE keyboardThread;
enum APPLE_KEYBOARD_TYPE appleKeyboardType;
DWORD mainThreadId;
DWORD keyboardThreadId;
BOOL clipboardSync;
wClipboard* clipboard;
UINT32 numServerFormats;
UINT32 requestedFormatId;
HANDLE clipboardRequestEvent;
CLIPRDR_FORMAT* serverFormats;
CliprdrClientContext* cliprdr;
UINT32 clipboardCapabilities;
rdpFile* connectionRdpFile;
// Keep track of window size and position, disable when in fullscreen mode.
BOOL disablewindowtracking;
// These variables are required for horizontal scrolling.
BOOL updating_scrollbars;
BOOL xScrollVisible;
int xMinScroll; // minimum horizontal scroll value
int xCurrentScroll; // current horizontal scroll value
int xMaxScroll; // maximum horizontal scroll value
// These variables are required for vertical scrolling.
BOOL yScrollVisible;
int yMinScroll; // minimum vertical scroll value
int yCurrentScroll; // current vertical scroll value
int yMaxScroll; // maximum vertical scroll value
CGEventFlags kbdFlags;
} mfContext;
#endif /* FREERDP_CLIENT_MAC_FREERDP_H */