Unable to change cursor with GTK3 - c

I am trying to change the cursor of a window dynamically with GTK3 but gtk_widget_get_parent_window doesn't seem to work.
Could someone please point out what I'm doing wrong? Thanks!
// https://developer.gnome.org/gtk3/stable/gtk-getting-started.html
// minimal example
#include <gtk/gtk.h>
static void
activate (GtkApplication* app,
gpointer user_data)
{
GtkWidget *window;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
// Here \/\/\/\/\/ .
GdkWindow* w = gtk_widget_get_parent_window(window);
GdkCursor* c = gdk_cursor_new_for_display(gdk_display_get_default(), GDK_WATCH);
gdk_window_set_cursor(w, c);
// /\/\/\/\/\ .
gtk_widget_show_all (window);
}
int
main (int argc,
char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
(main.exe:16508): Gdk-CRITICAL **: gdk_window_set_cursor: assertion
'GDK_IS_WINDOW (window)' failed
I am using GTK 3.16 with msys2
Many thanks in advance.

Extending #andlabs comment
Any attempt to change the cursor needs to be done after the widget has been added to the widget hierarchy or in GTK terms realized.
Calling gtk_widget_get_parent_window() or even gtk_widget_get_window() before a realize event has been fired for the widget will result in a NULL pointers in both cases.
Like #andlabs it is safer to use gtk_widget_get_window() in combination with a GtkWindow.
The solution.
static GdkWindow* G_WINDOW = 0;
static GdkCursor* G_CURSOR = 0;
// call after WindowRealize()
void changecursor()
{
assert(G_WINDOW != NULL);
gdk_window_set_cursor(G_WINDOW, G_CURSOR);
}
static void WindowRealize(GtkWidget *window, gpointer data)
{
G_CURSOR_HAND = gdk_cursor_new_for_display(gdk_display_get_default(), GDK_HAND2);
G_WINDOW = gtk_widget_get_window(window);
}
static void activate(GtkApplication* app,gpointer user_data)
{
GtkWidget *window = gtk_application_window_new(app);
...
g_signal_connect(window, "realize", G_CALLBACK(WindowRealize), NULL);
gtk_widget_show_all (window);
}

Related

Segfault in gtk_window_new

I have a simple GTK app written in C that segfaults on the line window = gtk_window_new(GTK_WINDOW_TOPLEVEL)
Here is the code:
#include <gtk/gtk.h>
int main(int argc, char **argv) {
GtkApplication *app = NULL;
GtkWidget *window = NULL;
app = gtk_application_new("com.github.Toothless204", G_APPLICATION_FLAGS_NONE);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_application_add_window(app, GTK_WINDOW(window));
int status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref(app);
return status;
}
I have googled around to find an answer but didn't find anything that actually provided an answer as to what the problem could be
Problem: tried to create a window before the GTK+ initialization functions was called by the GtkApplication.
Before using GTK+, you need to initialize it.
https://developer.gnome.org/gtk3/stable/gtk3-General.html
#include <gtk/gtk.h>
int main(int argc, char **argv) {
GtkWidget *window = NULL;
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_widget_show (window);
g_signal_connect (window, "destroy",
G_CALLBACK (gtk_main_quit), NULL);
gtk_main();
return 0;
}
For the same reason GtkApplication windows must be added after the GApplication 'startup' signal has been emitted.
https://wiki.gnome.org/HowDoI/GtkApplication
#include <gtk/gtk.h>
static void activate (GApplication *app, gpointer user_data) {
GtkWidget *window;
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_application_add_window(GTK_APPLICATION(app), GTK_WINDOW(window));
gtk_widget_show (window);
}
int main (int argc, char **argv) {
GtkApplication *app;
int status;
app = gtk_application_new ("com.github.Toothless204", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}

locale mismatch between gnuplot and gtk/c scripted output

I am coding a GUI (using GTK3) for a simple program that performs a simulation and plots the requested graph (using gnuplot).
When I'm using only gnuplot, I have no problem. The graph looks exactly like I want. However, when I try using this same code from GTK, it doesn't work anymore. It truncates all my value. Why ? What should I do to fix this?
This is the expected result (gnuplot without GTK):
And this is the actual result (gnuplot with GTK) :
#include <gtk/gtk.h>
static void
activate (GtkApplication* app,
gpointer user_data)
{
GtkWidget *window;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
gtk_widget_show_all (window);
FILE *gp = popen("gnuplot -persist", "w");
fprintf(gp, "plot '-' using 1:2 with lines\n");
int i;
for(i = 0; i < 13; i++){
fprintf(gp, "%d %f\n", i, 0.1*i);
}
pclose(gp);
}
int
main (int argc,
char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}

C: How to replace GtkAlignment function with newer GtkWidget align property

I am a new C programmer coming from Java. After reading some old books and articles, I've written the following code:
#include <gtk/gtk.h>
static void activate(GtkApplication* app, gpointer user_data) {
GtkWidget *window;
GtkWidget *button1;
GtkWidget *box;
box = gtk_alignment_new(0, 0, 0, 0);
window = gtk_application_window_new(app);
gtk_window_set_title(GTK_WINDOW(window), "Calculator");
gtk_window_set_default_size(GTK_WINDOW(window), 300, 400);
gtk_container_add(GTK_CONTAINER(window), box);
button1 = gtk_button_new();
gtk_button_set_label(GTK_BUTTON(button1), "1");
gtk_widget_set_size_request(button1, 40, 30);
gtk_container_add(GTK_CONTAINER(box), button1);
gtk_widget_show_all(window);
}
int main(int argc, char **argv) {
GtkApplication *app;
int status;
app = gtk_application_new("me.test.calculator", G_APPLICATION_FLAGS_NONE);
g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref(app);
return status;
}
The code compiles and runs correctly. The problem is that gtk_alignment_new is deprecated and I want to get rid of it.
I've tried replacing gtk_alignment_new with:
gtk_widget_set_halign(box, GTK_ALIGN_START);
gtk_widget_set_valign(box, GTK_ALIGN_START);
but the window does not show up when using this method. Thanks.
You want to set the halign/valign properties of the button (and then add the button straight into the window) to achieve the same functional results as your original code. 'box' is no longer needed at all.
Note that a GtkWindow is a GtkBin so only takes a single child: you will need to add additional containers in between to actually make a calculator. Maybe start by adding a GtkGrid as the sole window child and then attach all your buttons into the grid.
Using jku's advice I've written the following code which compiles and runs correctly without using gtk_alignment_new:
#include <gtk/gtk.h>
static void activate(GtkApplication* app, gpointer user_data) {
GtkWidget *window;
GtkWidget *button1;
GtkWidget *fixed;
fixed = gtk_fixed_new();
window = gtk_application_window_new(app);
gtk_window_set_title(GTK_WINDOW(window), "Calculator");
gtk_window_set_default_size(GTK_WINDOW(window), 300, 400);
gtk_container_add(GTK_CONTAINER(window), fixed);
button1 = gtk_button_new();
gtk_button_set_label(GTK_BUTTON(button1), "1");
gtk_widget_set_size_request(button1, 45, 35);
gtk_fixed_put(GTK_FIXED(fixed), button1, 5, 200);
gtk_widget_show_all(window);
}
int main(int argc, char **argv) {
GtkApplication *app;
int status;
app = gtk_application_new("me.test.calculator", G_APPLICATION_FLAGS_NONE);
g_signal_connect(app, "activate", G_CALLBACK(activate), NULL);
status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref(app);
return status;
}
NOTE: I ended up using GtxFixed because the size of the window will be fixed as well.

C - GTK - g_application_quit

I have a problem with quitting a gtk application. The function call of g_application_quit results in the subsequent error:
GLib-GIO-CRITICAL **: g_application_quit: assertion 'G_IS_APPLICATION (application)' failed
The code snippet looks like this:
g_signal_connect(app_window, "destroy", G_CALLBACK(g_application_quit), app);
I tried this also, but still throws the same error:
g_signal_connect(app_window, "destroy", G_CALLBACK(g_application_quit), G_APPLICATION(app));
The app got initialized as:
GtkApplication *app = gtk_application_new("my.ne.sweeper", G_APPLICATION_FLAGS_NONE);
Any help is appreciated. Thank you.
You don't need to connect g_application_quit to window's destroy signal explicitly if You are using G_APPLICATION, it is done automatically.
Here goes the minimalistic example:
#include <gtk/gtk.h>
static void activate (GtkApplication* app, gpointer data) {
GtkWidget *window;
window = gtk_application_window_new(app);
gtk_window_set_default_size(GTK_WINDOW (window), 400, 200);
gtk_widget_show_all(window);
}
int main (int argc, char **argv) {
GtkApplication *app;
int status;
app = gtk_application_new("your.app.name", G_APPLICATION_FLAGS_NONE);
g_signal_connect(app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run(G_APPLICATION(app), argc, argv);
g_object_unref(app);
return status;
}

GTK Basic Window App on Mac - Warning, Deprecated

I'm running a basic GTK app from the GTK website's tutorials, and I'm getting the following warning:-
*** WARNING: Method userSpaceScaleFactor in class NSView is deprecated on 10.7 and later. It should not be used in new applications. Use convertRectToBacking: instead.
I've installed the gtk+ and gtk+3 packages with brew. Here is the code from the file:-
#include
static void
activate (GtkApplication* app,
gpointer user_data)
{
GtkWidget *window;
window = gtk_application_window_new (app);
gtk_window_set_title (GTK_WINDOW (window), "Window");
gtk_window_set_default_size (GTK_WINDOW (window), 200, 200);
gtk_widget_show_all (window);
}
int
main (int argc,
char **argv)
{
GtkApplication *app;
int status;
app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
g_signal_connect (app, "activate", G_CALLBACK (activate), NULL);
status = g_application_run (G_APPLICATION (app), argc, argv);
g_object_unref (app);
return status;
}
I'm running OS X 10.10.5, MacBook Pro 13in Retina.
Any ideas? Thanks!

Resources