Segfault when calling gtk_drawing_area_new - gtk3

I have just a simple program
#include <gtk/gtk.h>
int main() {
GtkWidget * drawingarea = gtk_drawing_area_new(); // <-- Segfault
return 0;
}
which just creates a drawing area. But it segfaults. Why? I'm using ubuntu 18.04.

Using gtk_init before the call to gtk_drawing_area_new solves this problem.

Related

Why does gtk3 call the ClosureNotify function in the example code, but gkt4 doesn't?

When this example program
#include <gtk/gtk.h>
static void draw_func(
GtkDrawingArea* drawing_area,
cairo_t *cr,
#ifdef GTK3
#else
int width,
int height,
#endif
gpointer user_data
) {
printf("draw!\n");
}
struct Ctx {
char *text;
GtkWidget *drawing_area;
};
static void ctx_destroy_notify(
gpointer data
#ifdef GTK3
, GClosure* closure
#endif
) {
struct Ctx *ctx = data;
printf("drop!\n");
free(ctx->text);
g_object_unref(ctx->drawing_area);
free(ctx);
}
static void
activate (GtkApplication* app,
gpointer user_data)
{
GtkWidget *drawing_area = gtk_drawing_area_new();
GtkWidget *window = gtk_application_window_new (app);
struct Ctx *ctx = malloc(sizeof(struct Ctx));
ctx->text = strdup("Hallo");
ctx->drawing_area = g_object_ref(drawing_area);
#ifdef GTK3
g_signal_connect_data(G_OBJECT(drawing_area), "draw", G_CALLBACK(draw_func), ctx, ctx_destroy_notify, G_CONNECT_AFTER);
#else
gtk_drawing_area_set_draw_func( GTK_DRAWING_AREA(drawing_area), draw_func, ctx, ctx_destroy_notify);
#endif
#ifdef GTK3
gtk_container_add (GTK_CONTAINER (window), drawing_area);
#else
gtk_window_set_child (GTK_WINDOW(window), drawing_area);
#endif
#ifdef GTK3
gtk_widget_show_all(window);
#else
gtk_widget_show(window);
#endif
gtk_window_close(GTK_WINDOW(window));
}
int
main (int argc,
char **argv)
{
GtkApplication * app = gtk_application_new ("org.example.test", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
g_application_run (G_APPLICATION (app), argc, argv);
printf("end of main loop\n");
g_object_unref (app);
}
is run with this Makefile:
.PHONY: test
test: test3 test4
./test3
./test4
test3: test.c
gcc -g -O0 -DGTK3 `pkg-config --cflags gtk+-3.0` -o test3 test.c `pkg-config --libs gtk+-3.0`
test4: test.c
gcc -g -O0 -DGTK4 `pkg-config --cflags gtk4` -o test4 test.c `pkg-config --libs gtk4`
The output is:
./test3
drop!
end of main loop
./test4
end of main loop
So ctx_destroy_notify is called with gtk3 but not with gtk4. Note, that gtk_widget_show (window); gtk_window_close(GTK_WINDOW(window)); can be replaced with g_object_run_dispose(G_OBJECT(window)); with the same result.
Why do gtk3 and gtk4 behave differently here?
[ to be ignored: stackoverflow wants a little bit more text, so that the text to code ratio is acceptable to its heuristic... ]
Edit 31.12.2022: Add first few lines of source, which were missing because of copy-and-paste mistake.
Okay, as nobody jumped on this, I try to answer that myself.
The code, obviously, contains a circular reference: drawing_area -> draw callback -> ctx -> drawing_area
The reference ctx -> drawing_area is correctly created with 
g_object_ref(), the other references are implied by gtk.
The function ctx_destroy_notify() in the code would break the reference
cycle with g_object_unref() if it gets called.
It is true, that gtk3 calls ctx_destroy_notify() when the application window is closed. This is a result of the fact that gtk3 immediately disposes the child widgets when a window is destroyed. But this is just an implementation detail.
There were substantial changes in this area between gtk3 and gtk4. See "Life-cycle handling" at https://docs.gtk.org/gtk4/migrating-3to4.html.
Here is a related discussion: https://gitlab.gnome.org/GNOME/gtk/-/issues/3243
In short: While the destroy_data notify of signal_connect_data() can be used to clean up the user data of the callback when the object is destroyed, it can not reliably be used to break a reference cycle which prevents the object from being destroyed in the first place.
Possible approaches to clean up the reference cycle would be:
subclass one of the widgets and make the ctx data part of it
For gtk4: Use a "win.close" action
Use weak references in ctx

Learning GUI programming with GTK+3

I am new to GUI programming. I recently installed Gtk+3 version on Linux. But, when I typed following code:
#include <gtk/gtk.h>
#include <stdio.h>
static int count = 0;
void button_clicked(GtkWidget *button, gpointer data)
{
printf(“%s pressed %d time(s) \n”, (char *) data, ++count);
}
int main (int argc, char *argv[])
{
GtkWidget *window;
GtkWidget *button;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
button = gtk_button_new_with_label(“Hello World!”);
gtk_container_add(GTK_CONTAINER(window), button);
g_signal_connect(GTK_OBJECT (button), “clicked”,
GTK_SIGNAL_FUNC (button_clicked),
“Button 1”);
gtk_widget_show(button);
gtk_widget_show(window);
gtk_main ();
return 0;
}
To run this code I used this command: $ gcc gtk1.c –o gtk1 pkg-config --cflags --libs gtk+-3.0
but I had error like this
undefined reference to GTK_OBJECT;
undefined reference to GTK_SIGNAL_FUNC;
This is because your code sample is for an old version of GTK+ 2. GTK_OBJECT was deprecated in the late GTK+ 2.x versions, and finally removed in GTK+ 3. Same for GTK_SIGNAL_FUNC. Both have been moved to the GObject library, where they now stand as G_OBJECT and G_CALLBACK.
To avoid using outdated code, just get started with the code samples from the GTK+ 3 documentation.

What could be wrong: GLib-GObject-WARNING **: cannot register existing type 'PangoCairoFont'

I spent many weeks trying to get gtk+ 3.22 to build on Visual Studio 2015. Finally I got it built but the small GUI program failed to initialize gtk. The error is shown as below:
gtk+_gtk_test.exe:15980): Gtk-WARNING **: Could not find the icon 'window-minimize-symbolic-ltr'. The 'hicolor' theme
was not found either, perhaps you need to install it.
You can get a copy from:
http://icon-theme.freedesktop.org/releases
(gtk+_gtk_test.exe:15980): GLib-GObject-WARNING **: cannot register existing type 'PangoCairoFont'
(gtk+_gtk_test.exe:15980): GLib-GObject-CRITICAL **: g_type_interface_add_prerequisite: assertion 'G_TYPE_IS_INTERFACE (interface_type)' failed
(gtk+_gtk_test.exe:15980): Glib-CRITICAL **: g_once_init_leave: assertion 'result != 0' failed
The first warning exists because the executable cannot locate the icon files. I have already figured out how to fix this. However, I am unable to get the second Warning fixed. This is my first gtk+ project. When I debug the code, it seems that PangoCairoFont type failed because of the existence of PangoCairoWin32Font type.
What could be wrong here? Appreciate your advice.
Source code of the program:
#include <gtk/gtk.h>
void hello(GtkWidget *widget, gpointer data)
{
g_print("Hello, World\n");
}
gint delete_event(GtkWidget *widget, GdkEvent event, gpointer data)
{
/* when this fucntion returns FALSE, the delete-event
signal becomes a destroy signal*/
return FALSE;
}
void end_program(GtkWidget *widget, gpointer data)
{
/* End the main loop */
gtk_main_quit();
}
int main(int argc, char **argv)
{
GtkWindow *window;
GtkButton *button;
/* initialize Gtk+ */
gtk_init(&argc, &argv);
/* create window, set default height and width to 200px */
window = g_object_new(GTK_TYPE_WINDOW,
"default-height", 200,
"default-width", 200,
"border-width", 12,
"title", "GtkHello",
NULL);
/* add signal handlers for window */
g_signal_connect(window, "delete-event", G_CALLBACK(delete_event),
NULL);
g_signal_connect(window,
"destroy", G_CALLBACK(end_program),
NULL);
/* create button */
button = g_object_new(GTK_TYPE_BUTTON,
"label", "_Hello, World!\nClick here.",
"use-underline", TRUE,
NULL);
g_signal_connect(button,
"clicked", G_CALLBACK(hello),
NULL);
g_signal_connect_swapped(button,
"clicked", G_CALLBACK(gtk_widget_destroy),
window);
gtk_container_add(GTK_CONTAINER(window), GTK_WIDGET(button));
gtk_widget_show_all(GTK_WIDGET(window));
/* start main loop */
gtk_main();
return 0;
}
I figured out. I mistakenly built pangocairo module into a static lib instead of DLL. This lib is further linked into different DLLs so the global variable has several copies, which caused the problem.

