Hi all,
Update: I commented the code which I think was collecting the clipping
region and now I can see the clock on the window, but still the events for
draw are not coming continuously, so all I get is a static image of a clock,
which changes if the redraw event occurs when I resize the window. Below is
the Code which I commented:
static void
egg_clock_face_redraw_canvas (EggClockFace *clock)
{
GtkWidget *widget;
//cairo_region_t *region; //commented this
widget = GTK_WIDGET (clock);
if (!gtk_widget_get_window(widget)) return;
//region = gdk_window_get_clip_region (gtk_widget_get_window(widget));
//this too
/* redraw the cairo canvas completely by exposing it */
//gdk_window_invalidate_region (gtk_widget_get_window(widget), region,
TRUE); //this one also
gdk_window_process_updates (gtk_widget_get_window(widget), TRUE);
//cairo_region_destroy(region); //and this, after this I can see the
clock :) its 5:50pm over here!!!
}
Ramesh.
On Fri, May 20, 2011 at 4:41 PM, Ramesh Chandra <[email protected]> wrote:
> Hi all,
>
> I'm new to linux, Gtk and cairo. Now I want to create a window using Gtk
> and then draw on it a rectangle using Cairo with a surface of type cairo-gl,
> how should I go about it. I'm using Eclipse (c/c++)as the development IDE,
> and I have Gtk3.0 installed, I'm able to create simple widgets using Gtk,
> like buttons and all. I have tried starting with a simple eggclock code that
> I found on the net, since it was written with th older Gtk(2+), I migrated
> it to version 3, it got build successfully, but when I execute it, all I get
> is an empty Gtk window. Below is the code for this sample:
>
> clock.h:
> #ifndef __EGG_CLOCK_FACE_H__
> #define __EGG_CLOCK_FACE_H__
>
> #include <gtk/gtk.h>
>
> G_BEGIN_DECLS
>
> #define EGG_TYPE_CLOCK_FACE (egg_clock_face_get_type ())
> #define EGG_CLOCK_FACE(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj),
> EGG_TYPE_CLOCK_FACE, EggClockFace))
> #define EGG_CLOCK_FACE_CLASS(obj) (G_TYPE_CHECK_CLASS_CAST ((obj),
> EGG_CLOCK_FACE, EggClockFaceClass))
> #define EGG_IS_CLOCK_FACE(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj),
> EGG_TYPE_CLOCK_FACE))
> #define EGG_IS_CLOCK_FACE_CLASS(obj) (G_TYPE_CHECK_CLASS_TYPE ((obj),
> EGG_TYPE_CLOCK_FACE))
> #define EGG_CLOCK_FACE_GET_CLASS (G_TYPE_INSTANCE_GET_CLASS ((obj),
> EGG_TYPE_CLOCK_FACE, EggClockFaceClass))
>
> typedef struct _EggClockFace EggClockFace;
> typedef struct _EggClockFaceClass EggClockFaceClass;
>
> struct _EggClockFace
> {
> GtkDrawingArea parent;
>
> /* < private > */
> };
>
> struct _EggClockFaceClass
> {
> GtkDrawingAreaClass parent_class;
>
> void (* time_changed) (EggClockFace *clock,
> int hours, int minutes);
> };
>
> GtkWidget *egg_clock_face_new (void);
>
> G_END_DECLS
>
> #endif
>
> clock.c:
> #include <gtk/gtk.h>
> #include <math.h>
> #include <time.h>
>
> #include "clock.h"
> #include "clock-marshallers.h"
>
> #define EGG_CLOCK_FACE_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE
> ((obj), EGG_TYPE_CLOCK_FACE, EggClockFacePrivate))
>
> G_DEFINE_TYPE (EggClockFace, egg_clock_face, GTK_TYPE_DRAWING_AREA);
>
> static gboolean egg_clock_face_expose (GtkWidget *clock, GdkEventExpose
> *event);
> static gboolean egg_clock_face_button_press (GtkWidget *clock,
> GdkEventButton *event);
> static gboolean egg_clock_face_button_release (GtkWidget *clock,
> GdkEventButton *event);
> static gboolean egg_clock_face_motion_notify (GtkWidget *clock,
> GdkEventMotion *event);
> static gboolean egg_clock_face_update (gpointer data);
>
> typedef struct _EggClockFacePrivate EggClockFacePrivate;
>
> struct _EggClockFacePrivate
> {
> struct tm time; /* the time on the clock face */
> int minute_offset; /* the offset of the minutes hand */
>
> gboolean dragging; /* true if the interface is being dragged */
> };
>
> enum
> {
> TIME_CHANGED,
> LAST_SIGNAL
> };
>
> static guint egg_clock_face_signals[LAST_SIGNAL] = { 0 };
>
> static void
> egg_clock_face_class_init (EggClockFaceClass *class)
> {
> GObjectClass *obj_class;
> GtkWidgetClass *widget_class;
>
> obj_class = G_OBJECT_CLASS (class);
> widget_class = GTK_WIDGET_CLASS (class);
>
> /* GtkWidget signals */
> widget_class->draw = egg_clock_face_expose;
> widget_class->button_press_event = egg_clock_face_button_press;
> widget_class->button_release_event = egg_clock_face_button_release;
> widget_class->motion_notify_event = egg_clock_face_motion_notify;
>
> /* EggClockFace signals */
> egg_clock_face_signals[TIME_CHANGED] = g_signal_new (
> "time-changed",
> G_OBJECT_CLASS_TYPE (obj_class),
> G_SIGNAL_RUN_FIRST,
> G_STRUCT_OFFSET (EggClockFaceClass, time_changed),
> NULL, NULL,
> _clock_marshal_VOID__INT_INT,
> G_TYPE_NONE, 2,
> G_TYPE_INT,
> G_TYPE_INT);
>
> g_type_class_add_private (obj_class, sizeof (EggClockFacePrivate));
> }
>
> static void
> egg_clock_face_init (EggClockFace *clock)
> {
> gtk_widget_add_events (GTK_WIDGET (clock),
> GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK |
> GDK_POINTER_MOTION_MASK);
>
> egg_clock_face_update (clock);
>
> /* update the clock once a second */
> g_timeout_add (1000, egg_clock_face_update, clock);
> }
>
> static void
> draw_me (GtkWidget *clock, cairo_t *cr)
> {
> EggClockFacePrivate *priv;
> double x, y;
> double radius;
> int i;
> int hours, minutes, seconds;
>
> priv = EGG_CLOCK_FACE_GET_PRIVATE (clock);
>
> GtkAllocation allocation;
>
> gtk_widget_get_allocation(clock, &allocation);
> //X = allocation.X
>
> x = allocation.width / 2;
> y = allocation.height / 2;
> radius = MIN (allocation.width / 2,
> allocation.height / 2) - 5;
>
> /* clock back */
> cairo_arc (cr, x, y, radius, 0, 2 * M_PI);
> cairo_set_source_rgb (cr, 1, 1, 1);
> cairo_fill_preserve (cr);
> cairo_set_source_rgb (cr, 0, 0, 0);
> cairo_stroke (cr);
>
> /* clock ticks */
> for (i = 0; i < 12; i++)
> {
> int inset;
>
> cairo_save (cr); /* stack-pen-size */
>
> if (i % 3 == 0)
> {
> inset = 0.2 * radius;
> }
> else
> {
> inset = 0.1 * radius;
> cairo_set_line_width (cr, 0.5 *
> cairo_get_line_width (cr));
> }
>
> cairo_move_to (cr,
> x + (radius - inset) * cos (i * M_PI / 6),
> y + (radius - inset) * sin (i * M_PI / 6));
> cairo_line_to (cr,
> x + radius * cos (i * M_PI / 6),
> y + radius * sin (i * M_PI / 6));
> cairo_stroke (cr);
> cairo_restore (cr); /* stack-pen-size */
> }
>
> /* clock hands */
> hours = priv->time.tm_hour;
> minutes = priv->time.tm_min + priv->minute_offset;
> seconds = priv->time.tm_sec;
> /* hour hand:
> * the hour hand is rotated 30 degrees (pi/6 r) per hour +
> * 1/2 a degree (pi/360 r) per minute
> */
> cairo_save (cr);
> cairo_set_line_width (cr, 2.5 * cairo_get_line_width (cr));
> cairo_move_to (cr, x, y);
> cairo_line_to (cr, x + radius / 2 * sin (M_PI / 6 * hours +
> M_PI / 360 * minutes),
> y + radius / 2 * -cos (M_PI / 6 * hours +
> M_PI / 360 * minutes));
> cairo_stroke (cr);
> cairo_restore (cr);
> /* minute hand:
> * the minute hand is rotated 6 degrees (pi/30 r) per minute
> */
> cairo_move_to (cr, x, y);
> cairo_line_to (cr, x + radius * 0.75 * sin (M_PI / 30 * minutes),
> y + radius * 0.75 * -cos (M_PI / 30 * minutes));
> cairo_stroke (cr);
> /* seconds hand:
> * operates identically to the minute hand
> */
> cairo_save (cr);
> cairo_set_source_rgb (cr, 1, 0, 0); /* red */
> cairo_move_to (cr, x, y);
> cairo_line_to (cr, x + radius * 0.7 * sin (M_PI / 30 * seconds),
> y + radius * 0.7 * -cos (M_PI / 30 * seconds));
> cairo_stroke (cr);
> cairo_restore (cr);
> }
>
> static gboolean
> egg_clock_face_expose (GtkWidget *clock, GdkEventExpose *event)
> {
> cairo_t *cr;
>
> /* get a cairo_t */
> cr = gdk_cairo_create (gtk_widget_get_window(clock));//clock->window);
>
> cairo_rectangle (cr,
> event->area.x, event->area.y,
> event->area.width, event->area.height);
> cairo_clip (cr);
>
> draw_me (clock, cr);
>
> cairo_destroy (cr);
>
> return FALSE;
> }
>
> static gboolean
> egg_clock_face_button_press (GtkWidget *clock, GdkEventButton *event)
> {
> EggClockFacePrivate *priv;
> int minutes;
> double lx, ly;
> double px, py;
> double u, d2;
>
> priv = EGG_CLOCK_FACE_GET_PRIVATE (clock);
>
> minutes = priv->time.tm_min + priv->minute_offset;
>
> /* From
> * http://mathworld.wolfram.com/Point-LineDistance2-Dimensional.html
> */
> GtkAllocation allocation;
>
> gtk_widget_get_allocation(clock, &allocation);
> px = event->x - allocation.width / 2;
> py = allocation.height / 2 - event->y;
> lx = sin (M_PI / 30 * minutes); ly = cos (M_PI / 30 * minutes);
> u = lx * px + ly * py;
>
> /* on opposite side of origin */
> if (u < 0) return FALSE;
>
> d2 = pow (px - u * lx, 2) + pow (py - u * ly, 2);
>
> if (d2 < 25) /* 5 pixels away from the line */
> {
> priv->dragging = TRUE;
> g_print ("got minute hand\n");
> }
>
> return FALSE;
> }
>
> static void
> egg_clock_face_redraw_canvas (EggClockFace *clock)
> {
> GtkWidget *widget;
> cairo_region_t *region;
>
> widget = GTK_WIDGET (clock);
>
> if (!gtk_widget_get_window(widget)) return;
>
> region = gdk_window_get_clip_region (gtk_widget_get_window(widget));
>
> /* redraw the cairo canvas completely by exposing it */
> gdk_window_invalidate_region (gtk_widget_get_window(widget), region,
> TRUE);
> gdk_window_process_updates (gtk_widget_get_window(widget), TRUE);
>
> cairo_region_destroy(region);
> //gdk_region_destroy (region);
> }
>
> static emit_time_changed_signal (EggClockFace *clock, int x, int y)
> {
> EggClockFacePrivate *priv;
> double phi;
> int hour, minute;
>
> priv = EGG_CLOCK_FACE_GET_PRIVATE (clock);
>
> /* decode the minute hand */
> /* normalise the coordinates around the origin */
> GtkAllocation allocation;
>
> gtk_widget_get_allocation(clock, &allocation);
> x -= allocation.width / 2;
> y -= allocation.height / 2;
>
> /* phi is a bearing from north clockwise, use the same geometry as we
> * did to position the minute hand originally */
> phi = atan2 (x, -y);
> if (phi < 0)
> phi += M_PI * 2;
>
> hour = priv->time.tm_hour;
> minute = phi * 30 / M_PI;
>
> /* update the offset */
> priv->minute_offset = minute - priv->time.tm_min;
> egg_clock_face_redraw_canvas (clock);
>
> g_signal_emit (clock,
> egg_clock_face_signals[TIME_CHANGED],
> 0,
> hour, minute);
> }
>
> static gboolean
> egg_clock_face_motion_notify (GtkWidget *clock, GdkEventMotion *event)
> {
> EggClockFacePrivate *priv;
> int x, y;
>
> priv = EGG_CLOCK_FACE_GET_PRIVATE (clock);
>
> if (priv->dragging)
> {
> emit_time_changed_signal (EGG_CLOCK_FACE (clock),
> event->x, event->y);
> }
> }
>
> static gboolean
> egg_clock_face_button_release (GtkWidget *clock, GdkEventButton *event)
> {
> EggClockFacePrivate *priv;
>
> priv = EGG_CLOCK_FACE_GET_PRIVATE (clock);
>
> if (priv->dragging)
> {
> priv = EGG_CLOCK_FACE_GET_PRIVATE (clock);
> priv->dragging = FALSE;
> emit_time_changed_signal (EGG_CLOCK_FACE (clock),
> event->x, event->y);
> }
>
> return FALSE;
> }
>
> static gboolean
> egg_clock_face_update (gpointer data)
> {
> EggClockFace *clock;
> EggClockFacePrivate *priv;
> time_t timet;
>
> clock = EGG_CLOCK_FACE (data);
> priv = EGG_CLOCK_FACE_GET_PRIVATE (clock);
>
> /* update the time */
> time (&timet);
> localtime_r (&timet, &priv->time);
>
> egg_clock_face_redraw_canvas (clock);
>
> return TRUE; /* keep running this event */
> }
>
> GtkWidget *
> egg_clock_face_new (void)
> {
> return g_object_new (EGG_TYPE_CLOCK_FACE, NULL);
> }
>
> cloock-marshallers.h:
> #ifndef ___clock_marshal_MARSHAL_H__
> #define ___clock_marshal_MARSHAL_H__
>
> #include <glib-object.h>
>
> G_BEGIN_DECLS
>
> /* VOID:INT,INT (clock-marshallers.list:2) */
> extern void _clock_marshal_VOID__INT_INT (GClosure *closure,
> GValue *return_value,
> guint n_param_values,
> const GValue *param_values,
> gpointer invocation_hint,
> gpointer marshal_data);
>
> G_END_DECLS
>
> #endif /* ___clock_marshal_MARSHAL_H__ */
>
>
> clock-marshallers.c:
>
> #include <glib-object.h>
>
>
> #ifdef G_ENABLE_DEBUG
> #define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
> #define g_marshal_value_peek_char(v) g_value_get_char (v)
> #define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
> #define g_marshal_value_peek_int(v) g_value_get_int (v)
> #define g_marshal_value_peek_uint(v) g_value_get_uint (v)
> #define g_marshal_value_peek_long(v) g_value_get_long (v)
> #define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
> #define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
> #define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
> #define g_marshal_value_peek_enum(v) g_value_get_enum (v)
> #define g_marshal_value_peek_flags(v) g_value_get_flags (v)
> #define g_marshal_value_peek_float(v) g_value_get_float (v)
> #define g_marshal_value_peek_double(v) g_value_get_double (v)
> #define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
> #define g_marshal_value_peek_param(v) g_value_get_param (v)
> #define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
> #define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
> #define g_marshal_value_peek_object(v) g_value_get_object (v)
> #define g_marshal_value_peek_variant(v) g_value_get_variant (v)
> #else /* !G_ENABLE_DEBUG */
> /* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
> * Do not access GValues directly in your code. Instead, use the
> * g_value_get_*() functions
> */
> #define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
> #define g_marshal_value_peek_char(v) (v)->data[0].v_int
> #define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
> #define g_marshal_value_peek_int(v) (v)->data[0].v_int
> #define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
> #define g_marshal_value_peek_long(v) (v)->data[0].v_long
> #define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
> #define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
> #define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
> #define g_marshal_value_peek_enum(v) (v)->data[0].v_long
> #define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
> #define g_marshal_value_peek_float(v) (v)->data[0].v_float
> #define g_marshal_value_peek_double(v) (v)->data[0].v_double
> #define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
> #define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
> #define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
> #define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
> #define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
> #define g_marshal_value_peek_variant(v) (v)->data[0].v_pointer
> #endif /* !G_ENABLE_DEBUG */
>
>
> /* VOID:INT,INT (clock-marshallers.list:2) */
> void
> _clock_marshal_VOID__INT_INT (GClosure *closure,
> GValue *return_value G_GNUC_UNUSED,
> guint n_param_values,
> const GValue *param_values,
> gpointer invocation_hint G_GNUC_UNUSED,
> gpointer marshal_data)
> {
> typedef void (*GMarshalFunc_VOID__INT_INT) (gpointer data1,
> gint arg_1,
> gint arg_2,
> gpointer data2);
> register GMarshalFunc_VOID__INT_INT callback;
> register GCClosure *cc = (GCClosure*) closure;
> register gpointer data1, data2;
>
> g_return_if_fail (n_param_values == 3);
>
> if (G_CCLOSURE_SWAP_DATA (closure))
> {
> data1 = closure->data;
> data2 = g_value_peek_pointer (param_values + 0);
> }
> else
> {
> data1 = g_value_peek_pointer (param_values + 0);
> data2 = closure->data;
> }
> callback = (GMarshalFunc_VOID__INT_INT) (marshal_data ? marshal_data :
> cc->callback);
>
> callback (data1,
> g_marshal_value_peek_int (param_values + 1),
> g_marshal_value_peek_int (param_values + 2),
> data2);
> }
>
>
> main.c:
> #include <gtk/gtk.h>
>
> #include "clock.h"
>
> static void
> time_changed_cb (EggClockFace *clock, int hours, int minutes, gpointer
> data)
> {
> g_print ("::time-changed - %02i:%02i\n", hours, minutes);
> }
>
> int
> main (int argc, char **argv)
> {
> GtkWidget *window;
> GtkWidget *clock;
>
> gtk_init (&argc, &argv);
>
> window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
>
> clock = egg_clock_face_new ();
> gtk_container_add (GTK_CONTAINER (window), clock);
>
> g_signal_connect (window, "destroy",
> G_CALLBACK (gtk_main_quit), NULL);
>
> g_signal_connect (clock, "time-changed",
> G_CALLBACK (time_changed_cb), NULL);
>
> gtk_widget_show_all (window);
>
> gtk_main ();
> }
>
> Thanks in advance.
>
> Ramesh.
>
_______________________________________________
gtk-list mailing list
[email protected]
http://mail.gnome.org/mailman/listinfo/gtk-list