I want to send a custom signal with user data. The user data (coming from a GtkEntry
) is not filled upon connecting the signal, but is when the signal is emitted.
How can I emit a signal with the content of a GtkEntry
as user data?
Right now I have a signal handler for the "standard" signal button_press_event
. This handler reads the GtkEntry
's and emits the custom signal. This is where I want de GtkEntry
data to be sent as user data.
I do not want to send a pointer to GtkEntry
, since the GtkEntry
belongs to login_credentials_screen.c
I have a UI file:
<!-- Generated with glade 3.38.2 -->
<interface>
<requires lib="gtk+" version="3.24"/>
<object class="GtkWindow">
<property name="can-focus">False</property>
<child>
<object class="GtkBox">
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="orientation">vertical</property>
<child>
<object class="GtkLabel">
<property name="height-request">80</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="label" translatable="yes">Enter the correct user code
and company code to log in</property>
<property name="justify">center</property>
<style>
<class name="text_large"/>
</style>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
<child>
<object class="GtkBox">
<property name="height-request">40</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">center</property>
<property name="valign">center</property>
<property name="margin-top">5</property>
<property name="spacing">20</property>
<child>
<object class="GtkEntry" id="user_code_input">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="placeholder-text" translatable="yes">User code</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">0</property>
</packing>
</child>
<child>
<object class="GtkEntry" id="company_code_input">
<property name="visible">True</property>
<property name="can-focus">True</property>
<property name="placeholder-text" translatable="yes">Company code</property>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">1</property>
</packing>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">2</property>
</packing>
</child>
<child>
<object class="GtkEventBox" id="login_button">
<property name="visible">True</property>
<property name="can-focus">False</property>
<child>
<object class="GtkLabel">
<property name="width-request">250</property>
<property name="height-request">60</property>
<property name="visible">True</property>
<property name="can-focus">False</property>
<property name="halign">center</property>
<property name="margin-top">15</property>
<property name="label" translatable="yes">Log in</property>
<style>
<class name="login_buttons"/>
<class name="text_normal"/>
</style>
</object>
</child>
</object>
<packing>
<property name="expand">False</property>
<property name="fill">True</property>
<property name="position">3</property>
</packing>
</child>
</object>
</child>
</object>
</interface>
I have main.c
:
#include <glib.h>
#include <gtk/gtk.h>
#include "login_credentials_screen.h"
void on_button_clicked(GtkWidget *widget, GdkEvent *event, gpointer data);
void main(void)
{
login_cred_subscribe_login_button_callback(on_button_clicked);
}
void on_button_clicked(GtkWidget *widget, GdkEvent *event, gpointer data)
{
printf("Userdata: %s\n", data);
}
And login_credentials_screen.c
:
GtkBuilder *login_credentials_builder;
GObject *login_credentials_screen;
GObject *user_code_entry;
GObject *company_code_entry;
void init_login_credentials_screen(void)
{
login_credentials_builder = gtk_builder_new_from_file("login_credentials_screen.ui");
login_credentials_screen = gtk_builder_get_object(login_credentials_builder, "login_credentials_screen");
user_code_entry = gtk_builder_get_object(login_credentials_builder, "user_code_input");
company_code_entry = gtk_builder_get_object(login_credentials_builder, "company_code_input");
g_signal_connect(gtk_builder_get_object(login_credentials_builder, "login_button"), "button_press_event", G_CALLBACK(on_login_button_clicked), "login_button");
g_signal_new("login-button-clicked", G_TYPE_OBJECT, G_SIGNAL_RUN_FIRST, 0, NULL, NULL, g_cclosure_marshal_VOID__POINTER, G_TYPE_NONE, 1, G_TYPE_POINTER);
}
void login_cred_subscribe_login_button_callback(void *function)
{
g_signal_connect(gtk_builder_get_object(login_credentials_builder, "login_button"), "login-button-clicked", G_CALLBACK(function), NULL); //NULL needs to be something else?
}
void on_login_button_clicked(GtkWidget *widget, GdkEvent *event, gpointer data)
{
printf("%s\n", gtk_entry_get_text(GTK_ENTRY(user_code_entry)));
printf("%s\n", gtk_entry_get_text(GTK_ENTRY(company_code_entry)));
g_signal_emit_by_name(widget, "login-button-clicked", gtk_entry_get_text(GTK_ENTRY(company_code_entry)));
}
I noticed that the g_signal_connect
can be called with a variable (char *
in this case) as user_data
parameter, and the variable does not need to be set untill calling the emit
.
This results in the following:
char user_code_string[20];
void login_cred_subscribe_login_button_callback(void *function)
{
g_signal_connect(gtk_builder_get_object(login_credentials_builder, "login_button"), "login-button-clicked", G_CALLBACK(function), user_code_string);
}
void on_login_button_clicked(GtkWidget *widget, GdkEvent *event, gpointer data)
{
strncpy(user_code_string, gtk_entry_get_text(GTK_ENTRY(user_code_entry)), 20);
g_signal_emit_by_name(widget, "login-button-clicked");
}
Upon connecting (g_signal_connect
) the login-button-clicked
-signal, the variable does not need to be set.
Before emitting the signal (g_signal_emit_by_name
), the variable can be set.