]> git.tdb.fi Git - libs/gui.git/commitdiff
Touchscreen input device
authorMikko Rasa <tdb@tdb.fi>
Thu, 13 Nov 2014 20:40:25 +0000 (22:40 +0200)
committerMikko Rasa <tdb@tdb.fi>
Thu, 13 Nov 2014 20:40:25 +0000 (22:40 +0200)
Currently only implemented for Windows.

14 files changed:
source/graphics/android/window.cpp
source/graphics/cocoa/window.cpp
source/graphics/window.cpp
source/graphics/window.h
source/graphics/windows/window.cpp
source/graphics/windows/window_platform.h
source/graphics/x11/window.cpp
source/input/android/touchscreen.cpp [new file with mode: 0644]
source/input/cocoa/touchscreen.cpp [new file with mode: 0644]
source/input/touchscreen.cpp [new file with mode: 0644]
source/input/touchscreen.h [new file with mode: 0644]
source/input/windows/mouse.cpp
source/input/windows/touchscreen.cpp [new file with mode: 0644]
source/input/x11/touchscreen.cpp [new file with mode: 0644]

index 465d32529f4d2511a738f2b8f224e80487ff24a5..3a584203527743e18ae4d8c5b5e849bba3b66a50 100644 (file)
@@ -33,6 +33,10 @@ void Window::warp_pointer(int, int)
 {
 }
 
+void Window::platform_set_touch_input()
+{
+}
+
 void Window::platform_show()
 {
 }
index 321934c13b03d39140651be61330614a07236bbf..abaefe2fdc4c6e81980fa951746cacf354ba4def 100644 (file)
@@ -37,6 +37,10 @@ void Window::warp_pointer(int, int)
 {
 }
 
+void Window::platform_set_touch_input()
+{
+}
+
 void Window::platform_show()
 {
        show_window(priv->window);
index ebdc578e14d44524f982c74e29beb2503a7c0c99..d2fb37f893d23379a1df46914b175f3a7312bdc5 100644 (file)
@@ -37,6 +37,7 @@ void Window::init()
 {
        visible = false;
        kbd_autorepeat = true;
+       touch_input = false;
        resizing = false;
        priv = new Private;
 
@@ -85,6 +86,12 @@ void Window::set_keyboard_autorepeat(bool r)
        kbd_autorepeat = r;
 }
 
+void Window::set_touch_input(bool t)
+{
+       touch_input = t;
+       platform_set_touch_input();
+}
+
 void Window::show()
 {
        platform_show();
index 55751b3d5a15cf689972ac38e3dc0f890f2d4a64..70b40443d3d84575f93f4fefc51ffa99119da2c1 100644 (file)
@@ -38,6 +38,7 @@ protected:
        WindowOptions options;
        bool visible;
        bool kbd_autorepeat;
+       bool touch_input;
        bool resizing;
        Private *priv;
 
@@ -60,6 +61,11 @@ public:
        bool get_keyboard_autorepeat() const { return kbd_autorepeat; }
        void show_cursor(bool);
        void warp_pointer(int, int);
+       void set_touch_input(bool);
+private:
+       void platform_set_touch_input();
+public:
+       bool get_touch_input() const { return touch_input; }
 
        Display &get_display() const { return display; }
        const WindowOptions &get_options() const { return options; }
index e9989501565b303c16ae3fe9eaad4dce9d8b1ee2..2af6b83917e153664f8f82220ba56f0849f7e802 100644 (file)
@@ -1,3 +1,4 @@
+#define _WIN32_WINNT 0x0601
 #include <windowsx.h>
 #include <msp/core/application.h>
 #include <msp/core/systemerror.h>
@@ -22,6 +23,7 @@ LRESULT CALLBACK wndproc_(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam)
                ev.msg = msg;
                ev.wparam = wparam;
                ev.lparam = lparam;
+               ev.extra = GetMessageExtraInfo();
                if(wnd && wnd->event(ev))
                        return 0;
        }
@@ -129,6 +131,21 @@ void Window::warp_pointer(int, int)
 {
 }
 
+void Window::platform_set_touch_input()
+{
+       WORD winver = LOWORD(GetVersion);
+       if(winver<_WIN32_WINNT)
+       {
+               touch_input = false;
+               throw runtime_error("no touch support");
+       }
+
+       if(touch_input)
+               RegisterTouchWindow(priv->window, 3);  // TWF_FINETOUCH|TWF_WANTPALM
+       else
+               UnregisterTouchWindow(priv->window);
+}
+
 void Window::platform_show()
 {
        ShowWindow(priv->window, SW_SHOWNORMAL);
@@ -153,6 +170,7 @@ bool Window::event(const Event &evnt)
        case WM_RBUTTONUP:
        case WM_MOUSEWHEEL:
        case WM_MOUSEMOVE:
+       case WM_TOUCHMOVE:
                signal_input_event.emit(evnt);
                break;
        case WM_SIZE:
index 1ff5cf367669a9a63558cd750a5125bcf794509f..7d53f555e9c4d8dc5e902103c41b1d1e119ed61c 100644 (file)
@@ -17,6 +17,7 @@ struct PlatformEvent
        UINT msg;
        WPARAM wparam;
        LPARAM lparam;
+       LPARAM extra;
 };
 
 } // namespace Graphics
