/* * Deskflow -- mouse and keyboard sharing utility * SPDX-FileCopyrightText: (C) 2016 Symless Ltd. * SPDX-License-Identifier: GPL-2.0-only WITH LicenseRef-OpenSSL-Exception */ #import "platform/OSXMediaKeySupport.h" #import #import #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" int convertKeyIDToNXKeyType(KeyID id) { int type = -1; switch (id) { case kKeyAudioUp: type = NX_KEYTYPE_SOUND_UP; break; case kKeyAudioDown: type = NX_KEYTYPE_SOUND_DOWN; break; case kKeyBrightnessUp: type = NX_KEYTYPE_BRIGHTNESS_UP; break; case kKeyBrightnessDown: type = NX_KEYTYPE_BRIGHTNESS_DOWN; break; case kKeyAudioMute: type = NX_KEYTYPE_MUTE; break; case kKeyEject: type = NX_KEYTYPE_EJECT; break; case kKeyAudioPlay: type = NX_KEYTYPE_PLAY; break; case kKeyAudioNext: type = NX_KEYTYPE_NEXT; break; case kKeyAudioPrev: type = NX_KEYTYPE_PREVIOUS; break; default: break; } return type; } static KeyID convertNXKeyTypeToKeyID(uint32_t const type) { KeyID id = 0; switch (type) { case NX_KEYTYPE_SOUND_UP: id = kKeyAudioUp; break; case NX_KEYTYPE_SOUND_DOWN: id = kKeyAudioDown; break; case NX_KEYTYPE_MUTE: id = kKeyAudioMute; break; case NX_KEYTYPE_EJECT: id = kKeyEject; break; case NX_KEYTYPE_PLAY: id = kKeyAudioPlay; break; case NX_KEYTYPE_FAST: case NX_KEYTYPE_NEXT: id = kKeyAudioNext; break; case NX_KEYTYPE_REWIND: case NX_KEYTYPE_PREVIOUS: id = kKeyAudioPrev; break; default: break; } return id; } bool isMediaKeyEvent(CGEventRef event) { NSEvent *nsEvent = nil; @try { nsEvent = [NSEvent eventWithCGEvent:event]; if ([nsEvent subtype] != 8) { return false; } uint32_t const nxKeyId = ([nsEvent data1] & 0xFFFF0000) >> 16; if (convertNXKeyTypeToKeyID(nxKeyId)) { return true; } } @catch (NSException *e) { } return false; } bool getMediaKeyEventInfo(CGEventRef event, KeyID *const keyId, bool *const down, bool *const isRepeat) { NSEvent *nsEvent = nil; @try { nsEvent = [NSEvent eventWithCGEvent:event]; } @catch (NSException *e) { return false; } if (keyId) { *keyId = convertNXKeyTypeToKeyID(([nsEvent data1] & 0xFFFF0000) >> 16); } if (down) { *down = !([nsEvent data1] & 0x100); } if (isRepeat) { *isRepeat = [nsEvent data1] & 0x1; } return true; } bool fakeNativeMediaKey(KeyID id) { NSEvent *downRef = [NSEvent otherEventWithType:NSSystemDefined location:NSMakePoint(0, 0) modifierFlags:0xa00 timestamp:0 windowNumber:0 context:0 subtype:8 data1:(convertKeyIDToNXKeyType(id) << 16) | ((0xa) << 8) data2:-1]; CGEventRef downEvent = [downRef CGEvent]; NSEvent *upRef = [NSEvent otherEventWithType:NSSystemDefined location:NSMakePoint(0, 0) modifierFlags:0xa00 timestamp:0 windowNumber:0 context:0 subtype:8 data1:(convertKeyIDToNXKeyType(id) << 16) | ((0xb) << 8) data2:-1]; CGEventRef upEvent = [upRef CGEvent]; CGEventPost(0, downEvent); CGEventPost(0, upEvent); return true; }