BsLinuxKeyboard.cpp 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. //********************************** Banshee Engine (www.banshee3d.com) **************************************************//
  2. //**************** Copyright (c) 2016 Marko Pintera ([email protected]). All rights reserved. **********************//
  3. #include "Input/BsKeyboard.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 Keyboard implementation. */
  12. struct Keyboard::Pimpl
  13. {
  14. INT32 fileHandles[MAX_DEVICES];
  15. bool hasInputFocus;
  16. };
  17. Keyboard::Keyboard(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->keyboards)
  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. Keyboard::~Keyboard()
  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 Keyboard::capture()
  47. {
  48. input_event events[BUFFER_SIZE_KEYBOARD];
  49. for(UINT32 i = 0; i < MAX_DEVICES; i++)
  50. {
  51. if(m->fileHandles[i] == -1)
  52. continue;
  53. if(!m->hasInputFocus)
  54. continue;
  55. while(true)
  56. {
  57. ssize_t numReadBytes = read(m->fileHandles[i], &events, sizeof(events));
  58. if(numReadBytes < 0)
  59. break;
  60. UINT32 numEvents = numReadBytes / sizeof(input_event);
  61. for(UINT32 j = 0; j < numEvents; ++j)
  62. {
  63. switch(events[j].type)
  64. {
  65. case EV_KEY:
  66. {
  67. ButtonCode bc = (ButtonCode)events[j].code;
  68. if(bc < BC_MOUSE_LEFT)
  69. {
  70. if(events[j].value)
  71. mOwner->_notifyButtonPressed(0, bc, (UINT64)events[j].time.tv_usec);
  72. else
  73. mOwner->_notifyButtonReleased(0, bc, (UINT64)events[j].time.tv_usec);
  74. }
  75. }
  76. break;
  77. default: break;
  78. }
  79. }
  80. }
  81. }
  82. }
  83. void Keyboard::changeCaptureContext(UINT64 windowHandle)
  84. {
  85. m->hasInputFocus = windowHandle != (UINT64)-1;
  86. }
  87. }