From 79af58bcfa941e0f2c33b172c9e924522ebcdfea Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Thu, 19 Nov 2015 13:22:40 +0200 Subject: [PATCH] Rudimentary touchscreen support There are no touch-specific interactions yet, but this allows input to work with a touchscreen. --- source/container.cpp | 50 +++++++++++++++++++++++++++++---- source/container.h | 6 +++- source/root.cpp | 67 +++++++++++++++++++++++++++++++++++++++++++- source/root.h | 8 +++++- source/widget.cpp | 18 ++++++++++++ source/widget.h | 3 ++ 6 files changed, 143 insertions(+), 9 deletions(-) diff --git a/source/container.cpp b/source/container.cpp index b7bd2ad..21d31fb 100644 --- a/source/container.cpp +++ b/source/container.cpp @@ -16,7 +16,8 @@ Container::Container(): click_button(0), pointer_focus(0), pointer_grabbed(false), - input_focus(0) + input_focus(0), + touch_focus(0) { } Container::~Container() @@ -166,7 +167,7 @@ Widget *Container::get_final_input_focus() const void Container::button_press(int x, int y, unsigned btn) { - if(Widget *child = get_pointer_target(x, y)) + if(Widget *child = get_pointer_target(x, y, false)) { if(!click_focus) { @@ -185,7 +186,7 @@ void Container::button_press(int x, int y, unsigned btn) void Container::button_release(int x, int y, unsigned btn) { - if(Widget *child = get_pointer_target(x, y)) + if(Widget *child = get_pointer_target(x, y, false)) { if(child==click_focus && btn==click_button) { @@ -201,7 +202,7 @@ void Container::button_release(int x, int y, unsigned btn) void Container::pointer_motion(int x, int y) { - Widget *child = get_pointer_target(x, y); + Widget *child = get_pointer_target(x, y, false); if(!pointer_grabbed) set_pointer_focus((!click_focus || child->get_geometry().is_inside(x, y)) ? child : 0); @@ -212,12 +213,14 @@ void Container::pointer_motion(int x, int y) } } -Widget *Container::get_pointer_target(int x, int y) const +Widget *Container::get_pointer_target(int x, int y, bool touch) const { if(pointer_grabbed) return pointer_focus; - else if(click_focus) + else if(!touch && click_focus) return click_focus; + else if(touch && touch_focus) + return touch_focus; else { Widget *child = get_child_at(x, y); @@ -252,6 +255,41 @@ void Container::character(wchar_t ch) input_focus->character(ch); } +void Container::touch_press(int x, int y, unsigned finger) +{ + if(Widget *child = get_pointer_target(x, y, true)) + { + // TODO track focus for each finger separately + if(!touch_focus) + touch_focus = child; + + const Geometry &cgeom = child->get_geometry(); + child->touch_press(x-cgeom.x, y-cgeom.y, finger); + } +} + +void Container::touch_release(int x, int y, unsigned finger) +{ + if(Widget *child = get_pointer_target(x, y, true)) + { + // TODO track focus for each finger separately + if(child==touch_focus) + touch_focus = 0; + + const Geometry &cgeom = child->get_geometry(); + child->touch_release(x-cgeom.x, y-cgeom.y, finger); + } +} + +void Container::touch_motion(int x, int y, unsigned finger) +{ + if(Widget *child = get_pointer_target(x, y, true)) + { + const Geometry &cgeom = child->get_geometry(); + child->touch_motion(x-cgeom.x, y-cgeom.y, finger); + } +} + void Container::focus_out() { set_input_focus(0); diff --git a/source/container.h b/source/container.h index 2c29e5d..89e3259 100644 --- a/source/container.h +++ b/source/container.h @@ -40,6 +40,7 @@ protected: Widget *pointer_focus; bool pointer_grabbed; Widget *input_focus; + Widget *touch_focus; Container(); public: @@ -69,11 +70,14 @@ public: virtual void button_release(int, int, unsigned); virtual void pointer_motion(int, int); private: - Widget *get_pointer_target(int, int) const; + Widget *get_pointer_target(int, int, bool) const; public: virtual void pointer_leave(); virtual void key_press(unsigned, unsigned); virtual void key_release(unsigned, unsigned); + virtual void touch_press(int, int, unsigned); + virtual void touch_release(int, int, unsigned); + virtual void touch_motion(int, int, unsigned); virtual void character(wchar_t); virtual void focus_out(); protected: diff --git a/source/root.cpp b/source/root.cpp index 8b06f47..a90ea5a 100644 --- a/source/root.cpp +++ b/source/root.cpp @@ -16,15 +16,17 @@ Root::Root(const Resources &r, Graphics::Window &window): resources(r), keyboard(new Input::Keyboard(window)), mouse(new Input::Mouse(window)), + touchscreen(0), own_input(true) { init(&window); } -Root::Root(const Resources &r, Graphics::Window *window, Input::Keyboard *k, Input::Mouse *m): +Root::Root(const Resources &r, Graphics::Window *window, Input::Keyboard *k, Input::Mouse *m, Input::Touchscreen *t): resources(r), keyboard(k), mouse(m), + touchscreen(t), own_input(false) { init(window); @@ -68,6 +70,13 @@ void Root::init(Graphics::Window *window) keyboard->signal_button_release.connect(sigc::mem_fun(this, &Root::key_release_event)); keyboard->signal_character.connect(sigc::mem_fun(this, &Root::character_event)); } + + if(touchscreen) + { + touchscreen->signal_button_press.connect(sigc::mem_fun(this, &Root::touch_press_event)); + touchscreen->signal_button_release.connect(sigc::mem_fun(this, &Root::touch_release_event)); + touchscreen->signal_axis_motion.connect(sigc::mem_fun(this, &Root::touch_motion_event)); + } } Root::~Root() @@ -243,12 +252,68 @@ bool Root::character_event(StringCodec::unichar ch) return false; } +bool Root::touch_press_event(unsigned finger) +{ + if(visible) + { + Widget *old_focus = touch_focus; + + int x, y; + get_touch(finger, x, y); + touch_press(x, y, finger); + + if(touch_focus || old_focus) + return true; + } + + return false; +} + +bool Root::touch_release_event(unsigned finger) +{ + if(visible) + { + Widget *old_focus = touch_focus; + + int x, y; + get_touch(finger, x, y); + touch_release(x, y, finger); + + if(touch_focus || old_focus) + return true; + } + + return false; +} + +bool Root::touch_motion_event(unsigned axis, float, float) +{ + if(visible) + { + unsigned finger = axis/2; + int x, y; + get_touch(finger, x, y); + touch_motion(x, y, finger); + + if(touch_focus) + return true; + } + + return false; +} + void Root::get_pointer(int &x, int &y) { x = (mouse->get_axis_value(0)*0.5+0.5)*geom.w; y = (mouse->get_axis_value(1)*0.5+0.5)*geom.h; } +void Root::get_touch(unsigned finger, int &x, int &y) +{ + x = (touchscreen->get_axis_value(finger*2)*0.5+0.5)*geom.w; + y = (touchscreen->get_axis_value(finger*2+1)*0.5+0.5)*geom.h; +} + void Root::update_camera() { camera.set_position(GL::Vector3(geom.w/2.0f, geom.h/2.0f, geom.h/2.0f)); diff --git a/source/root.h b/source/root.h index 8e1bed9..5d721c0 100644 --- a/source/root.h +++ b/source/root.h @@ -7,6 +7,7 @@ #include #include #include +#include #include #include "panel.h" @@ -28,6 +29,7 @@ private: const Resources &resources; Input::Keyboard *keyboard; Input::Mouse *mouse; + Input::Touchscreen *touchscreen; bool own_input; Label *lbl_tooltip; int pointer_x; @@ -44,7 +46,7 @@ public: /** Creates a Root widget with custom input devices. If window is not null, it is used to set the widget's initial geometry. */ - Root(const Resources &, Graphics::Window *, Input::Keyboard *, Input::Mouse *); + Root(const Resources &, Graphics::Window *, Input::Keyboard *, Input::Mouse *, Input::Touchscreen * = 0); private: void init(Graphics::Window *); public: @@ -66,8 +68,12 @@ private: bool key_press_event(unsigned); bool key_release_event(unsigned); bool character_event(StringCodec::unichar); + bool touch_press_event(unsigned); + bool touch_release_event(unsigned); + bool touch_motion_event(unsigned, float, float); void get_pointer(int &, int &); + void get_touch(unsigned, int &, int &); void update_camera(); virtual void on_geometry_change(); diff --git a/source/widget.cpp b/source/widget.cpp index 76b6e61..38f8e92 100644 --- a/source/widget.cpp +++ b/source/widget.cpp @@ -240,6 +240,24 @@ void Widget::pointer_leave() clear_state(HOVER); } +void Widget::touch_press(int x, int y, unsigned finger) +{ + if(finger==0) + button_press(x, y, 1); +} + +void Widget::touch_release(int x, int y, unsigned finger) +{ + if(finger==0) + button_release(x, y, 1); +} + +void Widget::touch_motion(int x, int y, unsigned finger) +{ + if(finger==0) + pointer_motion(x, y); +} + void Widget::focus_in() { set_state(FOCUS); diff --git a/source/widget.h b/source/widget.h index 4550648..557e101 100644 --- a/source/widget.h +++ b/source/widget.h @@ -139,6 +139,9 @@ public: virtual void key_press(unsigned, unsigned) { } virtual void key_release(unsigned, unsigned) { } virtual void character(wchar_t) { } + virtual void touch_press(int, int, unsigned); + virtual void touch_release(int, int, unsigned); + virtual void touch_motion(int, int, unsigned); virtual void focus_in(); virtual void focus_out(); protected: -- 2.43.0