From a0de1b18bdd7ddc606320d34af83bd0111e06978 Mon Sep 17 00:00:00 2001 From: Martin Fleisz Date: Wed, 6 Mar 2013 13:33:09 +0100 Subject: [PATCH 01/11] core: Correct handling of MultifragMaxRequestSize (Fixes #1022) --- libfreerdp/core/capabilities.c | 5 ++++- libfreerdp/core/fastpath.c | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/libfreerdp/core/capabilities.c b/libfreerdp/core/capabilities.c index 5cec55fbd..da67ef59b 100644 --- a/libfreerdp/core/capabilities.c +++ b/libfreerdp/core/capabilities.c @@ -2190,10 +2190,13 @@ BOOL rdp_print_desktop_composition_capability_set(STREAM* s, UINT16 length) BOOL rdp_read_multifragment_update_capability_set(STREAM* s, UINT16 length, rdpSettings* settings) { + UINT32 multifragMaxRequestSize; if (length < 8) return FALSE; - stream_read_UINT32(s, settings->MultifragMaxRequestSize); /* MaxRequestSize (4 bytes) */ + stream_read_UINT32(s, multifragMaxRequestSize); /* MaxRequestSize (4 bytes) */ + if (settings->MultifragMaxRequestSize < multifragMaxRequestSize) + settings->MultifragMaxRequestSize = multifragMaxRequestSize; return TRUE; } diff --git a/libfreerdp/core/fastpath.c b/libfreerdp/core/fastpath.c index f2e67a96b..e37fed785 100644 --- a/libfreerdp/core/fastpath.c +++ b/libfreerdp/core/fastpath.c @@ -340,7 +340,7 @@ static int fastpath_recv_update_data(rdpFastPath* fastpath, STREAM* s) stream_check_size(fastpath->updateData, size); stream_copy(fastpath->updateData, comp_stream, size); - if (stream_get_size(fastpath->updateData) > rdp->settings->MultifragMaxRequestSize) + if (stream_get_length(fastpath->updateData) > rdp->settings->MultifragMaxRequestSize) { printf("fastpath PDU is bigger than MultifragMaxRequestSize\n"); return -1; From bcbb80fc19108a7034910d440aa5a111c8430df1 Mon Sep 17 00:00:00 2001 From: blazee Date: Sun, 10 Mar 2013 12:51:36 +0100 Subject: [PATCH 02/11] Android: Add basic .RDP file support --- .../domain/ConnectionReference.java | 13 +++ .../presentation/BookmarkActivity.java | 75 +++++++++++++ .../presentation/HomeActivity.java | 24 ++++- .../freerdpcore/utils/RDPFileParser.java | 101 ++++++++++++++++++ .../aFreeRDP/AndroidManifest.xml.cmake | 15 +++ 5 files changed, 224 insertions(+), 4 deletions(-) create mode 100644 client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/RDPFileParser.java diff --git a/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/ConnectionReference.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/ConnectionReference.java index 270139c51..4e4442dd7 100644 --- a/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/ConnectionReference.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/domain/ConnectionReference.java @@ -14,6 +14,7 @@ public class ConnectionReference public static final String PATH_MANUAL_BOOKMARK_ID = "MBMID/"; public static final String PATH_HOSTNAME = "HOST/"; public static final String PATH_PLACEHOLDER = "PLCHLD/"; + public static final String PATH_FILE = "FILE/"; public static String getManualBookmarkReference(long bookmarkId) { return (PATH_MANUAL_BOOKMARK_ID + bookmarkId); @@ -27,6 +28,10 @@ public class ConnectionReference return (PATH_PLACEHOLDER + name); } + public static String getFileReference(String uri) { + return (PATH_FILE + uri); + } + public static boolean isBookmarkReference(String refStr) { return refStr.startsWith(PATH_MANUAL_BOOKMARK_ID); } @@ -43,6 +48,10 @@ public class ConnectionReference return refStr.startsWith(PATH_PLACEHOLDER); } + public static boolean isFileReference(String refStr) { + return refStr.startsWith(PATH_FILE); + } + public static long getManualBookmarkId(String refStr) { return Integer.parseInt(refStr.substring(PATH_MANUAL_BOOKMARK_ID.length())); } @@ -54,4 +63,8 @@ public class ConnectionReference public static String getPlaceholder(String refStr) { return refStr.substring(PATH_PLACEHOLDER.length()); } + + public static String getFile(String refStr) { + return refStr.substring(PATH_FILE.length()); + } } diff --git a/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/BookmarkActivity.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/BookmarkActivity.java index 078852f3b..4d938f419 100644 --- a/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/BookmarkActivity.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/BookmarkActivity.java @@ -9,12 +9,16 @@ package com.freerdp.freerdpcore.presentation; +import java.io.File; +import java.io.IOException; + import com.freerdp.freerdpcore.R; import com.freerdp.freerdpcore.application.GlobalApp; import com.freerdp.freerdpcore.domain.BookmarkBase; import com.freerdp.freerdpcore.domain.ConnectionReference; import com.freerdp.freerdpcore.domain.ManualBookmark; import com.freerdp.freerdpcore.services.BookmarkBaseGateway; +import com.freerdp.freerdpcore.utils.RDPFileParser; import android.app.AlertDialog; import android.content.ComponentName; @@ -25,11 +29,14 @@ import android.os.Bundle; import android.preference.ListPreference; import android.preference.Preference; import android.preference.PreferenceActivity; +import android.util.Log; public class BookmarkActivity extends PreferenceActivity implements OnSharedPreferenceChangeListener { public static final String PARAM_CONNECTION_REFERENCE = "conRef"; + private static final String TAG = "BookmarkActivity"; + private int current_preferences; private static final int PREFERENCES_BOOKMARK = 1; private static final int PREFERENCES_CREDENTIALS = 2; @@ -78,6 +85,26 @@ public class BookmarkActivity extends PreferenceActivity implements OnSharedPref bookmark.get().setHostname(ConnectionReference.getHostname(refStr)); new_bookmark = true; } + else if (ConnectionReference.isFileReference(refStr)) + { + String file = ConnectionReference.getFile(refStr); + + bookmark = new ManualBookmark(); + bookmark.setLabel(file); + + try + { + RDPFileParser rdpFile = new RDPFileParser(file); + updateBookmarkFromFile((ManualBookmark)bookmark, rdpFile); + + bookmark.setLabel(new File(file).getName()); + new_bookmark = true; + } + catch (IOException e) + { + Log.e(TAG, "Failed reading RDP file", e); + } + } } } @@ -144,6 +171,54 @@ public class BookmarkActivity extends PreferenceActivity implements OnSharedPref setIntentComponentNames(); } + private void updateBookmarkFromFile(ManualBookmark bookmark, RDPFileParser rdpFile) + { + String s; + Integer i; + + s = rdpFile.getString("full address"); + if (s != null) + { + // this gets complicated as it can include port + if (s.lastIndexOf(":") > s.lastIndexOf("]")) + { + try + { + String port = s.substring(s.lastIndexOf(":") + 1); + bookmark.setPort(Integer.parseInt(port)); + } + catch (NumberFormatException e) + { + Log.e(TAG, "Malformed address"); + } + + s = s.substring(0, s.lastIndexOf(":")); + } + + // or even be an ipv6 address + if (s.startsWith("[") && s.endsWith("]")) + s = s.substring(1, s.length() - 1); + + bookmark.setHostname(s); + } + + i = rdpFile.getInteger("server port"); + if (i != null) + bookmark.setPort(i); + + s = rdpFile.getString("username"); + if (s != null) + bookmark.setUsername(s); + + s = rdpFile.getString("domain"); + if (s != null) + bookmark.setDomain(s); + + i = rdpFile.getInteger("connect to console"); + if (i != null) + bookmark.getAdvancedSettings().setConsoleMode(i == 1); + } + private void setIntentComponentNames() { // we set the component name for our sub-activity calls here because we don't know the package diff --git a/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/HomeActivity.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/HomeActivity.java index 8abd471c9..6330cb18e 100644 --- a/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/HomeActivity.java +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/presentation/HomeActivity.java @@ -26,26 +26,27 @@ import android.app.AlertDialog; import android.content.DialogInterface; import android.content.Intent; import android.content.res.Configuration; +import android.net.Uri; import android.os.Bundle; import android.text.Editable; import android.text.TextWatcher; import android.util.Log; +import android.view.ContextMenu; +import android.view.ContextMenu.ContextMenuInfo; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.View; -import android.view.ContextMenu; import android.view.View.OnClickListener; -import android.view.ContextMenu.ContextMenuInfo; import android.view.View.OnCreateContextMenuListener; import android.webkit.WebView; import android.webkit.WebViewClient; +import android.widget.AdapterView; +import android.widget.AdapterView.AdapterContextMenuInfo; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.ListView; -import android.widget.AdapterView; -import android.widget.AdapterView.AdapterContextMenuInfo; public class HomeActivity extends Activity { @@ -87,6 +88,21 @@ public class HomeActivity extends Activity addBookmarkPlaceholder.setName(ADD_BOOKMARK_PLACEHOLDER); addBookmarkPlaceholder.setLabel(getResources().getString(R.string.list_placeholder_add_bookmark)); + // check for passed .rdp file and open it in a new bookmark + Intent caller = getIntent(); + Uri callParameter = caller.getData(); + + if (Intent.ACTION_VIEW.equals(caller.getAction()) && callParameter != null) + { + String refStr = ConnectionReference.getFileReference(callParameter.getPath()); + Bundle bundle = new Bundle(); + bundle.putString(BookmarkActivity.PARAM_CONNECTION_REFERENCE, refStr); + + Intent bookmarkIntent = new Intent(this.getApplicationContext(), BookmarkActivity.class); + bookmarkIntent.putExtras(bundle); + startActivity(bookmarkIntent); + } + // load views clearTextButton = (Button) findViewById(R.id.clear_search_btn); superBarEditText = (EditText) findViewById(R.id.superBarEditText); diff --git a/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/RDPFileParser.java b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/RDPFileParser.java new file mode 100644 index 000000000..a903ed2eb --- /dev/null +++ b/client/Android/FreeRDPCore/src/com/freerdp/freerdpcore/utils/RDPFileParser.java @@ -0,0 +1,101 @@ +/* + Simple .RDP file parser + + Copyright 2013 Blaz Bacnik + + This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. + If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. +*/ + +package com.freerdp.freerdpcore.utils; + +import java.io.BufferedReader; +import java.io.FileReader; +import java.io.IOException; +import java.util.HashMap; +import java.util.Locale; + +public class RDPFileParser { + + private static final int MAX_ERRORS = 20; + private static final int MAX_LINES = 500; + + private HashMap options; + + private void init() + { + options = new HashMap(); + } + + public RDPFileParser() + { + init(); + } + + public RDPFileParser(String filename) throws IOException + { + init(); + parse(filename); + } + + public void parse(String filename) throws IOException + { + BufferedReader br = new BufferedReader(new FileReader(filename)); + String line = null; + + int errors = 0; + int lines = 0; + boolean ok; + + while ((line = br.readLine()) != null) + { + lines++; ok = false; + + if (errors > MAX_ERRORS || lines > MAX_LINES) + throw new IOException("Parsing limits exceeded"); + + String[] fields = line.split(":", 3); + + if (fields.length == 3) + { + if (fields[1].equals("s")) + { + options.put(fields[0].toLowerCase(Locale.ENGLISH), fields[2]); + ok = true; + } + else if (fields[1].equals("i")) + { + try + { + Integer i = Integer.parseInt(fields[2]); + options.put(fields[0].toLowerCase(Locale.ENGLISH), i); + ok = true; + } + catch (NumberFormatException e) { } + } + else if (fields[1].equals("b")) + { + ok = true; + } + } + + if (!ok) errors++; + } + } + + public String getString(String optionName) + { + if (options.get(optionName) instanceof String) + return (String) options.get(optionName); + else + return null; + } + + public Integer getInteger(String optionName) + { + if (options.get(optionName) instanceof Integer) + return (Integer) options.get(optionName); + else + return null; + } +} diff --git a/client/Android/aFreeRDP/AndroidManifest.xml.cmake b/client/Android/aFreeRDP/AndroidManifest.xml.cmake index e0d01c824..f63717dd8 100644 --- a/client/Android/aFreeRDP/AndroidManifest.xml.cmake +++ b/client/Android/aFreeRDP/AndroidManifest.xml.cmake @@ -23,6 +23,21 @@ + + + + + + + + + + From d94369291402088faca0044a98651e1cbbe35f8c Mon Sep 17 00:00:00 2001 From: blazee Date: Sun, 10 Mar 2013 14:41:11 +0100 Subject: [PATCH 03/11] Android: Fix build --- client/Android/FreeRDPCore/jni/android_freerdp.c | 4 ++-- client/Android/aFreeRDP/CMakeLists.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/Android/FreeRDPCore/jni/android_freerdp.c b/client/Android/FreeRDPCore/jni/android_freerdp.c index cf7945374..d571e1083 100644 --- a/client/Android/FreeRDPCore/jni/android_freerdp.c +++ b/client/Android/FreeRDPCore/jni/android_freerdp.c @@ -796,12 +796,12 @@ JNIEXPORT jboolean JNICALL jni_freerdp_update_graphics( JNIEXPORT void JNICALL jni_freerdp_send_key_event( JNIEnv *env, jclass cls, jint instance, jint keycode, jboolean down) { - RDP_SCANCODE scancode; + DWORD scancode; ANDROID_EVENT* event; freerdp* inst = (freerdp*)instance; - scancode = freerdp_keyboard_get_rdp_scancode_from_virtual_key_code(keycode); + scancode = GetVirtualScanCodeFromVirtualKeyCode(keycode, 4); int flags = (down == JNI_TRUE) ? KBD_FLAGS_DOWN : KBD_FLAGS_RELEASE; flags |= (RDP_SCANCODE_EXTENDED(scancode)) ? KBD_FLAGS_EXTENDED : 0; event = (ANDROID_EVENT*) android_event_key_new(flags, RDP_SCANCODE_CODE(scancode)); diff --git a/client/Android/aFreeRDP/CMakeLists.txt b/client/Android/aFreeRDP/CMakeLists.txt index 9dd3b6179..d17533b75 100644 --- a/client/Android/aFreeRDP/CMakeLists.txt +++ b/client/Android/aFreeRDP/CMakeLists.txt @@ -38,7 +38,7 @@ if(ANDROID_BUILD_JAVA) COMMAND ${ANT_COMMAND} ${ANDROID_BUILD_TYPE} WORKING_DIRECTORY "${ANDROID_SOURCE_DIR}" MAIN_DEPENDENCY AndroidManifest.xml - DEPENDS freerdp-android local.properties android-lib + DEPENDS freerdp-android local.properties #android-lib ) add_custom_target(android-package ALL SOURCES "${APK}") SET_DIRECTORY_PROPERTIES(PROPERTIES ADDITIONAL_MAKE_CLEAN_FILES "gen;bin") From 7696388c4dd7df8527b31929fb97e5e4f48ea310 Mon Sep 17 00:00:00 2001 From: Christian Hofstaedtler Date: Mon, 11 Mar 2013 02:25:14 +0100 Subject: [PATCH 04/11] add Password Dialog files --- client/Mac/PasswordDialog.h | 26 + client/Mac/PasswordDialog.m | 56 ++ client/Mac/PasswordDialog.xib | 976 ++++++++++++++++++++++++++++++++++ 3 files changed, 1058 insertions(+) create mode 100644 client/Mac/PasswordDialog.h create mode 100644 client/Mac/PasswordDialog.m create mode 100644 client/Mac/PasswordDialog.xib diff --git a/client/Mac/PasswordDialog.h b/client/Mac/PasswordDialog.h new file mode 100644 index 000000000..db294d667 --- /dev/null +++ b/client/Mac/PasswordDialog.h @@ -0,0 +1,26 @@ +// +// PasswordDialog.h +// FreeRDP +// +// Created by Christian Hofstaedtler on 3/10/13. +// +// + +#import + +@interface PasswordDialog : NSWindowController + +@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* serverName; +@property (retain) NSString* userName; +@property (retain) NSString* password; + +- (BOOL) runModal; + +@end diff --git a/client/Mac/PasswordDialog.m b/client/Mac/PasswordDialog.m new file mode 100644 index 000000000..757ee0732 --- /dev/null +++ b/client/Mac/PasswordDialog.m @@ -0,0 +1,56 @@ +// +// PasswordDialog.m +// FreeRDP +// +// Created by Christian Hofstaedtler on 3/10/13. +// +// + +#import "PasswordDialog.h" + +@interface PasswordDialog () + +@end + +@implementation PasswordDialog + +@synthesize userNameText; +@synthesize passwordText; +@synthesize messageLabel; +@synthesize serverName; +@synthesize userName; +@synthesize password; + +- (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.serverName]; + [messageLabel setStringValue:[NSString stringWithFormat:@"Authenticate to %@", self.serverName]]; + if (self.userName != nil) { + [userNameText setStringValue:self.userName]; + [self.window makeFirstResponder:passwordText]; + } +} + +- (IBAction)onOK:(NSObject *)sender { + self.userName = self.userNameText.stringValue; + self.password = self.passwordText.stringValue; + [self.window orderOut:nil]; + [NSApp stopModalWithCode:TRUE]; +} + +- (IBAction)onCancel:(NSObject *)sender { + [self.window orderOut:nil]; + [NSApp stopModalWithCode:FALSE]; +} + +- (BOOL) runModal { + return [NSApp runModalForWindow:self.window]; +} + +@end diff --git a/client/Mac/PasswordDialog.xib b/client/Mac/PasswordDialog.xib new file mode 100644 index 000000000..3e1e08673 --- /dev/null +++ b/client/Mac/PasswordDialog.xib @@ -0,0 +1,976 @@ + + + + 1080 + 12C60 + 3084 + 1187.34 + 625.00 + + com.apple.InterfaceBuilder.CocoaPlugin + 3084 + + + IBNSLayoutConstraint + NSButton + NSButtonCell + NSCustomObject + NSSecureTextField + NSSecureTextFieldCell + NSTextField + NSTextFieldCell + NSView + NSWindowTemplate + + + com.apple.InterfaceBuilder.CocoaPlugin + + + PluginDependencyRecalculationVersion + + + + + PasswordDialog + + + FirstResponder + + + NSApplication + + + 257 + 2 + {{196, 240}, {480, 270}} + 544735232 + Window + NSWindow + + + + + 256 + + + + 268 + {{46, 127}, {108, 17}} + + + _NS:1535 + YES + + 68157504 + 272630784 + Password: + + LucidaGrande + 13 + 1044 + + _NS:1535 + + + 6 + System + controlColor + + 3 + MC42NjY2NjY2NjY3AA + + + + 6 + System + controlTextColor + + 3 + MAA + + + + NO + + + + 268 + {{159, 124}, {233, 22}} + + + _NS:9 + YES + + 342884416 + 272630848 + + + Password + _NS:9 + + YES + + 6 + System + textBackgroundColor + + 3 + MQA + + + + 6 + System + textColor + + + + NSAllRomanInputSourcesLocaleIdentifier + + + NO + + + + 268 + {{46, 206}, {346, 17}} + + + _NS:1535 + YES + + 68157504 + 272630784 + Connect to SERVER_NAME + + + _NS:1535 + + + + + NO + + + + 268 + {{384, 13}, {82, 32}} + + + _NS:9 + YES + + 67108864 + 134217728 + Cancel + + _NS:9 + + -2038284288 + 129 + + Gw + 200 + 25 + + NO + + + + 268 + {{302, 13}, {82, 32}} + + + _NS:9 + YES + + 67108864 + 134217728 + OK + + _NS:9 + + -2038284288 + 129 + + + DQ + 200 + 25 + + NO + + + + 268 + {{46, 158}, {108, 17}} + + + _NS:1535 + YES + + 68157504 + 272630784 + Username: + + _NS:1535 + + + + + NO + + + + 268 + {{159, 156}, {233, 22}} + + + _NS:9 + YES + + -1804599231 + 272630784 + + + billg + _NS:9 + + YES + + + + NO + + + {480, 270} + + + + {{0, 0}, {1440, 878}} + {10000000000000, 10000000000000} + YES + + + + + + + window + + + + 3 + + + + passwordText + + + + 48 + + + + usernameText + + + + 49 + + + + messageLabel + + + + 50 + + + + onOK: + + + + 51 + + + + onCancel: + + + + 52 + + + + userNameText + + + + 53 + + + + delegate + + + + 4 + + + + + + 0 + + + + + + -2 + + + File's Owner + + + -1 + + + First Responder + + + -3 + + + Application + + + 1 + + + + + + + + 2 + + + + + 6 + 0 + + 6 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 4 + 0 + + 4 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 5 + 0 + + 6 + 1 + + 12 + + 1000 + + 6 + 24 + 3 + + + + 4 + 0 + + 4 + 1 + + 20 + + 1000 + + 8 + 29 + 3 + + + + 3 + 0 + + 4 + 1 + + 10 + + 1000 + + 6 + 24 + 3 + + + + 6 + 0 + + 6 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 5 + 0 + + 6 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 5 + 0 + + 5 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 5 + 0 + + 6 + 1 + + 8 + + 1000 + + 6 + 24 + 3 + + + + 10 + 0 + + 10 + 1 + + 0.0 + + 1000 + + 5 + 22 + 2 + + + + 10 + 0 + + 10 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 11 + 0 + + 11 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 5 + 0 + + 5 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 5 + 0 + + 5 + 1 + + 0.0 + + 1000 + + 6 + 24 + 2 + + + + 3 + 0 + + 3 + 1 + + 47 + + 1000 + + 3 + 9 + 3 + + + + 5 + 0 + + 5 + 1 + + 49 + + 1000 + + 3 + 9 + 3 + + + + + + + + + + + + + 5 + + + + + + + + 6 + + + + + + + + 7 + + + + + 7 + 0 + + 0 + 1 + + 340 + + 1000 + + 3 + 9 + 1 + + + + + + + 8 + + + + + + + + 9 + + + + + 7 + 0 + + 0 + 1 + + 70 + + 1000 + + 3 + 9 + 1 + + + + + + + 10 + + + + + 7 + 0 + + 0 + 1 + + 102 + + 1000 + + 3 + 9 + 1 + + + + + + + 11 + + + + + 7 + 0 + + 0 + 1 + + 233 + + 1000 + + 3 + 9 + 1 + + + + + + + 12 + + + + + 13 + + + + + 14 + + + + + 15 + + + + + 16 + + + + + 17 + + + + + 18 + + + + + 19 + + + + + 20 + + + + + 21 + + + + + 22 + + + + + 25 + + + + + 27 + + + + + 28 + + + + + 30 + + + + + 31 + + + + + 32 + + + + + 34 + + + + + 37 + + + + + 39 + + + + + 41 + + + + + 42 + + + + + 43 + + + + + 44 + + + + + 45 + + + + + 46 + + + + + 47 + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + {{357, 418}, {480, 270}} + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + + + + + + + + + + + + + + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + com.apple.InterfaceBuilder.CocoaPlugin + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + com.apple.InterfaceBuilder.CocoaPlugin + + + + + + 53 + + + 0 + IBCocoaFramework + YES + 3 + YES + + From 8e9d5418160db5d5d291517ec5ebf1f6fa34695c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sun, 10 Mar 2013 21:27:27 -0400 Subject: [PATCH 05/11] client/Android: fix keyboard --- client/Android/FreeRDPCore/jni/android_freerdp.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/Android/FreeRDPCore/jni/android_freerdp.c b/client/Android/FreeRDPCore/jni/android_freerdp.c index cf7945374..8a4165a06 100644 --- a/client/Android/FreeRDPCore/jni/android_freerdp.c +++ b/client/Android/FreeRDPCore/jni/android_freerdp.c @@ -796,15 +796,15 @@ JNIEXPORT jboolean JNICALL jni_freerdp_update_graphics( JNIEXPORT void JNICALL jni_freerdp_send_key_event( JNIEnv *env, jclass cls, jint instance, jint keycode, jboolean down) { - RDP_SCANCODE scancode; + DWORD scancode; ANDROID_EVENT* event; freerdp* inst = (freerdp*)instance; - scancode = freerdp_keyboard_get_rdp_scancode_from_virtual_key_code(keycode); + scancode = GetVirtualScanCodeFromVirtualKeyCode(keycode, 4); int flags = (down == JNI_TRUE) ? KBD_FLAGS_DOWN : KBD_FLAGS_RELEASE; - flags |= (RDP_SCANCODE_EXTENDED(scancode)) ? KBD_FLAGS_EXTENDED : 0; - event = (ANDROID_EVENT*) android_event_key_new(flags, RDP_SCANCODE_CODE(scancode)); + flags |= (scancode & KBDEXT) ? KBD_FLAGS_EXTENDED : 0; + event = (ANDROID_EVENT*) android_event_key_new(flags, scancode & 0xFF); android_push_event(inst, event); From 0408d32e97ad22cd8db7af61d0fc8fd6512752fc Mon Sep 17 00:00:00 2001 From: Christian Hofstaedtler Date: Mon, 11 Mar 2013 02:32:05 +0100 Subject: [PATCH 06/11] MacFreeRDP: hook up password dialog --- client/Mac/MRDPView.h | 1 + client/Mac/MRDPView.m | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/client/Mac/MRDPView.h b/client/Mac/MRDPView.h index e8bb0f153..ab08884da 100644 --- a/client/Mac/MRDPView.h +++ b/client/Mac/MRDPView.h @@ -113,6 +113,7 @@ void pointer_setDefault(rdpContext* context); int rdp_connect(void); BOOL mac_pre_connect(freerdp* instance); BOOL mac_post_connect(freerdp* instance); +BOOL mac_authenticate(freerdp* instance, char** username, char** password, char** domain); void mac_context_new(freerdp* instance, rdpContext* context); void mac_context_free(freerdp* instance, rdpContext* context); void mac_set_bounds(rdpContext* context, rdpBounds* bounds); diff --git a/client/Mac/MRDPView.m b/client/Mac/MRDPView.m index d4f79c1ff..a44d3c7a5 100644 --- a/client/Mac/MRDPView.m +++ b/client/Mac/MRDPView.m @@ -44,6 +44,7 @@ #import "MRDPView.h" #import "MRDPCursor.h" +#import "PasswordDialog.h" // RAIL_TODO DELETE WHEN DONE TESTING #define MRDP_DRAW_INDIVIDUAL_RECTS @@ -1012,6 +1013,7 @@ int rdp_connect() instance->ContextNew = mac_context_new; instance->ContextFree = mac_context_free; instance->ReceiveChannelData = receive_channel_data; + instance->Authenticate = mac_authenticate; freerdp_context_new(instance); status = freerdp_connect(instance); @@ -1243,6 +1245,31 @@ BOOL mac_post_connect(freerdp* instance) return TRUE; } +BOOL mac_authenticate(freerdp* instance, char** username, char** password, char** domain) +{ + PasswordDialog * dialog = [PasswordDialog new]; + + dialog.serverName = [NSString stringWithCString:instance->settings->ServerHostname encoding:NSUTF8StringEncoding]; + + if (*username) + dialog.userName = [NSString stringWithCString:*username encoding:NSUTF8StringEncoding]; + + if (*password) + dialog.password = [NSString stringWithCString:*password encoding:NSUTF8StringEncoding]; + + BOOL ok = [dialog runModal]; + if (ok) { + const char* submittedUsername = [dialog.userName cStringUsingEncoding:NSUTF8StringEncoding]; + *username = malloc((strlen(submittedUsername) + 1) * sizeof(char)); + strcpy(*username, submittedUsername); + + const char* submittedPassword = [dialog.password cStringUsingEncoding:NSUTF8StringEncoding]; + *password = malloc((strlen(submittedPassword) + 1) * sizeof(char)); + strcpy(*password, submittedPassword); + } + return ok; +} + /** ********************************************************************* * create a new mouse cursor * From c64cf47469fbe99ff8488a1c47410cdc4f2d495d Mon Sep 17 00:00:00 2001 From: Christian Hofstaedtler Date: Mon, 11 Mar 2013 02:35:06 +0100 Subject: [PATCH 07/11] MacFreeRDP: use CoreGraphics for drawing --- client/Mac/MRDPView.h | 3 +- client/Mac/MRDPView.m | 273 ++++++++++++++-------------------------- client/Mac/MainMenu.xib | 39 +++--- 3 files changed, 108 insertions(+), 207 deletions(-) diff --git a/client/Mac/MRDPView.h b/client/Mac/MRDPView.h index ab08884da..78722aec6 100644 --- a/client/Mac/MRDPView.h +++ b/client/Mac/MRDPView.h @@ -41,11 +41,11 @@ NSMutableArray* cursors; NSMutableArray* windows; NSTimer* pasteboard_timer; - NSRect rect; NSRect prevWinPosition; int titleBarHeight; freerdp* rdp_instance; rdpContext* rdp_context; + CGContextRef bitmap_context; char* pixel_data; int width; int height; @@ -87,7 +87,6 @@ - (void) rdpRemoteAppError; - (void) saveStateInfo :(freerdp *) instance :(rdpContext *) context; - (void) onPasteboardTimerFired :(NSTimer *) timer; -- (void) my_draw_rect :(void *) context; - (void) releaseResources; - (void) setViewSize : (int) width : (int) height; diff --git a/client/Mac/MRDPView.m b/client/Mac/MRDPView.m index a44d3c7a5..b0e7b052a 100644 --- a/client/Mac/MRDPView.m +++ b/client/Mac/MRDPView.m @@ -45,6 +45,7 @@ #import "MRDPView.h" #import "MRDPCursor.h" #import "PasswordDialog.h" +#include // RAIL_TODO DELETE WHEN DONE TESTING #define MRDP_DRAW_INDIVIDUAL_RECTS @@ -57,8 +58,6 @@ MRDPView *g_mrdpview; struct kkey g_keys[]; -void convert_color_space(char *dest, char *src, NSRect* drawRect, int width, int height); - const char* error_code_names[] = { "RAIL_EXEC_S_OK", @@ -704,96 +703,36 @@ struct kkey g_keys[256] = * called when our view needs refreshing ***********************************************************************/ -- (void) drawRect:(NSRect)dirtyRect +- (void) drawRect:(NSRect)rect { if (!rdp_context) return; - + if (g_mrdpview->isRemoteApp && g_mrdpview->currentWindow) return; - - if (!bmiRep) - { - pixel_data = (char *) malloc(width * height * sizeof(struct rgba_data)); - bmiRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **) &pixel_data - pixelsWide:width - pixelsHigh:height - bitsPerSample:8 - samplesPerPixel:sizeof(struct rgba_data) - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bitmapFormat:0 //NSAlphaFirstBitmapFormat - bytesPerRow:width * sizeof(struct rgba_data) - bitsPerPixel:0]; - } - - [bmiRep drawInRect:dirtyRect fromRect:dirtyRect operation:NSCompositeCopy fraction:1.0 respectFlipped:NO hints:nil]; + + if(g_mrdpview->bitmap_context) + { + CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort]; + CGImageRef cgImage = CGBitmapContextCreateImage(g_mrdpview->bitmap_context); + + CGContextClipToRect(context, CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height)); + CGContextDrawImage(context, CGRectMake(0, 0, [self bounds].size.width, [self bounds].size.height), cgImage); + + CGImageRelease(cgImage); + } + else + { + // just clear the screen with black + [[NSColor redColor] set]; + NSRectFill([self bounds]); + } } /************************************************************************ instance methods ************************************************************************/ -/** ********************************************************************* - * called when RDP server wants us to update a rect with new data - ***********************************************************************/ - -- (void) my_draw_rect:(void*)context -{ - int w; - int h; - - rdpContext* ctx = (rdpContext*) context; - - struct rgba_data - { - char red; - char green; - char blue; - char alpha; - }; - - if (isRemoteApp && currentWindow) - { - NSRect vrect = [ [currentWindow view] frame]; - [[currentWindow view] setNeedsDisplayInRect:vrect]; - // actual drawing will be done in MRDPRailView:drawRect() - return; - } - - w = width; - h = height; - rect.origin.x = 0; - rect.origin.y = 0; - rect.size.width = w; - rect.size.height = h; - - if (!bmiRep) - { - pixel_data = (char *) malloc(w * h * sizeof(struct rgba_data)); - bmiRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **) &pixel_data - pixelsWide:w - pixelsHigh:h - bitsPerSample:8 - samplesPerPixel:sizeof(struct rgba_data) - hasAlpha:YES - isPlanar:NO - colorSpaceName:NSDeviceRGBColorSpace - bitmapFormat:0 //NSAlphaFirstBitmapFormat - bytesPerRow:w * sizeof(struct rgba_data) - bitsPerPixel:0]; - } - -#ifdef MRDP_DRAW_INDIVIDUAL_RECTS - [self setNeedsDisplayInRect:rect]; - return; -#endif - - convert_color_space(pixel_data, (char *) ctx->gdi->primary_buffer, &rect, w, h); - [self setNeedsDisplayInRect:rect]; -} - /** ********************************************************************* * save state info for use by other methods later on ***********************************************************************/ @@ -855,9 +794,14 @@ struct kkey g_keys[256] = - (void) rdpConnectError { - + NSString* message = @"Error connecting to server"; + if (connectErrorCode == AUTHENTICATIONERROR) + { + message = [NSString stringWithFormat:@"%@:\n%@", message, @"Authentication failure, check credentials."]; + } + NSAlert *alert = [[NSAlert alloc] init]; - [alert setMessageText:@"Error connecting to server"]; + [alert setMessageText:message]; [alert beginSheetModalForWindow:[g_mrdpview window] modalDelegate:g_mrdpview didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) @@ -1013,7 +957,7 @@ int rdp_connect() instance->ContextNew = mac_context_new; instance->ContextFree = mac_context_free; instance->ReceiveChannelData = receive_channel_data; - instance->Authenticate = mac_authenticate; + instance->Authenticate = mac_authenticate; freerdp_context_new(instance); status = freerdp_connect(instance); @@ -1046,45 +990,14 @@ BOOL mac_pre_connect(freerdp* instance) int len; int status; char* cptr; - - instance->settings->OffscreenSupportLevel = FALSE; - instance->settings->GlyphSupportLevel = GLYPH_SUPPORT_FULL; - instance->settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE; - instance->settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = FALSE; - instance->settings->OrderSupport[NEG_FAST_INDEX_INDEX] = FALSE; - instance->settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE; - instance->settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE; - - instance->settings->BitmapCacheEnabled = TRUE; - instance->settings->OrderSupport[NEG_MEMBLT_INDEX] = TRUE; - instance->settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = TRUE; - instance->settings->OrderSupport[NEG_MEM3BLT_INDEX] = FALSE; - instance->settings->OrderSupport[NEG_MEM3BLT_V2_INDEX] = FALSE; - instance->settings->BitmapCacheV2NumCells = 3; // 5; - instance->settings->BitmapCacheV2CellInfo[0].numEntries = 0x78; // 600; - instance->settings->BitmapCacheV2CellInfo[0].persistent = FALSE; - instance->settings->BitmapCacheV2CellInfo[1].numEntries = 0x78; // 600; - instance->settings->BitmapCacheV2CellInfo[1].persistent = FALSE; - instance->settings->BitmapCacheV2CellInfo[2].numEntries = 0x150; // 2048; - instance->settings->BitmapCacheV2CellInfo[2].persistent = FALSE; - instance->settings->BitmapCacheV2CellInfo[3].numEntries = 0; // 4096; - instance->settings->BitmapCacheV2CellInfo[3].persistent = FALSE; - instance->settings->BitmapCacheV2CellInfo[4].numEntries = 0; // 2048; - instance->settings->BitmapCacheV2CellInfo[4].persistent = FALSE; - - instance->settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE; - instance->settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE; - instance->settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE; - instance->settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = FALSE; - instance->settings->OrderSupport[NEG_POLYLINE_INDEX] = FALSE; - instance->settings->ColorDepth = 24; - instance->settings->SoftwareGdi = 1; - + rdpSettings* settings; + BOOL bitmap_cache; + // setup callbacks instance->update->BeginPaint = mac_begin_paint; instance->update->EndPaint = mac_end_paint; instance->update->SetBounds = mac_set_bounds; - instance->update->BitmapUpdate = mac_bitmap_update; + //instance->update->BitmapUpdate = mac_bitmap_update; NSArray *args = [[NSProcessInfo processInfo] arguments]; @@ -1155,9 +1068,49 @@ BOOL mac_pre_connect(freerdp* instance) [NSApp terminate:nil]; return TRUE; } - + freerdp_client_load_addins(instance->context->channels, instance->settings); - + + settings = instance->settings; + bitmap_cache = settings->BitmapCacheEnabled; + + instance->settings->ColorDepth = 32; + instance->settings->SoftwareGdi = TRUE; + + settings->OsMajorType = OSMAJORTYPE_UNIX; + settings->OsMinorType = OSMINORTYPE_NATIVE_XSERVER; + + settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE; + settings->OrderSupport[NEG_PATBLT_INDEX] = TRUE; + settings->OrderSupport[NEG_SCRBLT_INDEX] = TRUE; + settings->OrderSupport[NEG_OPAQUE_RECT_INDEX] = TRUE; + settings->OrderSupport[NEG_DRAWNINEGRID_INDEX] = FALSE; + settings->OrderSupport[NEG_MULTIDSTBLT_INDEX] = FALSE; + settings->OrderSupport[NEG_MULTIPATBLT_INDEX] = FALSE; + settings->OrderSupport[NEG_MULTISCRBLT_INDEX] = FALSE; + settings->OrderSupport[NEG_MULTIOPAQUERECT_INDEX] = TRUE; + settings->OrderSupport[NEG_MULTI_DRAWNINEGRID_INDEX] = FALSE; + settings->OrderSupport[NEG_LINETO_INDEX] = TRUE; + settings->OrderSupport[NEG_POLYLINE_INDEX] = TRUE; + settings->OrderSupport[NEG_MEMBLT_INDEX] = bitmap_cache; + + settings->OrderSupport[NEG_MEM3BLT_INDEX] = (settings->SoftwareGdi) ? TRUE : FALSE; + + settings->OrderSupport[NEG_MEMBLT_V2_INDEX] = bitmap_cache; + settings->OrderSupport[NEG_MEM3BLT_V2_INDEX] = FALSE; + settings->OrderSupport[NEG_SAVEBITMAP_INDEX] = FALSE; + settings->OrderSupport[NEG_GLYPH_INDEX_INDEX] = TRUE; + settings->OrderSupport[NEG_FAST_INDEX_INDEX] = TRUE; + settings->OrderSupport[NEG_FAST_GLYPH_INDEX] = TRUE; + + settings->OrderSupport[NEG_POLYGON_SC_INDEX] = (settings->SoftwareGdi) ? FALSE : TRUE; + settings->OrderSupport[NEG_POLYGON_CB_INDEX] = (settings->SoftwareGdi) ? FALSE : TRUE; + + settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE; + settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE; + + + [g_mrdpview setViewSize:instance->settings->DesktopWidth :instance->settings->DesktopHeight]; freerdp_channels_pre_connect(instance->context->channels, instance); @@ -1193,11 +1146,15 @@ BOOL mac_post_connect(freerdp* instance) rdp_pointer.Set = pointer_set; rdp_pointer.SetNull = pointer_setNull; rdp_pointer.SetDefault = pointer_setDefault; - - flags = CLRCONV_ALPHA; - flags |= CLRBUF_32BPP; - + + flags = CLRBUF_32BPP; gdi_init(instance, flags, NULL); + + rdpGdi* gdi = instance->context->gdi; + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + g_mrdpview->bitmap_context = CGBitmapContextCreate(gdi->primary_buffer, gdi->width, gdi->height, 8, gdi->width * 4, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst); + + pointer_cache_register_callbacks(instance->update); graphics_register_pointer(instance->context->graphics, &rdp_pointer); @@ -1252,20 +1209,20 @@ BOOL mac_authenticate(freerdp* instance, char** username, char** password, char* dialog.serverName = [NSString stringWithCString:instance->settings->ServerHostname encoding:NSUTF8StringEncoding]; if (*username) - dialog.userName = [NSString stringWithCString:*username encoding:NSUTF8StringEncoding]; + dialog.userName = [NSString stringWithCString:*username encoding:NSUTF8StringEncoding]; if (*password) - dialog.password = [NSString stringWithCString:*password encoding:NSUTF8StringEncoding]; + dialog.password = [NSString stringWithCString:*password encoding:NSUTF8StringEncoding]; BOOL ok = [dialog runModal]; if (ok) { - const char* submittedUsername = [dialog.userName cStringUsingEncoding:NSUTF8StringEncoding]; - *username = malloc((strlen(submittedUsername) + 1) * sizeof(char)); - strcpy(*username, submittedUsername); + const char* submittedUsername = [dialog.userName cStringUsingEncoding:NSUTF8StringEncoding]; + *username = malloc((strlen(submittedUsername) + 1) * sizeof(char)); + strcpy(*username, submittedUsername); - const char* submittedPassword = [dialog.password cStringUsingEncoding:NSUTF8StringEncoding]; - *password = malloc((strlen(submittedPassword) + 1) * sizeof(char)); - strcpy(*password, submittedPassword); + const char* submittedPassword = [dialog.password cStringUsingEncoding:NSUTF8StringEncoding]; + *password = malloc((strlen(submittedPassword) + 1) * sizeof(char)); + strcpy(*password, submittedPassword); } return ok; } @@ -1469,9 +1426,7 @@ void mac_end_paint(rdpContext* context) drawRect.origin.y = gdi->primary->hdc->hwnd->cinvalid[i].y; drawRect.size.width = gdi->primary->hdc->hwnd->cinvalid[i].w; drawRect.size.height = gdi->primary->hdc->hwnd->cinvalid[i].h; - - convert_color_space(g_mrdpview->pixel_data, (char *) gdi->primary_buffer, &drawRect, g_mrdpview->width, g_mrdpview->height); - + windows_to_apple_cords(&drawRect); [g_mrdpview setNeedsDisplayInRect:drawRect]; } @@ -1571,52 +1526,6 @@ int receive_channel_data(freerdp* instance, int chan_id, BYTE* data, int size, i return freerdp_channels_data(instance, chan_id, data, size, flags, total_size); } -/** ********************************************************************* - * convert an array containing ARGB data to RGBA - ***********************************************************************/ - -void convert_color_space(char* dest, char* src, NSRect* drawRect, int width, int height) -{ - int i; - int j; - int x; - int y; - int cx; - int cy; - int pixel; - int pixel1; - int pixel2; - int* src32; - int* dst32; - - if ((!dest) || (!src)) - return; - - x = drawRect->origin.x; - y = drawRect->origin.y; - cx = drawRect->size.width; - cy = drawRect->size.height; - - for (j = 0; j < cy; j++) - { - src32 = (int*)(src + ((y + j) * width + x) * 4); - dst32 = (int*)(dest + ((y + j) * width + x) * 4); - - for (i = 0; i < cx; i++) - { - pixel = *src32; - pixel1 = (pixel & 0x00ff0000) >> 16; - pixel2 = (pixel & 0x000000ff) << 16; - pixel = (pixel & 0xff00ff00) | pixel1 | pixel2; - *dst32 = pixel; - src32++; - dst32++; - } - } - - drawRect->origin.y = height - drawRect->origin.y - drawRect->size.height; -} - /** * Used to load plugins based on the commandline parameters. * This function is provided as a parameter to freerdp_parse_args(), that will call it diff --git a/client/Mac/MainMenu.xib b/client/Mac/MainMenu.xib index bff95a9d5..e535cbe12 100755 --- a/client/Mac/MainMenu.xib +++ b/client/Mac/MainMenu.xib @@ -2,22 +2,22 @@ 1070 - 11D50b - 2177 - 1138.32 - 568.00 + 12C60 + 3084 + 1187.34 + 625.00 com.apple.InterfaceBuilder.CocoaPlugin - 2177 + 3084 - NSView - NSMenu - NSWindowTemplate - NSMenuItem - NSCustomView IBNSLayoutConstraint NSCustomObject + NSCustomView + NSMenu + NSMenuItem + NSView + NSWindowTemplate com.apple.InterfaceBuilder.CocoaPlugin @@ -264,6 +264,7 @@ {1024, 768} + _NS:9 MRDPView @@ -273,7 +274,7 @@ - {{0, 0}, {1366, 746}} + {{0, 0}, {1440, 878}} {1024, 790} {1024, 790} 128 @@ -563,10 +564,10 @@ 0.0 1000 + 8 29 3 - @@ -579,10 +580,10 @@ 0.0 1000 + 8 29 3 - @@ -595,10 +596,10 @@ 0.0 1000 + 8 29 3 - @@ -611,10 +612,10 @@ 0.0 1000 + 8 29 3 - @@ -769,14 +770,6 @@ ./Classes/MRDPView.h - - NSLayoutConstraint - NSObject - - IBProjectSource - ./Classes/NSLayoutConstraint.h - - 0 From 5628927fc250d43db8444d8b014c76570578a231 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Sun, 10 Mar 2013 23:14:40 -0400 Subject: [PATCH 08/11] mfreerdp: make use of libwinpr-input --- client/Mac/MRDPRailView.m | 32 ++++--- client/Mac/MRDPView.h | 6 -- client/Mac/MRDPView.m | 190 +++++--------------------------------- 3 files changed, 44 insertions(+), 184 deletions(-) diff --git a/client/Mac/MRDPRailView.m b/client/Mac/MRDPRailView.m index f9e0e0655..7c9220dfb 100644 --- a/client/Mac/MRDPRailView.m +++ b/client/Mac/MRDPRailView.m @@ -27,14 +27,6 @@ MRDPRailView* g_mrdpRailView; -struct kkey -{ - int key_code; - int flags; -}; - -extern struct kkey g_keys[]; - - (void) updateDisplay { BOOL moveWindow = NO; @@ -553,9 +545,17 @@ extern struct kkey g_keys[]; - (void) keyDown:(NSEvent *) event { int key; + BOOL extended; + DWORD vkcode; + DWORD scancode; - key = [event keyCode]; - rdp_instance->input->KeyboardEvent(rdp_instance->input, g_keys[key].flags | KBD_FLAGS_DOWN, g_keys[key].key_code); + key = [event keyCode] + 8; + + vkcode = GetVirtualKeyCodeFromKeycode(key, KEYCODE_TYPE_APPLE); + scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4); + extended = (scancode & KBDEXT) ? KBDEXT : 0; + + rdp_instance->input->KeyboardEvent(rdp_instance->input, extended | KBD_FLAGS_DOWN, scancode & 0xFF); } /** ********************************************************************* @@ -565,9 +565,17 @@ extern struct kkey g_keys[]; - (void) keyUp:(NSEvent *) event { int key; + BOOL extended; + DWORD vkcode; + DWORD scancode; - key = [event keyCode]; - rdp_instance->input->KeyboardEvent(rdp_instance->input, g_keys[key].flags | KBD_FLAGS_RELEASE, g_keys[key].key_code); + key = [event keyCode] + 8; + + vkcode = GetVirtualKeyCodeFromKeycode(key, KEYCODE_TYPE_APPLE); + scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4); + extended = (scancode & KBDEXT) ? KBDEXT : 0; + + rdp_instance->input->KeyboardEvent(rdp_instance->input, extended | KBD_FLAGS_RELEASE, scancode & 0xFF); } /** ********************************************************************* diff --git a/client/Mac/MRDPView.h b/client/Mac/MRDPView.h index 78722aec6..398a43e93 100644 --- a/client/Mac/MRDPView.h +++ b/client/Mac/MRDPView.h @@ -179,9 +179,3 @@ struct rgba_data char alpha; }; -struct kkey -{ - int key_code; - int flags; -}; - diff --git a/client/Mac/MRDPView.m b/client/Mac/MRDPView.m index b0e7b052a..449d7c181 100644 --- a/client/Mac/MRDPView.m +++ b/client/Mac/MRDPView.m @@ -45,6 +45,10 @@ #import "MRDPView.h" #import "MRDPCursor.h" #import "PasswordDialog.h" + +#include +#include + #include // RAIL_TODO DELETE WHEN DONE TESTING @@ -56,8 +60,6 @@ MRDPView *g_mrdpview; @synthesize is_connected; -struct kkey g_keys[]; - const char* error_code_names[] = { "RAIL_EXEC_S_OK", @@ -69,166 +71,6 @@ const char* error_code_names[] = "RAIL_EXEC_E_SESSION_LOCKED" }; -struct kkey g_keys[256] = -{ - { 0x1e, 0 }, // a 0 - { 0x1f, 0 }, // s - { 0x20, 0 }, // d - { 0x21, 0 }, // f - { 0x23, 0 }, // h - { 0x22, 0 }, // g - { 0x2c, 0 }, // z - { 0x2d, 0 }, // x - { 0x2e, 0 }, // c - { 0x2f, 0 }, // v - { 0x00, 0 }, // 10 - { 0x30, 0 }, // b - { 0x10, 0 }, // q - { 0x11, 0 }, // w - { 0x12, 0 }, // e - { 0x13, 0 }, // r - { 0x15, 0 }, // y - { 0x14, 0 }, // t - { 0x02, 0 }, // 1 - { 0x03, 0 }, // 2 - { 0x04, 0 }, // 3 20 - { 0x05, 0 }, // 4 - { 0x07, 0 }, // 6 - { 0x06, 0 }, // 5 - { 0x0d, 0 }, // = or + - { 0x0a, 0 }, // 9 - { 0x08, 0 }, // 7 - { 0x0c, 0 }, // - or _ - { 0x09, 0 }, // 8 - { 0x0b, 0 }, // 0 - { 0x1b, 0 }, // ] or } 30 - { 0x18, 0 }, // o - { 0x16, 0 }, // u - { 0x1a, 0 }, // [ or { - { 0x17, 0 }, // i - { 0x19, 0 }, // p - { 0x1c, 0 }, // enter - { 0x26, 0 }, // l - { 0x24, 0 }, // j - { 0x28, 0 }, // ' or " - { 0x25, 0 }, // k 40 - { 0x27, 0 }, // ; or : - { 0x2b, 0 }, // \ or | - { 0x33, 0 }, // , or < - { 0x35, 0 }, // / or ? - { 0x31, 0 }, // n - { 0x32, 0 }, // m - { 0x34, 0 }, // . or > - { 0x0f, 0 }, // tab - { 0x39, 0 }, // space - { 0x29, 0 }, // ` or ~ 50 - { 0x0e, 0 }, // backspace - { 0x00, 0 }, // - { 0x01, 0 }, // esc - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, // 60 - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x53, 0 }, // KP. - { 0x00, 0 }, - { 0x37, 0 }, // KP* - { 0x00, 0 }, - { 0x4e, 0 }, // KP+ - { 0x00, 0 }, // 70 - { 0x45, 0 }, // num lock - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x35, 1 }, // KP/ - { 0x1c, 1 }, // KPEnter - { 0x00, 0 }, - { 0x4a, 0 }, // KP- - { 0x00, 0 }, - { 0x00, 0 }, // 80 - { 0x00, 0 }, - { 0x52, 0 }, // KP0 - { 0x4f, 0 }, // KP1 - { 0x50, 0 }, // KP2 - { 0x51, 0 }, // KP3 - { 0x4b, 0 }, // KP4 - { 0x4c, 0 }, // KP5 - { 0x4d, 0 }, // KP6 - { 0x47, 0 }, // KP7 - { 0x00, 0 }, // 90 - { 0x48, 0 }, // KP8 - { 0x49, 0 }, // KP9 - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, // 100 - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x5d, 1 }, // menu 110 - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x52, 1 }, // Insert - { 0x47, 1 }, // Home - { 0x49, 1 }, // PgUp - { 0x53, 1 }, // Delete - { 0x00, 0 }, - { 0x4f, 1 }, // End - { 0x00, 0 }, // 120 - { 0x51, 1 }, // PgDown - { 0x3b, 0 }, // f1 - { 0x4b, 1 }, // left - { 0x4d, 1 }, // right - { 0x50, 1 }, // down - { 0x48, 1 }, // up - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, - { 0x00, 0 }, -}; - /************************************************************************ methods we override ************************************************************************/ @@ -528,12 +370,20 @@ struct kkey g_keys[256] = - (void) keyDown:(NSEvent *) event { int key; + BOOL extended; + DWORD vkcode; + DWORD scancode; if (!is_connected) return; - key = [event keyCode]; - rdp_instance->input->KeyboardEvent(rdp_instance->input, g_keys[key].flags | KBD_FLAGS_DOWN, g_keys[key].key_code); + key = [event keyCode] + 8; + + vkcode = GetVirtualKeyCodeFromKeycode(key, KEYCODE_TYPE_APPLE); + scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4); + extended = (scancode & KBDEXT) ? KBDEXT : 0; + + rdp_instance->input->KeyboardEvent(rdp_instance->input, extended | KBD_FLAGS_DOWN, scancode & 0xFF); } /** ********************************************************************* @@ -543,12 +393,20 @@ struct kkey g_keys[256] = - (void) keyUp:(NSEvent *) event { int key; + BOOL extended; + DWORD vkcode; + DWORD scancode; if (!is_connected) return; - key = [event keyCode]; - rdp_instance->input->KeyboardEvent(rdp_instance->input, g_keys[key].flags | KBD_FLAGS_RELEASE, g_keys[key].key_code); + key = [event keyCode] + 8; + + vkcode = GetVirtualKeyCodeFromKeycode(key, KEYCODE_TYPE_APPLE); + scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4); + extended = (scancode & KBDEXT) ? KBDEXT : 0; + + rdp_instance->input->KeyboardEvent(rdp_instance->input, extended | KBD_FLAGS_RELEASE, scancode & 0xFF); } /** ********************************************************************* From 1f335709b3e22913fe74bbe87e2742e8ffb0e905 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 11 Mar 2013 00:35:15 -0400 Subject: [PATCH 09/11] mfreerdp: fix icon file --- client/Mac/CMakeLists.txt | 33 +++++++++++++----------- client/Mac/FreeRDP.icns | Bin 0 -> 60681 bytes client/Mac/Info.plist | 2 +- client/Mac/MRDPView.m | 53 +++++++++++++++++++------------------- 4 files changed, 46 insertions(+), 42 deletions(-) create mode 100644 client/Mac/FreeRDP.icns diff --git a/client/Mac/CMakeLists.txt b/client/Mac/CMakeLists.txt index 734b66933..2183eb9d2 100644 --- a/client/Mac/CMakeLists.txt +++ b/client/Mac/CMakeLists.txt @@ -10,13 +10,14 @@ include_directories(${FRAMEWORK_HEADERS_PATH} /System/Library/Frameworks) # set(CMAKE_OSX_SYSROOT MacOSX10.7.sdk) set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -mmacosx-version-min=10.4") set(GUI_TYPE MACOSX_BUNDLE) - + # Import libraries find_library(FOUNDATION_LIBRARY Foundation) find_library(COCOA_LIBRARY Cocoa) find_library(APPKIT_LIBRARY AppKit) 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.Mac") set(MACOSX_BUNDLE_LONG_VERSION_STRING "MacFreeRDP Version 1.0.1") @@ -27,35 +28,37 @@ set(MACOSX_BUNDLE_COPYRIGHT "Copyright 2012. All Rights Reserved.") set(MACOSX_BUNDLE_NSMAIN_NIB_FILE "MainMenu") set(MACOSX_BUNDLE_NSPRINCIPAL_CLASS "NSApplication") - + mark_as_advanced(COCOA_LIBRARY FOUNDATION_LIBRARY APPKIT_LIBRARY) set(EXTRA_LIBS ${COCOA_LIBRARY} ${FOUNDATION_LIBRARY} ${APPKIT_LIBRARY}) set(APP_TYPE MACOSX_BUNDLE) # OS X Interface Builder files -file(GLOB MacFreeRDP_XIBS *.xib) +file(GLOB ${MODULE_NAME}_XIBS *.xib) + +set(${MODULE_NAME}_RESOURCES ${${MODULE_NAME}_XIBS} ${MACOSX_BUNDLE_ICON_FILE}) # Headers -file(GLOB MacFreeRDP_Headers *.h) +file(GLOB ${MODULE_NAME}_HEADERS *.h) # Source -file(GLOB MacFreeRDP_Source *.m) +file(GLOB ${MODULE_NAME}_SOURCES *.m) -add_executable(MacFreeRDP +add_executable(${MODULE_NAME} ${APP_TYPE} - ${MacFreeRDP_Headers} - ${MacFreeRDP_Source} - ${MacFreeRDP_XIBS}) + ${${MODULE_NAME}_HEADERS} + ${${MODULE_NAME}_SOURCES} + ${${MODULE_NAME}_RESOURCES}) # This is necessary for the xib file part below configure_file(${CMAKE_CURRENT_SOURCE_DIR}/Info.plist ${CMAKE_CURRENT_BINARY_DIR}/Info.plist) # This allows for automatic xib to nib ibitool -set_target_properties(MacFreeRDP PROPERTIES RESOURCE "${MacFreeRDP_XIBS}") +set_target_properties(${MODULE_NAME} PROPERTIES RESOURCE "${${MODULE_NAME}_RESOURCES}") # Automatic ref counting # temporary turn off for x86_64 build issue -# set_target_properties(MacFreeRDP PROPERTIES XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES) +# set_target_properties(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_CLANG_ENABLE_OBJC_ARC YES) # Support for automatic reference counting requires non-fragile abi. set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fobjc-nonfragile-abi") @@ -67,10 +70,10 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fobjc-nonfragile-abi") # In the future the FreeRDP Xcode project should be pulled in for a couple of reasons: # 1) better step-into debugging 2) automatic dependency compilation and multi-arch compilation + linkage # If you know the solutions for 1 and 2, please add below. -set_target_properties(MacFreeRDP PROPERTIES XCODE_ATTRIBUTE_ARCHS "$(NATIVE_ARCH_ACTUAL)") +set_target_properties(${MODULE_NAME} PROPERTIES XCODE_ATTRIBUTE_ARCHS "$(NATIVE_ARCH_ACTUAL)") # Set the info plist to the custom instance -set_target_properties(MacFreeRDP PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist) +set_target_properties(${MODULE_NAME} PROPERTIES MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_BINARY_DIR}/Info.plist) set(${MODULE_PREFIX}_LIBS ${${MODULE_PREFIX}_LIBS} ${EXTRA_LIBS}) @@ -82,8 +85,8 @@ set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHI set_complex_link_libraries(VARIABLE ${MODULE_PREFIX}_LIBS MONOLITHIC ${MONOLITHIC_BUILD} MODULE winpr - MODULES winpr-crt) + MODULES winpr-input winpr-crt winpr-utils) target_link_libraries(${MODULE_NAME} ${${MODULE_PREFIX}_LIBS}) -set_property(TARGET MacFreeRDP PROPERTY FOLDER "Client/Mac") +set_property(TARGET ${MODULE_NAME} PROPERTY FOLDER "Client/Mac") diff --git a/client/Mac/FreeRDP.icns b/client/Mac/FreeRDP.icns new file mode 100644 index 0000000000000000000000000000000000000000..88bd44ca05621268824d56bc4e14371c27402c52 GIT binary patch literal 60681 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 CFBundleIconFile - + FreeRDP CFBundleIdentifier FreeRDP.Mac CFBundleInfoDictionaryVersion diff --git a/client/Mac/MRDPView.m b/client/Mac/MRDPView.m index 449d7c181..faa11e506 100644 --- a/client/Mac/MRDPView.m +++ b/client/Mac/MRDPView.m @@ -815,7 +815,7 @@ int rdp_connect() instance->ContextNew = mac_context_new; instance->ContextFree = mac_context_free; instance->ReceiveChannelData = receive_channel_data; - instance->Authenticate = mac_authenticate; + instance->Authenticate = mac_authenticate; freerdp_context_new(instance); status = freerdp_connect(instance); @@ -929,13 +929,13 @@ BOOL mac_pre_connect(freerdp* instance) freerdp_client_load_addins(instance->context->channels, instance->settings); - settings = instance->settings; + settings = instance->settings; bitmap_cache = settings->BitmapCacheEnabled; instance->settings->ColorDepth = 32; instance->settings->SoftwareGdi = TRUE; - settings->OsMajorType = OSMAJORTYPE_UNIX; + settings->OsMajorType = OSMAJORTYPE_UNIX; settings->OsMinorType = OSMINORTYPE_NATIVE_XSERVER; settings->OrderSupport[NEG_DSTBLT_INDEX] = TRUE; @@ -966,12 +966,11 @@ BOOL mac_pre_connect(freerdp* instance) settings->OrderSupport[NEG_ELLIPSE_SC_INDEX] = FALSE; settings->OrderSupport[NEG_ELLIPSE_CB_INDEX] = FALSE; - - - + [g_mrdpview setViewSize:instance->settings->DesktopWidth :instance->settings->DesktopHeight]; freerdp_channels_pre_connect(instance->context->channels, instance); + return TRUE; } @@ -1008,11 +1007,10 @@ BOOL mac_post_connect(freerdp* instance) flags = CLRBUF_32BPP; gdi_init(instance, flags, NULL); - rdpGdi* gdi = instance->context->gdi; - CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); - g_mrdpview->bitmap_context = CGBitmapContextCreate(gdi->primary_buffer, gdi->width, gdi->height, 8, gdi->width * 4, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst); + rdpGdi* gdi = instance->context->gdi; + CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB(); + g_mrdpview->bitmap_context = CGBitmapContextCreate(gdi->primary_buffer, gdi->width, gdi->height, 8, gdi->width * 4, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaNoneSkipFirst); - pointer_cache_register_callbacks(instance->update); graphics_register_pointer(instance->context->graphics, &rdp_pointer); @@ -1062,27 +1060,30 @@ BOOL mac_post_connect(freerdp* instance) BOOL mac_authenticate(freerdp* instance, char** username, char** password, char** domain) { - PasswordDialog * dialog = [PasswordDialog new]; + PasswordDialog * dialog = [PasswordDialog new]; - dialog.serverName = [NSString stringWithCString:instance->settings->ServerHostname encoding:NSUTF8StringEncoding]; + dialog.serverName = [NSString stringWithCString:instance->settings->ServerHostname encoding:NSUTF8StringEncoding]; - if (*username) - dialog.userName = [NSString stringWithCString:*username encoding:NSUTF8StringEncoding]; + if (*username) + dialog.userName = [NSString stringWithCString:*username encoding:NSUTF8StringEncoding]; - if (*password) - dialog.password = [NSString stringWithCString:*password encoding:NSUTF8StringEncoding]; + if (*password) + dialog.password = [NSString stringWithCString:*password encoding:NSUTF8StringEncoding]; - BOOL ok = [dialog runModal]; - if (ok) { - const char* submittedUsername = [dialog.userName cStringUsingEncoding:NSUTF8StringEncoding]; - *username = malloc((strlen(submittedUsername) + 1) * sizeof(char)); - strcpy(*username, submittedUsername); + BOOL ok = [dialog runModal]; + + if (ok) + { + const char* submittedUsername = [dialog.userName cStringUsingEncoding:NSUTF8StringEncoding]; + *username = malloc((strlen(submittedUsername) + 1) * sizeof(char)); + strcpy(*username, submittedUsername); - const char* submittedPassword = [dialog.password cStringUsingEncoding:NSUTF8StringEncoding]; - *password = malloc((strlen(submittedPassword) + 1) * sizeof(char)); - strcpy(*password, submittedPassword); - } - return ok; + const char* submittedPassword = [dialog.password cStringUsingEncoding:NSUTF8StringEncoding]; + *password = malloc((strlen(submittedPassword) + 1) * sizeof(char)); + strcpy(*password, submittedPassword); + } + + return ok; } /** ********************************************************************* From e01caae318546defb23982c4482cbbb1c69f1e31 Mon Sep 17 00:00:00 2001 From: Martin Fleisz Date: Mon, 11 Mar 2013 10:13:06 +0100 Subject: [PATCH 10/11] locale: Fix compile error on Windows --- libfreerdp/locale/keyboard.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libfreerdp/locale/keyboard.c b/libfreerdp/locale/keyboard.c index dbb5dcedc..fc6255fbd 100644 --- a/libfreerdp/locale/keyboard.c +++ b/libfreerdp/locale/keyboard.c @@ -47,8 +47,10 @@ DWORD X11_KEYCODE_TO_VIRTUAL_SCANCODE[256]; int freerdp_detect_keyboard(DWORD* keyboardLayoutId) { +#if defined(WITH_X11) if (*keyboardLayoutId == 0) freerdp_detect_keyboard_layout_from_xkb(keyboardLayoutId); +#endif if (*keyboardLayoutId == 0) freerdp_detect_keyboard_layout_from_system_locale(keyboardLayoutId); From 1ad2bda6b6d802084f1b981f72adb89ccd18dd87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Moreau?= Date: Mon, 11 Mar 2013 12:14:44 -0400 Subject: [PATCH 11/11] mfreerdp: code style cleanup --- client/Mac/MRDPCursor.h | 10 +-- client/Mac/MRDPCursor.m | 1 + client/Mac/MRDPView.h | 20 +++--- client/Mac/MRDPView.m | 150 +++++++++++++++++++++++----------------- 4 files changed, 101 insertions(+), 80 deletions(-) diff --git a/client/Mac/MRDPCursor.h b/client/Mac/MRDPCursor.h index 7c193e684..767ccbc52 100644 --- a/client/Mac/MRDPCursor.h +++ b/client/Mac/MRDPCursor.h @@ -24,11 +24,11 @@ @interface MRDPCursor : NSObject { @public - rdpPointer *pointer; - BYTE *cursor_data; // bitmapped pixel data - NSBitmapImageRep *bmiRep; - NSCursor *nsCursor; - NSImage *nsImage; + rdpPointer* pointer; + BYTE* cursor_data; + NSBitmapImageRep* bmiRep; + NSCursor* nsCursor; + NSImage* nsImage; } @end diff --git a/client/Mac/MRDPCursor.m b/client/Mac/MRDPCursor.m index 86e1c2d9b..6df626769 100644 --- a/client/Mac/MRDPCursor.m +++ b/client/Mac/MRDPCursor.m @@ -20,4 +20,5 @@ #import "MRDPCursor.h" @implementation MRDPCursor + @end diff --git a/client/Mac/MRDPView.h b/client/Mac/MRDPView.h index 398a43e93..08b3b42cf 100644 --- a/client/Mac/MRDPView.h +++ b/client/Mac/MRDPView.h @@ -45,14 +45,14 @@ int titleBarHeight; freerdp* rdp_instance; rdpContext* rdp_context; - CGContextRef bitmap_context; + CGContextRef bitmap_context; char* pixel_data; int width; int height; int argc; char** argv; - // RAIL stuff + /* RemoteApp */ MRDPWindow* currentWindow; NSPoint savedDragLocation; BOOL mouseInClientArea; @@ -63,7 +63,7 @@ BOOL saveInitialDragLoc; BOOL skipMoveWindowOnce; - // store state info for some keys + /* store state info for some keys */ int kdlshift; int kdrshift; int kdlctrl; @@ -76,11 +76,11 @@ @public NSWindow* ourMainWindow; - NSPasteboard* pasteboard_rd; // for reading from clipboard - NSPasteboard* pasteboard_wr; // for writing to clipboard + NSPasteboard* pasteboard_rd; /* for reading from clipboard */ + NSPasteboard* pasteboard_wr; /* for writing to clipboard */ int pasteboard_changecount; int pasteboard_format; - int is_connected; // true when connected to RDP server + int is_connected; } - (void) rdpConnectError; @@ -165,10 +165,10 @@ struct mac_context struct cursor { rdpPointer* pointer; - BYTE* cursor_data; // bitmapped pixel data - void* bmiRep; // NSBitmapImageRep - void* nsCursor; // NSCursor - void* nsImage; // NSImage + BYTE* cursor_data; + void* bmiRep; /* NSBitmapImageRep */ + void* nsCursor; /* NSCursor */ + void* nsImage; /* NSImage */ }; struct rgba_data diff --git a/client/Mac/MRDPView.m b/client/Mac/MRDPView.m index faa11e506..d0d1fc19d 100644 --- a/client/Mac/MRDPView.m +++ b/client/Mac/MRDPView.m @@ -996,13 +996,13 @@ BOOL mac_post_connect(freerdp* instance) void* wr_fds[32]; rdpPointer rdp_pointer; - memset(&rdp_pointer, 0, sizeof(rdpPointer)); + ZeroMemory(&rdp_pointer, sizeof(rdpPointer)); rdp_pointer.size = sizeof(rdpPointer); - rdp_pointer.New = pointer_new; - rdp_pointer.Free = pointer_free; - rdp_pointer.Set = pointer_set; - rdp_pointer.SetNull = pointer_setNull; - rdp_pointer.SetDefault = pointer_setDefault; + rdp_pointer.New = mf_Pointer_New; + rdp_pointer.Free = mf_Pointer_Free; + rdp_pointer.Set = mf_Pointer_Set; + rdp_pointer.SetNull = mf_Pointer_SetNull; + rdp_pointer.SetDefault = mf_Pointer_SetDefault; flags = CLRBUF_32BPP; gdi_init(instance, flags, NULL); @@ -1014,7 +1014,7 @@ BOOL mac_post_connect(freerdp* instance) pointer_cache_register_callbacks(instance->update); graphics_register_pointer(instance->context->graphics, &rdp_pointer); - // register file descriptors with the RunLoop + /* register file descriptors with the RunLoop */ if (!freerdp_get_fds(instance, rd_fds, &rd_count, 0, 0)) { printf("mac_post_connect: freerdp_get_fds() failed!\n"); @@ -1026,7 +1026,7 @@ BOOL mac_post_connect(freerdp* instance) } register_fds(fds, rd_count, instance); - // register channel manager file descriptors with the RunLoop + /* register channel manager file descriptors with the RunLoop */ if (!freerdp_channels_get_fds(instance->context->channels, instance, rd_fds, &rd_count, wr_fds, &wr_count)) { printf("ERROR: freerdp_channels_get_fds() failed\n"); @@ -1039,20 +1039,20 @@ BOOL mac_post_connect(freerdp* instance) register_channel_fds(fds, rd_count, instance); freerdp_channels_post_connect(instance->context->channels, instance); - // setup RAIL (remote app) + /* setup RemoteApp */ instance->context->rail = rail_new(instance->settings); rail_register_update_callbacks(instance->context->rail, instance->update); mac_rail_register_callbacks(instance, instance->context->rail); - // setup pasteboard (aka clipboard) for copy operations (write only) + /* setup pasteboard (aka clipboard) for copy operations (write only) */ g_mrdpview->pasteboard_wr = [NSPasteboard generalPasteboard]; - // setup pasteboard for read operations + /* setup pasteboard for read operations */ g_mrdpview->pasteboard_rd = [NSPasteboard generalPasteboard]; g_mrdpview->pasteboard_changecount = (int) [g_mrdpview->pasteboard_rd changeCount]; g_mrdpview->pasteboard_timer = [NSTimer scheduledTimerWithTimeInterval:0.5 target:g_mrdpview selector:@selector(onPasteboardTimerFired:) userInfo:nil repeats:YES]; - // we want to be notified when window resizes + /* we want to be notified when window resizes */ [[NSNotificationCenter defaultCenter] addObserver:g_mrdpview selector:@selector(windowDidResize:) name:NSWindowDidResizeNotification object:nil]; return TRUE; @@ -1060,7 +1060,7 @@ BOOL mac_post_connect(freerdp* instance) BOOL mac_authenticate(freerdp* instance, char** username, char** password, char** domain) { - PasswordDialog * dialog = [PasswordDialog new]; + PasswordDialog* dialog = [PasswordDialog new]; dialog.serverName = [NSString stringWithCString:instance->settings->ServerHostname encoding:NSUTF8StringEncoding]; @@ -1094,18 +1094,23 @@ BOOL mac_authenticate(freerdp* instance, char** username, char** password, char* * ************************************************************************/ -void pointer_new(rdpContext* context, rdpPointer* pointer) +void mf_Pointer_New(rdpContext* context, rdpPointer* pointer) { - BYTE* cursor_data; - MRDPCursor *mrdpCursor = [[MRDPCursor alloc] init]; - NSRect rect; + NSImage* image; + NSPoint hotSpot; + NSCursor* cursor; + BYTE* cursor_data; + NSMutableArray* ma; + NSBitmapImageRep* bmiRep; + MRDPCursor* mrdpCursor = [[MRDPCursor alloc] init]; + rect.size.width = pointer->width; rect.size.height = pointer->height; rect.origin.x = pointer->xPos; rect.origin.y = pointer->yPos; - cursor_data = (BYTE *) malloc(rect.size.width * rect.size.height * 4); + cursor_data = (BYTE*) malloc(rect.size.width * rect.size.height * 4); mrdpCursor->cursor_data = cursor_data; freerdp_alpha_cursor_convert(cursor_data, pointer->xorMaskData, pointer->andMaskData, @@ -1114,13 +1119,12 @@ void pointer_new(rdpContext* context, rdpPointer* pointer) // TODO if xorBpp is > 24 need to call freerdp_image_swap_color_order // see file df_graphics.c - // store cursor bitmap image in representation - required by NSImage - NSBitmapImageRep *bmiRep; + /* store cursor bitmap image in representation - required by NSImage */ bmiRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes:(unsigned char **) &cursor_data - pixelsWide:rect.size.width + pixelsWide:rect.size.width pixelsHigh:rect.size.height bitsPerSample:8 - samplesPerPixel:sizeof(struct rgba_data) + samplesPerPixel:4 hasAlpha:YES isPlanar:NO colorSpaceName:NSDeviceRGBColorSpace @@ -1129,23 +1133,22 @@ void pointer_new(rdpContext* context, rdpPointer* pointer) bitsPerPixel:0]; mrdpCursor->bmiRep = bmiRep; - // create an image using above representation - NSImage *image = [[NSImage alloc] initWithSize:[bmiRep size]]; + /* create an image using above representation */ + image = [[NSImage alloc] initWithSize:[bmiRep size]]; [image addRepresentation: bmiRep]; [image setFlipped:NO]; mrdpCursor->nsImage = image; - // need hotspot to create cursor - NSPoint hotSpot; + /* need hotspot to create cursor */ hotSpot.x = pointer->xPos; hotSpot.y = pointer->yPos; - NSCursor *cursor = [[NSCursor alloc] initWithImage: image hotSpot:hotSpot]; + cursor = [[NSCursor alloc] initWithImage: image hotSpot:hotSpot]; mrdpCursor->nsCursor = cursor; mrdpCursor->pointer = pointer; - // save cursor for later use in pointer_set() - NSMutableArray *ma = g_mrdpview->cursors; + /* save cursor for later use in mf_Pointer_Set() */ + ma = g_mrdpview->cursors; [ma addObject:mrdpCursor]; } @@ -1153,7 +1156,7 @@ void pointer_new(rdpContext* context, rdpPointer* pointer) * release resources on specified cursor ************************************************************************/ -void pointer_free(rdpContext* context, rdpPointer* pointer) +void mf_Pointer_Free(rdpContext* context, rdpPointer* pointer) { NSMutableArray* ma = g_mrdpview->cursors; @@ -1175,7 +1178,7 @@ void pointer_free(rdpContext* context, rdpPointer* pointer) * set specified cursor as the current cursor ************************************************************************/ -void pointer_set(rdpContext* context, rdpPointer* pointer) +void mf_Pointer_Set(rdpContext* context, rdpPointer* pointer) { NSMutableArray* ma = g_mrdpview->cursors; @@ -1196,7 +1199,7 @@ void pointer_set(rdpContext* context, rdpPointer* pointer) * do not display any mouse cursor ***********************************************************************/ -void pointer_setNull(rdpContext* context) +void mf_Pointer_SetNull(rdpContext* context) { } @@ -1204,7 +1207,7 @@ void pointer_setNull(rdpContext* context) * display default mouse cursor ***********************************************************************/ -void pointer_setDefault(rdpContext* context) +void mf_Pointer_SetDefault(rdpContext* context) { } @@ -1301,7 +1304,7 @@ void skt_activity_cb(CFSocketRef s, CFSocketCallBackType callbackType, { if (!freerdp_check_fds(info)) { - // lost connection or did not connect + /* lost connection or did not connect */ [NSApp terminate:nil]; } } @@ -1484,7 +1487,7 @@ void cliprdr_process_cb_monitor_ready_event(freerdp* instance) event = freerdp_event_new(RDP_EVENT_CLASS_CLIPRDR, RDP_EVENT_TYPE_CB_FORMAT_LIST, NULL, NULL); - format_list_event = (RDP_CB_FORMAT_LIST_EVENT*)event; + format_list_event = (RDP_CB_FORMAT_LIST_EVENT*) event; format_list_event->num_formats = 0; freerdp_channels_send_event(instance->context->channels, event); @@ -1547,32 +1550,40 @@ void process_cliprdr_event(freerdp* instance, RDP_EVENT* event) { switch (event->event_type) { - // Monitor Ready PDU is sent by server to indicate that it has been - // inited and is ready. This PDU is transmitted by the server after it has sent - // Clipboard Capabilities PDU + /* + * Monitor Ready PDU is sent by server to indicate that it has been + * initialized and is ready. This PDU is transmitted by the server after it has sent + * Clipboard Capabilities PDU + */ case RDP_EVENT_TYPE_CB_MONITOR_READY: cliprdr_process_cb_monitor_ready_event(instance); break; - // The Format List PDU is sent either by the client or the server when its - // local system clipboard is updated with new clipboard data. This PDU - // contains the Clipboard Format ID and name pairs of the new Clipboard - // Formats on the clipboard + /* + * The Format List PDU is sent either by the client or the server when its + * local system clipboard is updated with new clipboard data. This PDU + * contains the Clipboard Format ID and name pairs of the new Clipboard + * Formats on the clipboard + */ case RDP_EVENT_TYPE_CB_FORMAT_LIST: cliprdr_process_cb_format_list_event(instance, (RDP_CB_FORMAT_LIST_EVENT*) event); break; - // The Format Data Request PDU is sent by the receipient of the Format List PDU. - // It is used to request the data for one of the formats that was listed in the - // Format List PDU + /* + * The Format Data Request PDU is sent by the receipient of the Format List PDU. + * It is used to request the data for one of the formats that was listed in the + * Format List PDU + */ case RDP_EVENT_TYPE_CB_DATA_REQUEST: cliprdr_process_cb_data_request_event(instance); break; - // The Format Data Response PDU is sent as a reply to the Format Data Request PDU. - // It is used to indicate whether processing of the Format Data Request PDU - // was successful. If the processing was successful, the Format Data Response PDU - // includes the contents of the requested clipboard data + /* + * The Format Data Response PDU is sent as a reply to the Format Data Request PDU. + * It is used to indicate whether processing of the Format Data Request PDU + * was successful. If the processing was successful, the Format Data Response PDU + * includes the contents of the requested clipboard data + */ case RDP_EVENT_TYPE_CB_DATA_RESPONSE: cliprdr_process_cb_data_response_event(instance, (RDP_CB_DATA_RESPONSE_EVENT*) event); break; @@ -1648,14 +1659,14 @@ void mac_rail_CreateWindow(rdpRail* rail, rdpWindow* window) BOOL displayAsModal = NO; NSMutableArray * ma = g_mrdpview->windows; - // make sure window fits resolution + /* make sure window fits resolution */ if (window->windowWidth > g_mrdpview->width) window->windowWidth = g_mrdpview->width; if (window->windowHeight > g_mrdpview->height) window->windowHeight = g_mrdpview->height; - // center main window, which is the first to be created + /* center main window, which is the first to be created */ if ([ma count] == 0) { centerWindow = YES; @@ -1677,7 +1688,7 @@ void mac_rail_CreateWindow(rdpRail* rail, rdpWindow* window) } - // create NSWindow + /* create NSWindow */ NSRect winFrame = NSMakeRect(window->windowOffsetX, window->windowOffsetY, window->windowWidth, window->windowHeight); if (centerWindow) @@ -1688,18 +1699,19 @@ void mac_rail_CreateWindow(rdpRail* rail, rdpWindow* window) backing:NSBackingStoreBuffered defer:NO]; - // this does not work if specified during window creation in above code + /* this does not work if specified during window creation in above code */ [newWindow setStyleMask:NSBorderlessWindowMask]; - if (moveWindow) { - // let RDP server know that window has moved + if (moveWindow) + { + /* let RDP server know that window has moved */ RAIL_WINDOW_MOVE_ORDER windowMove; apple_to_windowMove(&winFrame, &windowMove); windowMove.windowId = window->windowId; mac_send_rail_client_event(g_mrdpview->rdp_instance->context->channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &windowMove); } - // create MRDPRailView and add to above window + /* create MRDPRailView and add to above window */ NSRect viewFrame = NSMakeRect(window->clientOffsetX, window->clientOffsetY, window->clientAreaWidth, window->clientAreaHeight); @@ -1707,30 +1719,33 @@ void mac_rail_CreateWindow(rdpRail* rail, rdpWindow* window) [newView setRdpInstance:g_mrdpview->rdp_instance width:g_mrdpview->width andHeight:g_mrdpview->height windowID: window->windowId]; [newWindow setContentView:newView]; - // save new window + /* save new window */ MRDPWindow * mrdpWindow = [[MRDPWindow alloc] init]; [mrdpWindow setWindowID:window->windowId]; [mrdpWindow setWindow:newWindow]; [mrdpWindow setView:newView]; - // add to list of windows + /* add to list of windows */ [ma addObject:mrdpWindow]; - // make new window current + /* make new window current */ g_mrdpview->currentWindow = mrdpWindow; if (displayAsModal) { - // display as modal window + /* display as modal window */ NSModalSession session = [NSApp beginModalSessionForWindow:newWindow]; + while (1) { if ([NSApp runModalSession:session] != NSRunContinuesResponse) break; } + [NSApp endModalSession:session]; } - else { + else + { [newWindow makeKeyAndOrderFront:NSApp]; [[g_mrdpview window] resignFirstResponder]; [g_mrdpview resignFirstResponder]; @@ -1751,22 +1766,27 @@ void mac_rail_MoveWindow(rdpRail* rail, rdpWindow* window) void mac_rail_ShowWindow(rdpRail* rail, rdpWindow* window, BYTE state) { + } void mac_rail_SetWindowText(rdpRail* rail, rdpWindow* window) { + } void mac_rail_SetWindowIcon(rdpRail* rail, rdpWindow* window, rdpIcon* icon) { + } void mac_rail_SetWindowRects(rdpRail* rail, rdpWindow* window) { + } void mac_rail_SetWindowVisibilityRects(rdpRail* rail, rdpWindow* window) { + } /** ********************************************************************* @@ -1944,21 +1964,21 @@ void mac_process_rail_server_localmovesize_event(freerdp* instance, RDP_EVENT *e case RAIL_WMSZ_MOVE: if (moveSize->isMoveSizeStart) { - // local window move in progress + /* local window move in progress */ [g_mrdpview->currentWindow view]->isMoveSizeInProgress = YES; [g_mrdpview->currentWindow view]->saveInitialDragLoc = YES; return; } - // local move has completed + /* local move has completed */ [g_mrdpview->currentWindow view]->isMoveSizeInProgress = NO; [g_mrdpview->currentWindow view]->saveInitialDragLoc = NO; - // let RDP server know where this window is located + /* let RDP server know where this window is located */ mac_send_rail_client_event(instance->context->channels, RDP_EVENT_TYPE_RAIL_CLIENT_WINDOW_MOVE, &windowMove); - // the event we just sent will cause an extra MoveWindow() to be invoked which we need to ignore + /* the event we just sent will cause an extra MoveWindow() to be invoked which we need to ignore */ [g_mrdpview->currentWindow view]->skipMoveWindowOnce = YES; break;