How to release input? (GTK4)

I need to make my window “input transparent”, the behavior is more or less like this:

  1. The window sits above others using gtk4-layer-shell (which relies on wlr-layer-shell).
  2. When a specific key, let’s say F1, is pressed, the window will ignore all input and pass it through to the window beneath it, except for the F1 key itself. Anything drawn on the window must stay the same.
  3. Pressing F1 again will make the window regrab the input.

I don’t know how to release the mouse or keyboard input in gtk4. For gtk3 i’ve found gdk_seat_ungrab and gtk_widget_input_shape_combine_region which don’t exist in gtk4. The migration guide from gtk3 to gtk4 doesn’t cover my particular case, and reading the linked functions hasn’t given me an idea of what to do.

Needless to say, the window’s background is transparent and I’m on wayland.

Hi @qtyra,

For pointer input you can use Gdk.Surface.set_input_region

1 Like

Thanks @lb90, it works perflectly! I’m almost done. I added these functions to my program:

static void toggle_mouse_input(GtkWidget *area)
{
    GdkSurface *surface = gtk_native_get_surface(gtk_widget_get_native(area));
    static gboolean enabled = TRUE;
    if (enabled) {
        cairo_region_t *region = cairo_region_create();
        gdk_surface_set_input_region(surface, region);
        enabled = FALSE;
    } else {
        int width = gtk_widget_get_width(area);
        int height = gtk_widget_get_width(area);
        cairo_rectangle_int_t rectangle = {.x = 0, .y = 0, .width = width, .height = height};
        cairo_region_t *region = cairo_region_create_rectangle(&rectangle);
        gdk_surface_set_input_region(surface, region);
        enabled = TRUE;
    }
    gtk_widget_queue_draw(area);
}

static gboolean key_pressed(GtkEventControllerKey *controller_key, guint keyval, guint keycode,
                            GdkModifierType state, GtkWidget *area)
{
    if (keyval == GDK_KEY_F1) {
        toggle_mouse_input(area);
        g_print("Hello toggle input\n");
    } else {
        // Forward the key event to the underlying window.
    }
    return TRUE;
}

As the comment points out, is there a function to do the same for the keyboard input? It’s a bit different though. I can’t just ignore the input because then I wouldn’t be able to press F1 again.

I believe that you have to use wlr-layer-shell for that, see set_keyboard_interactivity. To toggle that on F1 you may use the global shortcuts portal: Add a global shortcut portal by aleixpol · Pull Request #711 · flatpak/xdg-desktop-portal · GitHub

1 Like

I struggled so hard with dbus and portals, but I finally got it working exactly the way I wanted, thanks @lb90 !!!

1 Like

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