From e1837b2c78d48d2811ff77e8702810b7620dd4f8 Mon Sep 17 00:00:00 2001 From: notaz Date: Tue, 13 Mar 2012 00:40:44 +0200 Subject: [PATCH] support external mouse through X events --- README.OMAP | 7 +++ src/video/omapdss/config.c | 7 +++ src/video/omapdss/linux/xenv.c | 87 ++++++++++++++++++++++++---------- src/video/omapdss/linux/xenv.h | 11 ++++- src/video/omapdss/osdl.h | 2 + src/video/omapdss/osdl_video.c | 7 ++- src/video/omapdss/sdlif.c | 63 ++++++++++++++++++------ 7 files changed, 139 insertions(+), 45 deletions(-) diff --git a/README.OMAP b/README.OMAP index 29cbac2..ad662a3 100644 --- a/README.OMAP +++ b/README.OMAP @@ -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 diff --git a/src/video/omapdss/config.c b/src/video/omapdss/config.c index 5d5fb7b..0b7146a 100644 --- a/src/video/omapdss/config.c +++ b/src/video/omapdss/config.c @@ -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; diff --git a/src/video/omapdss/linux/xenv.c b/src/video/omapdss/linux/xenv.c index 3de7628..c2cd603 100644 --- a/src/video/omapdss/linux/xenv.c +++ b/src/video/omapdss/linux/xenv.c @@ -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; diff --git a/src/video/omapdss/linux/xenv.h b/src/video/omapdss/linux/xenv.h index 948381e..4c5281c 100644 --- a/src/video/omapdss/linux/xenv.h +++ b/src/video/omapdss/linux/xenv.h @@ -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); diff --git a/src/video/omapdss/osdl.h b/src/video/omapdss/osdl.h index 12a6f6e..ea5bce2 100644 --- a/src/video/omapdss/osdl.h +++ b/src/video/omapdss/osdl.h @@ -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, diff --git a/src/video/omapdss/osdl_video.c b/src/video/omapdss/osdl_video.c index e1b9d5c..9379cab 100644 --- a/src/video/omapdss/osdl_video.c +++ b/src/video/omapdss/osdl_video.c @@ -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) { diff --git a/src/video/omapdss/sdlif.c b/src/video/omapdss/sdlif.c index f7a6d28..7511ee4 100644 --- a/src/video/omapdss/sdlif.c +++ b/src/video/omapdss/sdlif.c @@ -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) -- 2.39.2