Skip to content

Commit

Permalink
Revert "fix(macos): Mouse input broken in-game (LizardByte#2550)"
Browse files Browse the repository at this point in the history
  • Loading branch information
BayLee4 committed Sep 27, 2024
1 parent 68eb8d2 commit ae3051f
Show file tree
Hide file tree
Showing 8 changed files with 78 additions and 311 deletions.
77 changes: 31 additions & 46 deletions .github/workflows/CI.yml
Original file line number Diff line number Diff line change
Expand Up @@ -779,42 +779,19 @@ jobs:
name: sunshine-macports
path: artifacts/

- name: Fix permissions
- name: Fix screen capture permissions
if: ${{ matrix.os_version != 12 }} # macOS-12 is okay
# can be removed if the following is fixed in the runner image
# https://github.com/actions/runner-images/issues/9529
# https://github.com/actions/runner-images/pull/9530
run: |
# https://apple.stackexchange.com/questions/362865/macos-list-apps-authorized-for-full-disk-access
# https://github.com/actions/runner-images/issues/9529
# https://github.com/actions/runner-images/pull/9530
# function to execute sql query for each value
function execute_sql_query {
local value=$1
local dbPath=$2
echo "Executing SQL query for value: $value"
sudo sqlite3 "$dbPath" "INSERT OR IGNORE INTO access VALUES($value);"
}
# Find all provisioner paths and store them in an array
readarray -t provisioner_paths < <(sudo find /opt /usr -name provisioner)
echo "Provisioner paths: ${provisioner_paths[@]}"
# Create an empty array
declare -a values=()
# Loop through the provisioner paths and add them to the values array
for p_path in "${provisioner_paths[@]}"; do
# Adjust the service name and other parameters as needed
values+=("'kTCCServiceAccessibility','${p_path}',1,2,4,1,NULL,NULL,0,'UNUSED',NULL,NULL,1592919552")
values+=("'kTCCServiceScreenCapture','${p_path}',1,2,4,1,NULL,NULL,0,'UNUSED',NULL,0,1687786159")
done
echo "Values: ${values[@]}"
# permissions for screen capture
values="'kTCCServiceScreenCapture','/opt/off/opt/runner/provisioner/provisioner',1,2,4,1,NULL,NULL,0,'UNUSED',NULL,0,1687786159"
if [[ "${{ matrix.os_version }}" == "14" ]]; then
# TCC access table in Sonoma has extra 4 columns: pid, pid_version, boot_uuid, last_reminded
for i in "${!values[@]}"; do
values[$i]="${values[$i]},NULL,NULL,'UNUSED',${values[$i]##*,}"
done
values="${values},NULL,NULL,'UNUSED',${values##*,}"
fi
# system and user databases
Expand All @@ -823,28 +800,36 @@ jobs:
"$HOME/Library/Application Support/com.apple.TCC/TCC.db"
)
for value in "${values[@]}"; do
for dbPath in "${dbPaths[@]}"; do
echo "Column names for $dbPath"
echo "-------------------"
sudo sqlite3 "$dbPath" "PRAGMA table_info(access);"
echo "Current permissions for $dbPath"
echo "-------------------"
sudo sqlite3 "$dbPath" "SELECT * FROM access WHERE service='kTCCServiceScreenCapture';"
execute_sql_query "$value" "$dbPath"
echo "Updated permissions for $dbPath"
echo "-------------------"
sudo sqlite3 "$dbPath" "SELECT * FROM access WHERE service='kTCCServiceScreenCapture';"
done
sqlQuery="INSERT OR IGNORE INTO access VALUES($values);"
for dbPath in "${dbPaths[@]}"; do
echo "Column names for $dbPath"
echo "-------------------"
sudo sqlite3 "$dbPath" "PRAGMA table_info(access);"
echo "Current permissions for $dbPath"
echo "-------------------"
sudo sqlite3 "$dbPath" "SELECT * FROM access WHERE service='kTCCServiceScreenCapture';"
sudo sqlite3 "$dbPath" "$sqlQuery"
echo "Updated permissions for $dbPath"
echo "-------------------"
sudo sqlite3 "$dbPath" "SELECT * FROM access WHERE service='kTCCServiceScreenCapture';"
done
- name: Run tests
id: test
timeout-minutes: 10
working-directory:
/opt/local/var/macports/build/_Users_runner_work_Sunshine_Sunshine_ports_multimedia_Sunshine/Sunshine/work/build/tests
run: |
<<<<<<< HEAD
sudo ./test_sunshine --gtest_color=yes
=======
sudo port test "Sunshine"