How to use GTK+ with ada

Anyone can show me some examples, simple, how to use GTK with Ada?
examples, like: How to use Glade with Ada, create an simple window....
an simple window, like this:
#include <gtk/gtk.h>
int main(int argc, char *argv[] )
{
GtkWidget *window;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_show (window);
gtk_main ();
return 0;
}
And, It's possible to use GtkMM, with ada ?
Thanks...
A few of my favorite GtkAda programs:
Animation demo
Linxtris
Mine Detector
Also, don't overlook the examples and testgtk folders of GtkAda itself.
Additional resources:
GTK+ API Documentation
Rosetta Code Category: Ada
Glade

How to create a GtkImage from a Cairo context?

I got a paint function that works using a Cairo context and the end result should be a GtkImage (without intermediate image creation). I tried to use the gdk_cairo_create function but this code:
...
GdkPixbuf *pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, 22, 22);
GtkWidget *image = gtk_image_new_from_pixbuf (pixbuf);
GdkDrawable *drawable = image->window;
cairo_t *ctx = gdk_cairo_create (drawable);
my_cairo_paint_function (ctx);
...
fails with:
Gdk-CRITICAL **: IA__gdk_cairo_create: assertion `GDK_IS_DRAWABLE (drawable)' failed
Same with a simple:
#include <gtk/gtk.h>
#include <cairo.h>
int
main (int argc, char *argv[])
{
gtk_init(&argc, &argv);
cairo_t *ctx = gdk_cairo_create (gtk_widget_get_window (gtk_image_new_from_file ("foobar.png")));
gtk_main();
return 0;
}
I don't understand why this fails. Any help is appreciated!
GtkImage doesn't have a GdkWindow, so the call to gtk_widget_get_window() or the access of widget->window returns NULL. You can put the GtkImage in a GtkEventBox and draw on the event box's GdkWindow.
Although, it looks like you're trying (with gdk_pixbuf_new) to create an empty space to draw on. In that case, GtkImage is not the widget you want -- use GtkDrawingArea. And don't forget to call your paint function in the handler for the event-expose signal!