summaryrefslogtreecommitdiffstats
path: root/server/Mac/mf_input.c
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--server/Mac/mf_input.c511
1 files changed, 511 insertions, 0 deletions
diff --git a/server/Mac/mf_input.c b/server/Mac/mf_input.c
new file mode 100644
index 0000000..fd4af85
--- /dev/null
+++ b/server/Mac/mf_input.c
@@ -0,0 +1,511 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * FreeRDP Mac OS X Server (Input)
+ *
+ * Copyright 2013 Corey Clayton <can.of.tuna@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 <ApplicationServices/ApplicationServices.h>
+#include <Carbon/Carbon.h>
+
+#include <winpr/windows.h>
+
+#include "mf_input.h"
+#include "mf_info.h"
+
+#include <freerdp/log.h>
+#define TAG SERVER_TAG("mac")
+
+static const CGKeyCode keymap[256] = {
+ 0xFF, // 0x0
+ kVK_Escape, // 0x1
+ kVK_ANSI_1, // 0x2
+ kVK_ANSI_2, // 0x3
+ kVK_ANSI_3, // 0x4
+ kVK_ANSI_4, // 0x5
+ kVK_ANSI_5, // 0x6
+ kVK_ANSI_6, // 0x7
+ kVK_ANSI_7, // 0x8
+ kVK_ANSI_8, // 0x9
+ kVK_ANSI_9, // 0xa
+ kVK_ANSI_0, // 0xb
+ kVK_ANSI_Minus, // 0xc
+ kVK_ANSI_Equal, // 0xd
+ kVK_Delete, // 0xe
+ kVK_Tab, // 0xf
+ kVK_ANSI_Q, // 0x10
+ kVK_ANSI_W, // 0x11
+ kVK_ANSI_E, // 0x12
+ kVK_ANSI_R, // 0x13
+ kVK_ANSI_T, // 0x14
+ kVK_ANSI_Y, // 0x15
+ kVK_ANSI_U, // 0x16
+ kVK_ANSI_I, // 0x17
+ kVK_ANSI_O, // 0x18
+ kVK_ANSI_P, // 0x19
+ kVK_ANSI_LeftBracket, // 0x1a
+ kVK_ANSI_RightBracket, // 0x1b
+ kVK_Return, // 0x1c
+ kVK_Control, // 0x1d
+ kVK_ANSI_A, // 0x1e
+ kVK_ANSI_S, // 0x1f
+ kVK_ANSI_D, // 0x20
+ kVK_ANSI_F, // 0x21
+ kVK_ANSI_G, // 0x22
+ kVK_ANSI_H, // 0x23
+ kVK_ANSI_J, // 0x24
+ kVK_ANSI_K, // 0x25
+ kVK_ANSI_L, // 0x26
+ kVK_ANSI_Semicolon, // 0x27
+ kVK_ANSI_Quote, // 0x28
+ kVK_ANSI_Grave, // 0x29
+ kVK_Shift, // 0x2a
+ kVK_ANSI_Backslash, // 0x2b
+ kVK_ANSI_Z, // 0x2c
+ kVK_ANSI_X, // 0x2d
+ kVK_ANSI_C, // 0x2e
+ kVK_ANSI_V, // 0x2f
+ kVK_ANSI_B, // 0x30
+ kVK_ANSI_N, // 0x31
+ kVK_ANSI_M, // 0x32
+ kVK_ANSI_Comma, // 0x33
+ kVK_ANSI_Period, // 0x34
+ kVK_ANSI_Slash, // 0x35
+ kVK_Shift, // 0x36
+ kVK_ANSI_KeypadMultiply, // 0x37
+ kVK_Option, // 0x38
+ kVK_Space, // 0x39
+ kVK_CapsLock, // 0x3a
+ kVK_F1, // 0x3b
+ kVK_F2, // 0x3c
+ kVK_F3, // 0x3d
+ kVK_F4, // 0x3e
+ kVK_F5, // 0x3f
+ kVK_F6, // 0x40
+ kVK_F7, // 0x41
+ kVK_F8, // 0x42
+ kVK_F9, // 0x43
+ kVK_F10, // 0x44
+ 0xFF, // 0x45 -- numlock
+ 0xFF, // 0x46 -- scroll lock
+ kVK_ANSI_Keypad7, // 0x47
+ kVK_ANSI_Keypad8, // 0x48
+ kVK_ANSI_Keypad9, // 0x49
+ kVK_ANSI_KeypadMinus, // 0x4a
+ kVK_ANSI_Keypad4, // 0x4b
+ kVK_ANSI_Keypad5, // 0x4c
+ kVK_ANSI_Keypad6, // 0x4d
+ kVK_ANSI_KeypadPlus, // 0x4e
+ kVK_ANSI_Keypad1, // 0x4f
+ kVK_ANSI_Keypad2, // 0x50
+ kVK_ANSI_Keypad3, // 0x51
+ kVK_ANSI_Keypad0, // 0x52
+ kVK_ANSI_KeypadDecimal, // 0x53
+ 0xFF, // 0x54
+ 0xFF, // 0x55
+ 0xFF, // 0x56
+ kVK_F11, // 0x57
+ kVK_F12, // 0x58
+ 0xFF, // 0x59 -- pause
+ 0xFF, // 0x5a
+ kVK_Control, // 0x5b
+ kVK_Control, // 0x5c
+ 0xFF, // 0x5d -- application
+ 0xFF, // 0x5e -- power
+ 0xFF, // 0x5f -- sleep
+ 0xFF, // 0x60
+ 0xFF, // 0x61
+ 0xFF, // 0x62
+ 0xFF, // 0x63 -- wake
+ 0xFF, // 0x64
+ 0xFF, // 0x65
+ 0xFF, // 0x66
+ 0xFF, // 0x67
+ 0xFF, // 0x68
+ 0xFF, // 0x69
+ 0xFF, // 0x6a
+ 0xFF, // 0x6b
+ 0xFF, // 0x6c
+ 0xFF, // 0x6d
+ 0xFF, // 0x6e
+ 0xFF, // 0x6f
+ 0xFF, // 0x70
+ 0xFF, // 0x71
+ 0xFF, // 0x72
+ 0xFF, // 0x73
+ 0xFF, // 0x74
+ 0xFF, // 0x75
+ 0xFF, // 0x76
+ 0xFF, // 0x77
+ 0xFF, // 0x78
+ 0xFF, // 0x79
+ 0xFF, // 0x7a
+ 0xFF, // 0x7b
+ 0xFF, // 0x7c
+ 0xFF, // 0x7d
+ 0xFF, // 0x7e
+ 0xFF, // 0x7f
+ 0xFF, // 0x80
+ 0xFF, // 0x81
+ 0xFF, // 0x82
+ 0xFF, // 0x83
+ 0xFF, // 0x84
+ 0xFF, // 0x85
+ 0xFF, // 0x86
+ 0xFF, // 0x87
+ 0xFF, // 0x88
+ 0xFF, // 0x89
+ 0xFF, // 0x8a
+ 0xFF, // 0x8b
+ 0xFF, // 0x8c
+ 0xFF, // 0x8d
+ 0xFF, // 0x8e
+ 0xFF, // 0x8f
+ 0xFF, // 0x90
+ 0xFF, // 0x91
+ 0xFF, // 0x92
+ 0xFF, // 0x93
+ 0xFF, // 0x94
+ 0xFF, // 0x95
+ 0xFF, // 0x96
+ 0xFF, // 0x97
+ 0xFF, // 0x98
+ 0xFF, // 0x99
+ 0xFF, // 0x9a
+ 0xFF, // 0x9b
+ 0xFF, // 0x9c
+ 0xFF, // 0x9d
+ 0xFF, // 0x9e
+ 0xFF, // 0x9f
+ 0xFF, // 0xa0
+ 0xFF, // 0xa1
+ 0xFF, // 0xa2
+ 0xFF, // 0xa3
+ 0xFF, // 0xa4
+ 0xFF, // 0xa5
+ 0xFF, // 0xa6
+ 0xFF, // 0xa7
+ 0xFF, // 0xa8
+ 0xFF, // 0xa9
+ 0xFF, // 0xaa
+ 0xFF, // 0xab
+ 0xFF, // 0xac
+ 0xFF, // 0xad
+ 0xFF, // 0xae
+ 0xFF, // 0xaf
+ 0xFF, // 0xb0
+ 0xFF, // 0xb1
+ 0xFF, // 0xb2
+ 0xFF, // 0xb3
+ 0xFF, // 0xb4
+ 0xFF, // 0xb5
+ 0xFF, // 0xb6
+ 0xFF, // 0xb7
+ 0xFF, // 0xb8
+ 0xFF, // 0xb9
+ 0xFF, // 0xba
+ 0xFF, // 0xbb
+ 0xFF, // 0xbc
+ 0xFF, // 0xbd
+ 0xFF, // 0xbe
+ 0xFF, // 0xbf
+ 0xFF, // 0xc0
+ 0xFF, // 0xc1
+ 0xFF, // 0xc2
+ 0xFF, // 0xc3
+ 0xFF, // 0xc4
+ 0xFF, // 0xc5
+ 0xFF, // 0xc6
+ 0xFF, // 0xc7
+ 0xFF, // 0xc8
+ 0xFF, // 0xc9
+ 0xFF, // 0xca
+ 0xFF, // 0xcb
+ 0xFF, // 0xcc
+ 0xFF, // 0xcd
+ 0xFF, // 0xce
+ 0xFF, // 0xcf
+ 0xFF, // 0xd0
+ 0xFF, // 0xd1
+ 0xFF, // 0xd2
+ 0xFF, // 0xd3
+ 0xFF, // 0xd4
+ 0xFF, // 0xd5
+ 0xFF, // 0xd6
+ 0xFF, // 0xd7
+ 0xFF, // 0xd8
+ 0xFF, // 0xd9
+ 0xFF, // 0xda
+ 0xFF, // 0xdb
+ 0xFF, // 0xdc
+ 0xFF, // 0xdd
+ 0xFF, // 0xde
+ 0xFF, // 0xdf
+ 0xFF, // 0xe0
+ 0xFF, // 0xe1
+ 0xFF, // 0xe2
+ 0xFF, // 0xe3
+ 0xFF, // 0xe4
+ 0xFF, // 0xe5
+ 0xFF, // 0xe6
+ 0xFF, // 0xe7
+ 0xFF, // 0xe8
+ 0xFF, // 0xe9
+ 0xFF, // 0xea
+ 0xFF, // 0xeb
+ 0xFF, // 0xec
+ 0xFF, // 0xed
+ 0xFF, // 0xee
+ 0xFF, // 0xef
+ 0xFF, // 0xf0
+ 0xFF, // 0xf1
+ 0xFF, // 0xf2
+ 0xFF, // 0xf3
+ 0xFF, // 0xf4
+ 0xFF, // 0xf5
+ 0xFF, // 0xf6
+ 0xFF, // 0xf7
+ 0xFF, // 0xf8
+ 0xFF, // 0xf9
+ 0xFF, // 0xfa
+ 0xFF, // 0xfb
+ 0xFF, // 0xfc
+ 0xFF, // 0xfd
+ 0xFF, // 0xfe
+};
+
+BOOL mf_input_keyboard_event(rdpInput* input, UINT16 flags, UINT8 code)
+{
+ CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
+ BOOL keyDown = TRUE;
+ CGEventRef kbEvent;
+ CGKeyCode kCode = 0xFF;
+
+ if (flags & KBD_FLAGS_RELEASE)
+ {
+ keyDown = FALSE;
+ }
+
+ if (flags & KBD_FLAGS_EXTENDED)
+ {
+ switch (code)
+ {
+ // case 0x52: //insert
+ case 0x53:
+ kCode = kVK_ForwardDelete;
+ break;
+
+ case 0x4B:
+ kCode = kVK_LeftArrow;
+ break;
+
+ case 0x47:
+ kCode = kVK_Home;
+ break;
+
+ case 0x4F:
+ kCode = kVK_End;
+ break;
+
+ case 0x48:
+ kCode = kVK_UpArrow;
+ break;
+
+ case 0x50:
+ kCode = kVK_DownArrow;
+ break;
+
+ case 0x49:
+ kCode = kVK_PageUp;
+ break;
+
+ case 0x51:
+ kCode = kVK_PageDown;
+ break;
+
+ case 0x4D:
+ kCode = kVK_RightArrow;
+ break;
+
+ default:
+ break;
+ }
+ }
+ else
+ {
+ kCode = keymap[code];
+ }
+
+ kbEvent = CGEventCreateKeyboardEvent(source, kCode, keyDown);
+ CGEventPost(kCGHIDEventTap, kbEvent);
+ CFRelease(kbEvent);
+ CFRelease(source);
+ return TRUE;
+}
+
+BOOL mf_input_unicode_keyboard_event(rdpInput* input, UINT16 flags, UINT16 code)
+{
+ return FALSE;
+}
+
+BOOL mf_input_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
+{
+ float width, height;
+ CGWheelCount wheelCount = 2;
+ INT32 scroll_x = 0;
+ INT32 scroll_y = 0;
+
+ if (flags & (PTR_FLAGS_WHEEL | PTR_FLAGS_HWHEEL))
+ {
+ INT32 scroll = flags & WheelRotationMask;
+
+ if (flags & PTR_FLAGS_WHEEL_NEGATIVE)
+ scroll = -(flags & WheelRotationMask) / 392;
+ else
+ scroll = (flags & WheelRotationMask) / 120;
+
+ if (flags & PTR_FLAGS_WHEEL)
+ scroll_y = scroll;
+ else
+ scroll_x = scroll;
+
+ CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
+ CGEventRef scrollEvent = CGEventCreateScrollWheelEvent(source, kCGScrollEventUnitLine,
+ wheelCount, scroll_y, scroll_x);
+ CGEventPost(kCGHIDEventTap, scrollEvent);
+ CFRelease(scrollEvent);
+ CFRelease(source);
+ }
+ else
+ {
+ mfInfo* mfi;
+ CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStateHIDSystemState);
+ CGEventType mouseType = kCGEventNull;
+ CGMouseButton mouseButton = kCGMouseButtonLeft;
+ mfi = mf_info_get_instance();
+ // width and height of primary screen (even in multimon setups
+ width = (float)mfi->servscreen_width;
+ height = (float)mfi->servscreen_height;
+ x += mfi->servscreen_xoffset;
+ y += mfi->servscreen_yoffset;
+
+ if (flags & PTR_FLAGS_MOVE)
+ {
+ if (mfi->mouse_down_left == TRUE)
+ {
+ mouseType = kCGEventLeftMouseDragged;
+ }
+ else if (mfi->mouse_down_right == TRUE)
+ {
+ mouseType = kCGEventRightMouseDragged;
+ }
+ else if (mfi->mouse_down_other == TRUE)
+ {
+ mouseType = kCGEventOtherMouseDragged;
+ }
+ else
+ {
+ mouseType = kCGEventMouseMoved;
+ }
+
+ CGEventRef move = CGEventCreateMouseEvent(source, mouseType, CGPointMake(x, y),
+ mouseButton // ignored for just movement
+ );
+ CGEventPost(kCGHIDEventTap, move);
+ CFRelease(move);
+ }
+
+ if (flags & PTR_FLAGS_BUTTON1)
+ {
+ mouseButton = kCGMouseButtonLeft;
+
+ if (flags & PTR_FLAGS_DOWN)
+ {
+ mouseType = kCGEventLeftMouseDown;
+ mfi->mouse_down_left = TRUE;
+ }
+ else
+ {
+ mouseType = kCGEventLeftMouseUp;
+ mfi->mouse_down_right = FALSE;
+ }
+ }
+ else if (flags & PTR_FLAGS_BUTTON2)
+ {
+ mouseButton = kCGMouseButtonRight;
+
+ if (flags & PTR_FLAGS_DOWN)
+ {
+ mouseType = kCGEventRightMouseDown;
+ mfi->mouse_down_right = TRUE;
+ }
+ else
+ {
+ mouseType = kCGEventRightMouseUp;
+ mfi->mouse_down_right = FALSE;
+ }
+ }
+ else if (flags & PTR_FLAGS_BUTTON3)
+ {
+ mouseButton = kCGMouseButtonCenter;
+
+ if (flags & PTR_FLAGS_DOWN)
+ {
+ mouseType = kCGEventOtherMouseDown;
+ mfi->mouse_down_other = TRUE;
+ }
+ else
+ {
+ mouseType = kCGEventOtherMouseUp;
+ mfi->mouse_down_other = FALSE;
+ }
+ }
+
+ CGEventRef mouseEvent =
+ CGEventCreateMouseEvent(source, mouseType, CGPointMake(x, y), mouseButton);
+ CGEventPost(kCGHIDEventTap, mouseEvent);
+ CFRelease(mouseEvent);
+ CFRelease(source);
+ }
+
+ return TRUE;
+}
+
+BOOL mf_input_extended_mouse_event(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
+{
+ return FALSE;
+}
+
+BOOL mf_input_keyboard_event_dummy(rdpInput* input, UINT16 flags, UINT16 code)
+{
+ return FALSE;
+}
+
+BOOL mf_input_unicode_keyboard_event_dummy(rdpInput* input, UINT16 flags, UINT16 code)
+{
+ return FALSE;
+}
+
+BOOL mf_input_mouse_event_dummy(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
+{
+ return FALSE;
+}
+
+BOOL mf_input_extended_mouse_event_dummy(rdpInput* input, UINT16 flags, UINT16 x, UINT16 y)
+{
+ return FALSE;
+}