support external mouse through X events
authornotaz <notasas@gmail.com>
Mon, 12 Mar 2012 22:40:44 +0000 (00:40 +0200)
committernotaz <notasas@gmail.com>
Mon, 12 Mar 2012 22:40:44 +0000 (00:40 +0200)
README.OMAP
src/video/omapdss/config.c
src/video/omapdss/linux/xenv.c
src/video/omapdss/linux/xenv.h
src/video/omapdss/osdl.h
src/video/omapdss/osdl_video.c
src/video/omapdss/sdlif.c

index 29cbac2..ad662a3 100644 (file)
@@ -77,6 +77,10 @@ SDL_OMAP_NO_TS_TRANSLATE:
   Disable automatic touchscreen screen -> layer coordinate translation,
   return real screen coordinates.
 
+SDL_OMAP_TS_FORCE_TSLIB:
+  Always use tslib to read touchscreen. Without this, use X events when they
+  are available (this gives external input device support).
+
 
 Config file
 -----------
@@ -94,6 +98,9 @@ force_doublebuf = 1/0
 # same as SDL_OMAP_NO_TS_TRANSLATE
 no_ts_translate = 1/0
 
+# same as SDL_OMAP_TS_FORCE_TSLIB
+ts_force_tslib = 1/0
+
 # can be used to bind a key to SDL keysym, good for quick ports.
 # Example:
 # bind ev_home = sdlk_space
index 5d5fb7b..0b7146a 100644 (file)
@@ -95,6 +95,10 @@ void omapsdl_config(struct SDL_PrivateVideoData *pdata)
                        pdata->cfg_no_ts_translate = !!strtol(p, NULL, 0);
                        continue;
                }
+               else if (check_token_eq(&p, "ts_force_tslib")) {
+                       pdata->cfg_ts_force_tslib = !!strtol(p, NULL, 0);
+                       continue;
+               }
 
 bad:
                err("config: failed to parse: %s", line);
@@ -115,6 +119,9 @@ void omapsdl_config_from_env(struct SDL_PrivateVideoData *pdata)
        tmp = getenv("SDL_OMAP_NO_TS_TRANSLATE");
        if (tmp != NULL)
                pdata->cfg_no_ts_translate = !!strtol(tmp, NULL, 0);
+       tmp = getenv("SDL_OMAP_TS_FORCE_TSLIB");
+       if (tmp != NULL)
+               pdata->cfg_ts_force_tslib = !!strtol(tmp, NULL, 0);
        tmp = getenv("SDL_OMAP_BORDER_CUT");
        if (tmp != NULL) {
                int l, r, t, b;
index 3de7628..c2cd603 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * (C) Gražvydas "notaz" Ignotas, 2009-2011
+ * (C) Gražvydas "notaz" Ignotas, 2009-2012
  *
  * This work is licensed under the terms of any of these licenses
  * (at your option):
@@ -142,7 +142,8 @@ static int x11h_init(void)
        attributes.cursor = transparent_cursor(&g_xstuff, display, win);
        g_xstuff.pXChangeWindowAttributes(display, win, CWOverrideRedirect | CWCursor, &attributes);
 
-       g_xstuff.pXSelectInput(display, win, ExposureMask | FocusChangeMask | KeyPressMask | KeyReleaseMask);
+       g_xstuff.pXSelectInput(display, win, ExposureMask | FocusChangeMask | KeyPressMask
+               | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask | PointerMotionMask);
        g_xstuff.pXMapWindow(display, win);
        g_xstuff.pXGrabKeyboard(display, win, False, GrabModeAsync, GrabModeAsync, CurrentTime);
        g_xstuff.pXkbSetDetectableAutoRepeat(display, 1, NULL);
@@ -157,32 +158,54 @@ fail:
        return -1;
 }
 
