From af802116df9f1def294754644275f70b5928a6b6 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Paul=20H=C3=A4nsch?= Date: Tue, 14 Jul 2026 17:03:45 +0200 Subject: [PATCH] additional widget/event classes, run input loop in separate thread --- glade1.c | 127 ++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 98 insertions(+), 29 deletions(-) diff --git a/glade1.c b/glade1.c index 5438e93..c3277dd 100644 --- a/glade1.c +++ b/glade1.c @@ -2,6 +2,9 @@ #include #include #include +#include // only for idle_loop variant +#include // only for idle_loop variant +#include // only for thread based variant static GtkBuilder *builder = NULL; static int chldin[2], chldout[2]; @@ -16,28 +19,63 @@ static int chldin[2], chldout[2]; // { GTK_TYPE_TEXT_VIEW, "set", &ca_text_view } // }; -void app_quit(GtkWidget *wdg, gpointer user_data) { - exit(0); +// ====== UI EVENTS ====== + +void e_si_activate(GtkWidget *wdg, gpointer d) { + printf("%s ACTIVATE\n", (char*) d); } -void text_content(GtkWidget *wdg, gpointer user_data) { - GtkEntry *e; - if (GTK_IS_ENTRY(wdg)) { - e = GTK_ENTRY( wdg ); - printf( "%s CHANGED %s\n", - gtk_buildable_get_name(GTK_BUILDABLE(wdg)), - gtk_entry_buffer_get_text( gtk_entry_get_buffer( e ) ) - ); - } +void e_button_clicked(GtkWidget *wdg, gpointer d) { + printf( + "%s CLICKED\n", + gtk_buildable_get_name(GTK_BUILDABLE(wdg)) + ); } -void button_click(GtkWidget *wdg, gpointer d) { - printf( "%s CLICKED\n", - GTK_IS_BUILDABLE(wdg)?gtk_buildable_get_name(GTK_BUILDABLE(wdg)):(char *)d - ); +// Radio Buttons and Checkboxes are "Toggle Buttons" +void e_tb_toggled(GtkWidget *wdg, gpointer d) { + GtkToggleButton *t = GTK_TOGGLE_BUTTON(wdg); + printf( + "%s TOGGLED %i\n", + gtk_buildable_get_name(GTK_BUILDABLE(wdg)), + gtk_toggle_button_get_active(t) + ); } -// ====== CLI ACTIONS ======= +// Radio Buttons and Checkboxes within menus are "Check Menu Items" +void e_cmi_toggled(GtkWidget *wdg, gpointer d) { + GtkCheckMenuItem *c = GTK_CHECK_MENU_ITEM(wdg); + printf( + "%s TOGGLED %i\n", + gtk_buildable_get_name(GTK_BUILDABLE(wdg)), + gtk_check_menu_item_get_active(c) + ); +} + +gboolean s_switch_state_set(GtkWidget *wdg, gboolean state, gpointer d) { + GtkSwitch *s = GTK_SWITCH(wdg); + printf( + "%s STATE-SET %i\n", + gtk_buildable_get_name(GTK_BUILDABLE(wdg)), + state + ); + return 0; +} + +void e_entry_changed(GtkWidget *wdg, gpointer user_data) { + GtkEntry *e = GTK_ENTRY(wdg); + printf( + "%s CHANGED %s\n", + gtk_buildable_get_name(GTK_BUILDABLE(wdg)), + gtk_entry_buffer_get_text(gtk_entry_get_buffer(e)) + ); +} + +void app_quit(GtkWidget *wdg, gpointer user_data) { + exit(0); +} + +// ====== CLI ACTIONS ====== void a_text_view_set(GtkTextView *v, char *c) { gtk_text_buffer_set_text( @@ -93,12 +131,12 @@ int action(char *cli) { if ( !wid || !wid[0] || !(wdg = GTK_WIDGET(gtk_builder_get_object(builder, wid))) ) return 0; - else if ( - (GTK_IS_BUTTON(wdg) && a_button(GTK_BUTTON(wdg), cmd, args)) + else if (0 || (GTK_IS_ENTRY(wdg) && a_entry(GTK_ENTRY(wdg), cmd, args)) || (GTK_IS_WINDOW(wdg) && a_window(GTK_WINDOW(wdg), cmd, args)) || (GTK_IS_TEXT_VIEW(wdg) && a_text_view(GTK_TEXT_VIEW(wdg), cmd, args)) || (GTK_IS_EDITABLE(wdg) && a_editable(GTK_EDITABLE(wdg), cmd, args)) + || (GTK_IS_BUTTON(wdg) && a_button(GTK_BUTTON(wdg), cmd, args)) || (GTK_IS_WIDGET(wdg) && a_widget(GTK_WIDGET(wdg), cmd, args)) ) return 1; else return 0; @@ -108,14 +146,21 @@ gboolean idle_readline(gpointer d) { static size_t s = 128; static char *buf = NULL; static int len = 0; int l; - if (!buf) buf = malloc(s); + static fd_set fds; + struct timeval t = { .tv_sec = 0, .tv_usec = 10000 }; + if (!buf) { + buf = malloc(s); + fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL) | O_NONBLOCK); + } + FD_ZERO(&fds); + FD_SET(STDIN_FILENO, &fds); + if ( select(STDIN_FILENO + 1, &fds, NULL, NULL, &t) <= 0) return G_SOURCE_CONTINUE; while ( (l = read(STDIN_FILENO, buf + len, s - len)) > 0) { len += l; if ( buf[len - 1] == '\n' && (len < 2 || buf[len - 2] != '\\') ) break; else if (len >= 2) buf[--len - 1] = '\n'; if ( len == s - 1 ) buf = realloc(buf, s+=128); - l = read(0, buf + len, s - len); } if ( l > 0 ) { buf[len - 1] = 0; @@ -124,23 +169,46 @@ gboolean idle_readline(gpointer d) { } else if (l == 0) { exit(0); } - return 1; + return G_SOURCE_CONTINUE; +} + +void* thread_readline(void *d) { + int l, len = 0; + size_t s = 128; + char *buf = malloc(s); + // if (!buf) buf = malloc(s); + + while ( (l = read(STDIN_FILENO, buf + len, s - len)) > 0 ) { + len += l; + if ( buf[len - 1] == '\n' && (len < 2 || buf[len - 2] != '\\') ) { + buf[len - 1] = 0; + action(buf); + len = 0; + } else if (len >= 2) buf[--len - 1] = '\n'; + if ( len == s - 1 ) buf = realloc(buf, s+=128); + } + exit(0); return NULL; } void init_widgets(gpointer wp, gpointer data) { - GtkWidget *wdg; + GtkWidget *wdg; const char *name; if (GTK_IS_BUILDABLE(wp)) { wdg = GTK_WIDGET(wp); - printf("%s load\n", gtk_buildable_get_name(GTK_BUILDABLE(wp))); + name = gtk_buildable_get_name(GTK_BUILDABLE(wp)); - if (GTK_IS_BUTTON(wdg)) g_signal_connect(wdg, "clicked", G_CALLBACK(button_click), NULL); - else if (GTK_IS_ENTRY(wdg) ) g_signal_connect(wdg, "changed", G_CALLBACK(text_content), NULL); - else if (GTK_IS_WINDOW(wdg)) g_signal_connect(wdg, "destroy", G_CALLBACK(app_quit), NULL); + if (strncmp(name, "___", 3) == 0 ) return; + else if (GTK_IS_TOGGLE_BUTTON(wdg)) g_signal_connect(wdg, "toggled", G_CALLBACK(e_tb_toggled), NULL); + else if (GTK_IS_CHECK_MENU_ITEM(wdg)) g_signal_connect(wdg, "toggled", G_CALLBACK(e_cmi_toggled), NULL); + else if (GTK_IS_ENTRY(wdg) ) g_signal_connect(wdg, "changed", G_CALLBACK(e_entry_changed), NULL); + else if (GTK_IS_WINDOW(wdg)) g_signal_connect(wdg, "destroy", G_CALLBACK(app_quit), NULL); + else if (GTK_IS_BUTTON(wdg)) g_signal_connect(wdg, "clicked", G_CALLBACK(e_button_clicked), NULL); + else { printf("%s unknown\n", name); return; } + printf("%s loaded\n", name); } else if (GTK_IS_STATUS_ICON(wp)) { printf("StatusIcon load\n"); - g_signal_connect(wp, "activate", G_CALLBACK(button_click), "StatusIcon"); + g_signal_connect(wp, "activate", G_CALLBACK(e_si_activate), "StatusIcon"); } } @@ -192,8 +260,9 @@ int main(int argc, char *argv[]) { g_slist_foreach(widgets, *init_widgets, NULL); g_slist_free(widgets); - fcntl(STDIN_FILENO, F_SETFL, fcntl(STDIN_FILENO, F_GETFL) | O_NONBLOCK); - g_idle_add(idle_readline, builder); + // g_idle_add(idle_readline, builder); + pthread_t rl; + pthread_create(&rl, NULL, thread_readline, NULL); gtk_main(); return 0; -- 2.47.3