mirror of
https://github.com/JetBrains/JetBrainsRuntime.git
synced 2025-12-06 09:29:38 +01:00
JBR-4306 Robot doesn't work as expected in some cases on macOS
(cherry picked from commits7d69734465,0f33031484,3b5ded0d02)
This commit is contained in:
@@ -65,6 +65,9 @@ static int* gsButtonEventNumber;
|
||||
static NSTimeInterval gNextKeyEventTime;
|
||||
static NSTimeInterval safeDelay;
|
||||
|
||||
#define KEY_CODE_COUNT 128
|
||||
static CGEventFlags keyOwnFlags[KEY_CODE_COUNT];
|
||||
|
||||
static inline CGKeyCode GetCGKeyCode(jint javaKeyCode);
|
||||
|
||||
static void PostMouseEvent(const CGPoint point, CGMouseButton button,
|
||||
@@ -103,6 +106,20 @@ static inline void autoDelay(BOOL isMove) {
|
||||
gNextKeyEventTime = [[NSDate date] timeIntervalSinceReferenceDate] + safeDelay;
|
||||
}
|
||||
|
||||
static void initKeyFlags() {
|
||||
CGEventSourceRef source = CGEventSourceCreate(kCGEventSourceStatePrivate);
|
||||
for (CGKeyCode keyCode = 0; keyCode < KEY_CODE_COUNT; keyCode++) {
|
||||
CGEventRef event = CGEventCreateKeyboardEvent(source, keyCode, true);
|
||||
if (event != NULL) {
|
||||
keyOwnFlags[keyCode] = CGEventGetFlags(event);
|
||||
CFRelease(event);
|
||||
}
|
||||
}
|
||||
if (source != NULL) {
|
||||
CFRelease(source);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_CRobot
|
||||
* Method: initRobot
|
||||
@@ -151,6 +168,8 @@ Java_sun_lwawt_macosx_CRobot_initRobot
|
||||
for (i = 0; i < gNumberOfButtons; ++i) {
|
||||
gsButtonEventNumber[i] = ROBOT_EVENT_NUMBER_START;
|
||||
}
|
||||
|
||||
initKeyFlags();
|
||||
}];
|
||||
}
|
||||
}
|
||||
@@ -279,6 +298,20 @@ Java_sun_lwawt_macosx_CRobot_mouseWheel
|
||||
}];
|
||||
}
|
||||
|
||||
// CGEventCreateKeyboardEvent incorrectly handles flags pertinent to non-modifier keys
|
||||
// (e.g. F1-F12 keys always Fn flag set, while arrow keys always have Fn and NumPad flags set).
|
||||
// Those flags are not cleared for following key presses automatically, so we need to do it ourselves.
|
||||
// See JBR-4306 for details.
|
||||
static void clearStickyFlags(CGEventRef event, CGKeyCode keyCode, CGEventFlags flagToCheck) {
|
||||
if (keyCode < KEY_CODE_COUNT && (keyOwnFlags[keyCode] & flagToCheck) == 0) {
|
||||
CGEventFlags flags = CGEventGetFlags(event);
|
||||
CGEventFlags updatedFlags = flags & ~flagToCheck;
|
||||
if (updatedFlags != flags) {
|
||||
CGEventSetFlags(event, updatedFlags);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Class: sun_lwawt_macosx_CRobot
|
||||
* Method: keyEvent
|
||||
@@ -294,11 +327,10 @@ Java_sun_lwawt_macosx_CRobot_keyEvent
|
||||
CGKeyCode keyCode = GetCGKeyCode(javaKeyCode);
|
||||
CGEventRef event = CGEventCreateKeyboardEvent(source, keyCode, keyPressed);
|
||||
if (event != NULL) {
|
||||
CGEventFlags flags = CGEventSourceFlagsState(kCGEventSourceStateHIDSystemState);
|
||||
if ((flags & kCGEventFlagMaskSecondaryFn) != 0) {
|
||||
flags ^= kCGEventFlagMaskSecondaryFn;
|
||||
CGEventSetFlags(event, flags);
|
||||
}
|
||||
// this assumes Robot isn't used to generate Fn key presses
|
||||
clearStickyFlags(event, keyCode, kCGEventFlagMaskSecondaryFn);
|
||||
// there is no NumPad key, so this won't hurt in any case
|
||||
clearStickyFlags(event, keyCode, kCGEventFlagMaskNumericPad);
|
||||
CGEventPost(kCGHIDEventTap, event);
|
||||
CFRelease(event);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user