You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

BaseTouchHandler.cxx 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196
  1. /* Copyright 2019 Aaron Sowry for Cendio AB
  2. * Copyright 2019-2020 Pierre Ossman for Cendio AB
  3. *
  4. * This is free software; you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation; either version 2 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This software is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this software; if not, write to the Free Software
  16. * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,
  17. * USA.
  18. */
  19. #ifdef HAVE_CONFIG_H
  20. #include <config.h>
  21. #endif
  22. #include <stdlib.h>
  23. #include <math.h>
  24. #define XK_MISCELLANY
  25. #include <rfb/keysymdef.h>
  26. #include <rfb/util.h>
  27. #include "GestureHandler.h"
  28. #include "BaseTouchHandler.h"
  29. // Sensitivity threshold for gestures
  30. static const int ZOOMSENS = 30;
  31. static const int SCRLSENS = 50;
  32. static const unsigned DOUBLE_TAP_TIMEOUT = 1000;
  33. static const unsigned DOUBLE_TAP_THRESHOLD = 50;
  34. BaseTouchHandler::BaseTouchHandler()
  35. {
  36. gettimeofday(&lastTapTime, NULL);
  37. }
  38. BaseTouchHandler::~BaseTouchHandler()
  39. {
  40. }
  41. void BaseTouchHandler::handleGestureEvent(const GestureEvent& ev)
  42. {
  43. double magnitude;
  44. switch (ev.type) {
  45. case GestureBegin:
  46. switch (ev.gesture) {
  47. case GestureOneTap:
  48. handleTapEvent(ev, 1);
  49. break;
  50. case GestureTwoTap:
  51. handleTapEvent(ev, 3);
  52. break;
  53. case GestureThreeTap:
  54. handleTapEvent(ev, 2);
  55. break;
  56. case GestureDrag:
  57. fakeMotionEvent(ev);
  58. fakeButtonEvent(true, 1, ev);
  59. break;
  60. case GestureLongPress:
  61. fakeMotionEvent(ev);
  62. fakeButtonEvent(true, 3, ev);
  63. break;
  64. case GestureTwoDrag:
  65. lastMagnitudeX = ev.magnitudeX;
  66. lastMagnitudeY = ev.magnitudeY;
  67. fakeMotionEvent(ev);
  68. break;
  69. case GesturePinch:
  70. lastMagnitudeX = hypot(ev.magnitudeX, ev.magnitudeY);
  71. fakeMotionEvent(ev);
  72. break;
  73. }
  74. break;
  75. case GestureUpdate:
  76. switch (ev.gesture) {
  77. case GestureOneTap:
  78. case GestureTwoTap:
  79. case GestureThreeTap:
  80. break;
  81. case GestureDrag:
  82. case GestureLongPress:
  83. fakeMotionEvent(ev);
  84. break;
  85. case GestureTwoDrag:
  86. // Always scroll in the same position.
  87. // We don't know if the mouse was moved so we need to move it
  88. // every update.
  89. fakeMotionEvent(ev);
  90. while ((ev.magnitudeY - lastMagnitudeY) > SCRLSENS) {
  91. fakeButtonEvent(true, 4, ev);
  92. fakeButtonEvent(false, 4, ev);
  93. lastMagnitudeY += SCRLSENS;
  94. }
  95. while ((ev.magnitudeY - lastMagnitudeY) < -SCRLSENS) {
  96. fakeButtonEvent(true, 5, ev);
  97. fakeButtonEvent(false, 5, ev);
  98. lastMagnitudeY -= SCRLSENS;
  99. }
  100. while ((ev.magnitudeX - lastMagnitudeX) > SCRLSENS) {
  101. fakeButtonEvent(true, 6, ev);
  102. fakeButtonEvent(false, 6, ev);
  103. lastMagnitudeX += SCRLSENS;
  104. }
  105. while ((ev.magnitudeX - lastMagnitudeX) < -SCRLSENS) {
  106. fakeButtonEvent(true, 7, ev);
  107. fakeButtonEvent(false, 7, ev);
  108. lastMagnitudeX -= SCRLSENS;
  109. }
  110. break;
  111. case GesturePinch:
  112. // Always scroll in the same position.
  113. // We don't know if the mouse was moved so we need to move it
  114. // every update.
  115. fakeMotionEvent(ev);
  116. magnitude = hypot(ev.magnitudeX, ev.magnitudeY);
  117. if (abs(magnitude - lastMagnitudeX) > ZOOMSENS) {
  118. fakeKeyEvent(true, XK_Control_L, ev);
  119. while ((magnitude - lastMagnitudeX) > ZOOMSENS) {
  120. fakeButtonEvent(true, 4, ev);
  121. fakeButtonEvent(false, 4, ev);
  122. lastMagnitudeX += ZOOMSENS;
  123. }
  124. while ((magnitude - lastMagnitudeX) < -ZOOMSENS) {
  125. fakeButtonEvent(true, 5, ev);
  126. fakeButtonEvent(false, 5, ev);
  127. lastMagnitudeX -= ZOOMSENS;
  128. }
  129. fakeKeyEvent(false, XK_Control_L, ev);
  130. }
  131. }
  132. break;
  133. case GestureEnd:
  134. switch (ev.gesture) {
  135. case GestureOneTap:
  136. case GestureTwoTap:
  137. case GestureThreeTap:
  138. case GesturePinch:
  139. case GestureTwoDrag:
  140. break;
  141. case GestureDrag:
  142. fakeMotionEvent(ev);
  143. fakeButtonEvent(false, 1, ev);
  144. break;
  145. case GestureLongPress:
  146. fakeMotionEvent(ev);
  147. fakeButtonEvent(false, 3, ev);
  148. break;
  149. }
  150. break;
  151. }
  152. }
  153. void BaseTouchHandler::handleTapEvent(const GestureEvent& ev,
  154. int buttonEvent)
  155. {
  156. GestureEvent newEv = ev;
  157. // If the user quickly taps multiple times we assume they meant to
  158. // hit the same spot, so slightly adjust coordinates
  159. if ((rfb::msSince(&lastTapTime) < DOUBLE_TAP_TIMEOUT) &&
  160. (firstDoubleTapEvent.type == ev.type)) {
  161. double dx = firstDoubleTapEvent.eventX - ev.eventX;
  162. double dy = firstDoubleTapEvent.eventY - ev.eventY;
  163. double distance = hypot(dx, dy);
  164. if (distance < DOUBLE_TAP_THRESHOLD) {
  165. newEv.eventX = firstDoubleTapEvent.eventX;
  166. newEv.eventY = firstDoubleTapEvent.eventY;
  167. } else {
  168. firstDoubleTapEvent = ev;
  169. }
  170. } else {
  171. firstDoubleTapEvent = ev;
  172. }
  173. gettimeofday(&lastTapTime, NULL);
  174. fakeMotionEvent(newEv);
  175. fakeButtonEvent(true, buttonEvent, newEv);
  176. fakeButtonEvent(false, buttonEvent, newEv);
  177. }