GHOST_IWindow *GHOST_SystemSDL::createWindow(const STR_String &title, GHOST_TInt32 left, GHOST_TInt32 top, GHOST_TUns32 width, GHOST_TUns32 height, GHOST_TWindowState state, GHOST_TDrawingContextType type, GHOST_GLSettings glSettings, const bool exclusive, const GHOST_TEmbedderWindowID parentWindow) { GHOST_WindowSDL *window = NULL; window = new GHOST_WindowSDL(this, title, left, top, width, height, state, parentWindow, type, ((glSettings.flags & GHOST_glStereoVisual) != 0), exclusive); if (window) { if (GHOST_kWindowStateFullScreen == state) { SDL_Window *sdl_win = window->getSDLWindow(); SDL_DisplayMode mode; static_cast<GHOST_DisplayManagerSDL *>(m_displayManager)->getCurrentDisplayModeSDL(mode); SDL_SetWindowDisplayMode(sdl_win, &mode); SDL_ShowWindow(sdl_win); SDL_SetWindowFullscreen(sdl_win, SDL_TRUE); } if (window->getValid()) { m_windowManager->addWindow(window); pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window)); } else { delete window; window = NULL; } } return window; }
GHOST_WindowSDL * GHOST_SystemSDL::findGhostWindow(SDL_Window *sdl_win) { if (sdl_win == NULL) return NULL; // It is not entirely safe to do this as the backptr may point // to a window that has recently been removed. // We should always check the window manager's list of windows // and only process events on these windows. std::vector<GHOST_IWindow *> & win_vec = m_windowManager->getWindows(); std::vector<GHOST_IWindow *>::iterator win_it = win_vec.begin(); std::vector<GHOST_IWindow *>::const_iterator win_end = win_vec.end(); for (; win_it != win_end; ++win_it) { GHOST_WindowSDL *window = static_cast<GHOST_WindowSDL *>(*win_it); if (window->getSDLWindow() == sdl_win) { return window; } } return NULL; }
void GHOST_SystemSDL::processEvent(SDL_Event *sdl_event) { GHOST_Event *g_event = NULL; switch (sdl_event->type) { case SDL_WINDOWEVENT: { SDL_WindowEvent &sdl_sub_evt = sdl_event->window; GHOST_WindowSDL *window = findGhostWindow(SDL_GetWindowFromID(sdl_sub_evt.windowID)); //assert(window != NULL); // can be NULL on close window. switch (sdl_sub_evt.event) { case SDL_WINDOWEVENT_EXPOSED: g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowUpdate, window); break; case SDL_WINDOWEVENT_RESIZED: g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window); break; case SDL_WINDOWEVENT_MOVED: g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowMove, window); break; case SDL_WINDOWEVENT_FOCUS_GAINED: g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowActivate, window); break; case SDL_WINDOWEVENT_FOCUS_LOST: g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowDeactivate, window); break; case SDL_WINDOWEVENT_CLOSE: g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowClose, window); break; } } break; case SDL_QUIT: g_event = new GHOST_Event(getMilliSeconds(), GHOST_kEventQuit, NULL); break; case SDL_MOUSEMOTION: { SDL_MouseMotionEvent &sdl_sub_evt = sdl_event->motion; SDL_Window *sdl_win = SDL_GetWindowFromID(sdl_sub_evt.windowID); GHOST_WindowSDL *window = findGhostWindow(sdl_win); assert(window != NULL); int x_win, y_win; SDL_GetWindowPosition(sdl_win, &x_win, &y_win); GHOST_TInt32 x_root = sdl_sub_evt.x + x_win; GHOST_TInt32 y_root = sdl_sub_evt.y + y_win; #if 0 if (window->getCursorGrabMode() != GHOST_kGrabDisable && window->getCursorGrabMode() != GHOST_kGrabNormal) { GHOST_TInt32 x_new = x_root; GHOST_TInt32 y_new = y_root; GHOST_TInt32 x_accum, y_accum; GHOST_Rect bounds; /* fallback to window bounds */ if (window->getCursorGrabBounds(bounds) == GHOST_kFailure) window->getClientBounds(bounds); /* could also clamp to screen bounds * wrap with a window outside the view will fail atm */ bounds.wrapPoint(x_new, y_new, 8); /* offset of one incase blender is at screen bounds */ window->getCursorGrabAccum(x_accum, y_accum); // cant use setCursorPosition because the mouse may have no focus! if (x_new != x_root || y_new != y_root) { if (1) { //xme.time > m_last_warp) { /* when wrapping we don't need to add an event because the * setCursorPosition call will cause a new event after */ SDL_WarpMouseInWindow(sdl_win, x_new - x_win, y_new - y_win); /* wrap */ window->setCursorGrabAccum(x_accum + (x_root - x_new), y_accum + (y_root - y_new)); // m_last_warp= lastEventTime(xme.time); } else { // setCursorPosition(x_new, y_new); /* wrap but don't accumulate */ SDL_WarpMouseInWindow(sdl_win, x_new - x_win, y_new - y_win); } g_event = new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, x_new, y_new); } else { g_event = new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, x_root + x_accum, y_root + y_accum); } } else #endif { g_event = new GHOST_EventCursor(getMilliSeconds(), GHOST_kEventCursorMove, window, x_root, y_root); } break; } case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONDOWN: { SDL_MouseButtonEvent &sdl_sub_evt = sdl_event->button; GHOST_TButtonMask gbmask = GHOST_kButtonMaskLeft; GHOST_TEventType type = (sdl_sub_evt.state == SDL_PRESSED) ? GHOST_kEventButtonDown : GHOST_kEventButtonUp; GHOST_WindowSDL *window = findGhostWindow(SDL_GetWindowFromID(sdl_sub_evt.windowID)); assert(window != NULL); /* process rest of normal mouse buttons */ if (sdl_sub_evt.button == SDL_BUTTON_LEFT) gbmask = GHOST_kButtonMaskLeft; else if (sdl_sub_evt.button == SDL_BUTTON_MIDDLE) gbmask = GHOST_kButtonMaskMiddle; else if (sdl_sub_evt.button == SDL_BUTTON_RIGHT) gbmask = GHOST_kButtonMaskRight; /* these buttons are untested! */ else if (sdl_sub_evt.button == SDL_BUTTON_X1) gbmask = GHOST_kButtonMaskButton4; else if (sdl_sub_evt.button == SDL_BUTTON_X2) gbmask = GHOST_kButtonMaskButton5; else break; g_event = new GHOST_EventButton(getMilliSeconds(), type, window, gbmask); break; } case SDL_MOUSEWHEEL: { SDL_MouseWheelEvent &sdl_sub_evt = sdl_event->wheel; GHOST_WindowSDL *window = findGhostWindow(SDL_GetWindowFromID(sdl_sub_evt.windowID)); assert(window != NULL); g_event = new GHOST_EventWheel(getMilliSeconds(), window, sdl_sub_evt.y); } break; case SDL_KEYDOWN: case SDL_KEYUP: { SDL_KeyboardEvent &sdl_sub_evt = sdl_event->key; SDL_Keycode sym = sdl_sub_evt.keysym.sym; GHOST_TEventType type = (sdl_sub_evt.state == SDL_PRESSED) ? GHOST_kEventKeyDown : GHOST_kEventKeyUp; GHOST_WindowSDL *window = findGhostWindow(SDL_GetWindowFromID(sdl_sub_evt.windowID)); assert(window != NULL); GHOST_TKey gkey = convertSDLKey(sdl_sub_evt.keysym.scancode); /* note, the sdl_sub_evt.keysym.sym is truncated, for unicode support ghost has to be modified */ /* printf("%d\n", sym); */ if (sym > 127) { switch (sym) { case SDLK_KP_DIVIDE: sym = '/'; break; case SDLK_KP_MULTIPLY: sym = '*'; break; case SDLK_KP_MINUS: sym = '-'; break; case SDLK_KP_PLUS: sym = '+'; break; case SDLK_KP_1: sym = '1'; break; case SDLK_KP_2: sym = '2'; break; case SDLK_KP_3: sym = '3'; break; case SDLK_KP_4: sym = '4'; break; case SDLK_KP_5: sym = '5'; break; case SDLK_KP_6: sym = '6'; break; case SDLK_KP_7: sym = '7'; break; case SDLK_KP_8: sym = '8'; break; case SDLK_KP_9: sym = '9'; break; case SDLK_KP_0: sym = '0'; break; case SDLK_KP_PERIOD: sym = '.'; break; default: sym = 0; break; } } else { if (sdl_sub_evt.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT)) { /* lame US keyboard assumptions */ if (sym >= 'a' && sym <= ('a' + 32)) { sym -= 32; } else { switch (sym) { case '`': sym = '~'; break; case '1': sym = '!'; break; case '2': sym = '@'; break; case '3': sym = '#'; break; case '4': sym = '$'; break; case '5': sym = '%'; break; case '6': sym = '^'; break; case '7': sym = '&'; break; case '8': sym = '*'; break; case '9': sym = '('; break; case '0': sym = ')'; break; case '-': sym = '_'; break; case '=': sym = '+'; break; case '[': sym = '{'; break; case ']': sym = '}'; break; case '\\': sym = '|'; break; case ';': sym = ':'; break; case '\'': sym = '"'; break; case ',': sym = '<'; break; case '.': sym = '>'; break; case '/': sym = '?'; break; default: break; } } } } g_event = new GHOST_EventKey(getMilliSeconds(), type, window, gkey, sym, NULL); } break; } if (g_event) { pushEvent(g_event); } }