diff options
author | Mitchell Stokes <mogurijin@gmail.com> | 2011-07-29 10:32:30 +0400 |
---|---|---|
committer | Mitchell Stokes <mogurijin@gmail.com> | 2011-07-29 10:32:30 +0400 |
commit | b46d8955509e805f06b76a6fd800ecb4edee113b (patch) | |
tree | 7ed0b1a3b5d04ab48d3e9062ff02ce54961ecb06 /intern/ghost/intern/GHOST_SystemSDL.cpp | |
parent | 6960127d2609620d52620539388ada5cb466bab2 (diff) | |
parent | 26589497529ca3c8da85391d4976d286a371e258 (diff) |
Merging r36529-38806bge_components
Diffstat (limited to 'intern/ghost/intern/GHOST_SystemSDL.cpp')
-rw-r--r-- | intern/ghost/intern/GHOST_SystemSDL.cpp | 555 |
1 files changed, 555 insertions, 0 deletions
diff --git a/intern/ghost/intern/GHOST_SystemSDL.cpp b/intern/ghost/intern/GHOST_SystemSDL.cpp new file mode 100644 index 00000000000..2c61acc2d93 --- /dev/null +++ b/intern/ghost/intern/GHOST_SystemSDL.cpp @@ -0,0 +1,555 @@ +/* + * $Id$ + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * Contributor(s): Campbell Barton + * + * ***** END GPL LICENSE BLOCK ***** + */ + +/** \file ghost/intern/GHOST_SystemSDL.cpp + * \ingroup GHOST + */ + +#include <assert.h> + +#include "GHOST_SystemSDL.h" + +#include "GHOST_WindowManager.h" + +#include "GHOST_EventCursor.h" +#include "GHOST_EventKey.h" +#include "GHOST_EventButton.h" +#include "GHOST_EventWheel.h" + +GHOST_SystemSDL::GHOST_SystemSDL() + : + GHOST_System() +{ + if(SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) != 0) { + printf ("Error initializing SDL: %s\n", SDL_GetError()); + } + + /* SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1); */ + /* SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 4); */ + SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); + SDL_GL_SetAttribute(SDL_GL_DEPTH_SIZE, 24); + SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_GREEN_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_BLUE_SIZE, 8); + SDL_GL_SetAttribute(SDL_GL_ALPHA_SIZE, 8); +} + +GHOST_SystemSDL::~GHOST_SystemSDL() +{ + SDL_Quit(); +} + +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, + bool stereoVisual, + const GHOST_TUns16 numOfAASamples, + const GHOST_TEmbedderWindowID parentWindow + ) +{ + GHOST_WindowSDL *window= NULL; + + window= new GHOST_WindowSDL (this, title, left, top, width, height, state, parentWindow, type, stereoVisual, 1); + + if (window) { + if (window->getValid()) { + m_windowManager->addWindow(window); + pushEvent(new GHOST_Event(getMilliSeconds(), GHOST_kEventWindowSize, window)); + } + else { + delete window; + window= NULL; + } + } + return window; +} + +GHOST_TSuccess +GHOST_SystemSDL::init() { + GHOST_TSuccess success = GHOST_System::init(); + + if (success) { + m_displayManager = new GHOST_DisplayManagerSDL(this); + + if (m_displayManager) { + return GHOST_kSuccess; + } + } + + return GHOST_kFailure; +} + +void +GHOST_SystemSDL::getMainDisplayDimensions(GHOST_TUns32& width, + GHOST_TUns32& height) const +{ + SDL_DisplayMode mode; + SDL_GetCurrentDisplayMode(0, &mode); /* note, always 0 display */ + width= mode.w; + height= mode.h; +} + +GHOST_TUns8 +GHOST_SystemSDL::getNumDisplays() const +{ + return SDL_GetNumVideoDisplays(); +} + +GHOST_TSuccess +GHOST_SystemSDL::getModifierKeys(GHOST_ModifierKeys& keys) const +{ + SDL_Keymod mod= SDL_GetModState(); + + keys.set(GHOST_kModifierKeyLeftShift, (mod & KMOD_LSHIFT) != 0); + keys.set(GHOST_kModifierKeyRightShift, (mod & KMOD_RSHIFT) != 0); + keys.set(GHOST_kModifierKeyLeftControl, (mod & KMOD_LCTRL) != 0); + keys.set(GHOST_kModifierKeyRightControl, (mod & KMOD_RCTRL) != 0); + keys.set(GHOST_kModifierKeyLeftAlt, (mod & KMOD_LALT) != 0); + keys.set(GHOST_kModifierKeyRightAlt, (mod & KMOD_RALT) != 0); + keys.set(GHOST_kModifierKeyOS, (mod & (KMOD_LGUI|KMOD_RGUI)) != 0); + + return GHOST_kSuccess; +} + +#define GXMAP(k,x,y) case x: k= y; break; + +static GHOST_TKey +convertSDLKey(SDL_Scancode key) +{ + GHOST_TKey type; + + if ((key >= SDL_SCANCODE_A) && (key <= SDL_SCANCODE_Z)) { + type= GHOST_TKey( key - SDL_SCANCODE_A + int(GHOST_kKeyA)); + } else if ((key >= SDL_SCANCODE_1) && (key <= SDL_SCANCODE_0)) { + type= GHOST_TKey(key - SDL_SCANCODE_1 + int(GHOST_kKey0)); + } else if ((key >= SDL_SCANCODE_F1) && (key <= SDL_SCANCODE_F12)) { + type= GHOST_TKey(key - SDL_SCANCODE_F1 + int(GHOST_kKeyF1)); + } else if ((key >= SDL_SCANCODE_F13) && (key <= SDL_SCANCODE_F24)) { + type= GHOST_TKey(key - SDL_SCANCODE_F13 + int(GHOST_kKeyF13)); + } else { + switch(key) { + /* TODO SDL_SCANCODE_NONUSBACKSLASH */ + + GXMAP(type,SDL_SCANCODE_BACKSPACE, GHOST_kKeyBackSpace); + GXMAP(type,SDL_SCANCODE_TAB, GHOST_kKeyTab); + GXMAP(type,SDL_SCANCODE_RETURN, GHOST_kKeyEnter); + GXMAP(type,SDL_SCANCODE_ESCAPE, GHOST_kKeyEsc); + GXMAP(type,SDL_SCANCODE_SPACE, GHOST_kKeySpace); + + GXMAP(type,SDL_SCANCODE_SEMICOLON, GHOST_kKeySemicolon); + GXMAP(type,SDL_SCANCODE_PERIOD, GHOST_kKeyPeriod); + GXMAP(type,SDL_SCANCODE_COMMA, GHOST_kKeyComma); + GXMAP(type,SDL_SCANCODE_APOSTROPHE, GHOST_kKeyQuote); + GXMAP(type,SDL_SCANCODE_GRAVE, GHOST_kKeyAccentGrave); + GXMAP(type,SDL_SCANCODE_MINUS, GHOST_kKeyMinus); + GXMAP(type,SDL_SCANCODE_SLASH, GHOST_kKeySlash); + GXMAP(type,SDL_SCANCODE_BACKSLASH, GHOST_kKeyBackslash); + GXMAP(type,SDL_SCANCODE_KP_EQUALS, GHOST_kKeyEqual); + GXMAP(type,SDL_SCANCODE_LEFTBRACKET, GHOST_kKeyLeftBracket); + GXMAP(type,SDL_SCANCODE_RIGHTBRACKET, GHOST_kKeyRightBracket); + GXMAP(type,SDL_SCANCODE_PAUSE, GHOST_kKeyPause); + + GXMAP(type,SDL_SCANCODE_LSHIFT, GHOST_kKeyLeftShift); + GXMAP(type,SDL_SCANCODE_RSHIFT, GHOST_kKeyRightShift); + GXMAP(type,SDL_SCANCODE_LCTRL, GHOST_kKeyLeftControl); + GXMAP(type,SDL_SCANCODE_RCTRL, GHOST_kKeyRightControl); + GXMAP(type,SDL_SCANCODE_LALT, GHOST_kKeyLeftAlt); + GXMAP(type,SDL_SCANCODE_RALT, GHOST_kKeyRightAlt); + GXMAP(type,SDL_SCANCODE_RGUI, GHOST_kKeyOS); + + GXMAP(type,SDL_SCANCODE_INSERT, GHOST_kKeyInsert); + GXMAP(type,SDL_SCANCODE_DELETE, GHOST_kKeyDelete); + GXMAP(type,SDL_SCANCODE_HOME, GHOST_kKeyHome); + GXMAP(type,SDL_SCANCODE_END, GHOST_kKeyEnd); + GXMAP(type,SDL_SCANCODE_PAGEUP, GHOST_kKeyUpPage); + GXMAP(type,SDL_SCANCODE_PAGEDOWN, GHOST_kKeyDownPage); + + GXMAP(type,SDL_SCANCODE_LEFT, GHOST_kKeyLeftArrow); + GXMAP(type,SDL_SCANCODE_RIGHT, GHOST_kKeyRightArrow); + GXMAP(type,SDL_SCANCODE_UP, GHOST_kKeyUpArrow); + GXMAP(type,SDL_SCANCODE_DOWN, GHOST_kKeyDownArrow); + + GXMAP(type,SDL_SCANCODE_CAPSLOCK, GHOST_kKeyCapsLock); + GXMAP(type,SDL_SCANCODE_SCROLLLOCK, GHOST_kKeyScrollLock); + GXMAP(type,SDL_SCANCODE_NUMLOCKCLEAR, GHOST_kKeyNumLock); + + /* keypad events */ + + /* note, sdl defines a bunch of kp defines I never saw before like + * SDL_SCANCODE_KP_PERCENT, SDL_SCANCODE_KP_XOR - campbell */ + GXMAP(type,SDL_SCANCODE_KP_0, GHOST_kKeyNumpad0); + GXMAP(type,SDL_SCANCODE_KP_1, GHOST_kKeyNumpad1); + GXMAP(type,SDL_SCANCODE_KP_2, GHOST_kKeyNumpad2); + GXMAP(type,SDL_SCANCODE_KP_3, GHOST_kKeyNumpad3); + GXMAP(type,SDL_SCANCODE_KP_4, GHOST_kKeyNumpad4); + GXMAP(type,SDL_SCANCODE_KP_5, GHOST_kKeyNumpad5); + GXMAP(type,SDL_SCANCODE_KP_6, GHOST_kKeyNumpad6); + GXMAP(type,SDL_SCANCODE_KP_7, GHOST_kKeyNumpad7); + GXMAP(type,SDL_SCANCODE_KP_8, GHOST_kKeyNumpad8); + GXMAP(type,SDL_SCANCODE_KP_9, GHOST_kKeyNumpad9); + GXMAP(type,SDL_SCANCODE_KP_PERIOD, GHOST_kKeyNumpadPeriod); + + GXMAP(type,SDL_SCANCODE_KP_ENTER, GHOST_kKeyNumpadEnter); + GXMAP(type,SDL_SCANCODE_KP_PLUS, GHOST_kKeyNumpadPlus); + GXMAP(type,SDL_SCANCODE_KP_MINUS, GHOST_kKeyNumpadMinus); + GXMAP(type,SDL_SCANCODE_KP_MULTIPLY, GHOST_kKeyNumpadAsterisk); + GXMAP(type,SDL_SCANCODE_KP_DIVIDE, GHOST_kKeyNumpadSlash); + + /* Media keys in some keyboards and laptops with XFree86/Xorg */ + GXMAP(type,SDL_SCANCODE_AUDIOPLAY, GHOST_kKeyMediaPlay); + GXMAP(type,SDL_SCANCODE_AUDIOSTOP, GHOST_kKeyMediaStop); + GXMAP(type,SDL_SCANCODE_AUDIOPREV, GHOST_kKeyMediaFirst); + // GXMAP(type,XF86XK_AudioRewind, GHOST_kKeyMediaFirst); + GXMAP(type,SDL_SCANCODE_AUDIONEXT, GHOST_kKeyMediaLast); + + default: + type= GHOST_kKeyUnknown; + break; + } + } + + return type; +} +#undef GXMAP + + +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; + 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 */ + g_event= new GHOST_EventKey(getMilliSeconds(), type, window, gkey, sdl_sub_evt.keysym.sym); + } + break; + } + + if (g_event) { + pushEvent(g_event); + } +} + +GHOST_TSuccess +GHOST_SystemSDL::getCursorPosition(GHOST_TInt32& x, + GHOST_TInt32& y) const +{ + int x_win, y_win; + SDL_Window *win= SDL_GetMouseFocus(); + SDL_GetWindowPosition(win, &x_win, &y_win); + + int xi, yi; + SDL_GetMouseState(&xi, &yi); + x= xi + x_win; + y= yi + x_win; + + return GHOST_kSuccess; +} + +GHOST_TSuccess +GHOST_SystemSDL::setCursorPosition(GHOST_TInt32 x, + GHOST_TInt32 y) +{ + int x_win, y_win; + SDL_Window *win= SDL_GetMouseFocus(); + SDL_GetWindowPosition(win, &x_win, &y_win); + + SDL_WarpMouseInWindow(win, x - x_win, y - y_win); + return GHOST_kSuccess; +} + +bool +GHOST_SystemSDL::generateWindowExposeEvents() +{ + vector<GHOST_WindowSDL *>::iterator w_start= m_dirty_windows.begin(); + vector<GHOST_WindowSDL *>::const_iterator w_end= m_dirty_windows.end(); + bool anyProcessed= false; + + for (;w_start != w_end; ++w_start) { + GHOST_Event * g_event= new + GHOST_Event( + getMilliSeconds(), + GHOST_kEventWindowUpdate, + *w_start + ); + + (*w_start)->validate(); + + if (g_event) { + printf("Expose events pushed\n"); + pushEvent(g_event); + anyProcessed= true; + } + } + + m_dirty_windows.clear(); + return anyProcessed; +} + + +bool +GHOST_SystemSDL::processEvents(bool waitForEvent) +{ + // Get all the current events -- translate them into + // ghost events and call base class pushEvent() method. + + bool anyProcessed= false; + + do { + GHOST_TimerManager* timerMgr= getTimerManager(); + + if (waitForEvent && m_dirty_windows.empty() && !SDL_HasEvents(SDL_FIRSTEVENT, SDL_LASTEVENT)) { + GHOST_TUns64 next= timerMgr->nextFireTime(); + + if (next==GHOST_kFireTimeNever) { + SDL_WaitEventTimeout(NULL, -1); + //SleepTillEvent(m_display, -1); + } else { + GHOST_TInt64 maxSleep= next - getMilliSeconds(); + + if(maxSleep >= 0) { + SDL_WaitEventTimeout(NULL, next - getMilliSeconds()); + // SleepTillEvent(m_display, next - getMilliSeconds()); // X11 + } + } + } + + if (timerMgr->fireTimers(getMilliSeconds())) { + anyProcessed= true; + } + + SDL_Event sdl_event; + while (SDL_PollEvent(&sdl_event)) { + processEvent(&sdl_event); + anyProcessed= true; + } + + if (generateWindowExposeEvents()) { + anyProcessed= true; + } + } while (waitForEvent && !anyProcessed); + + return anyProcessed; +} + + +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. + + vector<GHOST_IWindow *> & win_vec= m_windowManager->getWindows(); + + vector<GHOST_IWindow *>::iterator win_it= win_vec.begin(); + 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::addDirtyWindow(GHOST_WindowSDL *bad_wind) +{ + GHOST_ASSERT((bad_wind != NULL), "addDirtyWindow() NULL ptr trapped (window)"); + + m_dirty_windows.push_back(bad_wind); +} + + +GHOST_TSuccess GHOST_SystemSDL::getButtons(GHOST_Buttons& buttons) const +{ + Uint8 state= SDL_GetMouseState(NULL, NULL); + buttons.set(GHOST_kButtonMaskLeft, (state & SDL_BUTTON_LMASK) != 0); + buttons.set(GHOST_kButtonMaskMiddle, (state & SDL_BUTTON_MMASK) != 0); + buttons.set(GHOST_kButtonMaskRight, (state & SDL_BUTTON_RMASK) != 0); + + return GHOST_kSuccess; +} + +GHOST_TUns8 * +GHOST_SystemSDL::getClipboard(bool selection) const +{ + return (GHOST_TUns8 *)SDL_GetClipboardText(); +} + +void +GHOST_SystemSDL::putClipboard(GHOST_TInt8 *buffer, bool selection) const +{ + SDL_SetClipboardText(buffer); +} + +GHOST_TUns64 +GHOST_SystemSDL::getMilliSeconds() +{ + return GHOST_TUns64(SDL_GetTicks()); /* note, 32 -> 64bits */ +} |