From 588f879a1b94dd2969d3c9fd19b937ac14ab6e53 Mon Sep 17 00:00:00 2001 From: starlit Date: Fri, 31 Jul 2026 15:01:07 +0300 Subject: [PATCH 1/3] macOS: move the cursor without requesting accessibility permission Showing the go to flow bar moves the pointer into it, so that the mouse move handling doesn't immediately hide it again. That went through QCursor::setPos, which on macOS is implemented by synthesizing a mouse event and injecting it into the HID event stream (QCocoaCursor::setPos -> CGEventPost). macOS gates event injection behind the accessibility "control this computer" permission, so the app asked for far more access than it needed, with a system dialog that gives no hint about which feature wants it. Worse, the request is denied by default and never prompts inline, so on any machine without the grant the pointer simply never moved and the feature was quietly dead. Route the move through CGWarpMouseCursorPosition on macOS instead. It repositions the pointer without injecting an event and requires no permission at all. Behaviour is unchanged on every platform: Windows and Linux keep using QCursor::setPos, and macOS now actually performs the move it was always meant to. Warping doesn't deliver a mouse move to the application, which suits this caller exactly, since the intent is to reposition the pointer without triggering the move handling that hides the widget. --- YACReader/viewer.cpp | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/YACReader/viewer.cpp b/YACReader/viewer.cpp index 0050a7f2d..1986d540f 100644 --- a/YACReader/viewer.cpp +++ b/YACReader/viewer.cpp @@ -24,6 +24,34 @@ #include +#ifdef Q_OS_MACOS +#include +#endif + +namespace { +// QCursor::setPos moves the pointer by synthesizing a mouse event and injecting +// it into the HID event stream (QCocoaCursor::setPos -> CGEventPost). macOS +// gates that behind the accessibility "control this computer" permission, so on +// a machine that hasn't granted it the call is silently denied and the pointer +// never moves, while the user gets an unexplained permission request. +// +// CGWarpMouseCursorPosition repositions the pointer without injecting an event +// and needs no permission. It doesn't deliver a mouse move to the application, +// which suits the only caller here: the point is to reposition the pointer +// *without* triggering the move handling that would hide the widget again. +void moveCursorTo(const QPoint &globalPos) +{ +#ifdef Q_OS_MACOS + CGWarpMouseCursorPosition(CGPointMake(globalPos.x(), globalPos.y())); + // Warping leaves a short interval where physical mouse movement is filtered + // out; re-associating ends it so the next movement registers immediately. + CGAssociateMouseAndMouseCursorPosition(true); +#else + QCursor::setPos(globalPos); +#endif +} +} + Viewer::Viewer(QWidget *parent) : QScrollArea(parent), fullscreen(false), @@ -1332,7 +1360,7 @@ void Viewer::moveCursoToGoToFlow() cursorX = x1 + 10; if (cursorX >= x2) cursorX = x2 - 10; - cursor().setPos(mapToGlobal(QPoint(cursorX, cursorY))); + moveCursorTo(mapToGlobal(QPoint(cursorX, cursorY))); hideCursorTimer->stop(); showCursor(); } From e8af9981cd742be897b793d65c4cbbeff17d371d Mon Sep 17 00:00:00 2001 From: starlit Date: Fri, 31 Jul 2026 15:01:28 +0300 Subject: [PATCH 2/3] Update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 915a136fb..6c362977d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ Version counting is based on semantic versioning (Major.Feature.Patch) * Add an optional circular magnifying glass, with an optional ring drawn around it. The configured size is kept as a rectangle, so switching back and forth doesn't lose it. * Add optional edge easing for the magnifying glass. The magnified region is pushed toward the edges of the view, so content near the border can be inspected without pushing the cursor all the way into the corner. * Require a full wheel notch before the magnifying glass changes size or zoom, so a light trackpad gesture no longer resizes it. +* Fix showing the go to flow bar asking for permission to control the computer on macOS. Moving the cursor into the bar now works without granting any accessibility permission, where before it was silently doing nothing. ### YACReaderLibrary * Add a library repair function to restore missing covers and rescan files that previously failed to be added. From 6a95b5ab339c459d7a713355e519161d43a70fd9 Mon Sep 17 00:00:00 2001 From: starlit Date: Fri, 31 Jul 2026 23:15:58 +0300 Subject: [PATCH 3/3] Link the upstream Qt bug from the cursor warp workaround The macOS branch in moveCursorTo() exists only because QCursor::setPos is implemented with CGEventPost. That is now filed as QTBUG-148709, so point at it from the comment and note the condition under which this workaround can be removed. --- YACReader/viewer.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/YACReader/viewer.cpp b/YACReader/viewer.cpp index 1986d540f..e64c39ce6 100644 --- a/YACReader/viewer.cpp +++ b/YACReader/viewer.cpp @@ -39,6 +39,10 @@ namespace { // and needs no permission. It doesn't deliver a mouse move to the application, // which suits the only caller here: the point is to reposition the pointer // *without* triggering the move handling that would hide the widget again. +// +// Reported upstream as https://qt-project.atlassian.net/browse/QTBUG-148709. +// If Qt switches QCocoaCursor::setPos to the warp, this can go back to being a +// plain QCursor::setPos call once the fixed version is the minimum supported. void moveCursorTo(const QPoint &globalPos) { #ifdef Q_OS_MACOS