/* * OpenClonk, http://www.openclonk.org * * Copyright (c) 2005-2009, RedWolf Design GmbH, http://www.clonk.de/ * Copyright (c) 2009-2013, The OpenClonk Team and contributors * * Distributed under the terms of the ISC license; see accompanying file * "COPYING" for details. * * "Clonk" is a registered trademark of Matthes Bender, used with permission. * See accompanying file "TRADEMARK" for details. * * To redistribute this file separately, substitute the full license texts * for the above references. */ /* A wrapper class to OS dependent event and window interfaces, SDL version */ #include #include "C4App.h" #include #include #include #include #include #include #include #include #include static void sdlToC4MCBtn(const SDL_MouseButtonEvent &e, int32_t& button, DWORD& flags) { C4TimeMilliseconds lastLeftClick = C4TimeMilliseconds::Now(); C4TimeMilliseconds lastRightClick = C4TimeMilliseconds::Now(); static int lastX = 0, lastY = 0; static const int clickDist = 2; static const int clickDelay = 400; button = C4MC_Button_None; flags = 0; switch (e.button) { case SDL_BUTTON_LEFT: if (e.state == SDL_PRESSED) if (C4TimeMilliseconds::Now() - lastLeftClick < clickDelay && abs(lastX-e.x) <= clickDist && abs(lastY-e.y) <= clickDist) { lastLeftClick = 0; button = C4MC_Button_LeftDouble; } else { lastLeftClick = C4TimeMilliseconds::Now(); button = C4MC_Button_LeftDown; } else button = C4MC_Button_LeftUp; break; case SDL_BUTTON_RIGHT: if (e.state == SDL_PRESSED) if (C4TimeMilliseconds::Now() - lastRightClick < clickDelay) { lastRightClick = 0; button = C4MC_Button_RightDouble; } else { lastRightClick = C4TimeMilliseconds::Now(); button = C4MC_Button_RightDown; } else button = C4MC_Button_RightUp; break; case SDL_BUTTON_MIDDLE: if (e.state == SDL_PRESSED) button = C4MC_Button_MiddleDown; else button = C4MC_Button_MiddleUp; break; /*case SDL_BUTTON_WHEELUP: button = C4MC_Button_Wheel; flags = (+32) << 16; break; case SDL_BUTTON_WHEELDOWN: button = C4MC_Button_Wheel; flags = (-32) << 16; break;*/ } lastX = e.x; lastY = e.y; } /* C4AbstractApp */ C4AbstractApp::C4AbstractApp(): Active(false), pWindow(NULL), fQuitMsgReceived(false), // main thread #ifdef HAVE_PTHREAD MainThread (pthread_self()), #endif #ifdef _WIN32 idMainThread(0), #endif fDspModeSet(false) { } C4AbstractApp::~C4AbstractApp() { } bool C4AbstractApp::Init(int argc, char * argv[]) { // Set locale setlocale(LC_ALL,""); if (SDL_Init(SDL_INIT_VIDEO | SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE) < 0) { Log("Error initializing SDL."); return false; } //SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_INTERVAL); // Custom initialization return DoInit (argc, argv); } void C4AbstractApp::Clear() { SDL_Quit(); } void C4AbstractApp::Quit() { fQuitMsgReceived = true; } bool C4AbstractApp::FlushMessages() { // Always fail after quit message if (fQuitMsgReceived) return false; // Handle pending SDL messages SDL_Event event; while (SDL_PollEvent(&event)) { HandleSDLEvent(event); } return true; } void C4AbstractApp::HandleSDLEvent(SDL_Event& e) { // Directly handle QUIT messages. switch (e.type) { case SDL_QUIT: Quit(); break; case SDL_TEXTINPUT: ::pGUI->CharIn(e.text.text); break; case SDL_KEYDOWN: { Game.DoKeyboardInput(e.key.keysym.scancode, KEYEV_Down, e.key.keysym.mod & (KMOD_LALT | KMOD_RALT), e.key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL), e.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT), false, NULL); break; } case SDL_KEYUP: Game.DoKeyboardInput(e.key.keysym.scancode, KEYEV_Up, e.key.keysym.mod & (KMOD_LALT | KMOD_RALT), e.key.keysym.mod & (KMOD_LCTRL | KMOD_RCTRL), e.key.keysym.mod & (KMOD_LSHIFT | KMOD_RSHIFT), false, NULL); break; case SDL_MOUSEMOTION: C4GUI::MouseMove(C4MC_Button_None, e.motion.x, e.motion.y, 0, NULL); break; case SDL_MOUSEBUTTONUP: case SDL_MOUSEBUTTONDOWN: int32_t button; DWORD flags; sdlToC4MCBtn(e.button, button, flags); C4GUI::MouseMove(button, e.button.x, e.button.y, flags, NULL); break; case SDL_JOYAXISMOTION: case SDL_JOYHATMOTION: case SDL_JOYBALLMOTION: case SDL_JOYBUTTONDOWN: case SDL_JOYBUTTONUP: Application.pGamePadControl->FeedEvent(e); break; } } static int modeCount = 0; bool C4AbstractApp::GetIndexedDisplayMode(int32_t iIndex, int32_t *piXRes, int32_t *piYRes, int32_t *piBitDepth, int32_t *piRefreshRate, uint32_t iMonitor) { if (!modeCount) { modeCount = SDL_GetNumDisplayModes(iMonitor); } if (iIndex >= modeCount) return false; SDL_DisplayMode mode; SDL_GetDisplayMode(iMonitor, iIndex, &mode); *piXRes = mode.w; *piYRes = mode.h; *piBitDepth = SDL_BITSPERPIXEL(mode.format); *piRefreshRate = mode.refresh_rate; return true; } bool C4AbstractApp::SetVideoMode(int iXRes, int iYRes, unsigned int RefreshRate, unsigned int iMonitor, bool fFullScreen) { int res; if (!fFullScreen) { res = SDL_SetWindowFullscreen(pWindow->window, 0); if (res) { LogF("SDL_SetWindowFullscreen: %s", SDL_GetError()); return false; } if (iXRes != -1) pWindow->SetSize(iXRes, iYRes); C4Rect r; pWindow->GetSize(&r); OnResolutionChanged(r.Wdt, r.Hgt); return true; } SDL_DisplayMode mode; if (iXRes < 0 || iYRes < 0) { res = SDL_SetWindowFullscreen(pWindow->window, SDL_WINDOW_FULLSCREEN_DESKTOP); if (res) { LogF("SDL_SetWindowFullscreen: %s", SDL_GetError()); return false; } res = SDL_GetDesktopDisplayMode(iMonitor, &mode); if (res) { LogF("SDL_GetDesktopDisplayMode: %s", SDL_GetError()); return false; } OnResolutionChanged(mode.w, mode.h); return true; } for (int i = 0; i < modeCount; ++i) { res = SDL_GetDisplayMode(iMonitor, i, &mode); if (res) { LogF("SDL_GetDisplayMode: %s", SDL_GetError()); return false; } if (mode.w == iXRes && mode.h == iYRes && mode.refresh_rate == RefreshRate && SDL_BITSPERPIXEL(mode.format) == C4Draw::COLOR_DEPTH) { res = SDL_SetWindowDisplayMode(pWindow->window, &mode); if (res) { LogF("SDL_SetWindowDisplayMode: %s", SDL_GetError()); return false; } res = SDL_SetWindowFullscreen(pWindow->window, SDL_WINDOW_FULLSCREEN); if (res) { LogF("SDL_SetWindowFullscreen: %s", SDL_GetError()); return false; } OnResolutionChanged(mode.w, mode.h); return true; } } return false; } void C4AbstractApp::RestoreVideoMode() { if (pWindow && pWindow->window) SDL_SetWindowFullscreen(pWindow->window, 0); } bool C4AbstractApp::Copy(const StdStrBuf & text, bool fClipboard) { return SDL_SetClipboardText(text.getData()) == 0; } StdStrBuf C4AbstractApp::Paste(bool fClipboard) { char * text = SDL_GetClipboardText(); StdStrBuf buf; buf.Copy(text); SDL_free(text); return buf; } bool C4AbstractApp::IsClipboardFull(bool fClipboard) { return SDL_HasClipboardText(); } void C4AbstractApp::MessageDialog(const char * message) { SDL_ShowSimpleMessageBox(0, C4ENGINECAPTION, message, pWindow ? pWindow->window : 0); }