This changes the text handling so that keyboard events are sent to the framework first for handling, and then passed to the text input plugin, so that the framework has a chance to handle keys before they get given to the text field.
This is complicated by the async nature of the interaction with the framework, since GTK wants a synchronous response. So, in this change, I always tell GTK that the event was handled, and if it wasn't, then I re-dispatch the event once we know one way or the other.
This converts the GTK keyboard code to track the key down states of the lock modifiers NumLock and CapsLock so that they represent the actual "down" state of the key, rather than the lock state itself.
GTK tracks the lock state, and Flutter expects the down state.