0

I'm struggling to understand how this if statement works:

if (keyval == GDK_PLUS &&
    (event->state & ~consumed & ALL_ACCELS_MASK) == GDK_CONTROL_MASK)

founded here https://developer.gnome.org/gdk3/stable/gdk3-Keyboard-Handling.html#gdk-keymap-translate-keyboard-state

Full example code:

#define ALL_ACCELS_MASK (GDK_CONTROL_MASK | GDK_SHIFT_MASK | GDK_MOD1_MASK)

gdk_keymap_translate_keyboard_state (keymap, event->hardware_keycode,
                                     event->state, event->group,
                                     &keyval, NULL, NULL, &consumed);

if (keyval == GDK_PLUS &&
    (event->state & ~consumed & ALL_ACCELS_MASK) == GDK_CONTROL_MASK)
    // Control was pressed

My objective is to understand it so I can port it to Vala since the example given in Valadocs is the same written here in C, and not in Vala.

  • 1
    is the binary `&` operator left associative ? Is it even communitative? You could look this up. – wildplasser Apr 15 '18 at 22:07
  • @Otavio Pliger It is the logical AND ioerator – Vlad from Moscow Apr 15 '18 at 22:10
  • 1
    That's some very odd code. You don't normally see `&` chained like that. – tadman Apr 15 '18 at 22:10
  • @tadman You do when you’re combining bitmasks; here it looks like there’s an additional mask indicating what’s currently "valid". – Dave Newton Jul 17 '18 at 17:28
  • @DaveNewton That's what they're doing, but it does look odd to have an intermediate mask. – tadman Jul 17 '18 at 17:43
  • @tadman ¯\_(ツ)_/¯ Dunno. It's a little strange because it seems like you could just & with the desired mask but I'd have to actually think about it :/ – Dave Newton Jul 17 '18 at 17:55
  • @DaveNewton Yeah, that's the thing. You see chained `|` (or) a lot, but rarely do you ever see `&` piled on like that. Probably because there's a better way. – tadman Jul 17 '18 at 18:09

1 Answers1

6

First part

keyval == GDK_PLUS

This does exactly what it appears -- checks if keyval is equal to GDK_PLUS.


Second part

Let's work outwards.

~consumed

This is a bitwise not. It inverts the bits individually.

00101100 → Bitwise not → 11010011

(event->state & ~consumed & ALL_ACCELS_MASK)

& is bitwise and. It compares the bits in the two operands and sets the bits in the output only if they are both 1. For example,

  binary    hex   dec
  11010111  0xD7  215
& 01101101  0x6D  109
=====================
  01000101  0x45  69

Putting the full second part together:

(event->state & ~consumed & ALL_ACCELS_MASK) == GDK_CONTROL_MASK

This checks if the bitwise and of event->state, ~consumed, and ALL_ACCELS_MASK is equal to GDK_CONTROL_MASK.


Add a comment if you want clarification.

SIGSTACKFAULT
  • 919
  • 1
  • 12
  • 31
  • A bit of explanation of what `consumed` does and why it is logically inverted would be nice, i.e. *"Modifiers that affected the translation and are thus unavailable for application use are returned in consumed_modifiers."* [Gdk 3 Reference - keyboard handling](https://developer.gnome.org/gdk3/stable/gdk3-Keyboard-Handling.html) – David C. Rankin Apr 15 '18 at 22:45
  • "consumed_modifiers gives modifiers that should be masked out from state when comparing this key press to a hot key. For instance, on a US keyboard, the plus symbol is shifted, so when comparing a key press to a plus accelerator should be masked out." from [here](http://wrapl.sourceforge.net/doc/Gtk/Gdk/Keymap.html) – Otavio Pliger Apr 15 '18 at 23:13
  • I haven't the foggiest idea what this statement is for; I'm just breaking it down into bite-sized pieces for you. If anyone knows what this statement is for, feel free to edit. – SIGSTACKFAULT Apr 16 '18 at 02:30