From ae3051f01e00cff772aba9cccee8847c90c9290c Mon Sep 17 00:00:00 2001 From: BayLee4 <63376748+BayLee4@users.noreply.github.com> Date: Fri, 27 Sep 2024 23:01:35 +0200 Subject: [PATCH] Revert "fix(macos): Mouse input broken in-game (LizardByte#2550)" --- .github/workflows/CI.yml | 77 ++++++-------- packaging/macos/Portfile | 2 +- src/platform/common.h | 10 -- src/platform/linux/input/legacy_input.cpp | 30 ------ src/platform/macos/input.cpp | 124 ++++++++-------------- src/platform/windows/input.cpp | 15 --- src/utility.h | 11 -- tests/unit/test_mouse.cpp | 120 --------------------- 8 files changed, 78 insertions(+), 311 deletions(-) delete mode 100644 tests/unit/test_mouse.cpp diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index c022d193591..a5b5fe55498 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -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 @@ -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 diff --git a/packaging/macos/Portfile b/packaging/macos/Portfile index 678f742ac9b..69de434a28f 100644 --- a/packaging/macos/Portfile +++ b/packaging/macos/Portfile @@ -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 diff --git a/src/platform/common.h b/src/platform/common.h index 5c319dceed7..272d47ba11b 100644 --- a/src/platform/common.h +++ b/src/platform/common.h @@ -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 diff --git a/src/platform/linux/input/legacy_input.cpp b/src/platform/linux/input/legacy_input.cpp index 3d894d47390..2f11238d1cf 100644 --- a/src/platform/linux/input/legacy_input.cpp +++ b/src/platform/linux/input/legacy_input.cpp @@ -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. diff --git a/src/platform/macos/input.cpp b/src/platform/macos/input.cpp index 83c668eb20d..4a4230a4eb7 100644 --- a/src/platform/macos/input.cpp +++ b/src/platform/macos/input.cpp @@ -2,8 +2,6 @@ * @file src/platform/macos/input.cpp * @brief Definitions for macOS input handling. */ -#include "src/input.h" - #import #include #include @@ -12,11 +10,6 @@ #include "src/platform/common.h" #include "src/utility.h" -#include -#include -#include -#include - /** * @brief Delay for a double click, in milliseconds. * @todo Make this configurable. @@ -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(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(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(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(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(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(input.get()); + auto mouse = ((macos_input_t *) input.get()); switch (button) { case 1: @@ -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, @@ -533,7 +501,7 @@ const KeyCodeMap kKeyCodesMap[] = { input() { input_t result { new macos_input_t() }; - const auto macos_input = static_cast(result.get()); + auto macos_input = (macos_input_t *) result.get(); // Default to main display macos_input->display = CGMainDisplayID(); @@ -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); @@ -579,7 +547,7 @@ const KeyCodeMap kKeyCodesMap[] = { void freeInput(void *p) { - const auto *input = static_cast(p); + auto *input = (macos_input_t *) p; CFRelease(input->source); CFRelease(input->kb_event); diff --git a/src/platform/windows/input.cpp b/src/platform/windows/input.cpp index ea0551746cd..6d46aee8d56 100644 --- a/src/platform/windows/input.cpp +++ b/src/platform/windows/input.cpp @@ -542,21 +542,6 @@ namespace platf { send_input(i); } - util::point_t - get_mouse_loc(input_t &input) { - throw std::runtime_error("not implemented yet, has to pass tests"); - // TODO: Tests are failing, something wrong here? - POINT p; - if (!GetCursorPos(&p)) { - return util::point_t { 0.0, 0.0 }; - } - - return util::point_t { - (double) p.x, - (double) p.y - }; - } - void button_mouse(input_t &input, int button, bool release) { INPUT i {}; diff --git a/src/utility.h b/src/utility.h index e9adefd8930..eede4bf6922 100644 --- a/src/utility.h +++ b/src/utility.h @@ -9,7 +9,6 @@ #include #include #include -#include #include #include #include @@ -948,16 +947,6 @@ namespace util { return std::string_view((const char *) &data, sizeof(T)); } - struct point_t { - double x; - double y; - - friend std::ostream & - operator<<(std::ostream &os, const point_t &p) { - return (os << "Point(x: " << p.x << ", y: " << p.y << ")"); - } - }; - namespace endian { template struct endianness { diff --git a/tests/unit/test_mouse.cpp b/tests/unit/test_mouse.cpp deleted file mode 100644 index 53f619b298b..00000000000 --- a/tests/unit/test_mouse.cpp +++ /dev/null @@ -1,120 +0,0 @@ -/** - * @file tests/unit/test_mouse.cpp - * @brief Test src/input.*. - */ -#include - -#include "../tests_common.h" - -struct MouseHIDTest: PlatformTestSuite, testing::WithParamInterface { - void - SetUp() override { -#ifdef _WIN32 - // TODO: Windows tests are failing, `get_mouse_loc` seems broken and `platf::abs_mouse` too - // the alternative `platf::abs_mouse` method seem to work better during tests, - // but I'm not sure about real work - GTEST_SKIP() << "TODO Windows"; -#elif __linux__ - // TODO: Inputtino waiting https://github.com/games-on-whales/inputtino/issues/6 is resolved. - GTEST_SKIP() << "TODO Inputtino"; -#endif - } - - void - TearDown() override { - std::this_thread::sleep_for(std::chrono::milliseconds(200)); - } -}; - -INSTANTIATE_TEST_SUITE_P( - MouseInputs, - MouseHIDTest, - testing::Values( - util::point_t { 40, 40 }, - util::point_t { 70, 150 })); -// todo: add tests for hitting screen edges - -TEST_P(MouseHIDTest, MoveInputTest) { - util::point_t mouse_delta = GetParam(); - - BOOST_LOG(tests) << "MoveInputTest:: got param: " << mouse_delta; - platf::input_t input = platf::input(); - BOOST_LOG(tests) << "MoveInputTest:: init input"; - - BOOST_LOG(tests) << "MoveInputTest:: get current mouse loc"; - auto old_loc = platf::get_mouse_loc(input); - BOOST_LOG(tests) << "MoveInputTest:: got current mouse loc: " << old_loc; - - BOOST_LOG(tests) << "MoveInputTest:: move: " << mouse_delta; - platf::move_mouse(input, mouse_delta.x, mouse_delta.y); - std::this_thread::sleep_for(std::chrono::milliseconds(200)); - BOOST_LOG(tests) << "MoveInputTest:: moved: " << mouse_delta; - - BOOST_LOG(tests) << "MoveInputTest:: get updated mouse loc"; - auto new_loc = platf::get_mouse_loc(input); - BOOST_LOG(tests) << "MoveInputTest:: got updated mouse loc: " << new_loc; - - bool has_input_moved = old_loc.x != new_loc.x && old_loc.y != new_loc.y; - - if (!has_input_moved) { - BOOST_LOG(tests) << "MoveInputTest:: haven't moved"; - } - else { - BOOST_LOG(tests) << "MoveInputTest:: moved"; - } - - EXPECT_TRUE(has_input_moved); - - // Verify we moved as much as we requested - EXPECT_EQ(new_loc.x - old_loc.x, mouse_delta.x); - EXPECT_EQ(new_loc.y - old_loc.y, mouse_delta.y); -} - -TEST_P(MouseHIDTest, AbsMoveInputTest) { - util::point_t mouse_pos = GetParam(); - BOOST_LOG(tests) << "AbsMoveInputTest:: got param: " << mouse_pos; - - platf::input_t input = platf::input(); - BOOST_LOG(tests) << "AbsMoveInputTest:: init input"; - - BOOST_LOG(tests) << "AbsMoveInputTest:: get current mouse loc"; - auto old_loc = platf::get_mouse_loc(input); - BOOST_LOG(tests) << "AbsMoveInputTest:: got current mouse loc: " << old_loc; - -#ifdef _WIN32 - platf::touch_port_t abs_port { - 0, 0, - 65535, 65535 - }; -#elif __linux__ - platf::touch_port_t abs_port { - 0, 0, - 19200, 12000 - }; -#else - platf::touch_port_t abs_port {}; -#endif - BOOST_LOG(tests) << "AbsMoveInputTest:: move: " << mouse_pos; - platf::abs_mouse(input, abs_port, mouse_pos.x, mouse_pos.y); - std::this_thread::sleep_for(std::chrono::milliseconds(200)); - BOOST_LOG(tests) << "AbsMoveInputTest:: moved: " << mouse_pos; - - BOOST_LOG(tests) << "AbsMoveInputTest:: get updated mouse loc"; - auto new_loc = platf::get_mouse_loc(input); - BOOST_LOG(tests) << "AbsMoveInputTest:: got updated mouse loc: " << new_loc; - - bool has_input_moved = old_loc.x != new_loc.x || old_loc.y != new_loc.y; - - if (!has_input_moved) { - BOOST_LOG(tests) << "AbsMoveInputTest:: haven't moved"; - } - else { - BOOST_LOG(tests) << "AbsMoveInputTest:: moved"; - } - - EXPECT_TRUE(has_input_moved); - - // Verify we moved to the absolute coordinate - EXPECT_EQ(new_loc.x, mouse_pos.x); - EXPECT_EQ(new_loc.y, mouse_pos.y); -}