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

Reply via email to