haiku_direct_window.cpp 8.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344
  1. #include <UnicodeChar.h>
  2. #include "main/main.h"
  3. #include "os/keyboard.h"
  4. #include "haiku_direct_window.h"
  5. #include "key_mapping_haiku.h"
  6. HaikuDirectWindow::HaikuDirectWindow(BRect p_frame)
  7. : BDirectWindow(p_frame, "Godot", B_TITLED_WINDOW, B_QUIT_ON_WINDOW_CLOSE)
  8. {
  9. last_mouse_pos_valid = false;
  10. last_buttons_state = 0;
  11. last_button_mask = 0;
  12. last_key_modifier_state = 0;
  13. }
  14. HaikuDirectWindow::~HaikuDirectWindow() {
  15. if (update_runner) {
  16. delete update_runner;
  17. }
  18. }
  19. void HaikuDirectWindow::SetHaikuGLView(HaikuGLView* p_view) {
  20. view = p_view;
  21. }
  22. void HaikuDirectWindow::StartMessageRunner() {
  23. update_runner = new BMessageRunner(BMessenger(this),
  24. new BMessage(REDRAW_MSG), 1000000/30 /* 30 fps */);
  25. }
  26. void HaikuDirectWindow::StopMessageRunner() {
  27. delete update_runner;
  28. }
  29. void HaikuDirectWindow::SetInput(InputDefault* p_input) {
  30. input = p_input;
  31. }
  32. void HaikuDirectWindow::SetMainLoop(MainLoop* p_main_loop) {
  33. main_loop = p_main_loop;
  34. }
  35. bool HaikuDirectWindow::QuitRequested() {
  36. main_loop->notification(MainLoop::NOTIFICATION_WM_QUIT_REQUEST);
  37. return false;
  38. }
  39. void HaikuDirectWindow::DirectConnected(direct_buffer_info* info) {
  40. view->DirectConnected(info);
  41. view->EnableDirectMode(true);
  42. }
  43. void HaikuDirectWindow::MessageReceived(BMessage* message) {
  44. switch (message->what) {
  45. case REDRAW_MSG:
  46. if (Main::iteration() == true) {
  47. view->EnableDirectMode(false);
  48. Quit();
  49. }
  50. break;
  51. default:
  52. BDirectWindow::MessageReceived(message);
  53. }
  54. }
  55. void HaikuDirectWindow::DispatchMessage(BMessage* message, BHandler* handler) {
  56. switch (message->what) {
  57. case B_MOUSE_DOWN:
  58. case B_MOUSE_UP:
  59. HandleMouseButton(message);
  60. break;
  61. case B_MOUSE_MOVED:
  62. HandleMouseMoved(message);
  63. break;
  64. case B_MOUSE_WHEEL_CHANGED:
  65. HandleMouseWheelChanged(message);
  66. break;
  67. case B_KEY_DOWN:
  68. case B_KEY_UP:
  69. HandleKeyboardEvent(message);
  70. break;
  71. case B_MODIFIERS_CHANGED:
  72. HandleKeyboardModifierEvent(message);
  73. break;
  74. case B_WINDOW_RESIZED:
  75. HandleWindowResized(message);
  76. break;
  77. case LOCKGL_MSG:
  78. view->LockGL();
  79. break;
  80. case UNLOCKGL_MSG:
  81. view->UnlockGL();
  82. break;
  83. default:
  84. BDirectWindow::DispatchMessage(message, handler);
  85. }
  86. }
  87. void HaikuDirectWindow::HandleMouseButton(BMessage* message) {
  88. BPoint where;
  89. if (message->FindPoint("where", &where) != B_OK) {
  90. return;
  91. }
  92. uint32 modifiers = message->FindInt32("modifiers");
  93. uint32 buttons = message->FindInt32("buttons");
  94. uint32 button = buttons ^ last_buttons_state;
  95. last_buttons_state = buttons;
  96. // TODO: implement the mouse_mode checks
  97. //if (mouse_mode == MOUSE_MODE_CAPTURED) {
  98. // event.xbutton.x=last_mouse_pos.x;
  99. // event.xbutton.y=last_mouse_pos.y;
  100. //}
  101. InputEvent mouse_event;
  102. mouse_event.ID = ++event_id;
  103. mouse_event.type = InputEvent::MOUSE_BUTTON;
  104. mouse_event.device = 0;
  105. mouse_event.mouse_button.mod = GetKeyModifierState(modifiers);
  106. mouse_event.mouse_button.button_mask = GetMouseButtonState(buttons);
  107. mouse_event.mouse_button.x = where.x;
  108. mouse_event.mouse_button.y = where.y;
  109. mouse_event.mouse_button.global_x = where.x;
  110. mouse_event.mouse_button.global_y = where.y;
  111. switch (button) {
  112. default:
  113. case B_PRIMARY_MOUSE_BUTTON:
  114. mouse_event.mouse_button.button_index = 1;
  115. break;
  116. case B_SECONDARY_MOUSE_BUTTON:
  117. mouse_event.mouse_button.button_index = 2;
  118. break;
  119. case B_TERTIARY_MOUSE_BUTTON:
  120. mouse_event.mouse_button.button_index = 3;
  121. break;
  122. }
  123. mouse_event.mouse_button.pressed = (message->what == B_MOUSE_DOWN);
  124. if (message->what == B_MOUSE_DOWN && mouse_event.mouse_button.button_index == 1) {
  125. int32 clicks = message->FindInt32("clicks");
  126. if (clicks > 1) {
  127. mouse_event.mouse_button.doubleclick=true;
  128. }
  129. }
  130. input->parse_input_event(mouse_event);
  131. }
  132. void HaikuDirectWindow::HandleMouseMoved(BMessage* message) {
  133. BPoint where;
  134. if (message->FindPoint("where", &where) != B_OK) {
  135. return;
  136. }
  137. Point2i pos(where.x, where.y);
  138. uint32 modifiers = message->FindInt32("modifiers");
  139. uint32 buttons = message->FindInt32("buttons");
  140. if (!last_mouse_pos_valid) {
  141. last_mouse_position = pos;
  142. last_mouse_pos_valid = true;
  143. }
  144. Point2i rel = pos - last_mouse_position;
  145. InputEvent motion_event;
  146. motion_event.ID = ++event_id;
  147. motion_event.type = InputEvent::MOUSE_MOTION;
  148. motion_event.device = 0;
  149. motion_event.mouse_motion.mod = GetKeyModifierState(modifiers);
  150. motion_event.mouse_motion.button_mask = GetMouseButtonState(buttons);
  151. motion_event.mouse_motion.x = pos.x;
  152. motion_event.mouse_motion.y = pos.y;
  153. input->set_mouse_pos(pos);
  154. motion_event.mouse_motion.global_x = pos.x;
  155. motion_event.mouse_motion.global_y = pos.y;
  156. motion_event.mouse_motion.speed_x = input->get_mouse_speed().x;
  157. motion_event.mouse_motion.speed_y = input->get_mouse_speed().y;
  158. motion_event.mouse_motion.relative_x = rel.x;
  159. motion_event.mouse_motion.relative_y = rel.y;
  160. last_mouse_position = pos;
  161. input->parse_input_event(motion_event);
  162. }
  163. void HaikuDirectWindow::HandleMouseWheelChanged(BMessage* message) {
  164. float wheel_delta_y = 0;
  165. if (message->FindFloat("be:wheel_delta_y", &wheel_delta_y) != B_OK) {
  166. return;
  167. }
  168. InputEvent mouse_event;
  169. mouse_event.ID = ++event_id;
  170. mouse_event.type = InputEvent::MOUSE_BUTTON;
  171. mouse_event.device = 0;
  172. mouse_event.mouse_button.button_index = wheel_delta_y < 0 ? 4 : 5;
  173. mouse_event.mouse_button.mod = GetKeyModifierState(last_key_modifier_state);
  174. mouse_event.mouse_button.button_mask = last_button_mask;
  175. mouse_event.mouse_button.x = last_mouse_position.x;
  176. mouse_event.mouse_button.y = last_mouse_position.y;
  177. mouse_event.mouse_button.global_x = last_mouse_position.x;
  178. mouse_event.mouse_button.global_y = last_mouse_position.y;
  179. mouse_event.mouse_button.pressed = true;
  180. input->parse_input_event(mouse_event);
  181. mouse_event.ID = ++event_id;
  182. mouse_event.mouse_button.pressed = false;
  183. input->parse_input_event(mouse_event);
  184. }
  185. void HaikuDirectWindow::HandleKeyboardEvent(BMessage* message) {
  186. int32 raw_char = 0;
  187. int32 key = 0;
  188. int32 modifiers = 0;
  189. if (message->FindInt32("raw_char", &raw_char) != B_OK) {
  190. return;
  191. }
  192. if (message->FindInt32("key", &key) != B_OK) {
  193. return;
  194. }
  195. if (message->FindInt32("modifiers", &modifiers) != B_OK) {
  196. return;
  197. }
  198. InputEvent event;
  199. event.ID = ++event_id;
  200. event.type = InputEvent::KEY;
  201. event.device = 0;
  202. event.key.mod = GetKeyModifierState(modifiers);
  203. event.key.pressed = (message->what == B_KEY_DOWN);
  204. event.key.scancode = KeyMappingHaiku::get_keysym(raw_char, key);
  205. event.key.echo = message->HasInt32("be:key_repeat");
  206. event.key.unicode = 0;
  207. const char* bytes = NULL;
  208. if (message->FindString("bytes", &bytes) == B_OK) {
  209. event.key.unicode = BUnicodeChar::FromUTF8(&bytes);
  210. }
  211. //make it consistent accross platforms.
  212. if (event.key.scancode==KEY_BACKTAB) {
  213. event.key.scancode=KEY_TAB;
  214. event.key.mod.shift=true;
  215. }
  216. input->parse_input_event(event);
  217. }
  218. void HaikuDirectWindow::HandleKeyboardModifierEvent(BMessage* message) {
  219. int32 old_modifiers = 0;
  220. int32 modifiers = 0;
  221. if (message->FindInt32("be:old_modifiers", &old_modifiers) != B_OK) {
  222. return;
  223. }
  224. if (message->FindInt32("modifiers", &modifiers) != B_OK) {
  225. return;
  226. }
  227. int32 key = old_modifiers ^ modifiers;
  228. InputEvent event;
  229. event.ID = ++event_id;
  230. event.type = InputEvent::KEY;
  231. event.device = 0;
  232. event.key.mod = GetKeyModifierState(modifiers);
  233. event.key.pressed = ((modifiers & key) != 0);
  234. event.key.scancode = KeyMappingHaiku::get_modifier_keysym(key);
  235. event.key.echo = false;
  236. event.key.unicode = 0;
  237. input->parse_input_event(event);
  238. }
  239. void HaikuDirectWindow::HandleWindowResized(BMessage* message) {
  240. int32 width = 0;
  241. int32 height = 0;
  242. if ((message->FindInt32("width", &width) != B_OK) || (message->FindInt32("height", &height) != B_OK)) {
  243. return;
  244. }
  245. current_video_mode->width = width;
  246. current_video_mode->height = height;
  247. }
  248. inline InputModifierState HaikuDirectWindow::GetKeyModifierState(uint32 p_state) {
  249. last_key_modifier_state = p_state;
  250. InputModifierState state;
  251. state.shift = (p_state & B_SHIFT_KEY) != 0;
  252. state.control = (p_state & B_CONTROL_KEY) != 0;
  253. state.alt = (p_state & B_OPTION_KEY) != 0;
  254. state.meta = (p_state & B_COMMAND_KEY) != 0;
  255. return state;
  256. }
  257. inline int HaikuDirectWindow::GetMouseButtonState(uint32 p_state) {
  258. int state = 0;
  259. if (p_state & B_PRIMARY_MOUSE_BUTTON) {
  260. state |= 1 << 0;
  261. }
  262. if (p_state & B_SECONDARY_MOUSE_BUTTON) {
  263. state |= 1 << 1;
  264. }
  265. if (p_state & B_TERTIARY_MOUSE_BUTTON) {
  266. state |= 1 << 2;
  267. }
  268. last_button_mask = state;
  269. return state;
  270. }