I'm really new to C and GTK+ so my problem might be painfully obvious. I have tried to follow examples and tutorials found all over the net.
I want a combo box with three values, the middle one being the default. I can successfully set it up using Glade but I have decided to rewrite everything in C. The combobox is drawn but it is empty/blank. I don't know what I am doing wrong.
...
GtkTreeIter iter;
GtkListStore *liststore;
GtkWidget *combo;
liststore = gtk_list_store_new(1, G_TYPE_STRING);
gtk_list_store_insert_with_values (liststore, &iter, 0, 0, "Don't install.", -1);
gtk_list_store_insert_with_values (liststore, &iter, 1, 0, "This user only.", -1);
gtk_list_store_insert_with_values (liststore, &iter, 2, 0, "All users.", -1);
combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(liststore));
gtk_combo_box_set_active (GTK_COMBO_BOX(combo), 1);
...
gtk_grid_attach (GTK_GRID(grid), combo, 2, 4, 1, 1);
...
In your original code you correctly bound the data model to the combo box but you did not specified how the model should be presented (that is the view part of the whole model-view concept). This is what the GtkCellLayout is supposed to provide.
To give you an idea on why this added complexity is useful, here is an example that shows how to use the model to have custom background (this is bad UX and, depending on your theme, the background color can be totally ignored). I think the most difficult thing is avoiding memory leaks, so I added some comment on this regard:
#include <gtk/gtk.h>
int main(int argc, char **argv)
{
GtkWidget *window;
GtkListStore *liststore;
GtkWidget *combo;
GtkCellRenderer *column;
gtk_init(&argc, &argv);
liststore = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_STRING);
gtk_list_store_insert_with_values(liststore, NULL, -1,
0, "red",
1, "Don't install.",
-1);
gtk_list_store_insert_with_values(liststore, NULL, -1,
0, "green",
1, "This user only.",
-1);
gtk_list_store_insert_with_values(liststore, NULL, -1,
0, "yellow",
1, "All users.",
-1);
combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(liststore));
/* liststore is now owned by combo, so the initial reference can
* be dropped */
g_object_unref(liststore);
column = gtk_cell_renderer_text_new();
gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combo), column, TRUE);
/* column does not need to be g_object_unref()ed because it
* is GInitiallyUnowned and the floating reference has been
* passed to combo by the gtk_cell_layout_pack_start() call. */
gtk_cell_layout_set_attributes(GTK_CELL_LAYOUT(combo), column,
"cell-background", 0,
"text", 1,
NULL);
gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 1);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_container_add(GTK_CONTAINER(window), combo);
/* Also combo is GInitiallyUnowned and it is now owned
by window after the gtk_container_add() call. */
gtk_widget_show_all(window);
gtk_main();
return 0;
}
But if you intend to use only strings in your combo box, the code can be stripped down by leveraging GtkComboBoxText:
#include <gtk/gtk.h>
int main(int argc, char **argv)
{
GtkWidget *window, *combo;
gtk_init(&argc, &argv);
combo = gtk_combo_box_text_new();
gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), NULL, "Don't install.");
gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), NULL, "This user only.");
gtk_combo_box_text_append(GTK_COMBO_BOX_TEXT(combo), NULL, "All users");
gtk_combo_box_set_active(GTK_COMBO_BOX(combo), 1);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_container_add(GTK_CONTAINER(window), combo);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
I think I found the solution.
I had to insert a cell renderer into the combo box. I added this code between creating the combobox and setting the default active value.
GtkCellRenderer *combocell = gtk_cell_renderer_text_new ();
gtk_cell_layout_pack_start( GTK_CELL_LAYOUT(combo), combocell, TRUE );
gtk_cell_layout_set_attributes( GTK_CELL_LAYOUT(combo), combocell, "text", 0, NULL );
I still don't understand this and I have no idea what attributes are suppose to go with GtkCellLayout or how they work. Any supplemental reading would greatly be appreciated.
Related
I'm trying to use gtk3 radiobutton following the turorial bellow. The problem is I noticed the callback funcion is being called twice everytime I click in the button.
My question is why and how can I change this for the callback to be called one time when I click in a radio button?
https://developer.gnome.org/gnome-devel-demos/stable/radiobutton.c.html.en
#include <gtk/gtk.h>
static void foo(GtkWidget *widget, gpointer data)
{
char *id_radio = (char*)data;
g_print("%s\n", id_radio);
}
int main(int argc, char *argv[])
{
gtk_init(&argc, & argv);
GtkWidget *radio_1, *radio_2, *radio_3, *vbox, *window;
radio_1 = gtk_radio_button_new_with_label(NULL, "Radio 01");
radio_2 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio_1), "Radio 02");
radio_3 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio_1), "Radio 03");
vbox = gtk_box_new(GTK_ORIENTATION_VERTICAL, 0);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(window, "delete-event", G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(GTK_TOGGLE_BUTTON(radio_1), "toggled", G_CALLBACK(foo), (gpointer)"1");
g_signal_connect(GTK_TOGGLE_BUTTON(radio_2), "toggled", G_CALLBACK(foo), (gpointer)"2");
g_signal_connect(GTK_TOGGLE_BUTTON(radio_3), "toggled", G_CALLBACK(foo), (gpointer)"3");
gtk_box_pack_start(GTK_BOX(vbox), radio_1, 1, 1, 0);
gtk_box_pack_start(GTK_BOX(vbox), radio_2, 1, 1, 0);
gtk_box_pack_start(GTK_BOX(vbox), radio_3, 1, 1, 0);
gtk_container_add(GTK_CONTAINER(window), vbox);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
The "toggled" signal which is inherited from a toggle button, triggers both on deactivation and activation. when you select a radio button, the previously selected button gets deactivated (the first callback), and the newly pressed one activates (the second callback).
If you want to filter out just the activations, get the toggle button's state inside the callback with gtk_toggle_button_get_active ().
As per documentation from:
https://developer.gnome.org/gtk3/stable/GtkToggleButton.html#gtk-toggle-button-get-active
For context, I'm trying to make a program that changes stylized label text in response to some physical inputs on a beaglebone black (eg. get a signal, if high/low, show this text). In lieu of those inputs, which I don't have access to right now, I decided to use key-release as a substitute.
I've been basing my code off of this combo-box tutorial, which changes label text based on the text of a combo-box selection. I've modified that code to use stylized text as in the code below.
#include <gtk/gtk.h>
void combo_selected(GtkWidget *widget, gpointer window) {
gchar *text = g_strjoin(NULL,"<span font='48' weight='bold' color='#DDDDDD'>",gtk_combo_box_get_active_text(GTK_COMBO_BOX(widget)),"</span>",NULL); //label text, uses pango markup
gtk_label_set_markup(GTK_LABEL(window), text);
g_free(text);
}
int main(int argc, char *argv[]) {
GtkWidget *window;
GtkWidget *hbox;
GtkWidget *vbox;
GtkWidget *combo;
GtkWidget *label;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "GtkComboBox");
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_container_set_border_width(GTK_CONTAINER(window), 15);
gtk_window_set_default_size(GTK_WINDOW(window), 300, 200);
hbox = gtk_hbox_new(FALSE, 0);
vbox = gtk_vbox_new(FALSE, 15);
combo = gtk_combo_box_new_text();
gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Ubuntu");
gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Arch");
gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Fedora");
gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Mint");
gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Gentoo");
gtk_combo_box_append_text(GTK_COMBO_BOX(combo), "Debian");
gtk_box_pack_start(GTK_BOX(vbox), combo, FALSE, FALSE, 0);
gchar *str = "<span font='48' weight='bold' color='#DDDDDD'>Not Initialized</span>"; //label text, uses pango markup
label = gtk_label_new(NULL);
gtk_label_set_markup(GTK_LABEL(label), str); //add pango str to label
gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
gtk_box_pack_start(GTK_BOX(hbox), vbox, FALSE, FALSE, 0);
gtk_container_add(GTK_CONTAINER(window), hbox);
g_signal_connect(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
g_signal_connect(G_OBJECT(combo), "changed",
G_CALLBACK(combo_selected), (gpointer) label);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
That works, however when attempting to use a key-release or key-press instead of the combo box options, I get a segmentation fault. Below is the further-modified code (with some things commented out).
#include <gtk/gtk.h>
#include <unistd.h>
#include <stdio.h>
void fpcheck(GtkWidget *window, gpointer lbl) {
gchar *text = "<span font='48' weight='bold' color='#DDDDDD'>Press index finger firmly on sensor.</span>";
gtk_label_set_markup(GTK_LABEL(lbl), text);
//sleep(2); //placeholder -> fp detection
//text = "<span font='48' weight='bold' color='#DDDDDD'>Fingerprint recognized!</span>";
//gtk_label_set_markup(GTK_LABEL(lbl), text);
g_free(text);
}
int main(int argc, char *argv[]) {
GtkWidget *window; //main window
GtkWidget *align; //alignment settings
GtkWidget *lbl; //text
GdkColor color = {0, 0x0, 0x0, 0x0}; //window color
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL); //init window
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); //window pos on screen
gtk_window_set_default_size(GTK_WINDOW(window), 800, 480); //window size
//gtk_window_set_resizable(GTK_WINDOW(window), FALSE); //user cant resize
gtk_window_set_title(GTK_WINDOW(window),"User Display"); //window title
gtk_widget_modify_bg(window, GTK_STATE_NORMAL, &color); //set color to window
align = gtk_alignment_new(.5,.5,0,0); //x,y alignment
lbl = gtk_label_new(NULL); //label init
gchar *str = "<span font='48' weight='bold' color='#DDDDDD'>Not Initialized</span>"; //label text, uses pango markup
gtk_container_add(GTK_CONTAINER(align), lbl); //add label to alignment
gtk_container_add(GTK_CONTAINER(window), align); //add label to window
gtk_label_set_markup(GTK_LABEL(lbl), str); //add pango str to label
g_signal_connect(G_OBJECT(window), "key-release-event", G_CALLBACK(fpcheck), (gpointer) lbl); //calls fpcheck to change label
g_signal_connect(G_OBJECT(window), "destroy",
G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(window); //build the window all at once
gtk_main();
return 0;
}
If I comment out the gtk_label_set_markup line and g_free(text) line in fpcheck, there's no error but it doesn't do anything, of course. From looking at other online resources, I think this error is being cause by trying to access the GTK_LABEL(lbl) because of the first argument in fpcheck being incorrect, but thats just a guess and I don't know what I'd put there instead. In the example, it's just "Widget," referring to the combo-box, I think, since it gets the text from the selected option.
On that note, I tried removing that argument, and now instead of a segmentation error, I get the following error without even pressing/releasing.
(test:6698): GLib-GObject-WARNING **: invalid cast from 'GtkWindow' to 'GtkLabel'
(test:6698): Gtk-CRITICAL **: IA__gtk_label_set_markup: assertion 'GTK_IS_LABEL (label)' failed
I did a few gdb backtraces, but none of them seem to be particularly helpful. If anyone wants 'em, I can post them.
Any ideas on the problems I'm having?
Thanks.
key-release-event handler has this signature
gboolean
user_function (GtkWidget *widget,
GdkEvent *event,
gpointer user_data)
Your fpcheck() needs to look like that.
It's easier to find problems like this early if you learn the habit of doing e.g. g_assert (GTK_IS_LABEL (user_data)) as the first thing in every handler where the userdata definitely always has to be a label.
I have an old app, now compiling on Gtk 2, but I need to introduce the use of Cairo. I can't figure out how to create the necessary cairo context (cairo_t) from my Widgets.
Here's the code I'm trying to learn with so far, modified (*ahem* cribbed) from a Gtk 3 tutorial. The crux of the matter is creating a cairo surface from the window widget. As it stands, that call is a sketch and it won't compile, let alone run. Remember, my target is Gtk2, not 3, at least at this point.
/* Snitched from http://zetcode.com/gfx/cairo/cairobackends/ on 13 Jan 2014 */
#include <cairo.h>
#include <cairo-xlib.h>
#include <gtk/gtk.h>
int main(int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *darea;
cairo_surface_t *surface;
cairo_t *cr;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
darea = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(window), darea);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_window_set_default_size(GTK_WINDOW(window), 400, 90);
gtk_window_set_title(GTK_WINDOW(window), "GTK window");
surface = cairo_xlib_surface_create(
gtk_widget_get_display(window), /* must be Display *, not struct GdkDisplay * */
window, /* must be Drawable (no star) */
gtk_widget_get_visual(window), /* must be Visual * */
gtk_widget_get_width(window), /* int */
gtk_widget_get_height(window) /* int */
);
cr = cairo_create(surface);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_select_font_face(cr, "Sans", CAIRO_FONT_SLANT_NORMAL,
CAIRO_FONT_WEIGHT_NORMAL);
cairo_set_font_size(cr, 40.0);
cairo_move_to(cr, 10.0, 50.0);
cairo_show_text(cr, "Discipline is power.");
gtk_widget_show_all(window);
gtk_main();
return 0;
}
I hope the tutorial did not do cairo drawing in main()... The meaningful place to draw onto a GTK2 widget is in the expose-event (and if you want to force a redraw from somewhere else, just call gtk_widget_queue_draw()). It is easier to use gdk_cairo_create() to get a cairo context.
Something like this:
static gboolean
on_expose_event (GtkWidget *widget,
GdkEventExpose *event,
gpointer data)
{
cairo_t *cr;
cr = gdk_cairo_create (gtk_widget_get_window (widget));
cairo_move_to (cr, 30, 30);
cairo_show_text (cr, "Text");
cairo_destroy (cr);
return FALSE;
}
g_signal_connect(darea, "expose-event",
G_CALLBACK(on_expose_event), NULL);
Jan Bodnar has a more complete example (in the end).
This is all a lot nicer in GTK3 in my opinion. Still, even if your goal is to port to GTK3 it may make sense to change the drawing to use cairo first as you're doing -- changing to GTK3 afterwards should just simplify the code.
When I have GtkTextView in GtkScrolledWindow, it scrolls automatically when user appends new line at the bottom of the widget. When I put GtkTextView in GtkBox and then in GtkScrolledWindow I doesn't work. I need to put box between GtkTextView and scrollbar and I can't do that without placing whole thing in another box. Is there any way to preserve autoscrolling behaviour when using GtkBox inside GtkScrolledWindow?
There is code that ilustrates my problem:
#include <gtk/gtk.h>
int main(int argc, char *argv[]) {
GtkWidget *window;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(window),
gdk_screen_width()*0.5, gdk_screen_height()*0.5);
GtkWidget *main = gtk_box_new(0, 0);
gtk_container_add(GTK_CONTAINER(window), main);
/*/////////////////////////////////////////////////*/
/* IMPORTANT PART */
/* FIRST CASE (this one works correctly) */
GtkWidget *scrolled_window_first = gtk_scrolled_window_new(NULL, NULL);
GtkWidget *text_view_first = gtk_text_view_new();
gtk_container_add(GTK_CONTAINER(scrolled_window_first), text_view_first);
gtk_box_pack_start(GTK_BOX(main), scrolled_window_first, 1, 1, 0);
/* SECOND CASE (there is no auto scroll which I need) */
GtkWidget *scrolled_window_second = gtk_scrolled_window_new(NULL, NULL);
GtkWidget *text_view_second = gtk_text_view_new();
GtkWidget *box_from_second_example = gtk_box_new(0, 0);
GtkWidget *example_box_before_scroller = gtk_box_new(0,0);
GtkWidget *example_label = gtk_label_new("I need this box badly!");
gtk_box_pack_start(GTK_BOX(box_from_second_example), text_view_second, 1, 1, 0);
gtk_container_add(GTK_CONTAINER(scrolled_window_second), box_from_second_example);
gtk_container_add(GTK_CONTAINER(box_from_second_example), example_box_before_scroller);
gtk_box_pack_start(GTK_BOX(main), scrolled_window_second, 1, 1, 0);
/* END IMPORTANT PART */
/*/////////////////////////////////////////////////*/
gtk_container_add(GTK_CONTAINER(example_box_before_scroller), example_label);
g_signal_connect(GTK_WINDOW(window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_widget_show_all(window);
gtk_main ();
return 0;
}
The problem is GtkTextView implements GtkScrollable but GtkBox does not. This is not a minor issue: if you want to go the GtkBox way you should put it inside a GtkViewport and add the scrollability stuff... quite some code that involves deep understanding of how the whole thing scrolls.
Anyway if you are lazy enough you could also note GtkTextview is a GtkContainer. In other words you could add widgets around the GtkTextview without the need to incomodate GtkBox. Not exactly what you were looking for but maybe good enough for your purposes:
#include <gtk/gtk.h>
gint main(gint argc, gchar **argv)
{
GtkWidget *window, *scrolled_window, *text_view, *label;
gtk_init(&argc, &argv);
text_view = gtk_text_view_new();
gtk_text_buffer_set_text(gtk_text_view_get_buffer(GTK_TEXT_VIEW(text_view)),
"1\n\n\n2\n\n\n3\n\n\n4\n\n\n5\n\n\n6\n\n\n7\n\n\n8", -1);
/* Use this to set the size you want to reserve on the right */
gtk_text_view_set_border_window_size(GTK_TEXT_VIEW(text_view),
GTK_TEXT_WINDOW_RIGHT,
130);
/* Add whatever you want instead of a GtkLabel */
gtk_text_view_add_child_in_window(GTK_TEXT_VIEW(text_view),
gtk_label_new("You badly need this"),
GTK_TEXT_WINDOW_RIGHT,
0, 0);
scrolled_window = gtk_scrolled_window_new(NULL, NULL);
gtk_container_add(GTK_CONTAINER(scrolled_window), text_view);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(window), 320, 240);
gtk_container_add(GTK_CONTAINER(window), scrolled_window);
gtk_widget_show_all(window);
gtk_main ();
return 0;
}
Did you try to modify the GtkAdjustments the textview creates by default (GtkScrolledWindow implements the GtkScrollable afaik).
GtkAdjustment * gtk_scrollable_get_hadjustment (GtkScrollable *scrollable);
I think the best approach would be to detect insertions to the GtkTextBuffer (get the views buffer via
GtkTextBuffer * gtk_text_view_get_buffer (GtkTextView *text_view);
and hook a callback (which tests for \n) to its insert-text g_signal and use
void gtk_adjustment_set_value (GtkAdjustment *adjustment,
gdouble value);
to modify the scrolling height.
Note that this is untested and a simpler method might be around the corner.
This is what I have so far
GtkWidget* createConsoleBox()
{
GtkWidget* textArea = gtk_text_view_new();
GtkWidget* scrollbar = gtk_vscrollbar_new(gtk_text_view_get_vadjustment(GTK_TEXT_VIEW(textArea)));
GtkWidget* textEntry = gtk_entry_new();
GtkWidget* console = gtk_table_new(3, 2, FALSE);
gtk_table_attach_defaults(GTK_TABLE(console), textArea, 0, 1, 0, 1);
gtk_table_attach_defaults(GTK_TABLE(console), scrollbar, 1, 2, 0, 1);
gtk_table_attach_defaults(GTK_TABLE(console), textEntry, 0, 2, 1, 2);
return console;
}
I want the text view to be scrollable as the text begins to fill the box, but the box keeps on expanding to accommodate more text. How to do I limit the size of the text view and create a scrollable text view.
Thanks in advance :-)
I'm afraid you've misunderstood how scrollbars work in GTK; usually you don't create a scrollbar directly, but you place the widget you would like to scroll in a GtkScrolledWindow. This creates scrollbars automatically and connects them to the widget inside the scrolled window; in your case, the text view.
Here's what your createConsoleBox() function should look like:
GtkWidget* createConsoleBox()
{
GtkWidget* textArea = gtk_text_view_new();
GtkWidget* scrolledwindow = gtk_scrolled_window_new(NULL, NULL);
GtkWidget* textEntry = gtk_entry_new();
GtkWidget* console = gtk_table_new(3, 1, FALSE);
gtk_container_add(GTK_CONTAINER(scrolledwindow), textArea);
gtk_table_attach_defaults(GTK_TABLE(console), scrolledwindow, 0, 1, 0, 1);
gtk_table_attach_defaults(GTK_TABLE(console), textEntry, 0, 1, 1, 2);
return console;
}
What you experience is the result of the widget asking more space to its parent container.
Unless the parent container has some rules forbidding the expansion, it will give as much space as child widget asks.
A common way to avoid this is to set a given size for the child widget with gtk_widget_set_size_request(), followed by some way to make sure the parent can give shrink or grow, depending on the parent properties.
This sample code show one way to accomplish this.
#include <gtk/gtk.h>
GtkWidget* createConsoleBox()
{
GtkWidget* textArea = gtk_text_view_new();
GtkWidget* scrollbar= gtk_vscrollbar_new(gtk_text_view_get_vadjustment(GTK_TEXT_VIEW(textArea)));
GtkWidget* textEntry = gtk_entry_new();
GtkWidget* console = gtk_table_new(3, 2, FALSE);
gtk_table_attach_defaults(GTK_TABLE(console), textArea, 0, 1, 0, 1);
gtk_table_attach_defaults(GTK_TABLE(console), scrollbar, 1, 2, 0, 1);
gtk_table_attach_defaults(GTK_TABLE(console), textEntry, 0, 2, 1, 2);
//This code sets the preferred size for the widget, so it does not ask for extra space
gtk_widget_set_size_request(textArea, 320, 240);
return console;
}
int main(int argc,char* argv[]){
GtkWidget *window;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "Simple Sample");
gtk_window_set_default_size(GTK_WINDOW(window), 800, 600);// does not matter this size
gtk_container_add(GTK_CONTAINER(window), createConsoleBox());
gtk_widget_show_all(window);
gtk_window_set_resizable(GTK_WINDOW(window),FALSE);//because of this
gtk_main();
return 0;
}
gtk_window_set_resizable() is meant to make the window un-resizeable by the user (the App can still resize it), but has the extra propertie of tighting up the window to the size of its child widget. Each GtkContainer has it way of setting up expansion, tighness, etc. Is only matter of experimentation to find the right one for your needs.
If the window resizable property had been set to TRUE, the textarea would still have the given size for it, the container would just put a lot of extra space between the individual widgets inside the GtkTable.