Identify button modifiers in Gtk

tl;dr: How can I reliably test which modifier a user is pressing while clicking the mouse?

I’m using ImageView.imshow as a GUI to select points on an image. The functionalities already baked-in in imshow (zoom, pan, annotate) are the main reason why I’m hijacking that structure. But I need to add some way for the user to pick (and un-pick) a point on the displayed image. To do that I’ve used the drawing example in GtkReactive:

sigstart = map(c.mouse.buttonpress) do btn
    if btn.button == 1
        if btn.modifiers == 1 #shift
            push!(add, btn.position)
        elseif btn.modifiers == 5 #shift+ctrl
            push!(remove, btn.position)
        end
    end
end

where add and remove are signals that add or remove the coordinate from the list of chosen coordinates.

My problem is that Shift and Ctrl-Shift are not always 1 and 5 respectively (i.e. I sometimes get 16 and 17). I have no idea what governs this fickleness, but it means that I can’t use that as a mechanism to identify which modifiers the user pressed. I have tried to pry-out the way this is accomplished in ImageView.imshow (e.g. the users can press Ctrl with the scroll wheel to zoom), but without any success. Even trying to compare btn.button to GtkReactive.SHIFT didn’t work…

Anyone knows how to do this from within Julia (i.e. I’m not any wiser from reading the Gtk manual about modifiers)?

btn.Modifiers is using bit-valued flags, so each flag is one of 2^0 to 2^x and they’re just added together into one value
x & 0x01 == 0x01 is the shift key, which is the same as x & 1 == 1, x & 4 == 0x04 would be the control key, alt or another would be 16

1 Like

Thanks @y4lu! I hope I understood you correctly. This:

    sigstart = map(c.mouse.buttonpress) do btn
        if btn.button == 1
            if btn.modifiers & 0x01 == 0x01 #shift
                push!(add, btn.position)
            elseif btn.modifiers & 0x04 == 0x04 # ctrl
                push!(remove, btn.position)
            end
        end
    end

seems to be working! I couldn’t quite figure out how to test for if both the Shift and Ctrl are pressed together, but I’m willing to live with this (since it seems to not collide with the Ctrl zoom of imshow).
Thanks again!

Both of those can be true at the same time – IIUC Ctrl and Shift together will give you 0x05, for which

julia> 0x05 & 0x04 == 0x04 && 0x05 & 0x01 == 0x01
true

Also check the bit representation via bits.

Ideally you have to use gtk_accelerator_get_default_mod_mask to get the mask, to deal with caps lock and such.

I made a PR about this a while ago:

https://github.com/JuliaGraphics/Gtk.jl/pull/310/files

1 Like

Omg, that’s almost a year ago. Too bad, this sounds awesome. I left a message there.

I see, ok, so to get the Shift-Ctrl I did this:

sigstart = map(c.mouse.buttonpress) do btn
    if btn.button == 1
        if btn.modifiers & 0x01 == 0x01     # Shift and
            if btn.modifiers & 0x04 == 0x04 # Ctrl
                push!(remove, btn.position)
            else                            # anything really
                push!(add, btn.position)
            end
        end
    end
end