I have an Adw.Bin which contains a scrolled window with a drawing area. I want to grab focus on the bin and process key inputs like keyboard up, down, left, right, space bar. However, event after adding Gtk.EventControllerKey to the bin, it doesn’t receive the key presses.
The following is a minimal example. To keep the code simple, the bin contains a label (with a CSS frame to know its boundary). The bin has an event controller but it doesn’t work.
I think I can add the event controller to the main window and manually process the key inputs, but I think this is a bad approach, since other widgets inside the window like entries, buttons may not be accessible via keyboard. The issue is, I need to receive inputs of the arrow keys and space bar, which are also part of keyboard navigation.
So how do I grab those key presses when my widget is focused without disturbing other elements?
Do you do this with Gtk 4?
If so, widgets start their life cycle already being shown in Gtk4, so it is possible this never gets triggered. In my code I grab focus on mouse click, thus trough another event controller.
Your last code works, because ‘clicked’ event is actually happening and that’s why grab_focus() works.
Question - how do you see life cycle of this widget? Should focus be grabbed after certain UI interactions or every time windows come in focus? This would allow to place grab_focus() where would actually happen and matter. For example, it might be a click on widget, or opening window.
Edit: check this property for Gtk.Window:is-active Gtk.Window:is-active
I would listen for this property via window.connect(“notify::is-active”, callback_func) and then do grab_focus() within callback_func.
But if I replace the word ent with wid in signal handler, it doesn’t work.
In this case you needed to connect to wid.connect(“notify::is-active”, lambda _: ent.grab_focus()) - so Entry ent object would grab focus when Window wid object would get “is-active” property changed.
In my real app, the widget is a page in a stack. So whenever the page is visible the widget must be focused. How to do it?
See this Emmanuele comment - you need to connect stack signal “notify::visible-child-name”, and then in callback function check if name is page you want it to show, if yes, then grab focus for Entry object within that page. Something like this:
if stack.get_property("visible-child-name") == page_which_contains_entry:
Now to second question, is it possible to lock the focus to the widget? For example in the sample, if I press UP arrow, it goes to the button or DOWN arrow goes to the entry. I don’t want those keys to change the focus, is it possible?