GTK4 - forwarding X11 key events to Gtk widgets after grabbing keyboard

To avoid looking for a solution to an XY problem, I will first explain what my ultimate goal is: I am working on an X11 screen lock application that I’m migrating from GTK3 to GTK4. To prevent the window manager from messing with the window, I first enable the “override redirect” and then grab keyboard and mouse. In GTK3, using gtkmm, I was able to do it like this:

get_window()->set_override_redirect(true);

const auto grabSuccess =
    get_display()->get_default_seat()->grab(get_window(), Gdk::SEAT_CAPABILITY_ALL, true);
if (grabSuccess != Gdk::GRAB_SUCCESS) {
    throw padlock::Exception("Device grab failed with an error ('{}')", std::to_string(grabSuccess));
}

This code took care of overriding the WM and keyboard + mouse grabbing, while forwarding the X11 events to my GTK widgets (Gtk::Entry).

After reading the GTK3 to GTK4 migration notes, I realized that I’m on my own now with both the WM overriding and keyboard + mouse grabbing. I was successfully able to override the WM by using libX11 directly and grab the mouse and keyboard:

static void set_override_redirect(GdkSurface* surface, bool enable) {
    Display* display = GDK_SURFACE_XDISPLAY(surface);
    Window x11_window = GDK_SURFACE_XID(surface);
    XSetWindowAttributes attrs;
    attrs.override_redirect = enable ? True : False;
    XChangeWindowAttributes(display, x11_window, CWOverrideRedirect, &attrs);
    XFlush(display);
}

static bool grab_pointer(GdkSurface* surface) {
    ... // omitted for brevity
}

static bool grab_keyboard(GdkSurface* surface) {
    Display* display = GDK_SURFACE_XDISPLAY(surface);
    Window x11_window = GDK_SURFACE_XID(surface);
    const int result = XGrabKeyboard(display, x11_window, True, GrabModeAsync, GrabModeAsync, CurrentTime);
    return result == GrabSuccess;
}

This all seems to work fine, but now, I have been stuck on forwarding the X11 events to GTK/GDK. I understand that ultimately, the goal in GTK is to abstract the platform specific functionality away from the library, but I can’t find any mechanism that I could use to create new GDK events.
Did I just miss something or is it a correct conclusion to draw that it’s not possible in GTK4? Or did I approach the problem from a completely wrong angle in the first place?

I should also mention that the motivation to migrate from GTK3 to GKT4 was one, that GTK4 implements PasswordEntryBuffer, which mlocks its buffer and thus makes the application more secure, and two, I want to stay more up-to-date with the dependencies.

So to summarize my question: how can I migrate from GTK3 to GTK4 while maintaining all the functionality from my GTK3 application?

I would appreciate any pointers!

The short answer is: there is no such mechanism. Events, in GTK4, only come from the windowing system. Application code cannot synthesise events and inject them into the event queue.

This is not something GTK4 supports.

On a more general note:

  • X11 is considered legacy, at this point, so making it easy to implement X11-specific functionality is definitely not a design goal for the toolkit
  • lock screens are a privileged component, and should not be bolted on top of a session; the fact that they exist at all is an anti-pattern that is the result of the “mechanism, not policy” design of X11

The GtkPasswordEntryBuffer implementation is, at its core, the same provided by the code in GCR 3.x:

There’s not much more inside it.

My suggestion is to not migrate: there’s really no point in doing so. GTK3 will be maintained until GTK5 is release, and development of GTK5 has not even started, yet. It’s much more likely that most distributors will stop providing an X11 session rather than they’ll stop shipping GTK3, at this point.

Thanks a lot for your blazing fast response, Emmanuele!

Got it. Thanks for clearing it up, I thought I was missing something in the docs.

Although I see your point, I would disagree with this one. I have tried Wayland several times and always ran into some issues. I am very much looking forward to it being completely ready to replace X11, but I wouldn’t be too fast with drinking the Kool-Aid.

I’m not sure I follow here. And to be fair, I’m not particularly versed with GUI’s in general, so I might be missing the bigger picture here. But I don’t think I’m the first person, nor the last, to implement something like this. My goal with this application is to allow me (and possibly other people) to lock the screen and then quickly resume from where I left off after authenticating via PAM.

This is great news for me! Perhaps I should have dug a bit more into the source code. But if I’m looking at it correctly, I can’t use the gtkmm wrapper as it uses Glib::ustring without a custom allocator.

If GTK3 still remains supported for a few more years to come, I think taking your advice not to migrate is my best bet now. It’s a shame, though as I liked some of the new features that GTK4 brings to the table and the API is a lot cleaner, too. But I can’t have it all, so I will just stick with GTK3.

Thanks again for your fast response, I really appreciate it!

It is not really ever going to be possible to build an X11 screen locker in a fully secure way. For more info see this note: XSecureLock Known Security Issues. This is one of the (many) reasons X11 is being dropped in favor of Wayland.

If this is not just a personal project then personally I would not recommend developing a screen locker for others to use until you are fully experienced with GUI security in X11 and its limitations, perhaps by studying other implementations like XSecureLock.

I know there is already a wide array of other projects that I could use instead, and I am sure most these projects have gone long ways to implement it as securely as possible.

But that’s not my goal - rather, I wanted to resurrect my quite an old project, work on something fun and learn new things along the way. And even though I am a security-minded person, I don’t aim to go above and beyond with security on this one.
This project was merely meant to deter curious colleagues who seek from whose computer they could treat everyone to a beer if you leave your PC unlocked and unattended.

That being said, I want to at least get the low hanging fruit and I don’t want to undermine the security aspects that are already in place - by dumping a password to swap, for example.

And even though I made this project open-source, I don’t think there would be many people who would choose my screenlocker over the other, more battle-tested alternatives that are already out there. Still, I have a security disclaimer in the readme file.

I appreciate your security concerns, though!

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.