Using touch screen pressure data


Revision as of 18:14, 6 June 2008

Image:Ambox_content.png
This is an article from the old midgard wiki that hasn't yet been fully updated for this wiki, please update it.
Please see the talk page for discussion.


Sample Program:

/**
   This program demonstrates how to get pressure
   data to xlib application.

   Xsp extension provides 'rawmode' which is used
   when touchscreen is calibrated, in this mode
   it is possible to receive pressure information.
   This can be used as a workaround because we
   don't have Xi there (at least yet).
*/

#include <X11/X.h>
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/keysym.h>

#include <X11/extensions/Xsp.h>

#define uint unsigned int

Display *dpy;
Window win;
int screen;
int xres;
int yres;

/* device specific data */
#define DEV_X_DELTA 3378
#define DEV_Y_DELTA 3080
#define DEV_X_CORRECTION -300
#define DEV_Y_CORRECTION -454

/**
   translate raw device coordinates to screen coordinates
*/
#define TRANSLATE_RAW_COORDS(x, y) \
{ \
  * x += DEV_X_CORRECTION;\
  * y += DEV_Y_CORRECTION;\
  * x = xres - (xres * *x) / DEV_X_DELTA;\
  * y = yres - (yres * *y) / DEV_Y_DELTA;\
}

/**
   set foreground color of default gc
*/
static void
setcolor(uint r, uint g, uint b)
{
  XColor col;
  col.red   = r;
  col.green = g;
  col.blue  = b;
  XAllocColor(dpy,
              DefaultColormap (dpy, screen),
              &col);
  XSetForeground(dpy,
                 DefaultGC (dpy, screen),
                 col.pixel);
}

/**
   main program
*/
int
main (int argc, char *argv
{
  long key_pressed;

  XEvent event;
  XSPRawTouchscreenEvent xsp_event;

  int xsp_event_base=-1;
  int xsp_error_base=-1;
  int xsp_major=-1;
  int xsp_minor=-1;

  int t_x=0;
  int t_y=0;

  int circle_angle = 360*64;

  uint radius=0;
  uint done = 0;

  Atom atoms_WINDOW_STATE;
  Atom atoms_WINDOW_STATE_FULLSCREEN;

  /* open X display */
  dpy = XOpenDisplay(0);

  if (!dpy)
    goto exit;

  screen = DefaultScreen   (dpy);
  xres   = ScreenOfDisplay (dpy, DefaultScreen(dpy))->width;
  yres   = ScreenOfDisplay (dpy, DefaultScreen(dpy))->height;

  atoms_WINDOW_STATE
    = XInternAtom(dpy, "_NET_WM_STATE",False);
  atoms_WINDOW_STATE_FULLSCREEN
    = XInternAtom(dpy, "_NET_WM_STATE_FULLSCREEN",False);

  /* create the Window */
  win = XCreateSimpleWindow(dpy, RootWindow(dpy, screen), 0, 0,
                            xres, yres, 0,
                            BlackPixel(dpy, screen),
                            WhitePixel(dpy, screen));

  /* Set the wmhints needed for fullscreen */
  XChangeProperty(dpy, win, atoms_WINDOW_STATE, XA_ATOM, 32,
                  PropModeReplace,
                  (unsigned char *) &atoms_WINDOW_STATE_FULLSCREEN, 1);

  /* get xsp event base */
  XSPQueryExtension(dpy,
                    &xsp_event_base,
                    &xsp_error_base,
                    &xsp_major,
                    &xsp_minor);

  if (xsp_event_base < 0)
    goto exit;

  /* activate raw touchscreen data */
  XSPSetTSRawMode(dpy, True);

  XSelectInput(dpy, win, StructureNotifyMask | ExposureMask | KeyPressMask);
  XMapWindow(dpy, win);
  XClearWindow(dpy, win);

  XFlush(dpy);

  /* clean queue */
  XSync(dpy, True);

  setcolor(0, 0, 0);
  while (!done)
  {
    /* if there are events */
    if (XEventsQueued(dpy, QueuedAfterReading) > 0)
    {
      XNextEvent(dpy, &event);

      /* if it's xsp event */
      if (event.type == xsp_event_base)
        {
          memcpy(&xsp_event, &event,
                 sizeof(XSPRawTouchscreenEvent));

          t_x = xsp_event.x;
          t_y = xsp_event.y;

          /* translate raw coordinates */
          TRANSLATE_RAW_COORDS(&t_x, &t_y);

          /* draw filled circle in translated coords,
             using pressure for size */
          radius = xsp_event.pressure - 100;
          if (radius < 0)
            radius = 1;

          XFillArc(dpy,
                   win,
                   DefaultGC(dpy, screen),
                   t_x-radius,
                   t_y-radius,
                   radius+radius,
                   radius+radius,
                   0 ,
                   circle_angle);

          XFlush(dpy);
        }
      else
        {
          /* some other event */
          switch (event.type)
            {
            case KeyPress :
              done = 1;
              break;

            default :
              break;

            }
        }
    }
  }

  exit :

  /* set back normal event mode */
  XSPSetTSRawMode(dpy, False);

  XCloseDisplay(dpy);
  return 0;
}