Send Keyboard event to gtk window

I am trying to create a GTK window and send seval mouse events to it. My code currently is the following:

#include <webkit2/webkit2.h>
#include <gtk/gtk.h>

// ...
gtk_init (&argc, &argv);

WebKitWebView *main_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (GTK_WINDOW (main_window),
                                 300,
                                 300);

GtkWidget *web_view = WEBKIT_WEB_VIEW (webkit_web_view_new ());
gtk_container_add (GTK_CONTAINER (main_window), GTK_WIDGET (web_view));
g_signal_connect (main_window, "destroy", G_CALLBACK (destroyWindowCb),
                      NULL);
webkit_web_view_load_uri (web_view, "...");

gtk_widget_show_all (main_window);
gtk_main ();

How would I send keyboard event (e.g. arrow left, arrow up, etc) to said window. Can you give me any pointers? Thank you in advance

The short version is: you cannot send random events to random windows from random applications. If that were the case, anybody would be able to do very, very nasty things to your applications, your data, or your system.

The longer version depends on your answer to the question: what are you actually trying to achieve?

I am trying to automate an app. Please note that this is not a random application, but my own application (running in same address space). Is there really no way to send keyboard input to a GtkWidget*?

What about the gtk_test_widget_send_key functions? Doesn’t it do exactly that. I’ve tried including it in the code above but for some reason I cannot get it to work

The recommendation is to write your application separating the business logic from the UI; minimise the code you call in the event handlers, so if you’re testing key events in the same process you just need to call the same function you’d call in the key event handlers.

If you test your UI as a black box, you can use the accessibility API; there are scriptable tools, like dogtail, that let you write your tests.

Most of the gtk_test_* API was written for GTK2 and its own test suite; it’s not really usable outside of GTK, but it has to be public because the GTK test suite links against the same library as anybody else (unlike in GTK4, where we can link against the uninstalled static copy of GTK so we have access to its internals).

1 Like

Thank you again for your answear. I came accross the following code, why is this not possible?

          if (!GTK_IS_WIDGET (widget))
          {
            g_printerr ("Error: widget is not a GtkWidget\n");
            return;
          }

        GdkWindow *gdk_window (gtk_widget_get_window (widget));
        if (gdk_window == NULL)
          {
            g_printerr ("Error: Could not get GdkWindow from GtkWidget\n");
            return;
          }

        GdkEvent *event (gdk_event_new (GDK_KEY_PRESS));
        if (event == NULL)
          {
            g_printerr ("Error: Could not allocate gdk_event_new\n");
            return;
          }

        event->key.window           = g_object_ref (gdk_window);
        event->key.send_event       = TRUE;
        event->key.time             = (guint32)g_get_real_time ();
        event->key.state            = 0;
        event->key.keyval           = GDK_KEY_Up;
        event->key.length           = 0;
        event->key.string           = NULL;
        event->key.hardware_keycode = 0;
        event->key.group            = 0;
        event->key.is_modifier      = 0;

        gtk_main_do_event (static_cast<GdkEvent *> (event));
        gdk_event_free (event);

First of all, because that code is for GTK3 only: injecting events into the queue is not a thing that can be done with GTK4. This means that your testing code will be useless when porting to a newer version of GTK.

Additionally, because you cannot really know how GTK handles events internally: injecting an event requires you to understand the event handing state machine. GTK does not expose that information for a reason.

1 Like