Сигнал GDK, нажатия клавиш и маски клавиш

Я пытаюсь поймать клавишу пользователя, нажав Ctrl + d в окне графического интерфейса, чтобы выйти. Мой код выглядит так:

static gboolean
callback(GtkWidget   *widget,
         GdkEventKey *event,
         gpointer    data)
{
    if(event->state == GDK_CONTROL_MASK && event->keyval == 'd')
        gtk_main_quit();

    return FASLE;
}

Это работает на моем ноутбуке (Ubuntu 11.04, gcc 4.5.2, libgtk 2.24.4). Но когда я делаю то же самое в более новой системе (Ubuntu 12.10, gcc 4.7.2, libgtk 2.24.13), это не работает.

Я добавил g_print("%u\n", event->state); перед оператором if, это показывает, что когда я нажимаю Ctrl, event->state равно 20 вместо 4 или 1 ‹‹ 2 в документации. Если я изменю GDK_CONTROL_MASK на 20, он будет работать в более новой системе, но не в старой. Кто-нибудь, пожалуйста, скажите мне, почему это происходит и как это исправить.


person lllluuukke    schedule 25.04.2013    source источник


Ответы (2)


event->state – это битовое изображение, что означает, что значение 20 не означает "20 вместо 4". ", а "4 и 16 одновременно". Согласно заголовкам, значение 16 (1 << 4) соответствует модификатору MOD2, который может соответствовать клавише fn, присутствующей на ноутбуках.

Простое исправление состоит в том, чтобы использовать оператор & для проверки контроля, игнорируя другие модификаторы:

    if (event->state & GDK_CONTROL_MASK && event->keyval == 'd')

который будет работать на обеих системах.

person user4815162342    schedule 26.04.2013
comment
MOD2 является блокировкой номера во многих системах. Так что имеет смысл замаскировать это. Но только проверка того, установлен ли CONTROL, означает, что он также будет обрабатывать Ctrl+Alt+D, Ctrl+Shift+D и т. д. как Ctrl+D, что тоже не идеально. - person Mikel; 03.10.2017

Это происходит потому, что state также включает такие модификаторы, как Caps Lock и Num Lock.

Решение задокументировано по адресу https://developer.gnome.org/gtk3/stable/checklist-modifiers.html:

Используйте gtk_accelerator_get_default_mod_mask(), чтобы получить растровое изображение модификаторов, которые также являются клавишами быстрого доступа (Control, Alt, Shift, Super, Hyper и Meta), затем побитовое и состояние события, например:

GdkModifierType accel_mask = gtk_accelerator_get_default_mod_mask ();

if (event->state & accel_mask == GDK_CONTROL_MASK && event->keyval == 'd')
    ...
person Mikel    schedule 03.10.2017