From dcd8a5fd97447ccedabbddcae9d40f8c9fb5a90e Mon Sep 17 00:00:00 2001 From: Jim Grandpre Date: Thu, 27 May 2010 01:21:37 -0400 Subject: [PATCH] Added touch event definitions. Heavily modified events/SDL_touch*. --- include/SDL_events.h | 41 ++++ src/events/SDL_touch.c | 452 +++++++++++++++------------------------ src/events/SDL_touch_c.h | 89 ++++---- touchTest/touchPong | Bin 28731 -> 29171 bytes touchTest/touchSimp | Bin 28772 -> 28976 bytes 5 files changed, 252 insertions(+), 330 deletions(-) diff --git a/include/SDL_events.h b/include/SDL_events.h index fbdc46c94..87096d1d6 100644 --- a/include/SDL_events.h +++ b/include/SDL_events.h @@ -86,11 +86,19 @@ typedef enum SDL_JOYBUTTONDOWN, /**< Joystick button pressed */ SDL_JOYBUTTONUP, /**< Joystick button released */ + /*Touch events - is 0x700 the correct place?*/ + SDL_FINGERDOWN = 0x700, + SDL_FINGERUP, + SDL_FINGERMOTION, + SDL_TOUCHBUTTONDOWN, + SDL_TOUCHBUTTONUP, + /* Obsolete events */ SDL_EVENT_COMPAT1 = 0x7000, /**< SDL 1.2 events for compatibility */ SDL_EVENT_COMPAT2, SDL_EVENT_COMPAT3, + /** Events ::SDL_USEREVENT through ::SDL_LASTEVENT are for your use, * and should be allocated with SDL_RegisterEvents() */ @@ -289,6 +297,37 @@ typedef struct SDL_JoyButtonEvent Uint8 padding1; } SDL_JoyButtonEvent; + +/** + * \brief Touch finger motion/finger event structure (event.tmotion.*) + */ +typedef struct SDL_TouchFingerEvent +{ + Uint32 type; /**< ::SDL_FINGERMOTION OR + SDL_FINGERDOWN OR SDL_FINGERUP*/ + Uint32 windowID; /**< The window with mouse focus, if any */ + Uint8 touchId; /**< The touch device id */ + Uint8 state; /**< The current button state */ + Uint8 fingerId; + Uint8 padding1; +} SDL_TouchFingerEvent; + + +/** + * \brief Touch finger motion/finger event structure (event.tmotion.*) + */ +typedef struct SDL_TouchButtonEvent +{ + Uint32 type; /**< ::SDL_TOUCHBUTTONUP OR SDL_TOUCHBUTTONDOWN */ + Uint32 windowID; /**< The window with mouse focus, if any */ + Uint8 touchId; /**< The touch device index */ + Uint8 state; /**< The current button state */ + Uint8 button; /**< The button changing state */ + Uint8 padding1; + +} SDL_TouchButtonEvent; + + /** * \brief The "quit requested" event */ @@ -372,6 +411,8 @@ typedef union SDL_Event SDL_UserEvent user; /**< Custom event data */ SDL_SysWMEvent syswm; /**< System dependent window event data */ SDL_ProximityEvent proximity; /**< Proximity In or Out event */ + SDL_TouchFingerEvent tfinger; /**< Touch finger event data */ + SDL_TouchButtonEvent tbutton; /**< Touch button event data */ /** Temporarily here for backwards compatibility */ /*@{*/ diff --git a/src/events/SDL_touch.c b/src/events/SDL_touch.c index 0700abc01..88505daec 100644 --- a/src/events/SDL_touch.c +++ b/src/events/SDL_touch.c @@ -29,8 +29,7 @@ static int SDL_num_touch = 0; -static int SDL_current_touch = -1; -static SDL_Touch **SDL_touch = NULL; +static SDL_Touch **SDL_touchPads = NULL; /* Public functions */ @@ -39,24 +38,43 @@ SDL_TouchInit(void) { return (0); } - SDL_Touch * -SDL_GetTouch(int index) +SDL_GetTouch(int id) { + int index = SDL_GetTouchIndexId(id); if (index < 0 || index >= SDL_num_touch) { return NULL; } - return SDL_touch[index]; + return SDL_touchPads[index]; +} + +SDL_Finger * +SDL_GetFinger(SDL_Touch* touch,int id) +{ + int index = SDL_GetFingerIndexId(touch,id); + if(index < 0 || index >= touch->num_fingers) + return NULL; + return touch->fingers[index]; +} + +int +SDL_GetFingerIndexId(SDL_Touch* touch,int fingerid) +{ + int i; + for(i = 0;i < touch->num_fingers;i++) + if(touch->fingers[i]->id == fingerid) + return i; + return -1; } -static int +int SDL_GetTouchIndexId(int id) { int index; SDL_Touch *touch; for (index = 0; index < SDL_num_touch; ++index) { - touch = SDL_GetTouch(index); + touch = SDL_touchPads[index]; if (touch->id == id) { return index; } @@ -68,7 +86,7 @@ int SDL_AddTouch(const SDL_Touch * touch, char *name, int pressure_max, int pressure_min, int ends) { - SDL_Touch **touch; + SDL_Touch **touchPads; int selected_touch; int index; size_t length; @@ -78,58 +96,47 @@ SDL_AddTouch(const SDL_Touch * touch, char *name, int pressure_max, } /* Add the touch to the list of touch */ - touch = (SDL_Touch **) SDL_realloc(SDL_touch, + touchPads = (SDL_Touch **) SDL_realloc(SDL_touchPads, (SDL_num_touch + 1) * sizeof(*touch)); - if (!touch) { + if (!touchPads) { SDL_OutOfMemory(); return -1; } - SDL_touch = touch; + SDL_touchPads = touchPads; index = SDL_num_touch++; - SDL_touch[index] = (SDL_Touch *) SDL_malloc(sizeof(*SDL_touch[index])); - if (!SDL_touch[index]) { + SDL_touchPads[index] = (SDL_Touch *) SDL_malloc(sizeof(*SDL_touchPads[index])); + if (!SDL_touchPads[index]) { SDL_OutOfMemory(); return -1; } - *SDL_touch[index] = *touch; + *SDL_touchPads[index] = *touch; /* we're setting the touch properties */ length = 0; length = SDL_strlen(name); - SDL_touch[index]->focus = 0; - SDL_touch[index]->name = SDL_malloc((length + 2) * sizeof(char)); - SDL_strlcpy(SDL_touch[index]->name, name, length + 1); - SDL_touch[index]->pressure_max = pressure_max; - SDL_touch[index]->pressure_min = pressure_min; - SDL_touch[index]->cursor_shown = SDL_TRUE; - selected_touch = SDL_SelectTouch(index); - SDL_touch[index]->cur_cursor = NULL; - SDL_touch[index]->def_cursor = - /* we're assuming that all touch are in the computer sensing zone */ - SDL_touch[index]->proximity = SDL_TRUE; - /* we're assuming that all touch are working in the absolute position mode - thanx to that, the users that don't want to use many touch don't have to - worry about anything */ - SDL_touch[index]->relative_mode = SDL_FALSE; - SDL_touch[index]->current_end = 0; - SDL_touch[index]->total_ends = ends; - SDL_SelectTouch(selected_touch); + SDL_touchPads[index]->focus = 0; + SDL_touchPads[index]->name = SDL_malloc((length + 2) * sizeof(char)); + SDL_strlcpy(SDL_touchPads[index]->name, name, length + 1); + SDL_touchPads[index]->pressure_max = pressure_max; + SDL_touchPads[index]->pressure_min = pressure_min; + return index; } void -SDL_DelTouch(int index) +SDL_DelTouch(int id) { - SDL_Touch *touch = SDL_GetTouch(index); + int index = SDL_GetTouchIndexId(id); + SDL_Touch *touch = SDL_GetTouch(id); if (!touch) { return; } - touch->def_cursor = NULL; + SDL_free(touch->name); if (touch->FreeTouch) { @@ -137,19 +144,8 @@ SDL_DelTouch(int index) } SDL_free(touch); - SDL_touch[index] = NULL; -} - -void -SDL_ResetTouch(int index) -{ - SDL_Touch *touch = SDL_GetTouch(index); - - if (!touch) { - return; - } - - /* FIXME */ + SDL_num_touch--; + SDL_touchPads[index] = SDL_touchPads[SDL_num_touch]; } void @@ -157,15 +153,14 @@ SDL_TouchQuit(void) { int i; - for (i = 0; i < SDL_num_touch; ++i) { + for (i = SDL_num_touch-1; i > 0 ; --i) { SDL_DelTouch(i); } SDL_num_touch = 0; - SDL_current_touch = -1; - if (SDL_touch) { - SDL_free(SDL_touch); - SDL_touch = NULL; + if (SDL_touchPads) { + SDL_free(SDL_touchPads); + SDL_touchPads = NULL; } } @@ -174,20 +169,10 @@ SDL_GetNumTouch(void) { return SDL_num_touch; } - -int -SDL_SelectTouch(int index) -{ - if (index >= 0 && index < SDL_num_touch) { - SDL_current_touch = index; - } - return SDL_current_touch; -} - SDL_Window * -SDL_GetTouchFocusWindow(int index) +SDL_GetTouchFocusWindow(int id) { - SDL_Touch *touch = SDL_GetTouch(index); + SDL_Touch *touch = SDL_GetTouch(id); if (!touch) { return 0; @@ -195,110 +180,11 @@ SDL_GetTouchFocusWindow(int index) return touch->focus; } -static int SDLCALL -FlushTouchMotion(void *param, SDL_Event * event) -{ - if (event->type == SDL_TOUCHMOTION - && event->motion.which == (Uint8) SDL_current_touch) { - return 0; - } else { - return 1; - } -} - -int -SDL_SetRelativeTouchMode(int index, SDL_bool enabled) -{ - SDL_Touch *touch = SDL_GetTouch(index); - - if (!touch) { - return -1; - } - - /* Flush pending touch motion */ - touch->flush_motion = SDL_TRUE; - SDL_PumpEvents(); - touch->flush_motion = SDL_FALSE; - SDL_FilterEvents(FlushTouchMotion, touch); - - /* Set the relative mode */ - touch->relative_mode = enabled; - - - - if (!enabled) { - /* Restore the expected touch position */ - SDL_WarpTouchInWindow(touch->focus, touch->x, touch->y); - } - return 0; -} - -SDL_bool -SDL_GetRelativeTouchMode(int index) -{ - SDL_Touch *touch = SDL_GetTouch(index); - - if (!touch) { - return SDL_FALSE; - } - return touch->relative_mode; -} - -Uint8 -SDL_GetTouchState(int *x, int *y) -{ - SDL_Touch *touch = SDL_GetTouch(SDL_current_touch); - - if (!touch) { - if (x) { - *x = 0; - } - if (y) { - *y = 0; - } - return 0; - } - - if (x) { - *x = touch->x; - } - if (y) { - *y = touch->y; - } - return touch->buttonstate; -} - -Uint8 -SDL_GetRelativeTouchState(int index, int *x, int *y) -{ - SDL_Touch *touch = SDL_GetTouch(index); - - if (!touch) { - if (x) { - *x = 0; - } - if (y) { - *y = 0; - } - return 0; - } - - if (x) { - *x = touch->xdelta; - } - if (y) { - *y = touch->ydelta; - } - touch->xdelta = 0; - touch->ydelta = 0; - return touch->buttonstate; -} - void SDL_SetTouchFocus(int id, SDL_Window * window) { int index = SDL_GetTouchIndexId(id); - SDL_Touch *touch = SDL_GetTouch(index); + SDL_Touch *touch = SDL_GetTouch(id); int i; SDL_bool focus; @@ -312,7 +198,7 @@ SDL_SetTouchFocus(int id, SDL_Window * window) for (i = 0; i < SDL_num_touch; ++i) { SDL_Touch *check; if (i != index) { - check = SDL_GetTouch(i); + check = SDL_touchPads[i]; if (check && check->focus == touch->focus) { focus = SDL_TRUE; break; @@ -331,7 +217,7 @@ SDL_SetTouchFocus(int id, SDL_Window * window) for (i = 0; i < SDL_num_touch; ++i) { SDL_Touch *check; if (i != index) { - check = SDL_GetTouch(i); + check = SDL_touchPads[i]; if (check && check->focus == touch->focus) { focus = SDL_TRUE; break; @@ -344,43 +230,106 @@ SDL_SetTouchFocus(int id, SDL_Window * window) } } +int +SDL_AddFinger(SDL_Touch* touch,SDL_Finger* finger) +{ + int index; + SDL_Finger **fingers; + size_t length; + + if (SDL_GetFingerIndexId(touch,finger->id) != -1) { + SDL_SetError("Finger ID already in use"); + } + + /* Add the touch to the list of touch */ + fingers = (SDL_Finger **) SDL_realloc(touch->fingers, + (touch->num_fingers + 1) * sizeof(*touch)); + if (!fingers) { + SDL_OutOfMemory(); + return -1; + } + + touch->fingers = fingers; + index = SDL_num_touch++; + + touch->fingers[index] = (SDL_Finger *) SDL_malloc(sizeof(*(touch->fingers[index]))); + if (!touch->fingers[index]) { + SDL_OutOfMemory(); + return -1; + } + *touch->fingers[index] = *finger; + + return index; +} + int -SDL_SendProximity(int id, int x, int y, int type) +SDL_DelFinger(SDL_Touch* touch,int fingerid) { - int index = SDL_GetTouchIndexId(id); - SDL_Touch *touch = SDL_GetTouch(index); - int posted = 0; + int index = SLD_GetFingerIndexId(touch,fingerid); + SDL_Finger* finger = SDL_GetFinger(touch,fingerid); - if (!touch) { - return 0; + if (!finger) { + return; } + - touch->last_x = x; - touch->last_y = y; - if (SDL_GetEventState(type) == SDL_ENABLE) { - SDL_Event event; - event.proximity.which = (Uint8) index; - event.proximity.x = x; - event.proximity.y = y; - event.proximity.cursor = touch->current_end; - event.proximity.type = type; - /* FIXME: is this right? */ - event.proximity.windowID = touch->focus ? touch->focus->id : 0; - posted = (SDL_PushEvent(&event) > 0); - if (type == SDL_PROXIMITYIN) { - touch->proximity = SDL_TRUE; - } else { - touch->proximity = SDL_FALSE; - } + SDL_free(finger); + touch->num_fingers--; + touch->fingers[index] = touch->fingers[touch->num_fingers]; +} + + +int +SDL_SendFingerDown(int id, int fingerid, SDL_bool down, int x, int y, int pressure) +{ + SDL_Touch* touch = SDL_GetTouch(id); + if(down) { + SDL_Finger nf; + nf.id = id; + nf.x = x; + nf.y = y; + nf.pressure = pressure; + nf.xdelta = 0; + nf.ydelta = 0; + nf.last_x = x; + nf.last_y = y; + SDL_AddFinger(touch,&nf); + + posted = 0; + if (SDL_GetEventState(SDL_FINGERDOWN) == SDL_ENABLE) { + SDL_Event event; + event.tfinger.type = SDL_FINGERDOWN; + event.tfinger.touchId = (Uint8) id; + event.tfinger.state = touch->buttonstate; + event.tfinger.windowID = touch->focus ? touch->focus->id : 0; + event.fingerId = id; + posted = (SDL_PushEvent(&event) > 0); + } + return posted; + } + else { + SDL_DelFinger(touch,id); + posted = 0; + if (SDL_GetEventState(SDL_FINGERUP) == SDL_ENABLE) { + SDL_Event event; + event.tfinger.type = SDL_FINGERUP; + event.tfinger.touchId = (Uint8) id; + event.tfinger.state = touch->buttonstate; + event.tfinger.windowID = touch->focus ? touch->focus->id : 0; + event.fingerId = id; + posted = (SDL_PushEvent(&event) > 0); + } + return posted; } - return posted; } int -SDL_SendTouchMotion(int id, int relative, int x, int y, int pressure) +SDL_SendTouchMotion(int id, int fingerid, int relative, + int x, int y, int pressure) { int index = SDL_GetTouchIndexId(id); - SDL_Touch *touch = SDL_GetTouch(index); + SDL_Touch *touch = SDL_GetTouch(id); + SDL_Finger *finger = SDL_GetFinger(touch,fingerid); int posted; int xrel; int yrel; @@ -390,22 +339,15 @@ SDL_SendTouchMotion(int id, int relative, int x, int y, int pressure) return 0; } - /* if the touch is out of proximity we don't to want to have any motion from it */ - if (touch->proximity == SDL_FALSE) { - touch->last_x = x; - touch->last_y = y; - return 0; - } - /* the relative motion is calculated regarding the system cursor last position */ if (relative) { xrel = x; yrel = y; - x = (touch->last_x + x); - y = (touch->last_y + y); + x = (finger->last_x + x); + y = (finger->last_y + y); } else { - xrel = x - touch->last_x; - yrel = y - touch->last_y; + xrel = x - finger->last_x; + yrel = y - finger->last_y; } /* Drop events that don't change state */ @@ -417,18 +359,16 @@ SDL_SendTouchMotion(int id, int relative, int x, int y, int pressure) } /* Update internal touch coordinates */ - if (touch->relative_mode == SDL_FALSE) { - touch->x = x; - touch->y = y; - } else { - touch->x += xrel; - touch->y += yrel; - } - SDL_GetWindowSize(touch->focus, &x_max, &y_max); + finger->x = x; + finger->y = y; + + /*Should scale to window? Normalize? Maintain Aspect?*/ + //SDL_GetWindowSize(touch->focus, &x_max, &y_max); /* make sure that the pointers find themselves inside the windows */ /* only check if touch->xmax is set ! */ + /* if (x_max && touch->x > x_max) { touch->x = x_max; } else if (touch->x < 0) { @@ -440,46 +380,32 @@ SDL_SendTouchMotion(int id, int relative, int x, int y, int pressure) } else if (touch->y < 0) { touch->y = 0; } - - touch->xdelta += xrel; - touch->ydelta += yrel; - touch->pressure = pressure; + */ + finger->xdelta += xrel; + finger->ydelta += yrel; + finger->pressure = pressure; /* Post the event, if desired */ posted = 0; - if (SDL_GetEventState(SDL_TOUCHMOTION) == SDL_ENABLE && - touch->proximity == SDL_TRUE) { + if (SDL_GetEventState(SDL_FINGERMOTION) == SDL_ENABLE) { SDL_Event event; - event.motion.type = SDL_TOUCHMOTION; - event.motion.which = (Uint8) index; - event.motion.state = touch->buttonstate; - event.motion.x = touch->x; - event.motion.y = touch->y; - event.motion.z = touch->z; - event.motion.pressure = touch->pressure; - event.motion.pressure_max = touch->pressure_max; - event.motion.pressure_min = touch->pressure_min; - event.motion.rotation = 0; - event.motion.tilt_x = 0; - event.motion.tilt_y = 0; - event.motion.cursor = touch->current_end; - event.motion.xrel = xrel; - event.motion.yrel = yrel; - event.motion.windowID = touch->focus ? touch->focus->id : 0; + event.tfinger.type = SDL_FINGERMOTION; + event.tfinger.which = (Uint8) index; + event.tfinger.state = touch->buttonstate; + event.tfinger.windowID = touch->focus ? touch->focus->id : 0; posted = (SDL_PushEvent(&event) > 0); } - touch->last_x = touch->x; - touch->last_y = touch->y; + finger->last_x = finger->x; + finger->last_y = finger->y; return posted; } int SDL_SendTouchButton(int id, Uint8 state, Uint8 button) { - int index = SDL_GetTouchIndexId(id); - SDL_Touch *touch = SDL_GetTouch(index); + SDL_Touch *touch = SDL_GetTouch(id); int posted; Uint32 type; @@ -515,61 +441,23 @@ SDL_SendTouchButton(int id, Uint8 state, Uint8 button) if (SDL_GetEventState(type) == SDL_ENABLE) { SDL_Event event; event.type = type; - event.button.which = (Uint8) index; - event.button.state = state; - event.button.button = button; - event.button.x = touch->x; - event.button.y = touch->y; - event.button.windowID = touch->focus ? touch->focus->id : 0; - posted = (SDL_PushEvent(&event) > 0); - } - return posted; -} - -int -SDL_SendTouchWheel(int index, int x, int y) -{ - SDL_Touch *touch = SDL_GetTouch(index); - int posted; - - if (!touch || (!x && !y)) { - return 0; - } - - /* Post the event, if desired */ - posted = 0; - if (SDL_GetEventState(SDL_TOUCHWHEEL) == SDL_ENABLE) { - SDL_Event event; - event.type = SDL_TOUCHWHEEL; - event.wheel.which = (Uint8) index; - event.wheel.x = x; - event.wheel.y = y; - event.wheel.windowID = touch->focus ? touch->focus->id : 0; + event.tbutton.which = (Uint8) index; + event.tbutton.state = state; + event.tbutton.button = button; + event.tbutton.windowID = touch->focus ? touch->focus->id : 0; posted = (SDL_PushEvent(&event) > 0); } return posted; } - char * -SDL_GetTouchName(int index) +SDL_GetTouchName(int id) { - SDL_Touch *touch = SDL_GetTouch(index); + SDL_Touch *touch = SDL_GetTouch(id); if (!touch) { return NULL; } return touch->name; } -void -SDL_ChangeEnd(int id, int end) -{ - int index = SDL_GetTouchIndexId(id); - SDL_Touch *touch = SDL_GetTouch(index); - - if (touch) { - touch->current_end = end; - } -} - /* vi: set ts=4 sw=4 expandtab: */ diff --git a/src/events/SDL_touch_c.h b/src/events/SDL_touch_c.h index 62a950ceb..fdc221d79 100644 --- a/src/events/SDL_touch_c.h +++ b/src/events/SDL_touch_c.h @@ -25,50 +25,51 @@ #define _SDL_touch_c_h typedef struct SDL_Touch SDL_Touch; +typedef struct SDL_Finger SDL_Finger; + +struct SDL_Finger { + int id; + int x; + int y; + int z; /* for future use */ + int xdelta; + int ydelta; + int last_x, last_y; /* the last reported x and y coordinates */ + int pressure; +}; struct SDL_Touch { - /* Warp the touch to (x,y) */ - void (*WarpTouch) (SDL_Touch * touch, SDL_Window * window, int x, - int y); - - /* Free the touch when it's time */ - void (*FreeTouch) (SDL_Touch * touch); - - /* data common for tablets */ - int pressure; - int pressure_max; - int pressure_min; - int tilt; /* for future use */ - int rotation; /* for future use */ - int total_ends; - int current_end; - - /* Data common to all touch */ - int id; - SDL_Window *focus; - int which; - int x; - int y; - int z; /* for future use */ - int xdelta; - int ydelta; - int last_x, last_y; /* the last reported x and y coordinates */ - char *name; - Uint8 buttonstate; - SDL_bool relative_mode; - SDL_bool proximity; - SDL_bool flush_motion; - - SDL_Cursor *cursors; - SDL_Cursor *def_cursor; - SDL_Cursor *cur_cursor; - SDL_bool cursor_shown; - - void *driverdata; + + /* Free the touch when it's time */ + void (*FreeTouch) (SDL_Touch * touch); + + /* data common for tablets */ + int pressure_max; + int pressure_min; + int tilt; /* for future use */ + int rotation; /* for future use */ + + int total_ends; + int current_end; + + /* Data common to all touch */ + int id; + SDL_Window *focus; + + char *name; + Uint8 buttonstate; + SDL_bool relative_mode; + SDL_bool flush_motion; + + int num_fingers; + SDL_Finger** fingers; + + void *driverdata; }; + /* Initialize the touch subsystem */ extern int SDL_TouchInit(void); @@ -84,24 +85,16 @@ extern int SDL_AddTouch(const SDL_Touch * touch, char *name, /* Remove a touch at an index, clearing the slot for later */ extern void SDL_DelTouch(int index); -/* Clear the button state of a touch at an index */ -extern void SDL_ResetTouch(int index); - /* Set the touch focus window */ extern void SDL_SetTouchFocus(int id, SDL_Window * window); /* Send a touch motion event for a touch */ -extern int SDL_SendTouchMotion(int id, int relative, int x, int y, int z); +extern int SDL_SendTouchMotion(int id, int fingerid, + int relative, int x, int y, int z); /* Send a touch button event for a touch */ extern int SDL_SendTouchButton(int id, Uint8 state, Uint8 button); -/* Send a touch wheel event for a touch */ -extern int SDL_SendTouchWheel(int id, int x, int y); - -/* Send a proximity event for a touch */ -extern int SDL_SendProximity(int id, int x, int y, int type); - /* Shutdown the touch subsystem */ extern void SDL_TouchQuit(void); diff --git a/touchTest/touchPong b/touchTest/touchPong index 29e892b462ebea82de922f31e41e8095bcd2283e..16303ab5275a16d28c5fde83735805b32427c8f4 100755 GIT binary patch delta 6577 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

UEZauGTx} z-a!=|`$XbGu0Akl=v_I3qA&JuX1M=VP>>fr+`nPs(20{rkL@`*5}8=oXG(ryw6gzq z6=&{xfGlUBuk*hOvJk0gGr-aU5!bk)`@kYI5c#WPSFvUI#W)_CGptwtp2LO?%^3tH zOCQ*$CEwHgzeoLP+MzW3p_^Jo&cl;+?R=f+-n@p|on4}r@|tLu?u^#RZ=&UOk9Nv$ o;vbCf4!vIVk^F|*&{5F^SeW;4^bLrkW1^=Z9xklV9?1^=KkJAI%K!iX delta 6236 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 IDD4;cAAOm;H2?qr diff --git a/touchTest/touchSimp b/touchTest/touchSimp index 57e1c92596505a47915abd237a5d58eeb272e174..a3fbc3d7c7ef6d760057ff959a07159ba0d19463 100755 GIT binary patch delta 9799 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