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 Dec 5, 2024
1 parent f0a00ae commit d8d4ada
Show file tree
Hide file tree
Showing 3 changed files with 70 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 @@ -6,6 +6,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 @@ -219,6 +221,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 @@ -235,12 +242,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(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 @@ -412,6 +443,8 @@ const KeyCodeMap kKeyCodesMap[] = {
BOOST_LOG(warning) << "Unsupported mouse button for MacOS: "sv << button;
return;
}

print_accessibility_status(false, release);

mouse->mouse_down[mac_button] = !release;

Expand Down Expand Up @@ -511,6 +544,11 @@ const KeyCodeMap kKeyCodesMap[] = {

auto macos_input = (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
16 changes: 16 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 @@ -516,7 +518,21 @@

return std::make_unique<qos_t>(sockfd, reset_options);
}

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 d8d4ada

Please sign in to comment.