Esempio n. 1
0
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);
	}
}