GDK signal, keypress, and key masks

青春壹個敷衍的年華 提交于 2019-12-24 17:19:10

问题


I am trying to catch user key press Ctrl+d on a GUI window to quit. My code looks like this:

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

    return FASLE;
}

This works on my laptop(Ubuntu 11.04, gcc 4.5.2, libgtk 2.24.4). But when I do the same thing on a newer system(Ubuntu 12.10, gcc 4.7.2, libgtk 2.24.13), it doesn't work.

I added g_print("%u\n", event->state); before the if statement, it shows that when I press Ctrl, the event->state is 20 instead of 4 or 1 << 2 in the documentation. If I change the GDK_CONTROL_MASK to 20, it works on the newer system but not the old one. Someone please tell me why this happen and how to fix it.


回答1:


event->state is a bitmap, which means that a value of 20 doesn't mean "20 instead of 4", but "4 and 16 at the same time". According to the headers, the value 16 (1 << 4) corresponds to the MOD2 modifier, which might correspond to the fn key present on laptops.

A simple fix is to use the & operator to check for control while ignoring other modifiers:

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

which will work on both systems.




回答2:


This happens because state also includes modifiers like Caps Lock and Num Lock.

The solution is documented at https://developer.gnome.org/gtk3/stable/checklist-modifiers.html:

Use gtk_accelerator_get_default_mod_mask() to get a bitmap of the modifiers that are also accelerator keys (Control, Alt, Shift, Super, Hyper, and Meta), then bitwise and the event state, e.g.:

GdkModifierType accel_mask = gtk_accelerator_get_default_mod_mask ();

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


来源:https://stackoverflow.com/questions/16226043/gdk-signal-keypress-and-key-masks

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!