diff options
Diffstat (limited to '')
-rw-r--r-- | server/Mac/mf_input.c | 511 |
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; +} |