Blender  V3.3
GHOST_SystemSDL.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
7 #include <cassert>
8 
9 #include "GHOST_ContextSDL.h"
10 #include "GHOST_SystemSDL.h"
11 #include "GHOST_WindowSDL.h"
12 
13 #include "GHOST_WindowManager.h"
14 
15 #include "GHOST_EventButton.h"
16 #include "GHOST_EventCursor.h"
17 #include "GHOST_EventKey.h"
18 #include "GHOST_EventWheel.h"
19 
21 {
22  if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER) != 0) {
23  printf("Error initializing SDL: %s\n", SDL_GetError());
24  }
25 
26  SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
27  SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);
28  SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8);
29  SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8);
30  SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8);
31 }
32 
34 {
35  SDL_Quit();
36 }
37 
38 GHOST_IWindow *GHOST_SystemSDL::createWindow(const char *title,
39  int32_t left,
40  int32_t top,
45  GHOST_GLSettings glSettings,
46  const bool exclusive,
47  const bool /* is_dialog */,
48  const GHOST_IWindow *parentWindow)
49 {
50  GHOST_WindowSDL *window = nullptr;
51 
52  window = new GHOST_WindowSDL(this,
53  title,
54  left,
55  top,
56  width,
57  height,
58  state,
59  type,
60  ((glSettings.flags & GHOST_glStereoVisual) != 0),
61  exclusive,
62  parentWindow);
63 
64  if (window) {
66  SDL_Window *sdl_win = window->getSDLWindow();
67  SDL_DisplayMode mode;
68 
69  static_cast<GHOST_DisplayManagerSDL *>(m_displayManager)->getCurrentDisplayModeSDL(mode);
70 
71  SDL_SetWindowDisplayMode(sdl_win, &mode);
72  SDL_ShowWindow(sdl_win);
73  SDL_SetWindowFullscreen(sdl_win, SDL_TRUE);
74  }
75 
76  if (window->getValid()) {
77  m_windowManager->addWindow(window);
79  }
80  else {
81  delete window;
82  window = nullptr;
83  }
84  }
85  return window;
86 }
87 
88 GHOST_TSuccess GHOST_SystemSDL::init()
89 {
91 
92  if (success) {
94 
95  if (m_displayManager) {
96  return GHOST_kSuccess;
97  }
98  }
99 
100  return GHOST_kFailure;
101 }
102 
108 {
109  SDL_DisplayMode mode;
110  SDL_GetDesktopDisplayMode(0, &mode); /* NOTE: always 0 display. */
111  width = mode.w;
112  height = mode.h;
113 }
114 
116 {
117  SDL_DisplayMode mode;
118  SDL_GetCurrentDisplayMode(0, &mode); /* NOTE: always 0 display. */
119  width = mode.w;
120  height = mode.h;
121 }
122 
124 {
125  return SDL_GetNumVideoDisplays();
126 }
127 
129 {
131  nullptr,
132  0, /* Profile bit. */
133  3,
134  3,
137 
138  if (context->initializeDrawingContext()) {
139  return context;
140  }
141  delete context;
142 
143  return nullptr;
144 }
145 
147 {
148  delete context;
149 
150  return GHOST_kSuccess;
151 }
152 
154 {
155  SDL_Keymod mod = SDL_GetModState();
156 
157  keys.set(GHOST_kModifierKeyLeftShift, (mod & KMOD_LSHIFT) != 0);
158  keys.set(GHOST_kModifierKeyRightShift, (mod & KMOD_RSHIFT) != 0);
159  keys.set(GHOST_kModifierKeyLeftControl, (mod & KMOD_LCTRL) != 0);
160  keys.set(GHOST_kModifierKeyRightControl, (mod & KMOD_RCTRL) != 0);
161  keys.set(GHOST_kModifierKeyLeftAlt, (mod & KMOD_LALT) != 0);
162  keys.set(GHOST_kModifierKeyRightAlt, (mod & KMOD_RALT) != 0);
163  keys.set(GHOST_kModifierKeyOS, (mod & (KMOD_LGUI | KMOD_RGUI)) != 0);
164 
165  return GHOST_kSuccess;
166 }
167 
168 #define GXMAP(k, x, y) \
169  case x: \
170  k = y; \
171  break
172 
173 static GHOST_TKey convertSDLKey(SDL_Scancode key)
174 {
176 
177  if ((key >= SDL_SCANCODE_A) && (key <= SDL_SCANCODE_Z)) {
178  type = GHOST_TKey(key - SDL_SCANCODE_A + int(GHOST_kKeyA));
179  }
180  else if ((key >= SDL_SCANCODE_1) && (key <= SDL_SCANCODE_0)) {
181  type = (key == SDL_SCANCODE_0) ? GHOST_kKey0 :
182  GHOST_TKey(key - SDL_SCANCODE_1 + int(GHOST_kKey1));
183  }
184  else if ((key >= SDL_SCANCODE_F1) && (key <= SDL_SCANCODE_F12)) {
185  type = GHOST_TKey(key - SDL_SCANCODE_F1 + int(GHOST_kKeyF1));
186  }
187  else if ((key >= SDL_SCANCODE_F13) && (key <= SDL_SCANCODE_F24)) {
188  type = GHOST_TKey(key - SDL_SCANCODE_F13 + int(GHOST_kKeyF13));
189  }
190  else {
191  switch (key) {
192  /* TODO SDL_SCANCODE_NONUSBACKSLASH */
193 
194  GXMAP(type, SDL_SCANCODE_BACKSPACE, GHOST_kKeyBackSpace);
195  GXMAP(type, SDL_SCANCODE_TAB, GHOST_kKeyTab);
196  GXMAP(type, SDL_SCANCODE_RETURN, GHOST_kKeyEnter);
197  GXMAP(type, SDL_SCANCODE_ESCAPE, GHOST_kKeyEsc);
198  GXMAP(type, SDL_SCANCODE_SPACE, GHOST_kKeySpace);
199 
200  GXMAP(type, SDL_SCANCODE_SEMICOLON, GHOST_kKeySemicolon);
201  GXMAP(type, SDL_SCANCODE_PERIOD, GHOST_kKeyPeriod);
202  GXMAP(type, SDL_SCANCODE_COMMA, GHOST_kKeyComma);
203  GXMAP(type, SDL_SCANCODE_APOSTROPHE, GHOST_kKeyQuote);
204  GXMAP(type, SDL_SCANCODE_GRAVE, GHOST_kKeyAccentGrave);
205  GXMAP(type, SDL_SCANCODE_MINUS, GHOST_kKeyMinus);
206  GXMAP(type, SDL_SCANCODE_EQUALS, GHOST_kKeyEqual);
207 
208  GXMAP(type, SDL_SCANCODE_SLASH, GHOST_kKeySlash);
209  GXMAP(type, SDL_SCANCODE_BACKSLASH, GHOST_kKeyBackslash);
210  GXMAP(type, SDL_SCANCODE_KP_EQUALS, GHOST_kKeyEqual);
211  GXMAP(type, SDL_SCANCODE_LEFTBRACKET, GHOST_kKeyLeftBracket);
212  GXMAP(type, SDL_SCANCODE_RIGHTBRACKET, GHOST_kKeyRightBracket);
213  GXMAP(type, SDL_SCANCODE_PAUSE, GHOST_kKeyPause);
214 
215  GXMAP(type, SDL_SCANCODE_LSHIFT, GHOST_kKeyLeftShift);
216  GXMAP(type, SDL_SCANCODE_RSHIFT, GHOST_kKeyRightShift);
217  GXMAP(type, SDL_SCANCODE_LCTRL, GHOST_kKeyLeftControl);
218  GXMAP(type, SDL_SCANCODE_RCTRL, GHOST_kKeyRightControl);
219  GXMAP(type, SDL_SCANCODE_LALT, GHOST_kKeyLeftAlt);
220  GXMAP(type, SDL_SCANCODE_RALT, GHOST_kKeyRightAlt);
221  GXMAP(type, SDL_SCANCODE_LGUI, GHOST_kKeyOS);
222  GXMAP(type, SDL_SCANCODE_RGUI, GHOST_kKeyOS);
223  GXMAP(type, SDL_SCANCODE_APPLICATION, GHOST_kKeyApp);
224 
225  GXMAP(type, SDL_SCANCODE_INSERT, GHOST_kKeyInsert);
226  GXMAP(type, SDL_SCANCODE_DELETE, GHOST_kKeyDelete);
227  GXMAP(type, SDL_SCANCODE_HOME, GHOST_kKeyHome);
228  GXMAP(type, SDL_SCANCODE_END, GHOST_kKeyEnd);
229  GXMAP(type, SDL_SCANCODE_PAGEUP, GHOST_kKeyUpPage);
230  GXMAP(type, SDL_SCANCODE_PAGEDOWN, GHOST_kKeyDownPage);
231 
232  GXMAP(type, SDL_SCANCODE_LEFT, GHOST_kKeyLeftArrow);
233  GXMAP(type, SDL_SCANCODE_RIGHT, GHOST_kKeyRightArrow);
234  GXMAP(type, SDL_SCANCODE_UP, GHOST_kKeyUpArrow);
235  GXMAP(type, SDL_SCANCODE_DOWN, GHOST_kKeyDownArrow);
236 
237  GXMAP(type, SDL_SCANCODE_CAPSLOCK, GHOST_kKeyCapsLock);
238  GXMAP(type, SDL_SCANCODE_SCROLLLOCK, GHOST_kKeyScrollLock);
239  GXMAP(type, SDL_SCANCODE_NUMLOCKCLEAR, GHOST_kKeyNumLock);
240  GXMAP(type, SDL_SCANCODE_PRINTSCREEN, GHOST_kKeyPrintScreen);
241 
242  /* keypad events */
243 
244  /* NOTE: SDL defines a bunch of key-pad identifiers that aren't supported by GHOST,
245  * such as #SDL_SCANCODE_KP_PERCENT, #SDL_SCANCODE_KP_XOR. */
246  GXMAP(type, SDL_SCANCODE_KP_0, GHOST_kKeyNumpad0);
247  GXMAP(type, SDL_SCANCODE_KP_1, GHOST_kKeyNumpad1);
248  GXMAP(type, SDL_SCANCODE_KP_2, GHOST_kKeyNumpad2);
249  GXMAP(type, SDL_SCANCODE_KP_3, GHOST_kKeyNumpad3);
250  GXMAP(type, SDL_SCANCODE_KP_4, GHOST_kKeyNumpad4);
251  GXMAP(type, SDL_SCANCODE_KP_5, GHOST_kKeyNumpad5);
252  GXMAP(type, SDL_SCANCODE_KP_6, GHOST_kKeyNumpad6);
253  GXMAP(type, SDL_SCANCODE_KP_7, GHOST_kKeyNumpad7);
254  GXMAP(type, SDL_SCANCODE_KP_8, GHOST_kKeyNumpad8);
255  GXMAP(type, SDL_SCANCODE_KP_9, GHOST_kKeyNumpad9);
256  GXMAP(type, SDL_SCANCODE_KP_PERIOD, GHOST_kKeyNumpadPeriod);
257 
258  GXMAP(type, SDL_SCANCODE_KP_ENTER, GHOST_kKeyNumpadEnter);
259  GXMAP(type, SDL_SCANCODE_KP_PLUS, GHOST_kKeyNumpadPlus);
260  GXMAP(type, SDL_SCANCODE_KP_MINUS, GHOST_kKeyNumpadMinus);
261  GXMAP(type, SDL_SCANCODE_KP_MULTIPLY, GHOST_kKeyNumpadAsterisk);
262  GXMAP(type, SDL_SCANCODE_KP_DIVIDE, GHOST_kKeyNumpadSlash);
263 
264  /* Media keys in some keyboards and laptops with XFree86/Xorg */
265  GXMAP(type, SDL_SCANCODE_AUDIOPLAY, GHOST_kKeyMediaPlay);
266  GXMAP(type, SDL_SCANCODE_AUDIOSTOP, GHOST_kKeyMediaStop);
267  GXMAP(type, SDL_SCANCODE_AUDIOPREV, GHOST_kKeyMediaFirst);
268  // GXMAP(type, XF86XK_AudioRewind, GHOST_kKeyMediaFirst);
269  GXMAP(type, SDL_SCANCODE_AUDIONEXT, GHOST_kKeyMediaLast);
270 
271  default:
272  printf("Unknown\n");
274  break;
275  }
276  }
277 
278  return type;
279 }
280 #undef GXMAP
281 
282 static char convert_keyboard_event_to_ascii(const SDL_KeyboardEvent &sdl_sub_evt)
283 {
284  SDL_Keycode sym = sdl_sub_evt.keysym.sym;
285  if (sym > 127) {
286  switch (sym) {
287  case SDLK_KP_DIVIDE:
288  sym = '/';
289  break;
290  case SDLK_KP_MULTIPLY:
291  sym = '*';
292  break;
293  case SDLK_KP_MINUS:
294  sym = '-';
295  break;
296  case SDLK_KP_PLUS:
297  sym = '+';
298  break;
299  case SDLK_KP_1:
300  sym = '1';
301  break;
302  case SDLK_KP_2:
303  sym = '2';
304  break;
305  case SDLK_KP_3:
306  sym = '3';
307  break;
308  case SDLK_KP_4:
309  sym = '4';
310  break;
311  case SDLK_KP_5:
312  sym = '5';
313  break;
314  case SDLK_KP_6:
315  sym = '6';
316  break;
317  case SDLK_KP_7:
318  sym = '7';
319  break;
320  case SDLK_KP_8:
321  sym = '8';
322  break;
323  case SDLK_KP_9:
324  sym = '9';
325  break;
326  case SDLK_KP_0:
327  sym = '0';
328  break;
329  case SDLK_KP_PERIOD:
330  sym = '.';
331  break;
332  default:
333  sym = 0;
334  break;
335  }
336  }
337  else {
338  if (sdl_sub_evt.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT)) {
339  /* Weak US keyboard assumptions. */
340  if (sym >= 'a' && sym <= ('a' + 32)) {
341  sym -= 32;
342  }
343  else {
344  switch (sym) {
345  case '`':
346  sym = '~';
347  break;
348  case '1':
349  sym = '!';
350  break;
351  case '2':
352  sym = '@';
353  break;
354  case '3':
355  sym = '#';
356  break;
357  case '4':
358  sym = '$';
359  break;
360  case '5':
361  sym = '%';
362  break;
363  case '6':
364  sym = '^';
365  break;
366  case '7':
367  sym = '&';
368  break;
369  case '8':
370  sym = '*';
371  break;
372  case '9':
373  sym = '(';
374  break;
375  case '0':
376  sym = ')';
377  break;
378  case '-':
379  sym = '_';
380  break;
381  case '=':
382  sym = '+';
383  break;
384  case '[':
385  sym = '{';
386  break;
387  case ']':
388  sym = '}';
389  break;
390  case '\\':
391  sym = '|';
392  break;
393  case ';':
394  sym = ':';
395  break;
396  case '\'':
397  sym = '"';
398  break;
399  case ',':
400  sym = '<';
401  break;
402  case '.':
403  sym = '>';
404  break;
405  case '/':
406  sym = '?';
407  break;
408  default:
409  break;
410  }
411  }
412  }
413  }
414  return (char)sym;
415 }
416 
421 static SDL_Window *SDL_GetWindowFromID_fallback(Uint32 id)
422 {
423  SDL_Window *sdl_win = SDL_GetWindowFromID(id);
424  if (sdl_win == nullptr) {
425  sdl_win = SDL_GL_GetCurrentWindow();
426  }
427  return sdl_win;
428 }
429 
430 void GHOST_SystemSDL::processEvent(SDL_Event *sdl_event)
431 {
432  GHOST_Event *g_event = nullptr;
433 
434  switch (sdl_event->type) {
435  case SDL_WINDOWEVENT: {
436  SDL_WindowEvent &sdl_sub_evt = sdl_event->window;
437  GHOST_WindowSDL *window = findGhostWindow(
438  SDL_GetWindowFromID_fallback(sdl_sub_evt.windowID));
439  /* Can be nullptr on close window. */
440 #if 0
441  assert(window != nullptr);
442 #endif
443 
444  switch (sdl_sub_evt.event) {
445  case SDL_WINDOWEVENT_EXPOSED:
446  g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window);
447  break;
448  case SDL_WINDOWEVENT_RESIZED:
449  g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window);
450  break;
451  case SDL_WINDOWEVENT_MOVED:
452  g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowMove, window);
453  break;
454  case SDL_WINDOWEVENT_FOCUS_GAINED:
455  g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window);
456  break;
457  case SDL_WINDOWEVENT_FOCUS_LOST:
458  g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window);
459  break;
460  case SDL_WINDOWEVENT_CLOSE:
461  g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window);
462  break;
463  }
464 
465  break;
466  }
467 
468  case SDL_QUIT: {
470  g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventQuitRequest, window);
471  break;
472  }
473 
474  case SDL_MOUSEMOTION: {
475  SDL_MouseMotionEvent &sdl_sub_evt = sdl_event->motion;
476  SDL_Window *sdl_win = SDL_GetWindowFromID_fallback(sdl_sub_evt.windowID);
477  GHOST_WindowSDL *window = findGhostWindow(sdl_win);
478  assert(window != nullptr);
479 
480  int x_win, y_win;
481  SDL_GetWindowPosition(sdl_win, &x_win, &y_win);
482 
483  int32_t x_root = sdl_sub_evt.x + x_win;
484  int32_t y_root = sdl_sub_evt.y + y_win;
485 
486 #if 0
487  if (window->getCursorGrabMode() != GHOST_kGrabDisable &&
488  window->getCursorGrabMode() != GHOST_kGrabNormal) {
489  int32_t x_new = x_root;
490  int32_t y_new = y_root;
491  int32_t x_accum, y_accum;
493 
494  /* fallback to window bounds */
495  if (window->getCursorGrabBounds(bounds) == GHOST_kFailure)
496  window->getClientBounds(bounds);
497 
498  /* Could also clamp to screen bounds wrap with a window outside the view will
499  * fail at the moment. Use offset of 8 in case the window is at screen bounds. */
500  bounds.wrapPoint(x_new, y_new, 8, window->getCursorGrabAxis());
501  window->getCursorGrabAccum(x_accum, y_accum);
502 
503  /* Can't use #setCursorPosition because the mouse may have no focus! */
504  if (x_new != x_root || y_new != y_root) {
505  if (1 /* `xme.time > m_last_warp` */ ) {
506  /* when wrapping we don't need to add an event because the
507  * #setCursorPosition call will cause a new event after */
508  SDL_WarpMouseInWindow(sdl_win, x_new - x_win, y_new - y_win); /* wrap */
509  window->setCursorGrabAccum(x_accum + (x_root - x_new), y_accum + (y_root - y_new));
510  // m_last_warp = lastEventTime(xme.time);
511  }
512  else {
513  // setCursorPosition(x_new, y_new); /* wrap but don't accumulate */
514  SDL_WarpMouseInWindow(sdl_win, x_new - x_win, y_new - y_win);
515  }
516 
517  g_event = new GHOST_EventCursor(getMilliSeconds(),
519  window,
520  x_new,
521  y_new,
523  }
524  else {
525  g_event = new GHOST_EventCursor(getMilliSeconds(),
527  window,
528  x_root + x_accum,
529  y_root + y_accum,
531  }
532  }
533  else
534 #endif
535  {
536  g_event = new GHOST_EventCursor(getMilliSeconds(),
538  window,
539  x_root,
540  y_root,
542  }
543  break;
544  }
545  case SDL_MOUSEBUTTONUP:
546  case SDL_MOUSEBUTTONDOWN: {
547  SDL_MouseButtonEvent &sdl_sub_evt = sdl_event->button;
549  GHOST_TEventType type = (sdl_sub_evt.state == SDL_PRESSED) ? GHOST_kEventButtonDown :
551 
552  GHOST_WindowSDL *window = findGhostWindow(
553  SDL_GetWindowFromID_fallback(sdl_sub_evt.windowID));
554  assert(window != nullptr);
555 
556  /* process rest of normal mouse buttons */
557  if (sdl_sub_evt.button == SDL_BUTTON_LEFT) {
558  gbmask = GHOST_kButtonMaskLeft;
559  }
560  else if (sdl_sub_evt.button == SDL_BUTTON_MIDDLE) {
561  gbmask = GHOST_kButtonMaskMiddle;
562  }
563  else if (sdl_sub_evt.button == SDL_BUTTON_RIGHT) {
564  gbmask = GHOST_kButtonMaskRight;
565  /* these buttons are untested! */
566  }
567  else if (sdl_sub_evt.button == SDL_BUTTON_X1) {
568  gbmask = GHOST_kButtonMaskButton4;
569  }
570  else if (sdl_sub_evt.button == SDL_BUTTON_X2) {
571  gbmask = GHOST_kButtonMaskButton5;
572  }
573  else {
574  break;
575  }
576 
577  g_event = new GHOST_EventButton(
578  getMilliSeconds(), type, window, gbmask, GHOST_TABLET_DATA_NONE);
579  break;
580  }
581  case SDL_MOUSEWHEEL: {
582  SDL_MouseWheelEvent &sdl_sub_evt = sdl_event->wheel;
583  GHOST_WindowSDL *window = findGhostWindow(
584  SDL_GetWindowFromID_fallback(sdl_sub_evt.windowID));
585  assert(window != nullptr);
586  g_event = new GHOST_EventWheel(getMilliSeconds(), window, sdl_sub_evt.y);
587  break;
588  }
589  case SDL_KEYDOWN:
590  case SDL_KEYUP: {
591  SDL_KeyboardEvent &sdl_sub_evt = sdl_event->key;
592  GHOST_TEventType type = (sdl_sub_evt.state == SDL_PRESSED) ? GHOST_kEventKeyDown :
594  const bool is_repeat = sdl_sub_evt.repeat != 0;
595 
596  GHOST_WindowSDL *window = findGhostWindow(
597  SDL_GetWindowFromID_fallback(sdl_sub_evt.windowID));
598  assert(window != nullptr);
599 
600  GHOST_TKey gkey = convertSDLKey(sdl_sub_evt.keysym.scancode);
601  /* NOTE: the `sdl_sub_evt.keysym.sym` is truncated,
602  * for unicode support ghost has to be modified. */
603 
604  /* TODO(@campbellbarton): support full unicode, SDL supports this but it needs to be
605  * explicitly enabled via #SDL_StartTextInput which GHOST would have to wrap. */
606  char utf8_buf[sizeof(GHOST_TEventKeyData::utf8_buf)] = {'\0'};
607  if (type == GHOST_kEventKeyDown) {
608  utf8_buf[0] = convert_keyboard_event_to_ascii(sdl_sub_evt);
609  }
610 
611  g_event = new GHOST_EventKey(getMilliSeconds(), type, window, gkey, is_repeat, utf8_buf);
612  break;
613  }
614  }
615 
616  if (g_event) {
617  pushEvent(g_event);
618  }
619 }
620 
622 {
623  int x_win, y_win;
624  SDL_Window *win = SDL_GetMouseFocus();
625  SDL_GetWindowPosition(win, &x_win, &y_win);
626 
627  int xi, yi;
628  SDL_GetMouseState(&xi, &yi);
629  x = xi + x_win;
630  y = yi + x_win;
631 
632  return GHOST_kSuccess;
633 }
634 
636 {
637  int x_win, y_win;
638  SDL_Window *win = SDL_GetMouseFocus();
639  SDL_GetWindowPosition(win, &x_win, &y_win);
640 
641  SDL_WarpMouseInWindow(win, x - x_win, y - y_win);
642  return GHOST_kSuccess;
643 }
644 
645 bool GHOST_SystemSDL::generateWindowExposeEvents()
646 {
647  std::vector<GHOST_WindowSDL *>::iterator w_start = m_dirty_windows.begin();
648  std::vector<GHOST_WindowSDL *>::const_iterator w_end = m_dirty_windows.end();
649  bool anyProcessed = false;
650 
651  for (; w_start != w_end; ++w_start) {
653 
654  (*w_start)->validate();
655 
656  if (g_event) {
657  // printf("Expose events pushed\n");
658  pushEvent(g_event);
659  anyProcessed = true;
660  }
661  }
662 
663  m_dirty_windows.clear();
664  return anyProcessed;
665 }
666 
667 bool GHOST_SystemSDL::processEvents(bool waitForEvent)
668 {
669  /* Get all the current events - translate them into
670  * ghost events and call base class #pushEvent() method. */
671 
672  bool anyProcessed = false;
673 
674  do {
675  GHOST_TimerManager *timerMgr = getTimerManager();
676 
677  if (waitForEvent && m_dirty_windows.empty() && !SDL_HasEvents(SDL_FIRSTEVENT, SDL_LASTEVENT)) {
678  uint64_t next = timerMgr->nextFireTime();
679 
680  if (next == GHOST_kFireTimeNever) {
681  SDL_WaitEventTimeout(nullptr, -1);
682  // SleepTillEvent(m_display, -1);
683  }
684  else {
685  int64_t maxSleep = next - getMilliSeconds();
686 
687  if (maxSleep >= 0) {
688  SDL_WaitEventTimeout(nullptr, next - getMilliSeconds());
689  // SleepTillEvent(m_display, next - getMilliSeconds()); /* X11. */
690  }
691  }
692  }
693 
694  if (timerMgr->fireTimers(getMilliSeconds())) {
695  anyProcessed = true;
696  }
697 
698  SDL_Event sdl_event;
699  while (SDL_PollEvent(&sdl_event)) {
700  processEvent(&sdl_event);
701  anyProcessed = true;
702  }
703 
704  if (generateWindowExposeEvents()) {
705  anyProcessed = true;
706  }
707  } while (waitForEvent && !anyProcessed);
708 
709  return anyProcessed;
710 }
711 
712 GHOST_WindowSDL *GHOST_SystemSDL::findGhostWindow(SDL_Window *sdl_win)
713 {
714  if (sdl_win == nullptr) {
715  return nullptr;
716  }
717  /* It is not entirely safe to do this as the backptr may point
718  * to a window that has recently been removed.
719  * We should always check the window manager's list of windows
720  * and only process events on these windows. */
721 
722  const std::vector<GHOST_IWindow *> &win_vec = m_windowManager->getWindows();
723 
724  std::vector<GHOST_IWindow *>::const_iterator win_it = win_vec.begin();
725  std::vector<GHOST_IWindow *>::const_iterator win_end = win_vec.end();
726 
727  for (; win_it != win_end; ++win_it) {
728  GHOST_WindowSDL *window = static_cast<GHOST_WindowSDL *>(*win_it);
729  if (window->getSDLWindow() == sdl_win) {
730  return window;
731  }
732  }
733  return nullptr;
734 }
735 
737 {
738  GHOST_ASSERT((bad_wind != nullptr), "addDirtyWindow() nullptr ptr trapped (window)");
739 
740  m_dirty_windows.push_back(bad_wind);
741 }
742 
744 {
745  Uint8 state = SDL_GetMouseState(nullptr, nullptr);
746  buttons.set(GHOST_kButtonMaskLeft, (state & SDL_BUTTON_LMASK) != 0);
747  buttons.set(GHOST_kButtonMaskMiddle, (state & SDL_BUTTON_MMASK) != 0);
748  buttons.set(GHOST_kButtonMaskRight, (state & SDL_BUTTON_RMASK) != 0);
749 
750  return GHOST_kSuccess;
751 }
752 
753 char *GHOST_SystemSDL::getClipboard(bool /*selection*/) const
754 {
755  return (char *)SDL_GetClipboardText();
756 }
757 
758 void GHOST_SystemSDL::putClipboard(const char *buffer, bool /*selection*/) const
759 {
760  SDL_SetClipboardText(buffer);
761 }
762 
764 {
765  return uint64_t(SDL_GetTicks()); /* NOTE: 32 -> 64bits. */
766 }
#define GHOST_OPENGL_SDL_RESET_NOTIFICATION_STRATEGY
#define GHOST_OPENGL_SDL_CONTEXT_FLAGS
#define GHOST_ASSERT(x, info)
Definition: GHOST_Debug.h:54
static char convert_keyboard_event_to_ascii(const SDL_KeyboardEvent &sdl_sub_evt)
static SDL_Window * SDL_GetWindowFromID_fallback(Uint32 id)
static GHOST_TKey convertSDLKey(SDL_Scancode key)
#define GXMAP(k, x, y)
GHOST_TWindowState
Definition: GHOST_Types.h:129
@ GHOST_kWindowStateFullScreen
Definition: GHOST_Types.h:133
GHOST_TEventType
Definition: GHOST_Types.h:169
@ GHOST_kEventWindowClose
Definition: GHOST_Types.h:189
@ GHOST_kEventWindowMove
Definition: GHOST_Types.h:194
@ GHOST_kEventWindowSize
Definition: GHOST_Types.h:193
@ GHOST_kEventCursorMove
Definition: GHOST_Types.h:172
@ GHOST_kEventButtonUp
Definition: GHOST_Types.h:174
@ GHOST_kEventWindowActivate
Definition: GHOST_Types.h:190
@ GHOST_kEventWindowUpdate
Definition: GHOST_Types.h:192
@ GHOST_kEventWindowDeactivate
Definition: GHOST_Types.h:191
@ GHOST_kEventButtonDown
Definition: GHOST_Types.h:173
@ GHOST_kEventKeyDown
Definition: GHOST_Types.h:183
@ GHOST_kEventKeyUp
Definition: GHOST_Types.h:184
@ GHOST_kEventQuitRequest
Definition: GHOST_Types.h:187
static const GHOST_TabletData GHOST_TABLET_DATA_NONE
Definition: GHOST_Types.h:104
@ GHOST_glStereoVisual
Definition: GHOST_Types.h:62
GHOST_TKey
Definition: GHOST_Types.h:259
@ GHOST_kKeyInsert
Definition: GHOST_Types.h:346
@ GHOST_kKeySemicolon
Definition: GHOST_Types.h:288
@ GHOST_kKeyMediaPlay
Definition: GHOST_Types.h:398
@ GHOST_kKeyQuote
Definition: GHOST_Types.h:269
@ GHOST_kKeyNumpad3
Definition: GHOST_Types.h:357
@ GHOST_kKeyAccentGrave
Definition: GHOST_Types.h:322
@ GHOST_kKeyNumpad1
Definition: GHOST_Types.h:355
@ GHOST_kKeyLeftAlt
Definition: GHOST_Types.h:328
@ GHOST_kKeyRightShift
Definition: GHOST_Types.h:325
@ GHOST_kKeyNumLock
Definition: GHOST_Types.h:335
@ GHOST_kKeyEnter
Definition: GHOST_Types.h:265
@ GHOST_kKeyNumpadSlash
Definition: GHOST_Types.h:369
@ GHOST_kKeyRightArrow
Definition: GHOST_Types.h:339
@ GHOST_kKeyF13
Definition: GHOST_Types.h:384
@ GHOST_kKeyNumpad4
Definition: GHOST_Types.h:358
@ GHOST_kKeyPause
Definition: GHOST_Types.h:344
@ GHOST_kKeyCapsLock
Definition: GHOST_Types.h:334
@ GHOST_kKeyApp
Definition: GHOST_Types.h:332
@ GHOST_kKeyMinus
Definition: GHOST_Types.h:271
@ GHOST_kKeyMediaStop
Definition: GHOST_Types.h:399
@ GHOST_kKeyBackSpace
Definition: GHOST_Types.h:261
@ GHOST_kKey0
Definition: GHOST_Types.h:277
@ GHOST_kKeyDownPage
Definition: GHOST_Types.h:351
@ GHOST_kKeyDownArrow
Definition: GHOST_Types.h:341
@ GHOST_kKeyNumpadPeriod
Definition: GHOST_Types.h:364
@ GHOST_kKeyF1
Definition: GHOST_Types.h:372
@ GHOST_kKeyNumpadAsterisk
Definition: GHOST_Types.h:368
@ GHOST_kKeyPrintScreen
Definition: GHOST_Types.h:343
@ GHOST_kKeyLeftControl
Definition: GHOST_Types.h:326
@ GHOST_kKeyLeftBracket
Definition: GHOST_Types.h:319
@ GHOST_kKey1
Definition: GHOST_Types.h:278
@ GHOST_kKeyTab
Definition: GHOST_Types.h:262
@ GHOST_kKeyComma
Definition: GHOST_Types.h:270
@ GHOST_kKeyRightBracket
Definition: GHOST_Types.h:320
@ GHOST_kKeyBackslash
Definition: GHOST_Types.h:321
@ GHOST_kKeyOS
Definition: GHOST_Types.h:330
@ GHOST_kKeyNumpad2
Definition: GHOST_Types.h:356
@ GHOST_kKeyRightAlt
Definition: GHOST_Types.h:329
@ GHOST_kKeyPeriod
Definition: GHOST_Types.h:273
@ GHOST_kKeyNumpadPlus
Definition: GHOST_Types.h:366
@ GHOST_kKeyUpPage
Definition: GHOST_Types.h:350
@ GHOST_kKeyNumpad5
Definition: GHOST_Types.h:359
@ GHOST_kKeyLeftArrow
Definition: GHOST_Types.h:338
@ GHOST_kKeyEqual
Definition: GHOST_Types.h:289
@ GHOST_kKeyHome
Definition: GHOST_Types.h:348
@ GHOST_kKeyNumpad6
Definition: GHOST_Types.h:360
@ GHOST_kKeyNumpad8
Definition: GHOST_Types.h:362
@ GHOST_kKeyNumpad9
Definition: GHOST_Types.h:363
@ GHOST_kKeyEnd
Definition: GHOST_Types.h:349
@ GHOST_kKeyUpArrow
Definition: GHOST_Types.h:340
@ GHOST_kKeyDelete
Definition: GHOST_Types.h:347
@ GHOST_kKeyNumpad0
Definition: GHOST_Types.h:354
@ GHOST_kKeyA
Definition: GHOST_Types.h:292
@ GHOST_kKeyMediaFirst
Definition: GHOST_Types.h:400
@ GHOST_kKeyNumpad7
Definition: GHOST_Types.h:361
@ GHOST_kKeyRightControl
Definition: GHOST_Types.h:327
@ GHOST_kKeyEsc
Definition: GHOST_Types.h:267
@ GHOST_kKeyUnknown
Definition: GHOST_Types.h:260
@ GHOST_kKeyScrollLock
Definition: GHOST_Types.h:336
@ GHOST_kKeySlash
Definition: GHOST_Types.h:274
@ GHOST_kKeyNumpadEnter
Definition: GHOST_Types.h:365
@ GHOST_kKeyNumpadMinus
Definition: GHOST_Types.h:367
@ GHOST_kKeyLeftShift
Definition: GHOST_Types.h:324
@ GHOST_kKeyMediaLast
Definition: GHOST_Types.h:401
@ GHOST_kKeySpace
Definition: GHOST_Types.h:268
GHOST_TDrawingContextType
Definition: GHOST_Types.h:148
@ GHOST_kModifierKeyRightControl
Definition: GHOST_Types.h:124
@ GHOST_kModifierKeyLeftControl
Definition: GHOST_Types.h:123
@ GHOST_kModifierKeyRightAlt
Definition: GHOST_Types.h:122
@ GHOST_kModifierKeyOS
Definition: GHOST_Types.h:125
@ GHOST_kModifierKeyRightShift
Definition: GHOST_Types.h:120
@ GHOST_kModifierKeyLeftAlt
Definition: GHOST_Types.h:121
@ GHOST_kModifierKeyLeftShift
Definition: GHOST_Types.h:119
GHOST_TSuccess
Definition: GHOST_Types.h:74
@ GHOST_kFailure
Definition: GHOST_Types.h:74
@ GHOST_kSuccess
Definition: GHOST_Types.h:74
@ GHOST_kFireTimeNever
Definition: GHOST_Types.h:116
@ GHOST_kGrabDisable
Definition: GHOST_Types.h:406
@ GHOST_kGrabNormal
Definition: GHOST_Types.h:408
GHOST_TButton
Definition: GHOST_Types.h:156
@ GHOST_kButtonMaskRight
Definition: GHOST_Types.h:160
@ GHOST_kButtonMaskButton4
Definition: GHOST_Types.h:161
@ GHOST_kButtonMaskLeft
Definition: GHOST_Types.h:158
@ GHOST_kButtonMaskButton5
Definition: GHOST_Types.h:162
@ GHOST_kButtonMaskMiddle
Definition: GHOST_Types.h:159
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei height
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint y
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum type
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei width
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble top
static btDbvtVolume bounds(btDbvtNode **leaves, int count)
Definition: btDbvt.cpp:299
GHOST_TSuccess getCursorPosition(int32_t &x, int32_t &y) const
bool processEvents(bool waitForEvent)
GHOST_IContext * createOffscreenContext(GHOST_GLSettings glSettings)
uint8_t getNumDisplays() const
GHOST_TSuccess disposeContext(GHOST_IContext *context)
char * getClipboard(bool selection) const
GHOST_TSuccess setCursorPosition(int32_t x, int32_t y)
void addDirtyWindow(GHOST_WindowSDL *bad_wind)
void putClipboard(const char *buffer, bool selection) const
void getMainDisplayDimensions(uint32_t &width, uint32_t &height) const
GHOST_TSuccess getButtons(GHOST_Buttons &buttons) const
uint64_t getMilliSeconds()
GHOST_TSuccess getModifierKeys(GHOST_ModifierKeys &keys) const
void getAllDisplayDimensions(uint32_t &width, uint32_t &height) const
virtual GHOST_TSuccess init()
GHOST_TimerManager * getTimerManager() const
Definition: GHOST_System.h:422
GHOST_WindowManager * m_windowManager
Definition: GHOST_System.h:395
GHOST_TSuccess pushEvent(GHOST_IEvent *event)
GHOST_DisplayManager * m_displayManager
Definition: GHOST_System.h:389
bool fireTimers(uint64_t time)
GHOST_TSuccess addWindow(GHOST_IWindow *window)
GHOST_IWindow * getActiveWindow(void) const
const std::vector< GHOST_IWindow * > & getWindows() const
bool getValid() const
void getClientBounds(GHOST_Rect &bounds) const
SDL_Window * getSDLWindow()
GHOST_TSuccess getCursorGrabBounds(GHOST_Rect &bounds)
void setCursorGrabAccum(int32_t x, int32_t y)
Definition: GHOST_Window.h:440
GHOST_TAxisFlag getCursorGrabAxis() const
Definition: GHOST_Window.h:423
GHOST_TGrabCursorMode getCursorGrabMode() const
Definition: GHOST_Window.h:413
void getCursorGrabAccum(int32_t &x, int32_t &y) const
Definition: GHOST_Window.h:434
ccl_global float * buffer
const int state
static ulong * next
static int left
SymEdge< T > * sym(const SymEdge< T > *se)
Definition: delaunay_2d.cc:99
unsigned int uint32_t
Definition: stdint.h:80
__int64 int64_t
Definition: stdint.h:89
signed int int32_t
Definition: stdint.h:77
unsigned char uint8_t
Definition: stdint.h:78
unsigned __int64 uint64_t
Definition: stdint.h:90
void set(GHOST_TButton mask, bool down)
void set(GHOST_TModifierKey mask, bool down)
ccl_device_inline int mod(int x, int m)
Definition: util/math.h:490