diff --git a/base/PCMain.cpp b/base/PCMain.cpp index c0411fd100..0f10e27518 100644 --- a/base/PCMain.cpp +++ b/base/PCMain.cpp @@ -567,7 +567,7 @@ int main(int argc, char *argv[]) { case SDL_BUTTON_WHEELUP: { KeyInput key; - key.deviceId = DEVICE_ID_DEFAULT; + key.deviceId = DEVICE_ID_MOUSE; key.keyCode = KEYCODE_EXT_MOUSEWHEEL_UP; key.flags = KEY_DOWN; NativeKey(key); @@ -576,7 +576,7 @@ int main(int argc, char *argv[]) { case SDL_BUTTON_WHEELDOWN: { KeyInput key; - key.deviceId = DEVICE_ID_DEFAULT; + key.deviceId = DEVICE_ID_MOUSE; key.keyCode = KEYCODE_EXT_MOUSEWHEEL_DOWN; key.flags = KEY_DOWN; NativeKey(key); diff --git a/input/input_state.h b/input/input_state.h index 32e196a1e2..63435d8676 100644 --- a/input/input_state.h +++ b/input/input_state.h @@ -18,6 +18,7 @@ enum { DEVICE_ID_DEFAULT = 0, // Old Android DEVICE_ID_KEYBOARD = 1, // PC keyboard, android keyboards + DEVICE_ID_MOUSE = 2, // PC mouse only (not touchscreen!) DEVICE_ID_PAD_0 = 10, // Generic joypads DEVICE_ID_X360_0 = 20, // XInput joypads DEVICE_ID_ACCELEROMETER = 30, @@ -137,10 +138,12 @@ struct TouchInput { }; #undef KEY_DOWN +#undef KEY_UP enum { KEY_DOWN = 1, KEY_UP = 2, + KEY_HASWHEELDELTA = 4, }; struct KeyInput { diff --git a/input/keycodes.h b/input/keycodes.h index 369daae47e..5611cacc2c 100644 --- a/input/keycodes.h +++ b/input/keycodes.h @@ -224,7 +224,6 @@ typedef enum _keycode_t { KEYCODE_EXT_MOUSEWHEEL_DOWN = 1009 } keycode_t; - enum AndroidJoystickAxis { // Field descriptor #15 I JOYSTICK_AXIS_X = 0, diff --git a/ui/ui_screen.cpp b/ui/ui_screen.cpp index 8b913e8165..f3aeb597aa 100644 --- a/ui/ui_screen.cpp +++ b/ui/ui_screen.cpp @@ -41,6 +41,14 @@ void UIScreen::touch(const TouchInput &touch) { } } +void UIScreen::key(const KeyInput &key) { + if (root_) { + root_->Key(key); + } else { + ELOG("Tried to key without a view root"); + } +} + UI::EventReturn UIScreen::OnBack(UI::EventParams &e) { screenManager()->finishDialog(this, DR_OK); return UI::EVENT_DONE; diff --git a/ui/ui_screen.h b/ui/ui_screen.h index ff5dab0255..ae4e86d7c7 100644 --- a/ui/ui_screen.h +++ b/ui/ui_screen.h @@ -11,6 +11,7 @@ public: virtual void update(InputState &input); virtual void render(); virtual void touch(const TouchInput &touch); + virtual void key(const KeyInput &touch); // Some useful default event handlers UI::EventReturn OnBack(UI::EventParams &e); diff --git a/ui/view.cpp b/ui/view.cpp index b85da47bcc..0902ea4812 100644 --- a/ui/view.cpp +++ b/ui/view.cpp @@ -154,6 +154,11 @@ void Clickable::Touch(const TouchInput &input) { } } +void Clickable::Key(const KeyInput &input) { + // TODO: Replace most of Update with this. +} + + void Clickable::Update(const InputState &input_state) { if (!HasFocus()) return; diff --git a/ui/view.h b/ui/view.h index ab9c5c2d9b..ee6a4c23b2 100644 --- a/ui/view.h +++ b/ui/view.h @@ -21,6 +21,7 @@ #include "math/math_util.h" #include "math/geom2d.h" +struct KeyInput; struct TouchInput; struct InputState; @@ -255,6 +256,7 @@ public: // Please note that Touch is called ENTIRELY asynchronously from drawing! // Can even be called on a different thread! This is to really minimize latency, and decouple // touch response from the frame rate. + virtual void Key(const KeyInput &input) = 0; virtual void Touch(const TouchInput &input) = 0; virtual void Update(const InputState &input_state) = 0; @@ -332,6 +334,7 @@ public: InertView(LayoutParams *layoutParams) : View(layoutParams) {} + virtual void Key(const KeyInput &input) {} virtual void Touch(const TouchInput &input) {} virtual bool CanBeFocused() const { return false; } virtual void Update(const InputState &input_state) {} @@ -344,6 +347,7 @@ public: Clickable(LayoutParams *layoutParams) : View(layoutParams), downCountDown_(0), dragging_(false), down_(false) {} + virtual void Key(const KeyInput &input); virtual void Touch(const TouchInput &input); virtual void Update(const InputState &input_state); diff --git a/ui/viewgroup.cpp b/ui/viewgroup.cpp index 3d8f96170d..33fa15435a 100644 --- a/ui/viewgroup.cpp +++ b/ui/viewgroup.cpp @@ -1,6 +1,7 @@ #include "base/display.h" #include "base/functional.h" #include "base/logging.h" +#include "input/keycodes.h" #include "ui/ui_context.h" #include "ui/view.h" #include "ui/viewgroup.h" @@ -44,6 +45,15 @@ void ViewGroup::Touch(const TouchInput &input) { } } +void ViewGroup::Key(const KeyInput &input) { + for (auto iter = views_.begin(); iter != views_.end(); ++iter) { + // TODO: If there is a transformation active, transform input coordinates accordingly. + if ((*iter)->GetVisibility() == V_VISIBLE) + (*iter)->Key(input); + } +} + + void ViewGroup::Draw(UIContext &dc) { for (auto iter = views_.begin(); iter != views_.end(); ++iter) { // TODO: If there is a transformation active, transform input coordinates accordingly. @@ -443,6 +453,19 @@ void ScrollView::Layout() { views_[0]->Layout(); } +void ScrollView::Key(const KeyInput &input) { + if (input.flags & KEY_DOWN) { + switch (input.keyCode) { + case KEYCODE_EXT_MOUSEWHEEL_UP: + ScrollRelative(-250); + break; + case KEYCODE_EXT_MOUSEWHEEL_DOWN: + ScrollRelative(250); + break; + } + } +} + void ScrollView::Touch(const TouchInput &input) { if ((input.flags & TOUCH_DOWN) && input.id == 0) { scrollStart_ = scrollPos_; @@ -508,8 +531,28 @@ bool ScrollView::SubviewFocused(View *view) { void ScrollView::ScrollTo(float newScrollPos) { scrollTarget_ = newScrollPos; scrollToTarget_ = true; + ClampScrollTarget(); } +void ScrollView::ScrollRelative(float distance) { + scrollTarget_ = scrollPos_ + distance; + scrollToTarget_ = true; + ClampScrollTarget(); +} + +void ScrollView::ClampScrollTarget() { + // Clamp scrollTarget. + if (scrollTarget_ < 0.0f) { + scrollTarget_ = 0.0f; + } + float childHeight = views_[0]->GetBounds().h; + float scrollMax = std::max(0.0f, childHeight - bounds_.h); + if (scrollTarget_ > scrollMax) { + scrollTarget_ = scrollMax; + } +} + + void ScrollView::Update(const InputState &input_state) { ViewGroup::Update(input_state); if (scrollToTarget_) { diff --git a/ui/viewgroup.h b/ui/viewgroup.h index 2d460b266d..0321aef12e 100644 --- a/ui/viewgroup.h +++ b/ui/viewgroup.h @@ -21,6 +21,7 @@ public: virtual ~ViewGroup(); // Pass through external events to children. + virtual void Key(const KeyInput &input); virtual void Touch(const TouchInput &input); // By default, a container will layout to its own bounds. @@ -171,16 +172,20 @@ public: void Measure(const UIContext &dc, MeasureSpec horiz, MeasureSpec vert); void Layout(); + void Key(const KeyInput &input); void Touch(const TouchInput &input); void Draw(UIContext &dc); void ScrollTo(float newScrollPos); + void ScrollRelative(float distance); void Update(const InputState &input_state); // Override so that we can scroll to the active one after moving the focus. virtual bool SubviewFocused(View *view); private: + void ClampScrollTarget(); + GestureDetector gesture_; Orientation orientation_; float scrollPos_;