-static int x11h_update(int *is_down)
+static void x11h_update(int (*key_cb)(void *cb_arg, int kc, int is_pressed),
+                       int (*mouseb_cb)(void *cb_arg, int x, int y, int button, int is_pressed),
+                       int (*mousem_cb)(void *cb_arg, int x, int y),
+                       void *cb_arg)
 {
        XEvent evt;
+       int keysym;
 
        while (g_xstuff.pXPending(g_xstuff.display))
        {
                g_xstuff.pXNextEvent(g_xstuff.display, &evt);
                switch (evt.type)
                {
-                       case Expose:
-                               while (g_xstuff.pXCheckTypedEvent(g_xstuff.display, Expose, &evt))
-                                       ;
-                               break;
-
-                       case KeyPress:
-                               *is_down = 1;
-                               return g_xstuff.pXLookupKeysym(&evt.xkey, 0);
-
-                       case KeyRelease:
-                               *is_down = 0;
-                               return g_xstuff.pXLookupKeysym(&evt.xkey, 0);
-                               // printf("press %d\n", evt.xkey.keycode);
+               case Expose:
+                       while (g_xstuff.pXCheckTypedEvent(g_xstuff.display, Expose, &evt))
+                               ;
+                       break;
+
+               case KeyPress:
+                       keysym = g_xstuff.pXLookupKeysym(&evt.xkey, 0);
+                       if (key_cb != NULL)
+                               key_cb(cb_arg, keysym, 1);
+                       break;
+
+               case KeyRelease:
+                       keysym = g_xstuff.pXLookupKeysym(&evt.xkey, 0);
+                       if (key_cb != NULL)
+                               key_cb(cb_arg, keysym, 0);
+                       break;
+
+               case ButtonPress:
+                       if (mouseb_cb != NULL)
+                               mouseb_cb(cb_arg, evt.xbutton.x, evt.xbutton.y,
+                                         evt.xbutton.button, 1);
+                       break;
+
+               case ButtonRelease:
+                       if (mouseb_cb != NULL)
+                               mouseb_cb(cb_arg, evt.xbutton.x, evt.xbutton.y,
+                                         evt.xbutton.button, 0);
+                       break;
+
+               case MotionNotify:
+                       if (mousem_cb != NULL)
+                               mousem_cb(cb_arg, evt.xmotion.x, evt.xmotion.y);
+                       break;
                }
        }
-
-       return NoSymbol;
 }
 
 static struct termios g_kbd_termios_saved;
@@ -249,26 +272,38 @@ static void tty_end(void)
        g_kbdfd = -1;
 }
 
-int xenv_init(void)
+int xenv_init(int *have_mouse_events)
 {
+       int have_mouse = 0;
        int ret;
 
        ret = x11h_init();
-       if (ret == 0)
-               return 0;
+       if (ret == 0) {
+               have_mouse = 1;
+               goto out;
+       }
 
        ret = tty_init();
        if (ret == 0)
-               return 0;
+               goto out;
 
        fprintf(stderr, PFX "error: both x11h_init and tty_init failed\n");
-       return -1;
+       ret = -1;
+out:
+       if (have_mouse_events != NULL)
+               *have_mouse_events = have_mouse;
+       return ret;
 }
 
