Skip to content

Commit

Permalink
fix(macos): properly handle accessibility permission
Browse files Browse the repository at this point in the history
  • Loading branch information
Hazer committed Jul 14, 2024
1 parent 18e7dfb commit 6651bc7
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 0 deletions.
38 changes: 38 additions & 0 deletions src/platform/macos/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#include <chrono>
#include <mach/mach.h>

#include "misc.h"

#include "src/logging.h"
#include "src/platform/common.h"
#include "src/utility.h"
Expand Down Expand Up @@ -226,6 +228,11 @@ const KeyCodeMap kKeyCodesMap[] = {
};
// clang-format on

/**
* Used to avoid spamming permission requests when the user receives an input event
*/
bool accessibility_permission_requested;

int
keysym(int keycode) {
KeyCodeMap key_map {};
Expand All @@ -242,12 +249,36 @@ const KeyCodeMap kKeyCodesMap[] = {
return temp_map->mac_keycode;
}

std::string
default_accessibility_log_msg() {
return "Accessibility permission is not enabled,"
" please enable sunshine in "
"[System Settings > Privacy & Security > Privacy > Accessibility]"
", then please restart Sunshine for it to take effect";
}

void
print_accessibility_status(const bool is_keyboard_event, const bool release) {
if (!release) return;

if (!has_accessibility_permission()) {
if (!accessibility_permission_requested) {
accessibility_permission_requested = true;
request_accessibility_permission();
}
BOOST_LOG(info) << "Received " << (is_keyboard_event ? "keyboard" : "mouse") << " event but "
<< default_accessibility_log_msg();
}
}

void
keyboard_update(input_t &input, uint16_t modcode, bool release, uint8_t flags) {
auto key = keysym(modcode);

BOOST_LOG(debug) << "got keycode: 0x"sv << std::hex << modcode << ", translated to: 0x" << std::hex << key << ", release:" << release;

print_accessibility_status(true, release);

if (key < 0) {
return;
}
Expand Down Expand Up @@ -435,6 +466,8 @@ const KeyCodeMap kKeyCodesMap[] = {
return;
}

print_accessibility_status(false, release);

macos_input->mouse_down[mac_button] = !release;

// if the last mouse down was less than MULTICLICK_DELAY_MS, we send a double click event
Expand Down Expand Up @@ -535,6 +568,11 @@ const KeyCodeMap kKeyCodesMap[] = {

const auto macos_input = static_cast<macos_input_t *>(result.get());

accessibility_permission_requested = false;
if (request_accessibility_permission()) {
BOOST_LOG(info) << default_accessibility_log_msg() << ", to allow mouse clicks and keyboard inputs.";
}

// Default to main display
macos_input->display = CGMainDisplayID();

Expand Down
16 changes: 16 additions & 0 deletions src/platform/macos/misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,22 @@

#include <CoreGraphics/CoreGraphics.h>

namespace platf {
/**
* Prompts the user for Accessibility permission
* @return returns true if requested permission, false if already has permission
*/
bool
request_accessibility_permission();

/**
* Checks for Accessibility permission
* @return returns true if sunshine has Accessibility permission enabled
*/
bool
has_accessibility_permission();
}

namespace dyn {
typedef void (*apiproc)();

Expand Down
18 changes: 18 additions & 0 deletions src/platform/macos/misc.mm
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
#define __APPLE_USE_RFC_3542 1
#endif

#include <Carbon/Carbon.h>

#include <Foundation/Foundation.h>
#include <arpa/inet.h>
#include <dlfcn.h>
Expand Down Expand Up @@ -523,6 +525,22 @@ operator bool() override {
create_high_precision_timer() {
return std::make_unique<macos_high_precision_timer>();
}

bool
request_accessibility_permission() {
NSDictionary* options = @{static_cast<id> (kAXTrustedCheckOptionPrompt): @YES};
return !AXIsProcessTrustedWithOptions(static_cast<CFDictionaryRef> (options));
}

bool
has_accessibility_permission() {
NSDictionary* options = @{static_cast<id> (kAXTrustedCheckOptionPrompt): @NO};
// We use kAXTrustedCheckOptionPrompt == NO here,
// instead of using XIsProcessTrusted(),
// because this will update the accessibility list with sunshine current path
return AXIsProcessTrustedWithOptions(static_cast<CFDictionaryRef> (options));
}

} // namespace platf

namespace dyn {
Expand Down

0 comments on commit 6651bc7

Please sign in to comment.