bool TopWindow::OnEvent(const SDL_Event &event) { switch (event.type) { Window *w; #if SDL_MAJOR_VERSION < 2 case SDL_VIDEOEXPOSE: invalidated = false; Expose(); return true; #endif case SDL_KEYDOWN: w = GetFocusedWindow(); if (w == nullptr) w = this; if (!w->IsEnabled()) return false; #if SDL_MAJOR_VERSION >= 2 return w->OnKeyDown(event.key.keysym.sym); #else return w->OnKeyDown(event.key.keysym.sym) || (event.key.keysym.unicode != 0 && w->OnCharacter(event.key.keysym.unicode)); #endif #if SDL_MAJOR_VERSION >= 2 case SDL_TEXTINPUT: w = GetFocusedWindow(); if (w == nullptr) w = this; if (!w->IsEnabled()) return false; if (event.text.text && *event.text.text) { std::pair<unsigned, const char *> next = NextUTF8(event.text.text); bool handled = w->OnCharacter(next.first); while (next.second) { next = NextUTF8(next.second); handled = w->OnCharacter(next.first) || handled; } return handled; } else return false; #endif case SDL_KEYUP: w = GetFocusedWindow(); if (w == nullptr) w = this; if (!w->IsEnabled()) return false; return w->OnKeyUp(event.key.keysym.sym); #ifdef HAVE_MULTI_TOUCH case SDL_FINGERDOWN: if (SDL_GetNumTouchFingers(event.tfinger.touchId) == 2) return OnMultiTouchDown(); else return false; case SDL_FINGERUP: if (SDL_GetNumTouchFingers(event.tfinger.touchId) == 1) return OnMultiTouchUp(); else return false; #endif case SDL_MOUSEMOTION: // XXX keys return OnMouseMove(event.motion.x, event.motion.y, 0); case SDL_MOUSEBUTTONDOWN: #if SDL_MAJOR_VERSION < 2 if (event.button.button == SDL_BUTTON_WHEELUP) return OnMouseWheel(event.button.x, event.button.y, 1); else if (event.button.button == SDL_BUTTON_WHEELDOWN) return OnMouseWheel(event.button.x, event.button.y, -1); #endif return double_click.Check(RasterPoint(event.button.x, event.button.y)) ? OnMouseDouble(event.button.x, event.button.y) : OnMouseDown(event.button.x, event.button.y); case SDL_MOUSEBUTTONUP: #if SDL_MAJOR_VERSION < 2 if (event.button.button == SDL_BUTTON_WHEELUP || event.button.button == SDL_BUTTON_WHEELDOWN) /* the wheel has already been handled in SDL_MOUSEBUTTONDOWN */ return false; #endif double_click.Moved(RasterPoint(event.button.x, event.button.y)); return OnMouseUp(event.button.x, event.button.y); case SDL_QUIT: return OnClose(); #if SDL_MAJOR_VERSION < 2 case SDL_VIDEORESIZE: Resize(event.resize.w, event.resize.h); return true; #endif #if SDL_MAJOR_VERSION >= 2 case SDL_MOUSEWHEEL: int x, y; SDL_GetMouseState(&x, &y); return OnMouseWheel(x, y, event.wheel.y); case SDL_WINDOWEVENT: switch (event.window.event) { case SDL_WINDOWEVENT_RESIZED: Resize(event.window.data1, event.window.data2); return true; case SDL_WINDOWEVENT_RESTORED: case SDL_WINDOWEVENT_MOVED: case SDL_WINDOWEVENT_SHOWN: case SDL_WINDOWEVENT_MAXIMIZED: { SDL_Window* event_window = SDL_GetWindowFromID(event.window.windowID); if (event_window) { int w, h; SDL_GetWindowSize(event_window, &w, &h); if ((w >= 0) && (h >= 0)) { Resize(w, h); } } } return true; case SDL_WINDOWEVENT_EXPOSED: invalidated = false; Expose(); return true; } #endif } return false; }
bool CGenericTouchInputHandler::HandleTouchInput(TouchInput event, float x, float y, int64_t time, int32_t pointer /* = 0 */, float size /* = 0.0f */) { if (time < 0 || pointer < 0 || pointer >= TOUCH_MAX_POINTERS) return false; CSingleLock lock(m_critical); bool result = true; m_pointers[pointer].current.x = x; m_pointers[pointer].current.y = y; m_pointers[pointer].current.time = time; switch (event) { case TouchInputAbort: { triggerDetectors(event, pointer); setGestureState(TouchGestureUnknown); for (unsigned int pIndex = 0; pIndex < TOUCH_MAX_POINTERS; pIndex++) m_pointers[pIndex].reset(); OnTouchAbort(); break; } case TouchInputDown: { m_pointers[pointer].down.x = x; m_pointers[pointer].down.y = y; m_pointers[pointer].down.time = time; m_pointers[pointer].moving = false; m_pointers[pointer].size = size; // If this is the down event of the primary pointer // we start by assuming that it's a single touch if (pointer == 0) { // create new gesture detectors m_detectors.insert(new CGenericTouchSwipeDetector(this, m_dpi)); m_detectors.insert(new CGenericTouchPinchDetector(this, m_dpi)); m_detectors.insert(new CGenericTouchRotateDetector(this, m_dpi)); triggerDetectors(event, pointer); setGestureState(TouchGestureSingleTouch); result = OnSingleTouchStart(x, y); m_holdTimer->Start(TOUCH_HOLD_TIMEOUT); } // Otherwise it's the down event of another pointer else { triggerDetectors(event, pointer); // If we so far assumed single touch or still have the primary // pointer of a previous multi touch pressed down, we can update to multi touch if (m_gestureState == TouchGestureSingleTouch || m_gestureState == TouchGestureSingleTouchHold || m_gestureState == TouchGestureMultiTouchDone) { result = OnMultiTouchDown(x, y, pointer); m_holdTimer->Stop(true); if (m_gestureState == TouchGestureSingleTouch || m_gestureState == TouchGestureSingleTouchHold) m_holdTimer->Start(TOUCH_HOLD_TIMEOUT); setGestureState(TouchGestureMultiTouchStart); } // Otherwise we should ignore this pointer else { m_pointers[pointer].reset(); break; } } return result; } case TouchInputUp: { // unexpected event => abort if (!m_pointers[pointer].valid() || m_gestureState == TouchGestureUnknown) break; triggerDetectors(event, pointer); m_holdTimer->Stop(false); // Just a single tap with a pointer if (m_gestureState == TouchGestureSingleTouch || m_gestureState == TouchGestureSingleTouchHold) { result = OnSingleTouchEnd(x, y); if (m_gestureState == TouchGestureSingleTouch) OnTap(x, y, 1); } // A pan gesture started with a single pointer (ignoring any other pointers) else if (m_gestureState == TouchGesturePan) { float velocityX = 0.0f; // number of pixels per second float velocityY = 0.0f; // number of pixels per second m_pointers[pointer].velocity(velocityX, velocityY, false); result = OnTouchGestureEnd(x, y, x - m_pointers[pointer].down.x, y - m_pointers[pointer].down.y, velocityX, velocityY); } // we are in multi-touch else result = OnMultiTouchUp(x, y, pointer); // If we were in multi touch mode and lifted one pointer // we can go into the TouchGestureMultiTouchDone state which will allow // the user to go back into multi touch mode without lifting the primary pointer if (m_gestureState == TouchGestureMultiTouchStart || m_gestureState == TouchGestureMultiTouchHold || m_gestureState == TouchGestureMultiTouch) { setGestureState(TouchGestureMultiTouchDone); // after lifting the primary pointer, the secondary pointer will // become the primary pointer in the next event if (pointer == 0) { m_pointers[0] = m_pointers[1]; pointer = 1; } } // Otherwise abort else { if (m_gestureState == TouchGestureMultiTouchDone) { float velocityX = 0.0f; // number of pixels per second float velocityY = 0.0f; // number of pixels per second m_pointers[pointer].velocity(velocityX, velocityY, false); result = OnTouchGestureEnd(x, y, x - m_pointers[pointer].down.x, y - m_pointers[pointer].down.y, velocityX, velocityY); // if neither of the two pointers moved we have a single tap with multiple pointers if (m_gestureStateOld != TouchGestureMultiTouchHold && m_gestureStateOld != TouchGestureMultiTouch) OnTap(fabs((m_pointers[0].down.x + m_pointers[1].down.x) / 2), fabs((m_pointers[0].down.y + m_pointers[1].down.y) / 2), 2); } setGestureState(TouchGestureUnknown); m_pointers[pointer].reset(); } return result; } case TouchInputMove: { // unexpected event => abort if (!m_pointers[pointer].valid() || m_gestureState == TouchGestureUnknown || m_gestureState == TouchGestureMultiTouchDone) break; bool moving = false; for (unsigned int index = 0; index < TOUCH_MAX_POINTERS; index++) { if (m_pointers[index].valid() && m_pointers[index].moving) { moving = true; break; } } if (moving) { m_holdTimer->Stop(); // the touch is moving so we start a gesture if (m_gestureState == TouchGestureSingleTouch || m_gestureState == TouchGestureMultiTouchStart) result = OnTouchGestureStart(m_pointers[pointer].down.x, m_pointers[pointer].down.y); } triggerDetectors(event, pointer); if (m_gestureState == TouchGestureSingleTouch) { // Check if the touch has moved far enough to count as movement if (!m_pointers[pointer].moving) break; m_pointers[pointer].last.copy(m_pointers[pointer].down); setGestureState(TouchGesturePan); } else if (m_gestureState == TouchGestureMultiTouchStart) { setGestureState(TouchGestureMultiTouch); // set the starting point saveLastTouch(); } float offsetX = x - m_pointers[pointer].last.x; float offsetY = y - m_pointers[pointer].last.y; float velocityX = 0.0f; // number of pixels per second float velocityY = 0.0f; // number of pixels per second m_pointers[pointer].velocity(velocityX, velocityY); if (m_pointers[pointer].moving && (m_gestureState == TouchGestureSingleTouch || m_gestureState == TouchGestureSingleTouchHold || m_gestureState == TouchGesturePan)) result = OnSingleTouchMove(x, y, offsetX, offsetY, velocityX, velocityY); // Let's see if we have a pan gesture (i.e. the primary and only pointer moving) if (m_gestureState == TouchGesturePan) { result = OnTouchGesturePan(x, y, offsetX, offsetY, velocityX, velocityY); m_pointers[pointer].last.x = x; m_pointers[pointer].last.y = y; } else if (m_gestureState == TouchGestureMultiTouch) { if (moving) result = OnMultiTouchMove(x, y,offsetX, offsetY, velocityX, velocityY, pointer); } else break; return result; } default: CLog::Log(LOGDEBUG, "CGenericTouchInputHandler: unknown TouchInput"); break; } return false; }
bool TopWindow::OnEvent(const Event &event) { switch (event.type) { Window *w; case Event::NOP: case Event::QUIT: case Event::TIMER: case Event::USER: case Event::CALLBACK: break; case Event::KEY_DOWN: w = GetFocusedWindow(); if (w == nullptr) w = this; return w->OnKeyDown(event.param); case Event::KEY_UP: w = GetFocusedWindow(); if (w == nullptr) w = this; return w->OnKeyUp(event.param); case Event::MOUSE_MOTION: // XXX keys return OnMouseMove(event.point.x, event.point.y, 0); case Event::MOUSE_DOWN: return double_click.Check(event.point) ? OnMouseDouble(event.point.x, event.point.y) : OnMouseDown(event.point.x, event.point.y); case Event::MOUSE_UP: double_click.Moved(event.point); return OnMouseUp(event.point.x, event.point.y); case Event::MOUSE_WHEEL: return OnMouseWheel(event.point.x, event.point.y, (int)event.param); case Event::POINTER_DOWN: return OnMultiTouchDown(); case Event::POINTER_UP: return OnMultiTouchUp(); case Event::RESIZE: if (!surface_valid) /* postpone the resize if we're paused; the real resize will be handled by TopWindow::refresh() as soon as XCSoar is resumed */ return true; if (unsigned(event.point.x) == GetWidth() && unsigned(event.point.y) == GetHeight()) /* no-op */ return true; /* it seems the first page flip after a display orientation change is ignored on Android (tested on a Dell Streak / Android 2.2.2); let's do one dummy call before we really draw something */ screen->Flip(); Resize(event.point.x, event.point.y); return true; case Event::PAUSE: OnPause(); return true; case Event::RESUME: OnResume(); return true; } return false; }
bool TopWindow::OnEvent(const SDL_Event &event) { switch (event.type) { Window *w; #if SDL_MAJOR_VERSION < 2 case SDL_VIDEOEXPOSE: invalidated = false; Expose(); return true; #endif case SDL_KEYDOWN: w = GetFocusedWindow(); if (w == nullptr) w = this; if (!w->IsEnabled()) return false; #if SDL_MAJOR_VERSION >= 2 return w->OnKeyDown(event.key.keysym.sym); #else return w->OnKeyDown(event.key.keysym.sym) || (event.key.keysym.unicode != 0 && w->OnCharacter(event.key.keysym.unicode)); #endif #if SDL_MAJOR_VERSION >= 2 case SDL_TEXTINPUT: w = GetFocusedWindow(); if (w == nullptr) w = this; if (!w->IsEnabled()) return false; if (*event.text.text) { std::pair<unsigned, const char *> next = NextUTF8(event.text.text); bool handled = w->OnCharacter(next.first); while (next.second) { next = NextUTF8(next.second); handled = w->OnCharacter(next.first) || handled; } return handled; } else return false; #endif case SDL_KEYUP: w = GetFocusedWindow(); if (w == nullptr) w = this; if (!w->IsEnabled()) return false; return w->OnKeyUp(event.key.keysym.sym); #ifdef HAVE_MULTI_TOUCH case SDL_FINGERDOWN: if (SDL_GetNumTouchFingers(event.tfinger.touchId) == 2) return OnMultiTouchDown(); else return false; case SDL_FINGERUP: if (SDL_GetNumTouchFingers(event.tfinger.touchId) == 1) return OnMultiTouchUp(); else return false; #endif case SDL_MOUSEMOTION: // XXX keys #ifdef HAVE_HIGHDPI_SUPPORT { auto x = event.motion.x; auto y = event.motion.y; PointToReal(x, y); return OnMouseMove(x, y, 0); } #else return OnMouseMove(event.motion.x, event.motion.y, 0); #endif case SDL_MOUSEBUTTONDOWN: { #if SDL_MAJOR_VERSION < 2 if (event.button.button == SDL_BUTTON_WHEELUP) return OnMouseWheel(event.button.x, event.button.y, 1); else if (event.button.button == SDL_BUTTON_WHEELDOWN) return OnMouseWheel(event.button.x, event.button.y, -1); #endif #ifdef HAVE_HIGHDPI_SUPPORT auto x = event.button.x; auto y = event.button.y; PointToReal(x, y); return double_click.Check(RasterPoint(x, y)) ? OnMouseDouble(x, y) : OnMouseDown(x, y); #else return double_click.Check(RasterPoint(event.button.x, event.button.y)) ? OnMouseDouble(event.button.x, event.button.y) : OnMouseDown(event.button.x, event.button.y); #endif } case SDL_MOUSEBUTTONUP: { #if SDL_MAJOR_VERSION < 2 if (event.button.button == SDL_BUTTON_WHEELUP || event.button.button == SDL_BUTTON_WHEELDOWN) /* the wheel has already been handled in SDL_MOUSEBUTTONDOWN */ return false; #endif #ifdef HAVE_HIGHDPI_SUPPORT auto x = event.button.x; auto y = event.button.y; PointToReal(x, y); double_click.Moved(RasterPoint(x, y)); return OnMouseUp(x, y); #else double_click.Moved(RasterPoint(event.button.x, event.button.y)); return OnMouseUp(event.button.x, event.button.y); #endif } case SDL_QUIT: return OnClose(); #if SDL_MAJOR_VERSION < 2 case SDL_VIDEORESIZE: Resize(event.resize.w, event.resize.h); return true; #endif #if SDL_MAJOR_VERSION >= 2 case SDL_MOUSEWHEEL: { int x, y; SDL_GetMouseState(&x, &y); #ifdef HAVE_HIGHDPI_SUPPORT PointToReal(x, y); #endif return OnMouseWheel(x, y, event.wheel.y); } case SDL_WINDOWEVENT: switch (event.window.event) { case SDL_WINDOWEVENT_RESIZED: #ifndef HAVE_HIGHDPI_SUPPORT Resize(event.window.data1, event.window.data2); return true; #endif case SDL_WINDOWEVENT_RESTORED: case SDL_WINDOWEVENT_MOVED: case SDL_WINDOWEVENT_SHOWN: case SDL_WINDOWEVENT_MAXIMIZED: { SDL_Window* event_window = SDL_GetWindowFromID(event.window.windowID); if (event_window) { int w, h; SDL_GetWindowSize(event_window, &w, &h); if ((w >= 0) && (h >= 0)) { #ifdef HAVE_HIGHDPI_SUPPORT int real_w, real_h; SDL_GL_GetDrawableSize(event_window, &real_w, &real_h); point_to_real_x = static_cast<float>(real_w) / static_cast<float>(w); point_to_real_y = static_cast<float>(real_h) / static_cast<float>(h); Resize(real_w, real_h); #else Resize(w, h); #endif } #if defined(__MACOSX__) && __MACOSX__ SDL_SysWMinfo *wm_info = reinterpret_cast<SDL_SysWMinfo *>(alloca(sizeof(SDL_SysWMinfo))); SDL_VERSION(&wm_info->version); if ((SDL_GetWindowWMInfo(event_window, wm_info)) && (wm_info->subsystem == SDL_SYSWM_COCOA)) { [wm_info->info.cocoa.window setCollectionBehavior: NSWindowCollectionBehaviorFullScreenPrimary]; } Invalidate(); #endif } } return true; case SDL_WINDOWEVENT_EXPOSED: invalidated = false; Expose(); return true; } #endif }