Thank you Richard, the code you wrote works for me and it gave me ideas on how to re-structure mine. 2011/7/23 richard boaz <ivor.boaz@xxxxxxxxx>: > hi, > the problem isn't the mouse going "too fast" (this is "not possible", if it > can go fast, it can), it's that you're wanting to draw a line using points. > drawing a real line between the last point received by the drag event and > the new/next point will get you what you want, example code below. > and to answer your question, yes it can be made more efficient. > cheers, > richard > p.s. be careful re: your callback parameters, your drag function defined the > 2nd argument wrong. > ======== BEGIN CODE EXAMPLE ======== > #include <string.h> > #include <gtk/gtk.h> > enum { > MOUSE_CLICK, > MOUSE_DRAG, > TTL_MOUSE_EVENTS > }; > static inline void brush(cairo_t *cr, double x1, double y1, double x2, > double y2) > { > cairo_move_to(cr, x1, y1); > cairo_line_to(cr, x2, y2); > cairo_stroke(cr); > } > static gboolean handle_mouse(GtkWidget *widget, void *e, gpointer *t) > { > static struct { > gboolean isdragging; > cairo_t *cr; > double x, y; > } mouseState; > gint type = GPOINTER_TO_INT(t); > switch(type) > { > case MOUSE_CLICK: > { > GdkEventButton *event = (GdkEventButton*) e; > switch(event->type) > { > case GDK_BUTTON_PRESS: > { > mouseState.isdragging = TRUE; > mouseState.cr = gdk_cairo_create(widget->window); > cairo_set_source_rgb(mouseState.cr, 0, 0, 0); > cairo_set_line_width(mouseState.cr, 2); > mouseState.x = event->x; mouseState.y = event->y; > } > break; > case GDK_BUTTON_RELEASE: > { > cairo_destroy(mouseState.cr); > memset(&mouseState, 0, sizeof(mouseState)); > } > break; > default: > break; > } > } > break; > case MOUSE_DRAG: > { > GdkEventMotion *event = (GdkEventMotion*) e; > static GdkWindow *gdkWindow; > if (!gdkWindow) > { // initialize > gdkWindow = gdk_get_default_root_window(); > memset(&mouseState, 0, sizeof(mouseState)); > return TRUE; > } > if (!mouseState.isdragging || > (mouseState.x == event->x && mouseState.y == event->y)) > return TRUE; > brush(mouseState.cr, mouseState.x, mouseState.y, event->x, event->y); > mouseState.x = event->x; mouseState.y = event->y; > { > // even though we don't use the resulting information from this call, > // calling it is an indication to the main_loop() > // that we are ready to receive the next mouse motion notify event > gint x, y; > GdkModifierType state; > gdk_window_get_pointer(gdkWindow, &x, &y, &state); > } > } > break; > default: > break; > } > return TRUE; > } > int main( int argc, > char *argv[] ) > { > GtkWidget *window; > GtkWidget *main_vbox; > gtk_init (&argc, &argv); > > window = gtk_window_new(GTK_WINDOW_TOPLEVEL); > gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC > (gtk_main_quit), "WM destroy"); > gtk_widget_set_usize (GTK_WIDGET(window), 300, 200); > > main_vbox = gtk_vbox_new (FALSE, 1); > gtk_container_border_width (GTK_CONTAINER (main_vbox), 1); > gtk_container_add (GTK_CONTAINER (window), main_vbox); > gtk_widget_show (main_vbox); > > //gtkdrawable + cairo > GtkWidget *canvas = gtk_drawing_area_new(); > gtk_widget_set_size_request (canvas, 500, 600); > > //gtk_widget_add_events(canvas, GDK_BUTTON_PRESS_MASK); > gtk_widget_add_events(canvas, GDK_ALL_EVENTS_MASK); > g_signal_connect(canvas, "button-press-event", G_CALLBACK(handle_mouse), > GINT_TO_POINTER(MOUSE_CLICK)); > g_signal_connect(canvas, "button-release-event", G_CALLBACK(handle_mouse), > GINT_TO_POINTER(MOUSE_CLICK)); > g_signal_connect(canvas, "motion-notify-event",G_CALLBACK(handle_mouse), > GINT_TO_POINTER(MOUSE_DRAG)); > gtk_box_pack_start (GTK_BOX (main_vbox), canvas, FALSE, TRUE, 0); > > //ends gtkdrawable + cairo example > gtk_widget_show_all (window); > gtk_main (); > > return(0); > } > ======== END CODE EXAMPLE ======== > 2011/7/23 Carlos López Camey <c.lopez@xxxxxxxxx> >> >> Hello, I'm new to the list, GTK+ and C. I'm building a Paint-like >> application and was trying how to simulate the Brush tool with an >> example to see how it performs. I read about GtkImage, GtkBitmap and >> GtkPixmap but was recommended in #gtk+ over at irc.gnome.org to use a >> GtkDrawingArea + Cairo since in GTK3 some of these were deprecated, >> and it's encouraged to use cairo surfaces instead. >> >> The problem with my example is, when you click and "brush" with the >> mouse moving *too fast*, the signal doesn't come fast enough. What >> could/would be faster? using pixbufs + GtkImage? I couldn't find >> enough documentation about that, but that's why I am asking :) >> >> Here's what I got (or if you prefer http://paste.pocoo.org/show/444721/) >> >> Thank you! >> >> ----- canvas-test.c ------ >> #include <gtk/gtk.h> >> >> int isdragging = 0; >> >> /* Brush, paints a single pixel in coordinate x,y*/ >> void brush(cairo_t *cr, double x, double y){ >> cairo_set_source_rgb(cr, 0, 0, 0); >> cairo_set_line_width (cr, 1); >> cairo_rectangle(cr,x,y,1,1); >> cairo_stroke(cr); >> cairo_destroy(cr); >> } >> >> gboolean handle_mouse_click(GtkWidget *widget, GdkEventButton *event, >> gpointer user_data){ >> brush(gdk_cairo_create(widget->window), event->x, event->y); >> isdragging = 1; >> return TRUE; >> } >> >> gboolean handle_mouse_release(GtkWidget *widget, GdkEventButton >> *event, gpointer user_data){ >> if (event->button == 1) { >> isdragging = 0; >> } >> >> return TRUE; >> } >> >> gboolean handle_mouse_drag(GtkWidget *widget, GdkEventButton *event, >> gpointer user_data){ >> if (isdragging) >> brush(gdk_cairo_create(widget->window), event->x, event->y); >> return TRUE; >> } >> >> int main( int argc, >> char *argv[] ) >> { >> GtkWidget *window; >> GtkWidget *main_vbox; >> >> gtk_init (&argc, &argv); >> >> window = gtk_window_new (GTK_WINDOW_TOPLEVEL); >> gtk_signal_connect (GTK_OBJECT (window), "destroy", GTK_SIGNAL_FUNC >> (gtk_main_quit), "WM destroy"); >> gtk_widget_set_usize (GTK_WIDGET(window), 300, 200); >> >> main_vbox = gtk_vbox_new (FALSE, 1); >> gtk_container_border_width (GTK_CONTAINER (main_vbox), 1); >> gtk_container_add (GTK_CONTAINER (window), main_vbox); >> gtk_widget_show (main_vbox); >> >> //gtkdrawable + cairo >> GtkWidget *canvas = gtk_drawing_area_new(); >> gtk_widget_set_size_request (canvas, 500, 600); >> >> //gtk_widget_add_events(canvas, GDK_BUTTON_PRESS_MASK); >> gtk_widget_add_events(canvas, GDK_ALL_EVENTS_MASK); >> g_signal_connect(canvas, "button-press-event", >> G_CALLBACK(handle_mouse_click), NULL); >> g_signal_connect(canvas, "button-release-event", >> G_CALLBACK(handle_mouse_release), NULL); >> g_signal_connect(canvas, >> "motion-notify-event",G_CALLBACK(handle_mouse_drag), NULL); >> >> gtk_box_pack_start (GTK_BOX (main_vbox), canvas, FALSE, TRUE, 0); >> >> //ends gtkdrawable + cairo example >> gtk_widget_show_all (window); >> gtk_main (); >> >> return(0); >> } >> _______________________________________________ >> gtk-list mailing list >> gtk-list@xxxxxxxxx >> http://mail.gnome.org/mailman/listinfo/gtk-list > > _______________________________________________ gtk-list mailing list gtk-list@xxxxxxxxx http://mail.gnome.org/mailman/listinfo/gtk-list