- name: Test Logs
if: always()
run: |
logfile="/opt/local/var/macports/logs/_Users_runner_work_Sunshine_Sunshine_ports_multimedia_Sunshine/Sunshine/main.log"
cat "$logfile"
>>>>>>> parent of 02ddbefd (fix(macos): Mouse input broken in-game (#2550))

- name: Generate gcov report
# any except canceled or skipped
Expand Down
2 changes: 1 addition & 1 deletion packaging/macos/Portfile
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,4 @@ test.run yes
test.dir ${build.dir}/tests
test.target ""
test.cmd ./test_sunshine
test.args --gtest_color=yes --gtest_filter=-*HIDTest.*:-*DeathTest.*
test.args --gtest_color=yes
10 changes: 0 additions & 10 deletions src/platform/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -748,16 +748,6 @@ namespace platf {

input_t
input();
/**
* @brief Get the current mouse position on screen
* @param input The input_t instance to use.
* @return Screen coordinates of the mouse.
* @examples
* auto [x, y] = get_mouse_loc(input);
* @examples_end
*/
util::point_t
get_mouse_loc(input_t &input);
void
move_mouse(input_t &input, int deltaX, int deltaY);
void
Expand Down
30 changes: 0 additions & 30 deletions src/platform/linux/input/legacy_input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1090,36 +1090,6 @@ namespace platf {
#endif
}

util::point_t
get_mouse_loc(input_t &input) {
#ifdef SUNSHINE_BUILD_X11
Display *xdisplay = ((input_raw_t *) input.get())->display;
if (!xdisplay) {
return util::point_t {};
}
Window root, root_return, child_return;
root = DefaultRootWindow(xdisplay);
int root_x, root_y;
int win_x, win_y;
unsigned int mask_return;

if (XQueryPointer(xdisplay, root, &root_return, &child_return, &root_x, &root_y, &win_x, &win_y, &mask_return)) {
BOOST_LOG(debug)
<< "Pointer is at:"sv << std::endl
<< " x: " << root_x << std::endl
<< " y: " << root_y << std::endl;

return util::point_t { (double) root_x, (double) root_y };
}
else {
BOOST_LOG(debug) << "Unable to query x11 pointer"sv << std::endl;
}
#else
BOOST_LOG(debug) << "Unable to query wayland pointer"sv << std::endl;
#endif
return util::point_t {};
}

/**
* @brief Absolute mouse move.
* @param input The input_t instance to use.
Expand Down
124 changes: 46 additions & 78 deletions src/platform/macos/input.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@
* @file src/platform/macos/input.cpp
* @brief Definitions for macOS input handling.
*/
#include "src/input.h"

#import <Carbon/Carbon.h>
#include <chrono>
#include <mach/mach.h>
Expand All @@ -12,11 +10,6 @@
#include "src/platform/common.h"
#include "src/utility.h"

#include <ApplicationServices/ApplicationServices.h>
#include <CoreFoundation/CoreFoundation.h>
#include <iostream>
#include <thread>

/**
* @brief Delay for a double click, in milliseconds.
* @todo Make this configurable.
Expand Down Expand Up @@ -314,108 +307,85 @@ const KeyCodeMap kKeyCodesMap[] = {
}

// returns current mouse location:
util::point_t
inline CGPoint
get_mouse_loc(input_t &input) {
// Creating a new event every time to avoid any reuse risk
const auto macos_input = static_cast<macos_input_t *>(input.get());
const auto snapshot_event = CGEventCreate(macos_input->source);
const auto current = CGEventGetLocation(snapshot_event);
CFRelease(snapshot_event);
return util::point_t {
current.x,
current.y
};
return CGEventGetLocation(((macos_input_t *) input.get())->mouse_event);
}

void
post_mouse(
input_t &input,
const CGMouseButton button,
const CGEventType type,
const util::point_t raw_location,
const util::point_t previous_location,
const int click_count) {
BOOST_LOG(debug) << "mouse_event: "sv << button << ", type: "sv << type << ", location:"sv << raw_location.x << ":"sv << raw_location.y << " click_count: "sv << click_count;

const auto macos_input = static_cast<macos_input_t *>(input.get());
const auto display = macos_input->display;
const auto event = macos_input->mouse_event;
post_mouse(input_t &input, CGMouseButton button, CGEventType type, CGPoint location, int click_count) {
BOOST_LOG(debug) << "mouse_event: "sv << button << ", type: "sv << type << ", location:"sv << location.x << ":"sv << location.y << " click_count: "sv << click_count;

auto macos_input = (macos_input_t *) input.get();
auto display = macos_input->display;
auto event = macos_input->mouse_event;

// get display bounds for current display
const CGRect display_bounds = CGDisplayBounds(display);
CGRect display_bounds = CGDisplayBounds(display);

// limit mouse to current display bounds
const auto location = CGPoint {
std::clamp(raw_location.x, display_bounds.origin.x, display_bounds.origin.x + display_bounds.size.width - 1),
std::clamp(raw_location.y, display_bounds.origin.y, display_bounds.origin.y + display_bounds.size.height - 1)
};
location.x = std::clamp(location.x, display_bounds.origin.x, display_bounds.origin.x + display_bounds.size.width - 1);
location.y = std::clamp(location.y, display_bounds.origin.y, display_bounds.origin.y + display_bounds.size.height - 1);

CGEventSetType(event, type);
CGEventSetLocation(event, location);
CGEventSetIntegerValueField(event, kCGMouseEventButtonNumber, button);
CGEventSetIntegerValueField(event, kCGMouseEventClickState, click_count);

// Include deltas so some 3D applications can consume changes (game cameras, etc)
const double deltaX = raw_location.x - previous_location.x;
const double deltaY = raw_location.y - previous_location.y;
CGEventSetDoubleValueField(event, kCGMouseEventDeltaX, deltaX);
CGEventSetDoubleValueField(event, kCGMouseEventDeltaY, deltaY);

CGEventPost(kCGHIDEventTap, event);

// For why this is here, see:
// https://stackoverflow.com/questions/15194409/simulated-mouseevent-not-working-properly-osx
CGWarpMouseCursorPosition(location);
}

inline CGEventType
event_type_mouse(input_t &input) {
const auto macos_input = static_cast<macos_input_t *>(input.get());
auto macos_input = ((macos_input_t *) input.get());

if (macos_input->mouse_down[0]) {
return kCGEventLeftMouseDragged;
}
if (macos_input->mouse_down[1]) {
else if (macos_input->mouse_down[1]) {
return kCGEventOtherMouseDragged;
}
if (macos_input->mouse_down[2]) {
else if (macos_input->mouse_down[2]) {
return kCGEventRightMouseDragged;
}
return kCGEventMouseMoved;
else {
return kCGEventMouseMoved;
}
}

void
move_mouse(
input_t &input,
const int deltaX,
const int deltaY) {
const auto current = get_mouse_loc(input);

const auto location = util::point_t { current.x + deltaX, current.y + deltaY };
post_mouse(input, kCGMouseButtonLeft, event_type_mouse(input), location, current, 0);
move_mouse(input_t &input, int deltaX, int deltaY) {
auto current = get_mouse_loc(input);

CGPoint location = CGPointMake(current.x + deltaX, current.y + deltaY);

post_mouse(input, kCGMouseButtonLeft, event_type_mouse(input), location, 0);
}

void
abs_mouse(
input_t &input,
const touch_port_t &touch_port,
const float x,
const float y) {
const auto macos_input = static_cast<macos_input_t *>(input.get());
const auto scaling = macos_input->displayScaling;
const auto display = macos_input->display;

auto location = util::point_t { x * scaling, y * scaling };
abs_mouse(input_t &input, const touch_port_t &touch_port, float x, float y) {
auto macos_input = static_cast<macos_input_t *>(input.get());
auto scaling = macos_input->displayScaling;
auto display = macos_input->display;

CGPoint location = CGPointMake(x * scaling, y * scaling);
CGRect display_bounds = CGDisplayBounds(display);
// in order to get the correct mouse location for capturing display , we need to add the display bounds to the location
location.x += display_bounds.origin.x;
location.y += display_bounds.origin.y;

post_mouse(input, kCGMouseButtonLeft, event_type_mouse(input), location, get_mouse_loc(input), 0);
post_mouse(input, kCGMouseButtonLeft, event_type_mouse(input), location, 0);
}

void
button_mouse(input_t &input, const int button, const bool release) {
button_mouse(input_t &input, int button, bool release) {
CGMouseButton mac_button;
CGEventType event;

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

switch (button) {
case 1:
Expand All @@ -435,24 +405,22 @@ const KeyCodeMap kKeyCodesMap[] = {
return;
}

macos_input->mouse_down[mac_button] = !release;
mouse->mouse_down[mac_button] = !release;

// if the last mouse down was less than MULTICLICK_DELAY_MS, we send a double click event
const auto now = std::chrono::steady_clock::now();
const auto mouse_position = get_mouse_loc(input);

if (now < macos_input->last_mouse_event[mac_button][release] + MULTICLICK_DELAY_MS) {
post_mouse(input, mac_button, event, mouse_position, mouse_position, 2);
auto now = std::chrono::steady_clock::now();
if (now < mouse->last_mouse_event[mac_button][release] + MULTICLICK_DELAY_MS) {
post_mouse(input, mac_button, event, get_mouse_loc(input), 2);
}
else {
post_mouse(input, mac_button, event, mouse_position, mouse_position, 1);
post_mouse(input, mac_button, event, get_mouse_loc(input), 1);
}

macos_input->last_mouse_event[mac_button][release] = now;
mouse->last_mouse_event[mac_button][release] = now;
}

void
scroll(input_t &input, const int high_res_distance) {
scroll(input_t &input, int high_res_distance) {
CGEventRef upEvent = CGEventCreateScrollWheelEvent(
nullptr,
kCGScrollEventUnitLine,
Expand Down Expand Up @@ -533,7 +501,7 @@ const KeyCodeMap kKeyCodesMap[] = {
input() {
input_t result { new macos_input_t() };

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

// Default to main display
macos_input->display = CGMainDisplayID();
Expand All @@ -558,7 +526,7 @@ const KeyCodeMap kKeyCodesMap[] = {
}

// Input coordinates are based on the virtual resolution not the physical, so we need the scaling factor
const CGDisplayModeRef mode = CGDisplayCopyDisplayMode(macos_input->display);
CGDisplayModeRef mode = CGDisplayCopyDisplayMode(macos_input->display);
macos_input->displayScaling = ((CGFloat) CGDisplayPixelsWide(macos_input->display)) / ((CGFloat) CGDisplayModeGetPixelWidth(mode));
CFRelease(mode);

Expand All @@ -579,7 +547,7 @@ const KeyCodeMap kKeyCodesMap[] = {

void
freeInput(void *p) {
const auto *input = static_cast<macos_input_t *>(p);
auto *input = (macos_input_t *) p;

CFRelease(input->source);
CFRelease(input->kb_event);
Expand Down
Loading

0 comments on commit ae3051f

Please sign in to comment.