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 <[email protected]>
> 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
> [email protected]
> http://mail.gnome.org/mailman/listinfo/gtk-list
>
_______________________________________________
gtk-list mailing list
[email protected]
http://mail.gnome.org/mailman/listinfo/gtk-list