index b7fabd557064c3e7433ce76e049effd3c8beb6e1..1747da9b2ba7198acd07873179284194ba4800ac 100644 (file)
@@ -151,6 +151,10 @@ void Window::warp_pointer(int x, int y)
        XWarpPointer(display.get_private().display, None, priv->window, 0, 0, 0, 0, x, y);
 }
 
+void Window::platform_set_touch_input()
+{
+}
+
 void Window::platform_show()
 {
        XMapRaised(display.get_private().display, priv->window);
diff --git a/source/input/android/touchscreen.cpp b/source/input/android/touchscreen.cpp
new file mode 100644 (file)
index 0000000..bfbf7aa
--- /dev/null
@@ -0,0 +1,11 @@
+#include "touchscreen.h"
+
+namespace Msp {
+namespace Input {
+
+void Touchscreen::input_event(const Graphics::Window::Event &)
+{
+}
+
+} // namespace Input
+} // namespace Msp
diff --git a/source/input/cocoa/touchscreen.cpp b/source/input/cocoa/touchscreen.cpp
new file mode 100644 (file)
index 0000000..bfbf7aa
--- /dev/null
@@ -0,0 +1,11 @@
+#include "touchscreen.h"
+
+namespace Msp {
+namespace Input {
+
+void Touchscreen::input_event(const Graphics::Window::Event &)
+{
+}
+
+} // namespace Input
+} // namespace Msp
diff --git a/source/input/touchscreen.cpp b/source/input/touchscreen.cpp
new file mode 100644 (file)
index 0000000..95fd272
--- /dev/null
@@ -0,0 +1,80 @@
+#include "touchscreen.h"
+
+using namespace std;
+
+namespace Msp {
+namespace Input {
+
+Touchscreen::Touchscreen(Graphics::Window &w):
+       window(w)
+{
+       name = "Touchscreen";
+
+       window.set_touch_input(true);
+       window.signal_input_event.connect(sigc::mem_fun(this, &Touchscreen::input_event));
+}
+
+Touchscreen::~Touchscreen()
+{
+       window.set_touch_input(false);
+}
+
+string Touchscreen::get_button_name(unsigned btn) const
+{
+       if(btn==0)
+               return "Primary touch";
+       else
+               return Device::get_button_name(btn);
+}
+
+string Touchscreen::get_axis_name(unsigned axis) const
+{
+       if(axis==0)
+               return "Primary touch X";
+       else if(axis==1)
+               return "Primary touch Y";
+       else
+               return Device::get_axis_name(axis);
+}
+
+unsigned Touchscreen::map_point_id(unsigned id)
+{
+       unsigned unused = active_points.size();
+       for(unsigned i=0; i<active_points.size(); ++i)
+       {
+               if(active_points[i]==id)
+                       return i;
+               else if(active_points[i]==UNUSED && i<unused)
+                       unused = i;
+       }
+
+       if(unused<active_points.size())
+               active_points[unused] = id;
+       else
+               active_points.push_back(id);
+
+       return unused;
+}
+
+void Touchscreen::touch_down(unsigned id)
+{
+       unsigned i = map_point_id(id);
+       set_button_state(i, true, true);
+}
+
+void Touchscreen::touch_move(unsigned id, float x, float y)
+{
+       unsigned i = map_point_id(id);
+       set_axis_value(i*2, x, true);
+       set_axis_value(i*2+1, y, true);
+}
+
+void Touchscreen::touch_up(unsigned id)
+{
+       unsigned i = map_point_id(id);
+       set_button_state(i, true, false);
+       active_points[i] = UNUSED;
+}
+
+} // namespace Input
+} // namespace Msp
diff --git a/source/input/touchscreen.h b/source/input/touchscreen.h
new file mode 100644 (file)
index 0000000..363111c
--- /dev/null
@@ -0,0 +1,40 @@
+#ifndef MSP_INPUT_TOUCHSCREEN_H_
+#define MSP_INPUT_TOUCHSCREEN_H_
+
+#include <sigc++/trackable.h>
+#include <msp/graphics/window.h>
+#include "device.h"
+
+namespace Msp {
+namespace Input {
+
+class Touchscreen: public Device, public sigc::trackable
+{
+private:
+       enum
+       {
+               UNUSED = static_cast<unsigned>(-1)
+       };
+
+       Graphics::Window &window;
+       std::vector<unsigned> active_points;
+
+public:
+       Touchscreen(Graphics::Window &);
+       ~Touchscreen();
+
+       virtual std::string get_button_name(unsigned) const;
+       virtual std::string get_axis_name(unsigned) const;
+private:
+       void input_event(const Graphics::Window::Event &);
+
+       unsigned map_point_id(unsigned);
+       void touch_down(unsigned);
+       void touch_move(unsigned, float, float);
+       void touch_up(unsigned);
+};
+
+} // namespace Input
+} // namespace Msp
+
+#endif
index 77f84885a4f31c28d0ced2642f708fd0e6a39e00..aae5141b6d7f16d7593e2a6dc246472d77230801 100644 (file)
@@ -7,6 +7,10 @@ namespace Input {
 
 void Mouse::input_event(const Graphics::Window::Event &event)
 {
+       // http://msdn.microsoft.com/en-us/library/windows/desktop/ms703320.aspx
+       if(window.get_touch_input() && (event.extra&0xFFFFFF00)==0xFF515700)
+               return;
+
        switch(event.msg)
        {
        case WM_LBUTTONDOWN:
diff --git a/source/input/windows/touchscreen.cpp b/source/input/windows/touchscreen.cpp
new file mode 100644 (file)
index 0000000..180f1c0
--- /dev/null
@@ -0,0 +1,47 @@
+#define _WIN32_WINNT 0x0601
+#include <windows.h>
+#include <msp/graphics/window_private.h>
+#include "touchscreen.h"
+
+using namespace std;
+
+namespace Msp {
+namespace Input {
+
+void Touchscreen::input_event(const Graphics::Window::Event &event)
+{
+       if(event.msg==WM_TOUCHMOVE)
+       {
+               HTOUCHINPUT handle = reinterpret_cast<HTOUCHINPUT>(event.lparam);
+               unsigned n_points = LOWORD(event.wparam);
+               /* If I ever invent a legitimate use case for more touch points than an
+               average human has fingers, I'll come up with something else here. */
+               TOUCHINPUT touch_buffer[10];
+               if(!GetTouchInputInfo(handle, 10, touch_buffer, sizeof(TOUCHINPUT)))
+                       return;
+
+               for(unsigned i=0; i<n_points; ++i)
+               {
+                       const TOUCHINPUT &point = touch_buffer[i];
+
+                       POINT screen_pt = { point.x/100, point.y/100 };
+                       POINT client_pt = screen_pt;
+                       ScreenToClient(window.get_private().window, &client_pt);
+                       float x = (point.x/100.0f-screen_pt.x+client_pt.x)*2.0f/window.get_width()-1.0f;
+                       float y = 1.0f-(point.y/100.0f-screen_pt.y+client_pt.y)*2.0f/window.get_height();
+
+                       touch_move(point.dwID, x, y);
+                       if(point.dwFlags&TOUCHEVENTF_DOWN)
+                               touch_down(point.dwID);
+                       else if(point.dwFlags&TOUCHEVENTF_UP)
+                               touch_up(point.dwID);
+               }
+
+               CloseTouchInputHandle(handle);
+       }
+}
+
+
+
+} // namespace Input
+} // namespace Msp
diff --git a/source/input/x11/touchscreen.cpp b/source/input/x11/touchscreen.cpp
new file mode 100644 (file)
index 0000000..bfbf7aa
--- /dev/null
@@ -0,0 +1,11 @@
+#include "touchscreen.h"
+
+namespace Msp {
+namespace Input {
+
+void Touchscreen::input_event(const Graphics::Window::Event &)
+{
+}
+
+} // namespace Input
+} // namespace Msp