1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-17 13:41:07 +02:00

Merge pull request #154 from vmarkovtsev/feature/macosx_right_click

Enable right mouse button click emulation on MacOSX
This commit is contained in:
Alexander Shishkin 2016-01-18 16:44:07 +03:00
commit 698df110d8

View File

@ -79,7 +79,7 @@ extern boost::thread_specific_ptr<bool> inGuiThread;
SDL_Surface *screen = nullptr, //main screen surface SDL_Surface *screen = nullptr, //main screen surface
*screen2 = nullptr, //and hlp surface (used to store not-active interfaces layer) *screen2 = nullptr, //and hlp surface (used to store not-active interfaces layer)
*screenBuf = screen; //points to screen (if only advmapint is present) or screen2 (else) - should be used when updating controls which are not regularly redrawed *screenBuf = screen; //points to screen (if only advmapint is present) or screen2 (else) - should be used when updating controls which are not regularly redrawed
std::queue<SDL_Event> events; std::queue<SDL_Event> events;
boost::mutex eventsM; boost::mutex eventsM;
@ -187,7 +187,7 @@ static void SDLLogCallback(void* userdata,
{ {
//todo: convert SDL log priority to vcmi log priority //todo: convert SDL log priority to vcmi log priority
//todo: make separate log domain for SDL //todo: make separate log domain for SDL
logGlobal->debugStream() << "SDL(category " << category << "; priority " <<priority <<") "<<message; logGlobal->debugStream() << "SDL(category " << category << "; priority " <<priority <<") "<<message;
} }
@ -363,21 +363,21 @@ int main(int argc, char** argv)
} }
GH.mainFPSmng->init(); //(!)init here AFTER SDL_Init() while using SDL for FPS management GH.mainFPSmng->init(); //(!)init here AFTER SDL_Init() while using SDL for FPS management
atexit(SDL_Quit); atexit(SDL_Quit);
SDL_LogSetOutputFunction(&SDLLogCallback, nullptr); SDL_LogSetOutputFunction(&SDLLogCallback, nullptr);
int driversCount = SDL_GetNumRenderDrivers(); int driversCount = SDL_GetNumRenderDrivers();
std::string preferredDriverName = video["driver"].String(); std::string preferredDriverName = video["driver"].String();
logGlobal->infoStream() << "Found " << driversCount << " render drivers"; logGlobal->infoStream() << "Found " << driversCount << " render drivers";
for(int it = 0; it < driversCount; it++) for(int it = 0; it < driversCount; it++)
{ {
SDL_RendererInfo info; SDL_RendererInfo info;
SDL_GetRenderDriverInfo(it,&info); SDL_GetRenderDriverInfo(it,&info);
std::string driverName(info.name); std::string driverName(info.name);
if(!preferredDriverName.empty() && driverName == preferredDriverName) if(!preferredDriverName.empty() && driverName == preferredDriverName)
{ {
preferredDriverIndex = it; preferredDriverIndex = it;
@ -385,8 +385,8 @@ int main(int argc, char** argv)
} }
else else
logGlobal->infoStream() << "\t" << driverName; logGlobal->infoStream() << "\t" << driverName;
} }
config::CConfigHandler::GuiOptionsMap::key_type resPair(res["width"].Float(), res["height"].Float()); config::CConfigHandler::GuiOptionsMap::key_type resPair(res["width"].Float(), res["height"].Float());
if (conf.guiOptions.count(resPair) == 0) if (conf.guiOptions.count(resPair) == 0)
{ {
@ -440,10 +440,15 @@ int main(int argc, char** argv)
CCS->musich->setVolume(settings["general"]["music"].Float()); CCS->musich->setVolume(settings["general"]["music"].Float());
logGlobal->infoStream()<<"Initializing screen and sound handling: "<<pomtime.getDiff(); logGlobal->infoStream()<<"Initializing screen and sound handling: "<<pomtime.getDiff();
#ifdef __APPLE__
// Ctrl+click should be treated as a right click on Mac OS X
SDL_SetHint(SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK, "1");
#endif
#ifndef VCMI_NO_THREADED_LOAD #ifndef VCMI_NO_THREADED_LOAD
//we can properly play intro only in the main thread, so we have to move loading to the separate thread //we can properly play intro only in the main thread, so we have to move loading to the separate thread
boost::thread loading(init); boost::thread loading(init);
#else #else
init(); init();
#endif #endif
@ -632,7 +637,7 @@ void processCommand(const std::string &message)
for (auto & filename : list) for (auto & filename : list)
{ {
const bfs::path filePath = outPath / (filename.getName() + ".TXT"); const bfs::path filePath = outPath / (filename.getName() + ".TXT");
bfs::create_directories(filePath.parent_path()); bfs::create_directories(filePath.parent_path());
bfs::ofstream file(filePath); bfs::ofstream file(filePath);
@ -845,25 +850,25 @@ static bool checkVideoMode(int monitorIndex, int w, int h, int& bpp, bool fullsc
return true; return true;
} }
} }
return false; return false;
} }
static bool recreateWindow(int w, int h, int bpp, bool fullscreen) static bool recreateWindow(int w, int h, int bpp, bool fullscreen)
{ {
// VCMI will only work with 2 or 4 bytes per pixel // VCMI will only work with 2 or 4 bytes per pixel
vstd::amax(bpp, 16); vstd::amax(bpp, 16);
vstd::amin(bpp, 32); vstd::amin(bpp, 32);
if(bpp>16) if(bpp>16)
bpp = 32; bpp = 32;
int suggestedBpp = bpp; int suggestedBpp = bpp;
if(!checkVideoMode(0,w,h,suggestedBpp,fullscreen)) if(!checkVideoMode(0,w,h,suggestedBpp,fullscreen))
{ {
logGlobal->errorStream() << "Error: SDL says that " << w << "x" << h << " resolution is not available!"; logGlobal->errorStream() << "Error: SDL says that " << w << "x" << h << " resolution is not available!";
return false; return false;
} }
bool bufOnScreen = (screenBuf == screen); bool bufOnScreen = (screenBuf == screen);
screenBuf = nullptr; //it`s a link - just nullify screenBuf = nullptr; //it`s a link - just nullify
@ -873,34 +878,34 @@ static bool recreateWindow(int w, int h, int bpp, bool fullscreen)
SDL_FreeSurface(screen2); SDL_FreeSurface(screen2);
screen2 = nullptr; screen2 = nullptr;
} }
if(nullptr != screen) if(nullptr != screen)
{ {
SDL_FreeSurface(screen); SDL_FreeSurface(screen);
screen = nullptr; screen = nullptr;
} }
if(nullptr != screenTexture) if(nullptr != screenTexture)
{ {
SDL_DestroyTexture(screenTexture); SDL_DestroyTexture(screenTexture);
screenTexture = nullptr; screenTexture = nullptr;
} }
if(nullptr != mainRenderer) if(nullptr != mainRenderer)
{ {
SDL_DestroyRenderer(mainRenderer); SDL_DestroyRenderer(mainRenderer);
mainRenderer = nullptr; mainRenderer = nullptr;
} }
if(nullptr != mainWindow) if(nullptr != mainWindow)
{ {
SDL_DestroyWindow(mainWindow); SDL_DestroyWindow(mainWindow);
mainWindow = nullptr; mainWindow = nullptr;
} }
if(fullscreen) if(fullscreen)
{ {
//in full-screen mode always use desktop resolution //in full-screen mode always use desktop resolution
@ -911,33 +916,33 @@ static bool recreateWindow(int w, int h, int bpp, bool fullscreen)
{ {
mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED, w, h, 0); mainWindow = SDL_CreateWindow(NAME.c_str(), SDL_WINDOWPOS_CENTERED,SDL_WINDOWPOS_CENTERED, w, h, 0);
} }
if(nullptr == mainWindow) if(nullptr == mainWindow)
{ {
throw std::runtime_error("Unable to create window\n"); throw std::runtime_error("Unable to create window\n");
} }
//create first available renderer if preferred not set. Use no flags, so HW accelerated will be preferred but SW renderer also will possible //create first available renderer if preferred not set. Use no flags, so HW accelerated will be preferred but SW renderer also will possible
mainRenderer = SDL_CreateRenderer(mainWindow,preferredDriverIndex,0); mainRenderer = SDL_CreateRenderer(mainWindow,preferredDriverIndex,0);
if(nullptr == mainRenderer) if(nullptr == mainRenderer)
{ {
throw std::runtime_error("Unable to create renderer\n"); throw std::runtime_error("Unable to create renderer\n");
} }
SDL_RendererInfo info; SDL_RendererInfo info;
SDL_GetRendererInfo(mainRenderer,&info); SDL_GetRendererInfo(mainRenderer,&info);
logGlobal->infoStream() << "Created renderer " << info.name; logGlobal->infoStream() << "Created renderer " << info.name;
SDL_RenderSetLogicalSize(mainRenderer, w, h); SDL_RenderSetLogicalSize(mainRenderer, w, h);
SDL_RenderSetViewport(mainRenderer, nullptr); SDL_RenderSetViewport(mainRenderer, nullptr);
#if (SDL_BYTEORDER == SDL_BIG_ENDIAN) #if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
int bmask = 0xff000000; int bmask = 0xff000000;
int gmask = 0x00ff0000; int gmask = 0x00ff0000;
@ -955,13 +960,13 @@ static bool recreateWindow(int w, int h, int bpp, bool fullscreen)
{ {
logGlobal->errorStream() << "Unable to create surface"; logGlobal->errorStream() << "Unable to create surface";
logGlobal->errorStream() << w << " "<< h << " "<< bpp; logGlobal->errorStream() << w << " "<< h << " "<< bpp;
logGlobal->errorStream() << SDL_GetError(); logGlobal->errorStream() << SDL_GetError();
throw std::runtime_error("Unable to create surface"); throw std::runtime_error("Unable to create surface");
} }
//No blending for screen itself. Required for proper cursor rendering. //No blending for screen itself. Required for proper cursor rendering.
SDL_SetSurfaceBlendMode(screen, SDL_BLENDMODE_NONE); SDL_SetSurfaceBlendMode(screen, SDL_BLENDMODE_NONE);
screenTexture = SDL_CreateTexture(mainRenderer, screenTexture = SDL_CreateTexture(mainRenderer,
SDL_PIXELFORMAT_ARGB8888, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_STREAMING, SDL_TEXTUREACCESS_STREAMING,
@ -972,23 +977,23 @@ static bool recreateWindow(int w, int h, int bpp, bool fullscreen)
logGlobal->errorStream() << "Unable to create screen texture"; logGlobal->errorStream() << "Unable to create screen texture";
logGlobal->errorStream() << SDL_GetError(); logGlobal->errorStream() << SDL_GetError();
throw std::runtime_error("Unable to create screen texture"); throw std::runtime_error("Unable to create screen texture");
} }
screen2 = CSDL_Ext::copySurface(screen); screen2 = CSDL_Ext::copySurface(screen);
if(nullptr == screen2) if(nullptr == screen2)
{ {
throw std::runtime_error("Unable to copy surface\n"); throw std::runtime_error("Unable to copy surface\n");
} }
screenBuf = bufOnScreen ? screen : screen2; screenBuf = bufOnScreen ? screen : screen2;
SDL_SetRenderDrawColor(mainRenderer, 0, 0, 0, 0); SDL_SetRenderDrawColor(mainRenderer, 0, 0, 0, 0);
SDL_RenderClear(mainRenderer); SDL_RenderClear(mainRenderer);
SDL_RenderPresent(mainRenderer); SDL_RenderPresent(mainRenderer);
return true; return true;
} }
//used only once during initialization //used only once during initialization
@ -997,7 +1002,7 @@ static void setScreenRes(int w, int h, int bpp, bool fullscreen, bool resetVideo
if(!recreateWindow(w,h,bpp,fullscreen)) if(!recreateWindow(w,h,bpp,fullscreen))
{ {
throw std::runtime_error("Requested screen resolution is not available\n"); throw std::runtime_error("Requested screen resolution is not available\n");
} }
} }
static void fullScreenChanged() static void fullScreenChanged()
@ -1008,16 +1013,16 @@ static void fullScreenChanged()
const bool toFullscreen = full->Bool(); const bool toFullscreen = full->Bool();
auto bitsPerPixel = screen->format->BitsPerPixel; auto bitsPerPixel = screen->format->BitsPerPixel;
auto w = screen->w; auto w = screen->w;
auto h = screen->h; auto h = screen->h;
if(!recreateWindow(w,h,bitsPerPixel,toFullscreen)) if(!recreateWindow(w,h,bitsPerPixel,toFullscreen))
{ {
//will return false and report error if video mode is not supported //will return false and report error if video mode is not supported
return; return;
} }
GH.totalRedraw(); GH.totalRedraw();
} }
@ -1025,7 +1030,7 @@ static void handleEvent(SDL_Event & ev)
{ {
if((ev.type==SDL_QUIT) ||(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4 && (ev.key.keysym.mod & KMOD_ALT))) if((ev.type==SDL_QUIT) ||(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4 && (ev.key.keysym.mod & KMOD_ALT)))
{ {
handleQuit(); handleQuit();
return; return;
} }
else if(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4) else if(ev.type == SDL_KEYDOWN && ev.key.keysym.sym==SDLK_F4)
@ -1040,8 +1045,8 @@ static void handleEvent(SDL_Event & ev)
{ {
case FORCE_QUIT: case FORCE_QUIT:
{ {
handleQuit(false); handleQuit(false);
return; return;
} }
break; break;
case RETURN_TO_MAIN_MENU: case RETURN_TO_MAIN_MENU:
@ -1080,8 +1085,8 @@ static void handleEvent(SDL_Event & ev)
fullScreenChanged(); fullScreenChanged();
break; break;
default: default:
logGlobal->errorStream() << "Unknown user event. Code " << ev.user.code; logGlobal->errorStream() << "Unknown user event. Code " << ev.user.code;
break; break;
} }
return; return;
@ -1098,8 +1103,8 @@ static void handleEvent(SDL_Event & ev)
{ {
boost::unique_lock<boost::mutex> lock(eventsM); boost::unique_lock<boost::mutex> lock(eventsM);
events.push(ev); events.push(ev);
} }
} }
@ -1114,12 +1119,12 @@ static void mainLoop()
while(1) //main SDL events loop while(1) //main SDL events loop
{ {
SDL_Event ev; SDL_Event ev;
while(1 == SDL_PollEvent(&ev)) while(1 == SDL_PollEvent(&ev))
{ {
handleEvent(ev); handleEvent(ev);
} }
GH.renderFrame(); GH.renderFrame();
} }