Frage

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.

War es hilfreich?

Lösung

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.

Andere Tipps

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')
    ...
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top