Arastelion
Arastelion

Reputation: 343

Cairo and GTK+, unknown draw event call and program stop

I'm working with Cairo and GTK3.0 and I got problems that I have no clue on how to solve.

Currently I have 2 oddities that I do not have the knowledge of to solve.

  1. The draw event is called whenever the terminal floats over the drawing window.
  2. The program does not pas the gtk_main(); function.

I will provide my code below, which is very basic, it is based on this: http://zetcode.com/gfx/cairo/cairobackends/ , the GTK window part. I eventually just need a window that I can call the draw event on whenever I want in my code.

#include <cairo.h>
#include <gtk/gtk.h>
#include <stdio.h>
#include <stdlib.h>

typedef struct {
    int xStart;
    int yStart;
    int xEnd;
    int yEnd;
} lineData;

int i = 0;
int gonnaDraw = 0;
lineData *lines;
int lineSize = 0;

/**
 * The drawing with the cairo elements is done here.
 * The new line is saved to an array. 
 * Eventually there should be a loop that draws all lines in the array.
 */
static void do_drawing(cairo_t *cr) {
    printf("I'm endless, somehow.\n");
    if(lineSize != 0) { //We only want to draw in the infinite for loop, not before it.
        cairo_set_source_rgb(cr, 255, 0, 0);
        cairo_set_line_width(cr, 1.0);

        lineData newLine = { 10.0 + i, 50.0 + i, 100.0 + i, 50.0 + i };

        //lines[lineSize - 1] = newLine;

        cairo_move_to(cr, newLine.xStart, newLine.xEnd);
        cairo_line_to(cr, newLine.yStart, newLine.yEnd);

        cairo_stroke(cr);

        i = i + 10;
        printf("i: %d\n", i);
        gonnaDraw = 1;
    }
}

static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr, gpointer user_data) {
    do_drawing(cr);

    return FALSE;
}

int main (int argc, char *argv[]) {
    GtkWidget *window;
    GtkWidget *darea;
    printf("1\n");
    gtk_init(&argc, &argv);
    printf("2\n");
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    printf("3\n");
    darea = gtk_drawing_area_new();
    printf("4\n");
    gtk_container_add(GTK_CONTAINER(window), darea);
    printf("5\n");
    g_signal_connect(G_OBJECT(darea), "draw", G_CALLBACK(on_draw_event), NULL);
    g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
    printf("6\n");
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
    gtk_window_set_default_size(GTK_WINDOW(window), 800, 800);
    gtk_window_set_title(GTK_WINDOW(window), "GTK window");
    printf("7\n");
    gtk_widget_show_all(window);
    printf("8\n");
    gtk_main(); // If I'm removed I got no drawing window.
    printf("9\n"); // I do not show up.
    lines = (lineData *) malloc(lineSize * sizeof(lineData));

    for(;;) {
        if(gonnaDraw == 1) {
            lineSize++;
            printf("lineSize: %d\n", lineSize);
            lines = (lineData *) realloc(lines, lineSize * sizeof(lineData));
            gtk_widget_queue_draw(window);
            gonnaDraw = 0;
        }
    }

    return 0;
}

Compiled with standard method.

Upvotes: 0

Views: 421

Answers (1)

Armali
Armali

Reputation: 19375

You almost understand the GTK+ drawing model now. Question 1 is a consequence of it: when another window goes over yours, the window system tells GTK+ that that area needs to be redrawn. This is what i meant when I talked about clipping.
Now the other part is understanding the GTK+ event model. All window systems operate in such a way that all programs run on a loop that consists of while the program is alive, get a message from the window system and act on it. This is what gtk_main() does. gtk_main() not returning is normal; it doesn't return until a call to gtk_main_quit(). Apart from using signals to perform actions when a widget is interacted with, there are two ways you can "hook into" the main loop: g_timeout_add(), which runs a function on schedule, and g_idle_add(), which runs a function when next possible. The former is useful if you want something to happen every so often; the latter is useful if you want a worker thread to signal the UI to update. The GLib documentation on main loops will tell you more. I'm still not sure what your end goal is, so I suppose you can try playing with both to see what happens.
– andlabs

Upvotes: 1

Related Questions