Рейтинг:1

Программирование на C: обнаружение движения указателя мыши

флаг pt

Я работаю над проектом, в котором мне нужно установить флаг только тогда, когда указатель мыши не перемещался в течение определенного периода времени (например, 30 с): если мышь бездействовала в течение 30 с, установите нет_движения (нет_движения = правда;).

До сих пор я знаю, что сервер X Window является базой для многих сред рабочего стола, и я знаю, что для него есть исчерпывающая документация на x.org и tronche.com (Оттуда я понял, что есть событие для указателя, называемое Уведомление о движении).

С использованием подходящее шоу xserver-xorg | Версия grep Я узнал, что версия Xserver, установленная в моей системе, равна 1:7.7+22ubuntu1 (в Ubuntu 21.04)

Каков рекомендуемый способ получения обратной связи о движении указателя мыши?

Ценю ваше время, отвечая мне.

HuHa avatar
флаг es
Почему я чувствую какой-то злой запах «работают ли мои домашние офисные работники?» софт здесь?
Shobeira avatar
флаг pt
Я действительно пытаюсь рассчитать время. Мне нужно знать, сколько я работаю над проектом, поскольку мы сталкиваемся с 5-м карантином и все еще работаем из дома.
Рейтинг:0
флаг in

X11 довольно хорошо документирован для «Масок событий».

https://tronche.com/gui/x/xlib/events/mask.html

Или всегда есть XQueryPointer).

// Попробуйте эту программу C как основу того, что вы хотите сделать.

    #include <stdio.h>
#include <assert.h>
#include <X11/Xlib.h>
#include <X11/расширения/XInput2.h>

int main(int argc, char **argv)
{
    Дисплей *дисплей;
    Окно root_window;

    /* Инициализировать (FIXME: без проверки ошибок). */
    дисплей = XOpenDisplay (0);
    root_window = XRootWindow (дисплей, 0);

    /* проверка XInput */
    int xi_opcode, событие, ошибка;
    if (!XQueryExtension(display, "XInputExtension", &xi_opcode, &event, &error)) {
        fprintf(stderr, "Ошибка: расширение XInput не поддерживается!\n");
        вернуть 1;
    }

    /* Проверка XInput 2.0 */
    мажор = 2;
    инт минор = 0;
    int retval = XIQueryVersion(display, &major, &minor);
    если (возвращение != успех) {
        fprintf(stderr, "Ошибка: XInput 2.0 не поддерживается (древний X11?)\n");
        вернуть 1;
    }

    /*
     * Установите маску для получения событий XI_RawMotion. Потому что он сырой,
     * События XWarpPointer() не включены, вы можете использовать XI_Motion
     * вместо.
     */
    unsigned char mask_bytes[(XI_LASTEVENT + 7)/8] = {0}; /* необходимо обнулить! */
    XISetMask(mask_bytes, XI_RawMotion);

    /* Установить маску для получения событий от всех ведущих устройств */
    Маски XIEventMask[1];
    /* Вы можете использовать XIAllDevices для XWarpPointer() */
    evmasks[0].deviceid = XIAllMasterDevices;
    evmasks[0].mask_len = sizeof(mask_bytes);
    evmasks[0].mask = mask_bytes;
    XISelectEvents(display, root_window, evmasks, 1);

    XEvent xEvent;
    в то время как (1) {
        XNextEvent(отображение, &xevent);

        if (xevent.xcookie.type != GenericEvent || xevent.xcookie.extension != xi_opcode) {
            /* не событие XInput */
            Продолжить;
        }
        XGetEventData(отображение, &xevent.xcookie);
        если (xevent.xcookie.evtype != XI_RawMotion) {
            /*
             * Не является событием XI_RawMotion (вы можете обнаружить
             * также XI_Motion, см. комментарии выше).
             */
            XFreeEventData(отображение, &xevent.xcookie);
            Продолжить;
        }
        XFreeEventData(отображение, &xevent.xcookie);

        Окно root_return, child_return;
        int root_x_return, root_y_return;
        int win_x_return, win_y_return;
        беззнаковое целое mask_return;
        /*
         * Нам нужно:
         * child_return - активное окно под курсором
         * win_{x,y}_return - координата указателя относительно корневого окна
         */
        int retval = XQueryPointer(display, root_window, &root_return, &child_return,
                                   &root_x_return, &root_y_return,
                                   &win_x_return, &win_y_return,
                                   &mask_return);
        если (! ретвал) {
            /* указатель не находится на том же экране, игнорировать */
            Продолжить;
        }

        /* Мы использовали корневое окно в качестве ссылки, поэтому оба должны быть одинаковыми */
        утверждать (root_x_return == win_x_return);
        утверждать (root_y_return == win_y_return);

        printf("root: x %d y %d\n", root_x_return, root_y_return);

        если (дочерний_возврат) {
            интервал local_x, local_y;
            XTranslateCoordinates(дисплей, root_window, child_return,
                                  root_x_return, root_y_return,
                                  &local_x, &local_y, &child_return);
            printf("local: x %d y %d\n\n", local_x, local_y);
        }
    }

    XCloseDisplay (отображение);

    вернуть 0;
}
Shobeira avatar
флаг pt
Ценю ваш ответ. Итак, я на правильном пути? X window - хороший подход? Когда я искал маски событий, я нашел MotionNotify наиболее подходящей маской, так как мне нужен логический возврат для проблемы. Я думал о том, чтобы иметь соответствующую структуру X, инициализировать ее, а затем оценить ее по маске событий. Мне нужно движение/без_движения..
флаг in
Нет проблем, я думаю, если вы просто хотите обнаружить движение, это довольно просто... Просто следите за X\Y положения мыши, и если они изменятся, то у вас есть движение.. Первым шагом является получение событий указателя в первую очередь.

Ответить или комментировать

Большинство людей не понимают, что склонность к познанию нового открывает путь к обучению и улучшает межличностные связи. В исследованиях Элисон, например, хотя люди могли точно вспомнить, сколько вопросов было задано в их разговорах, они не чувствовали интуитивно связи между вопросами и симпатиями. В четырех исследованиях, в которых участники сами участвовали в разговорах или читали стенограммы чужих разговоров, люди, как правило, не осознавали, что задаваемый вопрос повлияет — или повлиял — на уровень дружбы между собеседниками.