mirror of
https://github.com/FreeRDP/FreeRDP.git
synced 2024-11-30 05:17:23 +08:00
[client,mac] fix keyboard state sync
* release all keyboard modifiers on pause * release/sync keyboard modifier states on resume * update modifier states on keyDown, keyUp and flagsChanged
This commit is contained in:
parent
db73c562a2
commit
feceb1c0f3
@ -37,6 +37,7 @@
|
||||
|
||||
#import "freerdp/freerdp.h"
|
||||
#import "freerdp/types.h"
|
||||
#import "freerdp/config.h"
|
||||
#import "freerdp/channels/channels.h"
|
||||
#import "freerdp/gdi/gdi.h"
|
||||
#import "freerdp/gdi/dc.h"
|
||||
@ -417,7 +418,7 @@ DWORD WINAPI mac_client_thread(void *param)
|
||||
mf_scale_mouse_event(context, PTR_FLAGS_MOVE, x, y);
|
||||
}
|
||||
|
||||
DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type)
|
||||
static DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type)
|
||||
{
|
||||
/**
|
||||
* In 99% of cases, the given key code is truly keyboard independent.
|
||||
@ -473,6 +474,22 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type)
|
||||
return keyCode;
|
||||
}
|
||||
|
||||
- (void)flagsChanged:(NSEvent *)event
|
||||
{
|
||||
if (!is_connected)
|
||||
return;
|
||||
|
||||
DWORD modFlags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
|
||||
|
||||
WINPR_ASSERT(instance);
|
||||
WINPR_ASSERT(instance->context);
|
||||
|
||||
rdpInput *input = instance->context->input;
|
||||
|
||||
updateFlagStates(input, modFlags, kbdModFlags);
|
||||
kbdModFlags = modFlags;
|
||||
}
|
||||
|
||||
- (void)keyDown:(NSEvent *)event
|
||||
{
|
||||
DWORD keyCode;
|
||||
@ -485,6 +502,8 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type)
|
||||
if (!is_connected)
|
||||
return;
|
||||
|
||||
[self flagsChanged:event];
|
||||
|
||||
keyFlags = KBD_FLAGS_DOWN;
|
||||
keyCode = [event keyCode];
|
||||
characters = [event charactersIgnoringModifiers];
|
||||
@ -500,12 +519,12 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type)
|
||||
keyFlags |= (scancode & KBDEXT) ? KBDEXT : 0;
|
||||
scancode &= 0xFF;
|
||||
vkcode &= 0xFF;
|
||||
#if 0
|
||||
WLog_ERR(TAG,
|
||||
"keyDown: keyCode: 0x%04X scancode: 0x%04X vkcode: 0x%04X keyFlags: %d name: %s",
|
||||
|
||||
#if defined(WITH_DEBUG_KBD)
|
||||
WLog_DBG(TAG, "keyDown: keyCode: 0x%04X scancode: 0x%04X vkcode: 0x%04X keyFlags: %d name: %s",
|
||||
keyCode, scancode, vkcode, keyFlags, GetVirtualKeyName(vkcode));
|
||||
#endif
|
||||
sync_keyboard_state(instance);
|
||||
|
||||
WINPR_ASSERT(instance->context);
|
||||
freerdp_input_send_keyboard_event(instance->context->input, keyFlags, scancode);
|
||||
}
|
||||
@ -522,6 +541,8 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type)
|
||||
if (!is_connected)
|
||||
return;
|
||||
|
||||
[self flagsChanged:event];
|
||||
|
||||
keyFlags = KBD_FLAGS_RELEASE;
|
||||
keyCode = [event keyCode];
|
||||
characters = [event charactersIgnoringModifiers];
|
||||
@ -537,107 +558,100 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type)
|
||||
keyFlags |= (scancode & KBDEXT) ? KBDEXT : 0;
|
||||
scancode &= 0xFF;
|
||||
vkcode &= 0xFF;
|
||||
#if 0
|
||||
WLog_DBG(TAG,
|
||||
"keyUp: key: 0x%04X scancode: 0x%04X vkcode: 0x%04X keyFlags: %d name: %s",
|
||||
#if defined(WITH_DEBUG_KBD)
|
||||
WLog_DBG(TAG, "keyUp: key: 0x%04X scancode: 0x%04X vkcode: 0x%04X keyFlags: %d name: %s",
|
||||
keyCode, scancode, vkcode, keyFlags, GetVirtualKeyName(vkcode));
|
||||
#endif
|
||||
WINPR_ASSERT(instance->context);
|
||||
freerdp_input_send_keyboard_event(instance->context->input, keyFlags, scancode);
|
||||
}
|
||||
|
||||
- (void)flagsChanged:(NSEvent *)event
|
||||
static BOOL updateFlagState(rdpInput *input, DWORD modFlags, DWORD kbdModFlags, DWORD flag)
|
||||
{
|
||||
int key;
|
||||
DWORD keyFlags;
|
||||
DWORD vkcode;
|
||||
DWORD scancode;
|
||||
DWORD modFlags;
|
||||
rdpInput *input;
|
||||
const BOOL press = ((modFlags & flag) != 0) && ((kbdModFlags & flag) == 0);
|
||||
const BOOL release = ((modFlags & flag) == 0) && ((kbdModFlags & flag) != 0);
|
||||
DWORD keyFlags = press ? KBD_FLAGS_DOWN : (release ? KBD_FLAGS_RELEASE : 0);
|
||||
const char *name = NULL;
|
||||
DWORD scancode = 0;
|
||||
|
||||
if (!is_connected)
|
||||
return;
|
||||
switch (flag)
|
||||
{
|
||||
case NSEventModifierFlagCapsLock:
|
||||
name = "NSEventModifierFlagCapsLock";
|
||||
scancode = RDP_SCANCODE_CAPSLOCK;
|
||||
break;
|
||||
case NSEventModifierFlagShift:
|
||||
name = "NSEventModifierFlagShift";
|
||||
scancode = RDP_SCANCODE_LSHIFT;
|
||||
break;
|
||||
|
||||
keyFlags = 0;
|
||||
key = [event keyCode];
|
||||
modFlags = [event modifierFlags] & NSEventModifierFlagDeviceIndependentFlagsMask;
|
||||
vkcode = GetVirtualKeyCodeFromKeycode(key, WINPR_KEYCODE_TYPE_APPLE);
|
||||
scancode = GetVirtualScanCodeFromVirtualKeyCode(vkcode, 4);
|
||||
keyFlags |= (scancode & KBDEXT) ? KBDEXT : 0;
|
||||
case NSEventModifierFlagControl:
|
||||
name = "NSEventModifierFlagControl";
|
||||
scancode = RDP_SCANCODE_LCONTROL;
|
||||
break;
|
||||
|
||||
case NSEventModifierFlagOption:
|
||||
name = "NSEventModifierFlagOption";
|
||||
scancode = RDP_SCANCODE_LMENU;
|
||||
break;
|
||||
|
||||
case NSEventModifierFlagCommand:
|
||||
name = "NSEventModifierFlagCommand";
|
||||
scancode = RDP_SCANCODE_LWIN;
|
||||
break;
|
||||
|
||||
case NSEventModifierFlagNumericPad:
|
||||
name = "NSEventModifierFlagNumericPad";
|
||||
scancode = RDP_SCANCODE_NUMLOCK;
|
||||
break;
|
||||
|
||||
case NSEventModifierFlagHelp:
|
||||
name = "NSEventModifierFlagHelp";
|
||||
scancode = RDP_SCANCODE_HELP;
|
||||
break;
|
||||
|
||||
case NSEventModifierFlagFunction:
|
||||
name = "NSEventModifierFlagFunction";
|
||||
scancode = RDP_SCANCODE_HELP;
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_ERR(TAG, "Invalid flag: 0x%08" PRIx32 ", not supported", flag);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
keyFlags |= (scancode & KBDEXT);
|
||||
scancode &= 0xFF;
|
||||
vkcode &= 0xFF;
|
||||
#if 0
|
||||
WLog_DBG(TAG,
|
||||
"flagsChanged: key: 0x%04X scancode: 0x%04X vkcode: 0x%04X extended: %d name: %s modFlags: 0x%04X",
|
||||
key - 8, scancode, vkcode, keyFlags, GetVirtualKeyName(vkcode), modFlags);
|
||||
|
||||
if (modFlags & NSEventModifierFlagCapsLock)
|
||||
WLog_DBG(TAG, "NSEventModifierFlagCapsLock");
|
||||
|
||||
if (modFlags & NSEventModifierFlagShift)
|
||||
WLog_DBG(TAG, "NSEventModifierFlagShift");
|
||||
|
||||
if (modFlags & NSEventModifierFlagControl)
|
||||
WLog_DBG(TAG, "NSEventModifierFlagControl");
|
||||
|
||||
if (modFlags & NSEventModifierFlagOption)
|
||||
WLog_DBG(TAG, "NSEventModifierFlagOption");
|
||||
|
||||
if (modFlags & NSEventModifierFlagCommand)
|
||||
WLog_DBG(TAG, "NSEventModifierFlagCommand");
|
||||
|
||||
if (modFlags & NSEventModifierFlagNumericPad)
|
||||
WLog_DBG(TAG, "NSEventModifierFlagNumericPad");
|
||||
|
||||
if (modFlags & NSEventModifierFlagHelp)
|
||||
WLog_DBG(TAG, "NSEventModifierFlagHelp");
|
||||
|
||||
#if defined(WITH_DEBUG_KBD)
|
||||
if (press || release)
|
||||
WLog_DBG(TAG, "changing flag %s[0x%08" PRIx32 "] to %s", name, flag,
|
||||
press ? "DOWN" : "RELEASE");
|
||||
#endif
|
||||
|
||||
WINPR_ASSERT(instance);
|
||||
WINPR_ASSERT(instance->context);
|
||||
if (press)
|
||||
return freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_DOWN, scancode);
|
||||
|
||||
input = instance->context->input;
|
||||
if (release)
|
||||
return freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_RELEASE, scancode);
|
||||
|
||||
if ((modFlags & NSEventModifierFlagCapsLock) && !(kbdModFlags & NSEventModifierFlagCapsLock))
|
||||
freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_DOWN, scancode);
|
||||
else if (!(modFlags & NSEventModifierFlagCapsLock) &&
|
||||
(kbdModFlags & NSEventModifierFlagCapsLock))
|
||||
freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_RELEASE, scancode);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ((modFlags & NSEventModifierFlagShift) && !(kbdModFlags & NSEventModifierFlagShift))
|
||||
freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_DOWN, scancode);
|
||||
else if (!(modFlags & NSEventModifierFlagShift) && (kbdModFlags & NSEventModifierFlagShift))
|
||||
freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_RELEASE, scancode);
|
||||
static BOOL updateFlagStates(rdpInput *input, UINT32 modFlags, UINT32 kbdModFlags)
|
||||
{
|
||||
updateFlagState(input, modFlags, kbdModFlags, NSEventModifierFlagCapsLock);
|
||||
updateFlagState(input, modFlags, kbdModFlags, NSEventModifierFlagShift);
|
||||
updateFlagState(input, modFlags, kbdModFlags, NSEventModifierFlagControl);
|
||||
updateFlagState(input, modFlags, kbdModFlags, NSEventModifierFlagOption);
|
||||
updateFlagState(input, modFlags, kbdModFlags, NSEventModifierFlagCommand);
|
||||
updateFlagState(input, modFlags, kbdModFlags, NSEventModifierFlagNumericPad);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
if ((modFlags & NSEventModifierFlagControl) && !(kbdModFlags & NSEventModifierFlagControl))
|
||||
freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_DOWN, scancode);
|
||||
else if (!(modFlags & NSEventModifierFlagControl) && (kbdModFlags & NSEventModifierFlagControl))
|
||||
freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_RELEASE, scancode);
|
||||
|
||||
if ((modFlags & NSEventModifierFlagOption) && !(kbdModFlags & NSEventModifierFlagOption))
|
||||
freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_DOWN, scancode);
|
||||
else if (!(modFlags & NSEventModifierFlagOption) && (kbdModFlags & NSEventModifierFlagOption))
|
||||
freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_RELEASE, scancode);
|
||||
|
||||
if ((modFlags & NSEventModifierFlagCommand) && !(kbdModFlags & NSEventModifierFlagCommand))
|
||||
freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_DOWN, scancode);
|
||||
else if (!(modFlags & NSEventModifierFlagCommand) && (kbdModFlags & NSEventModifierFlagCommand))
|
||||
freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_RELEASE, scancode);
|
||||
|
||||
if ((modFlags & NSEventModifierFlagNumericPad) &&
|
||||
!(kbdModFlags & NSEventModifierFlagNumericPad))
|
||||
freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_DOWN, scancode);
|
||||
else if (!(modFlags & NSEventModifierFlagNumericPad) &&
|
||||
(kbdModFlags & NSEventModifierFlagNumericPad))
|
||||
freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_RELEASE, scancode);
|
||||
|
||||
if ((modFlags & NSEventModifierFlagHelp) && !(kbdModFlags & NSEventModifierFlagHelp))
|
||||
freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_DOWN, scancode);
|
||||
else if (!(modFlags & NSEventModifierFlagHelp) && (kbdModFlags & NSEventModifierFlagHelp))
|
||||
freerdp_input_send_keyboard_event(input, keyFlags | KBD_FLAGS_RELEASE, scancode);
|
||||
|
||||
kbdModFlags = modFlags;
|
||||
static BOOL releaseFlagStates(rdpInput *input, UINT32 kbdModFlags)
|
||||
{
|
||||
return updateFlagStates(input, 0, kbdModFlags);
|
||||
}
|
||||
|
||||
- (void)releaseResources
|
||||
@ -751,6 +765,8 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type)
|
||||
{
|
||||
[self removeTrackingArea:ta];
|
||||
}
|
||||
releaseFlagStates(instance->context->input, kbdModFlags);
|
||||
kbdModFlags = 0;
|
||||
}
|
||||
|
||||
- (void)resume
|
||||
@ -758,6 +774,10 @@ DWORD fixKeyCode(DWORD keyCode, unichar keyChar, enum APPLE_KEYBOARD_TYPE type)
|
||||
if (!self.is_connected)
|
||||
return;
|
||||
|
||||
releaseFlagStates(instance->context->input, kbdModFlags);
|
||||
kbdModFlags = 0;
|
||||
freerdp_input_send_focus_in_event(instance->context->input, 0);
|
||||
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
self->pasteboard_timer =
|
||||
[NSTimer scheduledTimerWithTimeInterval:0.5
|
||||
@ -1496,27 +1516,4 @@ void windows_to_apple_cords(MRDPView *view, NSRect *r)
|
||||
});
|
||||
}
|
||||
|
||||
void sync_keyboard_state(freerdp *instance)
|
||||
{
|
||||
UINT32 flags = 0;
|
||||
CGEventFlags currentFlags = CGEventSourceFlagsState(kCGEventSourceStateHIDSystemState);
|
||||
mfContext *context;
|
||||
|
||||
WINPR_ASSERT(instance);
|
||||
context = (mfContext *)instance->context;
|
||||
WINPR_ASSERT(context);
|
||||
|
||||
if (context->kbdFlags != currentFlags)
|
||||
{
|
||||
if (currentFlags & kCGEventFlagMaskAlphaShift)
|
||||
flags |= KBD_SYNC_CAPS_LOCK;
|
||||
|
||||
if (currentFlags & kCGEventFlagMaskNumericPad)
|
||||
flags |= KBD_SYNC_NUM_LOCK;
|
||||
|
||||
freerdp_input_send_synchronize_event(instance->context->input, flags);
|
||||
context->kbdFlags = currentFlags;
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
Loading…
Reference in New Issue
Block a user