#include <stdbool.h>
#include <gtk/gtk.h>
/*
Structure:
GtkWindow
GtkFixed
GtkDrawingArea
GtkButton
( Commented out lines are for test purposes. )
What i want:
I want do draw into an "hidden" Bitmap (as example for a double-buffer-system). If needed or at an
interval its content should be transferred into the Program-Window.
You can comment-in "direct_test" in the function "callback__drawingarea".
This works. (But I have to mouse-click for every new picture)
But if I try to draw via the function "testdraw" ("direct_test" is commented out), all what I get is an
black Screen, instead of a sort of "animation".
User "dboles" suggested "GtkTickCallback" ... But I don't understand the mechanism. The DrawingArea
needs its callback-function. So I has to use the GtkTickCallback-function to fire in it "gtk_widget_queue_draw" ?
Is my combination of an idle-function (with included draw-operations) and gtk_widget_queue_draw wrong ?
*/
GtkWidget *Window,*Area;
cairo_surface_t *CairoSurface;
cairo_t *Cairo;
guint IdleID;
bool Order_executed;
bool Startbutton_clicked;
bool callback__button_start(void);
gboolean callback__drawingarea(GtkWidget *widget, cairo_t *cr,gpointer data);
gboolean idle_function(gpointer user_data);
void testdraw(void);
int main(void)
{
GtkWidget *fixed,*button_start;
gtk_init(NULL,NULL);
Window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(Window),1000,1000);
g_signal_connect(Window,"delete-event",(GCallback)gtk_main_quit,NULL);
g_signal_connect(Window,"destroy",(GCallback)gtk_main_quit,NULL);
fixed = gtk_fixed_new();
gtk_container_add(GTK_CONTAINER(Window),fixed);
Area = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(fixed),Area);
g_signal_connect((GtkWidget *)Area,"draw",(GCallback)callback__drawingarea,NULL);
gtk_widget_set_size_request(Area,1000,1000);
button_start = gtk_button_new_with_label("Start");
gtk_container_add(GTK_CONTAINER(fixed),button_start);
g_signal_connect((GtkWidget *)button_start,"clicked",(GCallback)callback__button_start,NULL);
// gtk_fixed_move((GtkFixed*)fixed,button_start, 900,900);
// Creating the "Background-Videomemory":
// Formats CAIRO_FORMAT_RGB30 and CAIRO_FORMAT_RGB16_565 results as well in black-screen. All others shows no effect
CairoSurface = cairo_image_surface_create(CAIRO_FORMAT_RGB24,1000,1000);
Cairo = cairo_create(CairoSurface);
IdleID = g_idle_add(idle_function,NULL);
gtk_widget_show_all(Window);
gtk_main();
}
bool callback__button_start(void)
{
Startbutton_clicked = true; // See function “callback__drawingarea”
Order_executed = true; // See function “idle_function”
gtk_widget_queue_draw(Area);
//gtk_widget_queue_draw_area(Area,0,0,1000,1000);
return true;
}
gboolean callback__drawingarea(GtkWidget *widget,cairo_t *cr,gpointer data)
{
unsigned long x,y,i; // for direct_test
if(Startbutton_clicked == false)
{
// This also catches the mandatory calling of the function at program start.
return false;
}
//#define direct_test
#ifdef direct_test
cairo_set_source_rgb(cr,1.0,0.0,0.0);
for(i=0;i!=100;i++)
{
x = rand() % 400;
y = rand() % 400;
cairo_rectangle(cr,x,y,10,10);
}
cairo_fill(cr);
return false;
#endif
//cairo_surface_flush(CairoSurface);
cairo_set_source_surface(cr,CairoSurface,0,0); // This should do, what BitBlt under Windows do
cairo_paint(cr);
//cairo_fill(cr); // Does not work at all
Order_executed = true;
return false;
}
gboolean idle_function(gpointer user_data)
{
testdraw();
if(Order_executed == true)
{
Order_executed = false;
gtk_widget_queue_draw_area(Area,0,0,1000,1000);
//gtk_widget_queue_draw(Area);
}
return true;
}
// This function draws into the Background-Bitmap
void testdraw(void)
{
unsigned long x,y;
x = rand() % 400;
y = rand() % 400;
cairo_set_source_rgb(Cairo,1.0,0.0,0.0);
cairo_rectangle(Cairo,x,y,10,10);
}