void Android_OnTouch(int touch_device_id_in, int pointer_finger_id_in, int action, float x, float y, float p) { SDL_TouchID touchDeviceId = 0; SDL_FingerID fingerId = 0; if (!Android_Window) { return; } touchDeviceId = (SDL_TouchID)touch_device_id_in; if (!SDL_GetTouch(touchDeviceId)) { SDL_Touch touch; memset( &touch, 0, sizeof(touch) ); touch.id = touchDeviceId; touch.x_min = 0.0f; touch.x_max = (float)Android_ScreenWidth; touch.native_xres = touch.x_max - touch.x_min; touch.y_min = 0.0f; touch.y_max = (float)Android_ScreenHeight; touch.native_yres = touch.y_max - touch.y_min; touch.pressure_min = 0.0f; touch.pressure_max = 1.0f; touch.native_pressureres = touch.pressure_max - touch.pressure_min; if (SDL_AddTouch(&touch, "") < 0) { SDL_Log("error: can't add touch %s, %d", __FILE__, __LINE__); } } fingerId = (SDL_FingerID)pointer_finger_id_in; switch (action) { case ACTION_DOWN: case ACTION_POINTER_1_DOWN: SDL_SendMouseMotion(Android_Window, 0, x, y); SDL_SendMouseButton(Android_Window, SDL_PRESSED, SDL_BUTTON_LEFT); SDL_SendFingerDown(touchDeviceId, fingerId, SDL_TRUE, x, y, p); break; case ACTION_MOVE: SDL_SendMouseMotion(Android_Window, 0, x, y); SDL_SendTouchMotion(touchDeviceId, fingerId, SDL_FALSE, x, y, p); break; case ACTION_UP: case ACTION_POINTER_1_UP: SDL_SendMouseButton(Android_Window, SDL_RELEASED, SDL_BUTTON_LEFT); SDL_SendFingerDown(touchDeviceId, fingerId, SDL_FALSE, x, y, p); break; default: break; } }
extern void SDL_ANDROID_MainThreadPushMultitouchButton(int id, int pressed, int x, int y, int force) { #if SDL_VERSION_ATLEAST(1,3,0) SDL_SendFingerDown(0, id, pressed ? 1 : 0, (float)x / (float)window->w, (float)y / (float)window->h, force); #endif }
void X11_PumpEvents(_THIS) { SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; /* Update activity every 30 seconds to prevent screensaver */ if (_this->suspend_screensaver) { Uint32 now = SDL_GetTicks(); if (!data->screensaver_activity || (int) (now - data->screensaver_activity) >= 30000) { XResetScreenSaver(data->display); data->screensaver_activity = now; } } /* Keep processing pending events */ while (X11_Pending(data->display)) { X11_DispatchEvent(_this); } #ifdef SDL_INPUT_LINUXEV /* Process Touch events - TODO When X gets touch support, use that instead*/ int i = 0,rd; char name[256]; struct input_event ev[64]; int size = sizeof (struct input_event); for(i = 0;i < SDL_GetNumTouch();++i) { SDL_Touch* touch = SDL_GetTouchIndex(i); if(!touch) printf("Touch %i/%i DNE\n",i,SDL_GetNumTouch()); EventTouchData* data; data = (EventTouchData*)(touch->driverdata); if(data == NULL) { printf("No driver data\n"); continue; } if(data->eventStream <= 0) printf("Error: Couldn't open stream\n"); rd = read(data->eventStream, ev, size * 64); //printf("Got %i/%i bytes\n",rd,size); if(rd >= size) { for (i = 0; i < rd / sizeof(struct input_event); i++) { switch (ev[i].type) { case EV_ABS: //printf("Got position x: %i!\n",data->x); switch (ev[i].code) { case ABS_X: data->x = ev[i].value; break; case ABS_Y: data->y = ev[i].value; break; case ABS_PRESSURE: data->pressure = ev[i].value; if(data->pressure < 0) data->pressure = 0; break; case ABS_MISC: if(ev[i].value == 0) data->up = SDL_TRUE; break; } break; case EV_MSC: if(ev[i].code == MSC_SERIAL) data->finger = ev[i].value; break; case EV_SYN: //printf("Id: %i\n",touch->id); if(data->up) { SDL_SendFingerDown(touch->id,data->finger, SDL_FALSE,data->x,data->y, data->pressure); } else if(data->x >= 0 || data->y >= 0) SDL_SendTouchMotion(touch->id,data->finger, SDL_FALSE,data->x,data->y, data->pressure); //printf("Synched: %i tx: %i, ty: %i\n", // data->finger,data->x,data->y); data->x = -1; data->y = -1; data->pressure = -1; data->finger = 0; data->up = SDL_FALSE; break; } } } } #endif }
void X11_PumpEvents(_THIS) { SDL_VideoData *data = (SDL_VideoData *) _this->driverdata; /* Update activity every 30 seconds to prevent screensaver */ if (_this->suspend_screensaver) { Uint32 now = SDL_GetTicks(); if (!data->screensaver_activity || (int) (now - data->screensaver_activity) >= 30000) { XResetScreenSaver(data->display); #if SDL_USE_LIBDBUS SDL_dbus_screensaver_tickle(_this); #endif data->screensaver_activity = now; } } /* Keep processing pending events */ while (X11_Pending(data->display)) { X11_DispatchEvent(_this); } /* FIXME: Only need to do this when there are pending focus changes */ X11_HandleFocusChanges(_this); /*Dont process evtouch events if XInput2 multitouch is supported*/ if(X11_Xinput2IsMultitouchSupported()) { return; } #ifdef SDL_INPUT_LINUXEV /* Process Touch events*/ int i = 0,rd; struct input_event ev[64]; int size = sizeof (struct input_event); /* !!! FIXME: clean the tabstops out of here. */ for(i = 0;i < SDL_GetNumTouch();++i) { SDL_Touch* touch = SDL_GetTouchIndex(i); if(!touch) printf("Touch %i/%i DNE\n",i,SDL_GetNumTouch()); EventTouchData* data; data = (EventTouchData*)(touch->driverdata); if(data == NULL) { printf("No driver data\n"); continue; } if(data->eventStream <= 0) printf("Error: Couldn't open stream\n"); rd = read(data->eventStream, ev, size * 64); if(rd >= size) { for (i = 0; i < rd / sizeof(struct input_event); i++) { switch (ev[i].type) { case EV_ABS: switch (ev[i].code) { case ABS_X: data->x = ev[i].value; break; case ABS_Y: data->y = ev[i].value; break; case ABS_PRESSURE: data->pressure = ev[i].value; if(data->pressure < 0) data->pressure = 0; break; case ABS_MISC: if(ev[i].value == 0) data->up = SDL_TRUE; break; } break; case EV_MSC: if(ev[i].code == MSC_SERIAL) data->finger = ev[i].value; break; case EV_KEY: if(ev[i].code == BTN_TOUCH) if(ev[i].value == 0) data->up = SDL_TRUE; break; case EV_SYN: if(!data->down) { data->down = SDL_TRUE; SDL_SendFingerDown(touch->id,data->finger, data->down, data->x, data->y, data->pressure); } else if(!data->up) SDL_SendTouchMotion(touch->id,data->finger, SDL_FALSE, data->x,data->y, data->pressure); else { data->down = SDL_FALSE; SDL_SendFingerDown(touch->id,data->finger, data->down, data->x,data->y, data->pressure); data->x = -1; data->y = -1; data->pressure = -1; data->finger = 0; data->up = SDL_FALSE; } break; } } } } #endif }
int SDL_SendTouchMotion(SDL_TouchID id, SDL_FingerID fingerid, int relative, float xin, float yin, float pressurein) { SDL_Touch *touch; SDL_Finger *finger; int posted; Sint16 xrel, yrel; Uint16 x; Uint16 y; Uint16 pressure; touch = SDL_GetTouch(id); if (!touch) { return SDL_TouchNotFoundError(id); } //scale to Integer coordinates x = (Uint16)((xin+touch->x_min)*(touch->xres)/(touch->native_xres)); y = (Uint16)((yin+touch->y_min)*(touch->yres)/(touch->native_yres)); pressure = (Uint16)((pressurein+touch->pressure_min)*(touch->pressureres)/(touch->native_pressureres)); if(touch->flush_motion) { return 0; } finger = SDL_GetFinger(touch,fingerid); if(finger == NULL || !finger->down) { return SDL_SendFingerDown(id,fingerid,SDL_TRUE,xin,yin,pressurein); } else { /* the relative motion is calculated regarding the last position */ if (relative) { xrel = x; yrel = y; x = (finger->last_x + x); y = (finger->last_y + y); } else { if(xin < touch->x_min) x = finger->last_x; /*If movement is only in one axis,*/ if(yin < touch->y_min) y = finger->last_y; /*The other is marked as -1*/ if(pressurein < touch->pressure_min) pressure = finger->last_pressure; xrel = x - finger->last_x; yrel = y - finger->last_y; //printf("xrel,yrel (%i,%i)\n",(int)xrel,(int)yrel); } /* Drop events that don't change state */ if (!xrel && !yrel) { #if 0 printf("Touch event didn't change state - dropped!\n"); #endif return 0; } /* Update internal touch coordinates */ 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) { touch->x = 0; } if (y_max && touch->y > y_max) { touch->y = y_max; } else if (touch->y < 0) { touch->y = 0; } */ finger->xdelta = xrel; finger->ydelta = yrel; finger->pressure = pressure; /* Post the event, if desired */ posted = 0; if (SDL_GetEventState(SDL_FINGERMOTION) == SDL_ENABLE) { SDL_Event event; event.tfinger.type = SDL_FINGERMOTION; event.tfinger.touchId = id; event.tfinger.fingerId = fingerid; event.tfinger.x = x; event.tfinger.y = y; event.tfinger.dx = xrel; event.tfinger.dy = yrel; event.tfinger.pressure = pressure; event.tfinger.state = touch->buttonstate; event.tfinger.windowID = touch->focus ? touch->focus->id : 0; posted = (SDL_PushEvent(&event) > 0); } finger->last_x = finger->x; finger->last_y = finger->y; finger->last_pressure = finger->pressure; return posted; } }
/* We need our own event queue, because Free Heroes 2 game uses * SDL_SetEventFilter(), and it calls SDL_Flip() from inside * it's custom filter function, and SDL_Flip() does not work * when it's not called from the main() thread. * So we, like, push the events into our own queue, * read each event from that queue inside SDL_ANDROID_PumpEvents(), * unlock the mutex, and push the event to SDL queue, * which is then immediately read by SDL from the same thread, * and then SDL invokes event filter function from FHeroes2. * FHeroes2 call SDL_Flip() from inside that event filter function, * and it works, because it is called from the main() thread. */ extern void SDL_ANDROID_PumpEvents() { static int oldMouseButtons = 0; SDL_Event ev; SDL_ANDROID_processAndroidTrackballDampening(); SDL_ANDROID_processMoveMouseWithKeyboard(); #if SDL_VERSION_ATLEAST(1,3,0) SDL_Window * window = SDL_GetFocusWindow(); if( !window ) return; #endif if( !BufferedEventsMutex ) BufferedEventsMutex = SDL_CreateMutex(); SDL_mutexP(BufferedEventsMutex); while( BufferedEventsStart != BufferedEventsEnd ) { ev = BufferedEvents[BufferedEventsStart]; BufferedEvents[BufferedEventsStart].type = 0; BufferedEventsStart++; if( BufferedEventsStart >= MAX_BUFFERED_EVENTS ) BufferedEventsStart = 0; SDL_mutexV(BufferedEventsMutex); switch( ev.type ) { case SDL_MOUSEMOTION: SDL_SendMouseMotion( ANDROID_CurrentWindow, 0, ev.motion.x, ev.motion.y ); break; case SDL_MOUSEBUTTONDOWN: if( ((oldMouseButtons & SDL_BUTTON(ev.button.button)) != 0) != ev.button.state ) { oldMouseButtons = (oldMouseButtons & ~SDL_BUTTON(ev.button.button)) | (ev.button.state ? SDL_BUTTON(ev.button.button) : 0); SDL_SendMouseButton( ANDROID_CurrentWindow, ev.button.state, ev.button.button ); } break; case SDL_KEYDOWN: //__android_log_print(ANDROID_LOG_INFO, "libSDL", "SDL_KEYDOWN: %i %i", ev->key.keysym.sym, ev->key.state); SDL_SendKeyboardKey( ev.key.state, &ev.key.keysym ); break; case SDL_JOYAXISMOTION: if( ev.jaxis.which < MAX_MULTITOUCH_POINTERS+1 && SDL_ANDROID_CurrentJoysticks[ev.jaxis.which] ) SDL_PrivateJoystickAxis( SDL_ANDROID_CurrentJoysticks[ev.jaxis.which], ev.jaxis.axis, ev.jaxis.value ); break; case SDL_JOYBUTTONDOWN: if( ev.jbutton.which < MAX_MULTITOUCH_POINTERS+1 && SDL_ANDROID_CurrentJoysticks[ev.jbutton.which] ) SDL_PrivateJoystickButton( SDL_ANDROID_CurrentJoysticks[ev.jbutton.which], ev.jbutton.button, ev.jbutton.state ); break; case SDL_JOYBALLMOTION: if( ev.jball.which < MAX_MULTITOUCH_POINTERS+1 && SDL_ANDROID_CurrentJoysticks[ev.jbutton.which] ) SDL_PrivateJoystickBall( SDL_ANDROID_CurrentJoysticks[ev.jball.which], ev.jball.ball, ev.jball.xrel, ev.jball.yrel ); break; #if SDL_VERSION_ATLEAST(1,3,0) //if( ANDROID_CurrentWindow ) // SDL_SendWindowEvent(ANDROID_CurrentWindow, SDL_WINDOWEVENT_MINIMIZED, 0, 0); #else case SDL_ACTIVEEVENT: SDL_PrivateAppActive(ev.active.gain, ev.active.state); break; #endif #if SDL_VERSION_ATLEAST(1,3,0) case SDL_FINGERMOTION: SDL_SendTouchMotion(0, ev.tfinger.fingerId, 0, (float)ev.tfinger.x / (float)window->w, (float)ev.tfinger.y / (float)window->h, ev.tfinger.pressure); break; case SDL_FINGERDOWN: SDL_SendFingerDown(0, ev.tfinger.fingerId, ev.tfinger.state ? 1 : 0, (float)ev.tfinger.x / (float)window->w, (float)ev.tfinger.y / (float)window->h, ev.tfinger.pressure); break; case SDL_TEXTINPUT: SDL_SendKeyboardText(ev.text.text); break; case SDL_MOUSEWHEEL: SDL_SendMouseWheel( ANDROID_CurrentWindow, ev.wheel.x, ev.wheel.y ); break; #endif } SDL_mutexP(BufferedEventsMutex); } SDL_mutexV(BufferedEventsMutex); };