Почему данные Atspi.DeviceEvent одинаковы после каждого события нажатия клавиши? - PullRequest
0 голосов
/ 09 ноября 2018

Я действительно изо всех сил пытаюсь заставить AT-SPI работать в приложении Vala.

У меня есть возможность заметить, что клавиша была нажата через Atspi.register_keystroke_listener , но я не могу заставить ее передать что-либо полезное в функцию обратного вызова. При каждом нажатии клавиши он возвращает одни и те же данные независимо от нажатой клавиши, и в stroke.event_string , похоже, никогда ничего не содержится.

Ниже приведено упрощенное демонстрационное приложение, в котором показана проблема.

public class Demo.Application : Gtk.Application {
    private static Application? _app = null;

    private Atspi.DeviceListenerCB listener_cb;
    private Atspi.DeviceListener listener;

    public Application () {
        Object (
            application_id: "com.bytepixie.snippetpixie",
            flags: ApplicationFlags.HANDLES_COMMAND_LINE
        );
    }

    protected override void activate () {
        message ("Activated");

        Atspi.init();

        listener_cb = (Atspi.DeviceListenerCB) on_key_released_event;
        listener = new Atspi.DeviceListener ((owned) listener_cb);

        try {
            Atspi.register_keystroke_listener (listener, null, 0, Atspi.EventType.KEY_RELEASED_EVENT, Atspi.KeyListenerSyncType.ALL_WINDOWS | Atspi.KeyListenerSyncType.CANCONSUME);
        } catch (Error e) {
            message ("Could not keystroke listener: %s", e.message);
            Atspi.exit ();
            quit ();
        }
    }

    private bool on_key_released_event (Atspi.DeviceEvent stroke) {
        message ("id: %u, hw_code: %d, modifiers: %d, timestamp: %u, event_string: %s, is_text: %s",
            stroke.id,
            stroke.hw_code,
            stroke.modifiers,
            stroke.timestamp,
            stroke.event_string,
            stroke.is_text.to_string ()
        );

        return false;
    }

    public override int command_line (ApplicationCommandLine command_line) {
        hold ();
        activate ();
        return 0;
    }

    public static new Application get_default () {
        if (_app == null) {
            _app = new Application ();
        }
        return _app;
    }

    public static int main (string[] args) {
        var app = get_default ();
        return app.run (args);
    }
}

Когда скомпилирован и запущен, а затем нажаты клавиши "qwerty", я получаю следующее.

ian@ians-apollo:~/Documents/atspi-test$ valac demo.vala --pkg gtk+-3.0 --pkg atspi-2
ian@ians-apollo:~/Documents/atspi-test$ ./demo 
** Message: 18:35:59.373: demo.vala:15: Activated

(demo:18257): GLib-GObject-CRITICAL **: 18:35:59.456: g_object_unref: assertion 'G_IS_OBJECT (object)' failed
** Message: 18:36:00.716: demo.vala:32: id: 22029, hw_code: 4, modifiers: 0, timestamp: 0, event_string: (null), is_text: true
q** Message: 18:36:01.046: demo.vala:32: id: 22029, hw_code: 4, modifiers: 0, timestamp: 0, event_string: (null), is_text: true
w** Message: 18:36:01.477: demo.vala:32: id: 22029, hw_code: 4, modifiers: 0, timestamp: 0, event_string: (null), is_text: true
e** Message: 18:36:01.837: demo.vala:32: id: 22029, hw_code: 4, modifiers: 0, timestamp: 0, event_string: (null), is_text: true
r** Message: 18:36:02.187: demo.vala:32: id: 22029, hw_code: 4, modifiers: 0, timestamp: 0, event_string: (null), is_text: true
t** Message: 18:36:02.583: demo.vala:32: id: 22029, hw_code: 4, modifiers: 0, timestamp: 0, event_string: (null), is_text: true
y** Message: 18:36:10.587: demo.vala:32: id: 22029, hw_code: 4, modifiers: 0, timestamp: 0, event_string: (null), is_text: true

Вы можете увидеть «qwerty» в начале каждой строки в консоли, поскольку я не использую нажатия клавиш, но нет никакой разницы в выводе данных каждый раз.

Что мне не хватает? Есть ли какое-то кэширование, которое нужно очищать после каждого события?

1 Ответ

0 голосов
/ 11 ноября 2018

Потребовалось некоторое время, чтобы понять это, и демо было очень полезно.В сущности, сигнатура функции C для обратного вызова неправильная.

Чтение документации C для AtspiDeviceListenerCB сигнатура функции должна быть:

gboolean
(*AtspiDeviceListenerCB) (const AtspiDeviceEvent *stroke,
                          void *user_data);

The user_data - после stroke.

В примере программы Vala on_key_released_event - это метод Demo.Application.Vala поместит ссылку на экземпляр в качестве первого параметра метода в сгенерированном C. Использование переключателя --ccode с valac показывает следующее в сгенерированном C:

static gboolean demo_application_on_key_released_event (DemoApplication* self,
                                                 AtspiDeviceEvent* stroke);

Решение состоит в том, чтобы сообщитькомпилятор Vala для размещения ссылки на экземпляр в другую позицию.В примере программы это означает изменение:

private bool on_key_released_event (Atspi.DeviceEvent stroke) {

на

[CCode (instance_pos = -1)]
private bool on_key_released_event (Atspi.DeviceEvent stroke) {

Деталь атрибута CCode instance_pos может быть другим значением, но -1 помещает параметр экземпляра какпоследний параметр в сигнатуре функции.Мы могли бы использовать 2 вместо этого.Подробнее об изменении позиции сгенерированных аргументов функции C см. Vala Writing Bindings Manually, документ .

Другим решением было бы вообще не использовать данные экземпляра и использовать вместо него DeviceListener.simple.

Было бы неплохо подумать, что компилятору Vala доступно достаточно информации, чтобы понять, что метод объекта, который используется в качестве обратного вызова, должен иметь параметр экземпляра в другой позиции в сгенерированном C.не потратил время на изучение этой возможности.

...