1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #ifndef REMOTING_HOST_TOUCH_INJECTOR_WIN_H_
6 #define REMOTING_HOST_TOUCH_INJECTOR_WIN_H_
7 
8 #include <windows.h>
9 #include <stdint.h>
10 #include <map>
11 #include <memory>
12 #include <vector>
13 
14 #include "base/macros.h"
15 #include "base/scoped_native_library.h"
16 
17 namespace remoting {
18 
19 namespace protocol {
20 
21 class TouchEvent;
22 
23 }  // namespace protocol
24 
25 // This class calls InitializeTouchInjection() and InjectTouchInput() functions.
26 // The methods are virtual for mocking.
27 class TouchInjectorWinDelegate {
28  public:
29   virtual ~TouchInjectorWinDelegate();
30 
31   // Determines whether Windows touch injection functions can be used.
32   // Returns a non-null TouchInjectorWinDelegate on success.
33   static std::unique_ptr<TouchInjectorWinDelegate> Create();
34 
35   // These match the functions in MSDN.
36   virtual BOOL InitializeTouchInjection(UINT32 max_count, DWORD dw_mode);
37   virtual DWORD InjectTouchInput(UINT32 count,
38                                  const POINTER_TOUCH_INFO* contacts);
39 
40  protected:
41   // Ctor in protected scope for mocking.
42   // This object takes ownership of the |library|.
43   TouchInjectorWinDelegate(
44       base::NativeLibrary library,
45       BOOL(NTAPI* initialize_touch_injection_func)(UINT32, DWORD),
46       BOOL(NTAPI* inject_touch_input_func)(UINT32, const POINTER_TOUCH_INFO*));
47 
48  private:
49   base::ScopedNativeLibrary library_module_;
50 
51   // Pointers to Windows touch injection functions.
52   BOOL(NTAPI* initialize_touch_injection_func_)(UINT32, DWORD);
53   BOOL(NTAPI* inject_touch_input_func_)(UINT32, const POINTER_TOUCH_INFO*);
54 
55   DISALLOW_COPY_AND_ASSIGN(TouchInjectorWinDelegate);
56 };
57 
58 // This class converts TouchEvent objects to POINTER_TOUCH_INFO so that it can
59 // be injected using the Windows touch injection API, and calls the injection
60 // functions.
61 // This class expects good inputs and does not sanity check the inputs.
62 // This class just converts the object and hands it off to the Windows API.
63 class TouchInjectorWin {
64  public:
65   TouchInjectorWin();
66   ~TouchInjectorWin();
67 
68   // Returns false if initialization of touch injection APIs fails.
69   bool Init();
70 
71   // Deinitializes the object so that it can be reinitialized.
72   void Deinitialize();
73 
74   // Inject touch events.
75   void InjectTouchEvent(const protocol::TouchEvent& event);
76 
77   void SetInjectorDelegateForTest(
78       std::unique_ptr<TouchInjectorWinDelegate> functions);
79 
80  private:
81   // Helper methods called from InjectTouchEvent().
82   // These helpers adapt Chromoting touch events, which convey changes to touch
83   // points, to Windows touch descriptions, which must include descriptions for
84   // all currently-active touch points, not just the changed ones.
85   void AddNewTouchPoints(const protocol::TouchEvent& event);
86   void MoveTouchPoints(const protocol::TouchEvent& event);
87   void EndTouchPoints(const protocol::TouchEvent& event);
88   void CancelTouchPoints(const protocol::TouchEvent& event);
89 
90   // Set to null if touch injection is not available from the OS.
91   std::unique_ptr<TouchInjectorWinDelegate> delegate_;
92 
93   // TODO(rkuroiwa): crbug.com/470203
94   // This is a naive implementation. Check if we can achieve
95   // better performance by reducing the number of copies.
96   // To reduce the number of copies, we can have a vector of
97   // POINTER_TOUCH_INFO and a map from touch ID to index in the vector.
98   // When removing points from the vector, just swap it with the last element
99   // and resize the vector.
100   // All the POINTER_TOUCH_INFOs are stored as "move" points.
101   std::map<uint32_t, POINTER_TOUCH_INFO> touches_in_contact_;
102 
103   DISALLOW_COPY_AND_ASSIGN(TouchInjectorWin);
104 };
105 
106 }  // namespace remoting
107 
108 #endif  // REMOTING_HOST_TOUCH_INJECTOR_WIN_H_
109