'Generate BackSpace event gtk/C

In GTK/C, I want to propagate the backspace keypress to a button clicked. Following the suggestion in this previous post, I tried with a small program: create an GdkEventKey then use gtk_propagate_event to set the keypress to button. The program compiles normally but it did not function as I expected. I have found this, this and this but I couldn't get my code to work (when I click the btn_bspace, I want it to generate a backspace event in the text_entry). Could you look at my code and tell me what is wrong? Thank you very much!

//compile with gcc -o main main.c `pkg-config --cflags --libs gtk+-3.0`
#include <gtk/gtk.h>
#include <gdk/gdkkeysyms.h>

GtkWidget *btn_bspace;
GtkWidget *entry;
GtkWidget *window;
GtkWidget *box;

gboolean on_btn_bspace_clicked(GtkButton *button, gpointer data)
{
    guint keyval = GDK_KEY_BackSpace;
    
    GdkEvent* event = gdk_event_new(GDK_KEY_PRESS);
    ((GdkEventKey*)event)->window = gtk_widget_get_window(GTK_WIDGET(window));
    ((GdkEventKey*)event)->send_event = TRUE;
    ((GdkEventKey*)event)->time = GDK_CURRENT_TIME;
    ((GdkEventKey*)event)->state = GDK_KEY_PRESS_MASK;
    ((GdkEventKey*)event)->keyval = keyval;
    ((GdkEventKey*)event)->state = 0;
    ((GdkEventKey*)event)->length = 0;
    ((GdkEventKey*)event)->string = 0;
    ((GdkEventKey*)event)->hardware_keycode = 0xff08;
    ((GdkEventKey*)event)->group = 0;
    gtk_propagate_event(entry, event);
    return FALSE;
    }
    
int main(int argc, char *argv[])
{  
    gtk_init(&argc, &argv);
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
   
    box = gtk_box_new(FALSE, 0);
    gtk_container_add(GTK_CONTAINER(window), box);
    gtk_widget_show(box);
    
    entry = gtk_entry_new();
    gtk_entry_set_text(GTK_ENTRY(entry), "testing");
    gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0);
    gtk_widget_show(entry);
    
    btn_bspace = gtk_button_new_with_label("Backspace");
    g_signal_connect(btn_bspace, "clicked", G_CALLBACK(on_btn_bspace_clicked), NULL);
    gtk_box_pack_start(GTK_BOX(box), btn_bspace, TRUE, TRUE, 0);
    gtk_widget_show(btn_bspace);
    gtk_widget_show(window);                
    gtk_main();

    return 0;
}

// called when window is closed
void on_window_main_destroy()
{
    gtk_main_quit();
}

Update: assign ((GdkEventKey)event)->window to a GdkWindow



Solution 1:[1]

I am not sure if this is still a relevant issue for you, but I did some investigation into this issue to come up with a solution. Perhaps you or others can benefit from the information.

I tested out your code and was also getting no response to the button click event. In researching this, what seems to be the issue is that trying to match up a GtkWindow to a GdkWindow seems to falter. I am not proficient in how to get GTK objects to communicate with GDK objects. So, I looked at a different approach that just relied on GTK objects and events.

I took a look at the source code for the GtkEntry widget to see what type of signals it accepts and went at this with a different approach. Instead of utilizing a GDK event, I emitted a signal to the entry widget for a backspace. Backspace is one of the signals associated with a GtkEntry widget.

GTK Entry backspace signal

The "on_btn_bspace_clicked" function was revised as follows:

void on_btn_bspace_clicked(GtkEntry *ent, gpointer data)
{
    g_signal_emit (ent, g_signal_lookup ("backspace", G_OBJECT_CLASS_TYPE (GTK_WIDGET_GET_CLASS(GTK_ENTRY(ent)))), 0);
}

This actually simplified the code a bit.

Then within your mainline block, I revised the signal connection to utilize the "g_signal_connect_swapped" function which lets one reference the widget to be affected.

g_signal_connect_swapped(btn_bspace, "clicked", G_CALLBACK(on_btn_bspace_clicked), entry);

I tested this revision out and got the result that you were after.

Backspace button illustration

I hope this helps you out.

Regards.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 NoDakker