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.5KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198
  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 = sqrt(ev.magnitudeX * ev.magnitudeX +
  71. ev.magnitudeY * ev.magnitudeY);
  72. fakeMotionEvent(ev);
  73. break;
  74. }
  75. break;
  76. case GestureUpdate:
  77. switch (ev.gesture) {
  78. case GestureOneTap:
  79. case GestureTwoTap:
  80. case GestureThreeTap:
  81. break;
  82. case GestureDrag:
  83. case GestureLongPress:
  84. fakeMotionEvent(ev);
  85. break;
  86. case GestureTwoDrag:
  87. // Always scroll in the same position.
  88. // We don't know if the mouse was moved so we need to move it
  89. // every update.
  90. fakeMotionEvent(ev);
  91. while ((ev.magnitudeY - lastMagnitudeY) > SCRLSENS) {
  92. fakeButtonEvent(true, 4, ev);
  93. fakeButtonEvent(false, 4, ev);
  94. lastMagnitudeY += SCRLSENS;
  95. }
  96. while ((ev.magnitudeY - lastMagnitudeY) < -SCRLSENS) {
  97. fakeButtonEvent(true, 5, ev);
  98. fakeButtonEvent(false, 5, ev);
  99. lastMagnitudeY -= SCRLSENS;
  100. }
  101. while ((ev.magnitudeX - lastMagnitudeX) > SCRLSENS) {
  102. fakeButtonEvent(true, 6, ev);
  103. fakeButtonEvent(false, 6, ev);
  104. lastMagnitudeX += SCRLSENS;
  105. }
  106. while ((ev.magnitudeX - lastMagnitudeX) < -SCRLSENS) {
  107. fakeButtonEvent(true, 7, ev);
  108. fakeButtonEvent(false, 7, ev);
  109. lastMagnitudeX -= SCRLSENS;
  110. }
  111. break;
  112. case GesturePinch:
  113. // Always scroll in the same position.
  114. // We don't know if the mouse was moved so we need to move it
  115. // every update.
  116. fakeMotionEvent(ev);
  117. magnitude = sqrt(ev.magnitudeX * ev.magnitudeX +
  118. ev.magnitudeY * ev.magnitudeY);
  119. if (abs(magnitude - lastMagnitudeX) > ZOOMSENS) {
  120. fakeKeyEvent(true, XK_Control_L, ev);
  121. while ((magnitude - lastMagnitudeX) > ZOOMSENS) {
  122. fakeButtonEvent(true, 4, ev);
  123. fakeButtonEvent(false, 4, ev);
  124. lastMagnitudeX += ZOOMSENS;
  125. }
  126. while ((magnitude - lastMagnitudeX) < -ZOOMSENS) {
  127. fakeButtonEvent(true, 5, ev);
  128. fakeButtonEvent(false, 5, ev);
  129. lastMagnitudeX -= ZOOMSENS;
  130. }
  131. fakeKeyEvent(false, XK_Control_L, ev);
  132. }
  133. }
  134. break;
  135. case GestureEnd:
  136. switch (ev.gesture) {
  137. case GestureOneTap:
  138. case GestureTwoTap:
  139. case GestureThreeTap:
  140. case GesturePinch:
  141. case GestureTwoDrag:
  142. break;
  143. case GestureDrag:
  144. fakeMotionEvent(ev);
  145. fakeButtonEvent(false, 1, ev);
  146. break;
  147. case GestureLongPress:
  148. fakeMotionEvent(ev);
  149. fakeButtonEvent(false, 3, ev);
  150. break;
  151. }
  152. break;
  153. }
  154. }
  155. void BaseTouchHandler::handleTapEvent(const GestureEvent& ev,
  156. int buttonEvent)
  157. {
  158. GestureEvent newEv = ev;
  159. // If the user quickly taps multiple times we assume they meant to
  160. // hit the same spot, so slightly adjust coordinates
  161. if ((rfb::msSince(&lastTapTime) < DOUBLE_TAP_TIMEOUT) &&
  162. (firstDoubleTapEvent.type == ev.type)) {
  163. double dx = firstDoubleTapEvent.eventX - ev.eventX;
  164. double dy = firstDoubleTapEvent.eventY - ev.eventY;
  165. double distance = sqrt((dx * dx) + (dy * dy));
  166. if (distance < DOUBLE_TAP_THRESHOLD) {
  167. newEv.eventX = firstDoubleTapEvent.eventX;
  168. newEv.eventY = firstDoubleTapEvent.eventY;
  169. } else {
  170. firstDoubleTapEvent = ev;
  171. }
  172. } else {
  173. firstDoubleTapEvent = ev;
  174. }
  175. gettimeofday(&lastTapTime, NULL);
  176. fakeMotionEvent(newEv);
  177. fakeButtonEvent(true, buttonEvent, newEv);
  178. fakeButtonEvent(false, buttonEvent, newEv);
  179. }