GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Fri Oct 31, 2014 12:06 pm

All times are UTC




Post new topic Reply to topic  [ 3 posts ] 
Author Message
 Post subject: How to use gdk_device_get_history() ?
PostPosted: Fri Jul 13, 2012 12:40 pm 
Offline

Joined: Fri Jul 13, 2012 6:33 am
Posts: 2
I'm trying to code pressure-sensitive simple paint application with GTK3/GDK3.

I'm using gdk_device_get_history() to obtain positions and pressures of graphics tablets.

But this function returns "FALSE" in my environment so I can't obtain these inforamtion.

My environment is
OS: Ubuntu 12.10 Alpha2
GTK: libgtk-3-dev 3.5.6
Tablet: PTB-S1BK (Waltop Batteryless Tablet)
Driver: xserver-xorg-input-wacom 0.14.0
(GIMP 2.8 has been able to sense positions and pressures normally in my environment.)

Code:
#include <gtk/gtk.h>
#include <math.h>

static cairo_surface_t *gSurface = NULL;
static guint32 gStartTime;

static void close_window(void)
{
    if(gSurface) cairo_surface_destroy(gSurface);

    gtk_main_quit();
}

static void clear_surface(void)
{
    cairo_t *cr;

    cr = cairo_create(gSurface);

    cairo_set_source_rgb(cr, 1, 1, 1);
    cairo_paint(cr);

    cairo_destroy(cr);
}

static gboolean configure_event_cb(GtkWidget *widget, GdkEventConfigure *event, gpointer data)
{
    if(gSurface) cairo_surface_destroy(gSurface);

    gSurface = gdk_window_create_similar_surface(
                        gtk_widget_get_window(widget),
                        CAIRO_CONTENT_COLOR,
                        gtk_widget_get_allocated_width(widget),
                        gtk_widget_get_allocated_height(widget));

    clear_surface();

    return TRUE;
}

static gboolean draw_cb(GtkWidget *widget, cairo_t *cr, gpointer data)
{
    cairo_set_source_surface(cr, gSurface, 0, 0);
    cairo_paint(cr);

    return FALSE;
}

static void draw_brush(GtkWidget *widget, gdouble x, gdouble y, gdouble pressure)
{
    cairo_t *cr;
    double r = 10.0 * pressure;
    double d =  2.0 * r;

    cr = cairo_create(gSurface);

    cairo_arc(cr, x, y, r, 0.0, 2.0 * M_PI);
    cairo_fill(cr);

    cairo_destroy(cr);

    gtk_widget_queue_draw_area(widget, x - r, y - r, d, d);
}

static gboolean button_press_event_cb(GtkWidget *widget, GdkEventButton *event, gpointer data)
{
    if(gSurface == NULL) return FALSE;

    if(event->button == 1)
    {
        gdouble pressure = 0.5;
        gdk_event_get_axis((GdkEvent*)event, GDK_AXIS_PRESSURE, &pressure);
        draw_brush(widget, event->x, event->y, pressure);
        gStartTime = event->time;
    }
    else if(event->button == 3)
    {
        clear_surface();
        gtk_widget_queue_draw(widget);
    }

    return TRUE;
}

static gboolean motion_notify_event_cb(GtkWidget *widget, GdkEventMotion *event, gpointer data)
{
    GdkTimeCoord **events;
    int i, n_events;

    if(gSurface == NULL) return FALSE;

    if(event->state & GDK_BUTTON1_MASK)
    {
        if(gdk_device_get_history(event->device, event->window, gStartTime, event->time, &events, &n_events))
        {
            for(i = 0; i < n_events; i++)
            {
                double x = 0.0, y = 0.0, pressure = 0.5;

                gdk_device_get_axis(event->device, events[i]->axes, GDK_AXIS_X, &x);
                gdk_device_get_axis(event->device, events[i]->axes, GDK_AXIS_Y, &y);
                gdk_device_get_axis(event->device, events[i]->axes, GDK_AXIS_PRESSURE, &pressure);

                draw_brush(widget, x, y, pressure);
            }
            gdk_device_free_history(events, n_events);
        }
        gStartTime = event->time;
    }

    return TRUE;
}

int main(int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *canvus;
   
    gtk_init(&argc, &argv);
   
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    canvus = gtk_drawing_area_new();
    gtk_widget_set_size_request(canvus, 320, 320);
    gtk_container_add(GTK_CONTAINER(window), canvus);

    g_signal_connect(window, "destroy",             G_CALLBACK(close_window),           NULL);
    g_signal_connect(canvus, "draw",                G_CALLBACK(draw_cb),                NULL);
    g_signal_connect(canvus, "configure-event",     G_CALLBACK(configure_event_cb),     NULL);
    g_signal_connect(canvus, "motion-notify-event", G_CALLBACK(motion_notify_event_cb), NULL);
    g_signal_connect(canvus, "button-press-event",  G_CALLBACK(button_press_event_cb),  NULL);

    gtk_widget_add_events(canvus, GDK_BUTTON_PRESS_MASK | GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK);

    gtk_widget_show_all(window);

    gtk_main();

    return 0;
}


In button_press_event_cb(), event->x, event->y and gdk_event_get_axis() has performed correctly.

But gdk_device_get_history() hasn't.

Where did I go wrong? Help me, Please.


Top
 Profile  
 
 Post subject: Re: How to use gdk_device_get_history() ?
PostPosted: Fri Jul 13, 2012 3:47 pm 
Offline
GTK+ Guru

Joined: Fri Mar 25, 2011 5:16 pm
Posts: 177
Location: USA
I see you're using the unstable version of GTK. That along with Ubuntu Alpha2 and xorg make that a pretty specialised environment your using there. But I did find this in gimpdisplayshell-tool-events.c (apps folder line 855) I hope it helps.

Quote:
/* gdk_device_get_history() has several quirks. First
* is that events with borderline timestamps at both
* ends are included. Because of that we need to add 1
* to lower border. The second is due to poor X event
* resolution. We need to do -1 to ensure that the
* amount of events between timestamps is final or
* risk loosing some.
*/

And just below that:
Code:
                if (motion_mode == GIMP_MOTION_MODE_EXACT     &&
                    shell->display->config->use_event_history &&
                    gdk_device_get_history (mevent->device, mevent->window,
                                            last_motion_time + 1,
                                            mevent->time - 1,
                                            &history_events,
                                            &n_history_events))


Top
 Profile  
 
 Post subject: Re: How to use gdk_device_get_history() ?
PostPosted: Sat Jul 14, 2012 2:27 am 
Offline

Joined: Fri Jul 13, 2012 6:33 am
Posts: 2
Thanks for your reply.

I have modified the arguments of gdk_device_get_history() as follows.

Code:
if(gdk_device_get_history(event->device,
                          event->window,
                          gStartTime + 1,
                          event->time - 1,
                          &events,
                          &n_events))
{
    ...
}


But gdk_device_get_history() returns "FALSE".

I've tried on Ubuntu 12.04 with libgtk3-3.4.2 too, yet the result was the same.

I'll analyze GIMP or MyPaint source code.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 3 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group