Узнайте, имеет ли эффект QCursor :: setPos - PullRequest
4 голосов
/ 04 февраля 2020

QCursor::setPos() не работает на некоторых платформах при некоторых условиях. Например, в MacOS есть настройки доступности, позволяющие приложению разрешать или запрещать управление курсором. Есть ли способ узнать, имеет ли QCursor::setPos() эффект на данный момент?

Самое тривиальное решение, слегка изменить курсор с помощью QCursor::setPos и проверить, не сработало ли оно (с помощью QCursor::pos), по крайней мере, не в MacOS.

Примечание: Требуется универсальное c решение по крайней мере для Linux, Windows, Ma c.

1 Ответ

3 голосов
/ 16 февраля 2020

Кроссплатформенное решение мне не известно, что не означает, что его нет. Но для macOS вы можете использовать платформенный код c.

решение macOS

В платформе ApplicationServices macOS есть функция AXIsProcessTrusted, это

Возвращает, является ли текущий процесс доверенным клиентом доступности.

см. https://developer.apple.com/documentation/applicationservices/1460720-axisprocesstrusted?language=objc

Помимо вызова вышеуказанной функции, вам необходимо:

  • использовать условное выражение препроцессора Q_OS_MAC для включения спецификаций macOS c code
  • в инфраструктуру ApplicationServices
  • использовать * 1026 include *

Пример

Полный автономный пример может выглядеть так:

#include <iostream>
#include <QApplication>
#include <QMainWindow>
#ifdef Q_OS_MAC
#include <ApplicationServices/ApplicationServices.h>
#endif

class MainWindow : public QMainWindow {

public:
    explicit MainWindow(QWidget *parent = nullptr) : QMainWindow(parent) {
        this->setWindowTitle("Qt Cursor Test");
        this->resize(320, 240);
    }
};

int main(int argc, char *argv[]) {
    QApplication appl(argc, argv);
    MainWindow mainw_window;
    mainw_window.show();

    QCursor cursor;

#ifdef Q_OS_MAC
    if(AXIsProcessTrusted()) {
        std::cout << "trusted accessibility client" << std::endl;
        cursor.setPos(10,10);
    } else {
        std::cout << "not a trusted trusted accessibility client, so give the user a hint or do whatever is appropriate" << std::endl;
    }
#else
    cursor.setPos(10,10);
#endif

    return QApplication::exec();
}

Здание

Вам необходимо создать ссылку на ApplicationServices framework. В случае, если вы используете CMake для сборки, это может выглядеть так:

 cmake_minimum_required(VERSION 3.15)
 project(CursorTest)

 set(CMAKE_CXX_STANDARD 14)
 set(Qt5_DIR "/usr/local/Cellar/qt/5.14.1/lib/cmake/Qt5/")

 find_package(Qt5 COMPONENTS Widgets REQUIRED)

 add_executable(CursorTest main.cpp)

 target_link_libraries(CursorTest PRIVATE Qt5::Widgets  "-framework ApplicationServices")

Системный диалог

Возможно, вы захотите показать системный диалог для пользователей MacOS, что объясняет, что приложение хочет иметь доверие доступности, и предлагает открыть системные настройки по умолчанию, которые будут выглядеть следующим образом:

macOS system dialog

Тогда вы будете использовать Boolean AXIsProcessTrustedWithOptions(CFDictionaryRef options), который

Возвращает, является ли текущий процесс доверенным клиентом специальных возможностей.

options

Словарь параметров или NULL, чтобы не указывать параметры. Доступны следующие параметры: KEY: kAXTrustedCheckOptionPrompt VALUE: ACFBooleanRef, указывающий, будет ли пользователь уведомлен, если текущий процесс не заслуживает доверия. Это можно использовать, например, при запуске приложения, чтобы всегда предупреждать пользователя, если доступность не включена для текущего процесса. Подсказка происходит асинхронно и не влияет на возвращаемое значение.

см. https://developer.apple.com/documentation/applicationservices/1459186-axisprocesstrustedwithoptions?language=objc

Просто немного измените приведенный выше пример:

...
#ifdef Q_OS_MAC
    CFStringRef keys[] = { kAXTrustedCheckOptionPrompt };
    CFTypeRef values[] = { kCFBooleanTrue };
    CFDictionaryRef options = CFDictionaryCreate(NULL,
                                                 (const void **)&keys,
                                                 (const void **)&values,
                                                 sizeof(keys) / sizeof(keys[0]),
                                                 &kCFTypeDictionaryKeyCallBacks,
                                                 &kCFTypeDictionaryValueCallBacks);
    if(AXIsProcessTrustedWithOptions(options)) {
        std::cout << "trusted accessibility client" << std::endl;
        cursor.setPos(10,10);
    } else {
        std::cout << "not a trusted trusted accessibility client, so give the user a hint or do whatever is appropriate" << std::endl;
    }
    CFRelease(options);
#else
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...