BsLinuxMouse.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Input/BsMouse.h"
  4. #include "Input/BsInput.h"
  5. #include "Linux/BsLinuxInput.h"
  6. #include <fcntl.h>
  7. #include <linux/input.h>
  8. namespace bs
  9. {
  10. constexpr UINT32 MAX_DEVICES = 8;
  11. /** Contains private data for the Linux Mouse implementation. */
  12. struct Mouse::Pimpl
  13. {
  14. INT32 fileHandles[MAX_DEVICES];
  15. bool hasInputFocus;
  16. };
  17. Mouse::Mouse(const String& name, Input* owner)
  18. : mName(name), mOwner(owner)
  19. {
  20. InputPrivateData* pvtData = owner->_getPrivateData();
  21. m = bs_new<Pimpl>();
  22. m->hasInputFocus = true;
  23. for(UINT32 i = 0; i < MAX_DEVICES; i++)
  24. m->fileHandles[i] = -1;
  25. UINT32 idx = 0;
  26. for(auto& entry : pvtData->mice)
  27. {
  28. String eventPath = "/dev/input/event" + toString(entry);
  29. m->fileHandles[idx] = open(eventPath.c_str(), O_RDWR | O_NONBLOCK);
  30. if(m->fileHandles[idx] == -1)
  31. LOGERR("Failed to open input event file handle for device: " + mName);
  32. idx++;
  33. if(idx >= MAX_DEVICES)
  34. break;
  35. }
  36. }
  37. Mouse::~Mouse()
  38. {
  39. for(UINT32 i = 0; i < MAX_DEVICES; i++)
  40. {
  41. if(m->fileHandles[i] != -1)
  42. close(m->fileHandles[i]);
  43. }
  44. bs_delete(m);
  45. }
  46. void Mouse::capture()
  47. {
  48. INT32 relX = 0;
  49. INT32 relY = 0;
  50. INT32 relZ = 0;
  51. input_event events[BUFFER_SIZE_MOUSE];
  52. for(UINT32 i = 0; i < MAX_DEVICES; i++)
  53. {
  54. if(m->fileHandles[i] == -1)
  55. continue;
  56. while(true)
  57. {
  58. ssize_t numReadBytes = read(m->fileHandles[i], &events, sizeof(events));
  59. if(numReadBytes < 0)
  60. break;
  61. if(!m->hasInputFocus)
  62. continue;
  63. UINT32 numEvents = numReadBytes / sizeof(input_event);
  64. for(UINT32 j = 0; j < numEvents; ++j)
  65. {
  66. switch(events[j].type)
  67. {
  68. case EV_KEY:
  69. {
  70. ButtonCode bc = BC_UNASSIGNED;
  71. // Unnamed mouse buttons
  72. if(events[j].code >= BTN_MISC && events[j].code < BTN_MOUSE)
  73. bc = (ButtonCode)((INT32)BC_MOUSE_BTN4 + (events[j].code - BTN_MISC));
  74. // Named mouse buttons
  75. else if(events[j].code >= BTN_MOUSE && events[j].code < BTN_JOYSTICK)
  76. {
  77. switch (events[j].code)
  78. {
  79. case BTN_LEFT:
  80. bc = BC_MOUSE_LEFT;
  81. break;
  82. case BTN_MIDDLE:
  83. bc = BC_MOUSE_MIDDLE;
  84. break;
  85. case BTN_RIGHT:
  86. bc = BC_MOUSE_RIGHT;
  87. break;
  88. case BTN_SIDE:
  89. bc = BC_MOUSE_BTN15;
  90. break;
  91. case BTN_EXTRA:
  92. bc = BC_MOUSE_BTN16;
  93. break;
  94. case BTN_FORWARD:
  95. bc = BC_MOUSE_BTN17;
  96. break;
  97. case BTN_BACK:
  98. bc = BC_MOUSE_BTN18;
  99. break;
  100. case BTN_TASK:
  101. bc = BC_MOUSE_BTN19;
  102. break;
  103. default:
  104. break;
  105. }
  106. }
  107. if(bc != BC_UNASSIGNED)
  108. {
  109. if (events[j].value)
  110. mOwner->_notifyButtonPressed(0, bc, (UINT64) events[j].time.tv_usec);
  111. else
  112. mOwner->_notifyButtonReleased(0, bc, (UINT64) events[j].time.tv_usec);
  113. }
  114. }
  115. break;
  116. case EV_REL:
  117. {
  118. switch(events[j].code)
  119. {
  120. case REL_X:
  121. relX += events[j].value;
  122. break;
  123. case REL_Y:
  124. relY += events[j].value;
  125. break;
  126. case REL_WHEEL:
  127. relZ += events[j].value;
  128. break;
  129. default:
  130. break;
  131. }
  132. break;
  133. }
  134. default: break;
  135. }
  136. }
  137. }
  138. }
  139. if(relX != 0 || relY != 0 || relZ != 0)
  140. mOwner->_notifyMouseMoved(relX, relY, relZ);
  141. }
  142. void Mouse::changeCaptureContext(UINT64 windowHandle)
  143. {
  144. m->hasInputFocus = windowHandle != (UINT64)-1;
  145. }
  146. }