-int xenv_update(int *is_down)
+int xenv_update(int (*key_cb)(void *cb_arg, int kc, int is_pressed),
+               int (*mouseb_cb)(void *cb_arg, int x, int y, int button, int is_pressed),
+               int (*mousem_cb)(void *cb_arg, int x, int y),
+               void *cb_arg)
 {
-       if (g_xstuff.display)
-               return x11h_update(is_down);
+       if (g_xstuff.display) {
+               x11h_update(key_cb, mouseb_cb, mousem_cb, cb_arg);
+               return 0;
+       }
 
        // TODO: read tty?
        return -1;
index 948381e..4c5281c 100644 (file)
@@ -1,5 +1,12 @@
 
-int  xenv_init(void);
-int  xenv_update(int *is_down);
+int  xenv_init(int *have_mouse_events);
+
+/* read events from X, calling key_cb for key, mouseb_cb for mouse button
+ * and mousem_cb for mouse motion events */
+int  xenv_update(int (*key_cb)(void *cb_arg, int kc, int is_pressed),
+                int (*mouseb_cb)(void *cb_arg, int x, int y, int button, int is_pressed),
+                int (*mousem_cb)(void *cb_arg, int x, int y),
+                void *cb_arg);
+
 void xenv_finish(void);
 
index 12a6f6e..ea5bce2 100644 (file)
@@ -38,10 +38,12 @@ struct SDL_PrivateVideoData {
        int ts_xmul, ts_ymul;
        /* misc/config */
        unsigned int xenv_up:1;
+       unsigned int xenv_mouse:1;
        unsigned int app_uses_flip:1;
        unsigned int cfg_force_vsync:1;
        unsigned int cfg_force_doublebuf:1;
        unsigned int cfg_no_ts_translate:1;
+       unsigned int cfg_ts_force_tslib:1;
 };
 
 void *osdl_video_set_mode(struct SDL_PrivateVideoData *pdata,
index e1b9d5c..9379cab 100644 (file)
@@ -373,9 +373,12 @@ void *osdl_video_set_mode(struct SDL_PrivateVideoData *pdata,
                goto fail;
 
        if (!pdata->xenv_up) {
-               ret = xenv_init();
-               if (ret == 0)
+               int xenv_mouse = 0;
+               ret = xenv_init(&xenv_mouse);
+               if (ret == 0) {
                        pdata->xenv_up = 1;
+                       pdata->xenv_mouse = xenv_mouse;
+               }
        }
 
        if (buffers_try != buffers_set) {
index f7a6d28..7511ee4 100644 (file)
@@ -246,41 +246,74 @@ static int key_event_cb(void *cb_arg, int sdl_kc, int is_pressed)
        if (x < (min)) x = min; \
        if (x >= (max)) x = max
 
-static int ts_event_cb(void *cb_arg, int x, int y, unsigned int pressure)
+static void translate_mouse(SDL_VideoDevice *this, int *x, int *y)
 {
-       static int was_pressed;
-       SDL_VideoDevice *this = cb_arg;
        struct SDL_PrivateVideoData *pdata = this->hidden;
-       int xoffs;
 
        if (!pdata->cfg_no_ts_translate && pdata->layer_w != 0 && pdata->layer_h != 0) {
-               x = pdata->border_l + ((x - pdata->layer_x) * pdata->ts_xmul >> 16);
-               y = pdata->border_t + ((y - pdata->layer_y) * pdata->ts_ymul >> 16);
-               clamp(x, 0, this->screen->w);
-               clamp(y, 0, this->screen->h);
+               *x = pdata->border_l + ((*x - pdata->layer_x) * pdata->ts_xmul >> 16);
+               *y = pdata->border_t + ((*y - pdata->layer_y) * pdata->ts_ymul >> 16);
+               clamp(*x, 0, this->screen->w);
+               clamp(*y, 0, this->screen->h);
        }
+}
 
-       SDL_PrivateMouseMotion(0, 0, x, y);
+static int ts_event_cb(void *cb_arg, int x, int y, unsigned int pressure)
+{
+       static int was_pressed;
+       SDL_VideoDevice *this = cb_arg;
+       struct SDL_PrivateVideoData *pdata = this->hidden;
+
+       translate_mouse(this, &x, &y);
 
        pressure = !!pressure;
        if (pressure != was_pressed) {
-               SDL_PrivateMouseButton(pressure ? SDL_PRESSED : SDL_RELEASED, 1, 0, 0);
+               SDL_PrivateMouseButton(pressure ? SDL_PRESSED : SDL_RELEASED, 1, x, y);
                was_pressed = pressure;
        }
+       else
+               SDL_PrivateMouseMotion(0, 0, x, y);
+}
+
+static int mouseb_event_cb(void *cb_arg, int x, int y, int button, int is_pressed)
+{
+       SDL_VideoDevice *this = cb_arg;
+       struct SDL_PrivateVideoData *pdata = this->hidden;
+
+       translate_mouse(this, &x, &y);
+       SDL_PrivateMouseButton(is_pressed ? SDL_PRESSED : SDL_RELEASED, button, x, y);
+}
+
+static int mousem_event_cb(void *cb_arg, int x, int y)
+{
+       SDL_VideoDevice *this = cb_arg;
+       struct SDL_PrivateVideoData *pdata = this->hidden;
+
+       translate_mouse(this, &x, &y);
+       SDL_PrivateMouseMotion(0, 0, x, y);
 }
 
 static void omap_PumpEvents(SDL_VideoDevice *this) 
 {
        struct SDL_PrivateVideoData *pdata = this->hidden;
-       int dummy;
+       int read_tslib = 1;
 
        trace();
 
-       omapsdl_input_get_events(0, key_event_cb, ts_event_cb, this);
+       if (pdata->xenv_up) {
+               if (!pdata->cfg_ts_force_tslib) {
+                       xenv_update(NULL, mouseb_event_cb, mousem_event_cb, this);
+                       if (pdata->xenv_mouse)
+                               read_tslib = 0;
+               }
+               else {
+                       /* just flush X event queue */
+                       xenv_update(NULL, NULL, NULL, NULL);
+               }
+       }
 
-       // XXX: we might want to process some X events too
-       if (pdata->xenv_up)
-               xenv_update(&dummy);
+       omapsdl_input_get_events(0, key_event_cb,
+               read_tslib ? ts_event_cb : NULL, this);
 }
 
 static SDL_VideoDevice *omap_create(int devindex)