From ce0d1234ccd63dbe29439f0645b8eab00da0f2f7 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Mon, 11 Oct 2021 12:33:07 +0300 Subject: [PATCH 01/13] Add missing WITH_FFMPEG option --- CMakeModules/nel.cmake | 2 ++ nel/CMakeLists.txt | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/CMakeModules/nel.cmake b/CMakeModules/nel.cmake index f8d01a0bc..baddcfa9b 100644 --- a/CMakeModules/nel.cmake +++ b/CMakeModules/nel.cmake @@ -249,6 +249,8 @@ MACRO(NL_SETUP_DEFAULT_OPTIONS) OPTION(WITH_ASSIMP "Use assimp exporter" OFF) OPTION(WITH_LIBGSF "Use libgsf for max file library" OFF) + OPTION(WITH_FFMPEG "Use ffmpeg for audio decoder" OFF) + ### # GUI toolkits ### diff --git a/nel/CMakeLists.txt b/nel/CMakeLists.txt index 1530e75e3..b102310ab 100644 --- a/nel/CMakeLists.txt +++ b/nel/CMakeLists.txt @@ -20,7 +20,9 @@ ENDIF() IF(WITH_SOUND) FIND_PACKAGE(Ogg) FIND_PACKAGE(Vorbis) - FIND_PACKAGE(FFmpeg COMPONENTS AVCODEC AVFORMAT AVUTIL SWRESAMPLE) + IF(WITH_FFMPEG) + FIND_PACKAGE(FFmpeg REQUIRED COMPONENTS AVCODEC AVFORMAT AVUTIL SWRESAMPLE) + ENDIF() IF(WITH_DRIVER_OPENAL) FIND_PACKAGE(OpenAL) From b9d4aa2abdabcc09cf4a73121951820e6cccd9af Mon Sep 17 00:00:00 2001 From: kaetemi Date: Mon, 27 Sep 2021 16:51:37 +0800 Subject: [PATCH 02/13] Add Ubuntu 20.04 target to Azure Pipelines configuration --- azure-pipelines.yml | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 10d0b1e63..71303a253 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -81,3 +81,40 @@ jobs: cd build make -j`nproc` displayName: 'Make' + - job: ubuntu20 + timeoutInMinutes: 120 + pool: + vmImage: 'ubuntu-20.04' + steps: + - script: | + sudo apt update + sudo apt install -y software-properties-common + sudo apt update + sudo apt install cmake build-essential -y + sudo apt install bison autoconf automake -y + sudo apt install libpng-dev -y + sudo apt install libjpeg-dev -y + sudo apt install libgif-dev libfreetype6-dev -y + sudo apt install freeglut3-dev -y + sudo apt install liblua5.2-dev libluabind-dev libcpptest-dev -y + sudo apt install libogg-dev libvorbis-dev libopenal-dev -y + sudo apt install libavcodec-dev libavformat-dev libavdevice-dev libswscale-dev libpostproc-dev -y + sudo apt install libmysqlclient-dev -y + sudo apt install libxml2-dev -y + sudo apt install libcurl4-openssl-dev libssl-dev -y + sudo apt install libsquish-dev -y + sudo apt install liblzma-dev -y + sudo apt install libgsf-1-dev -y + sudo apt install qtbase5-dev qttools5-dev qttools5-dev-tools + displayName: 'Dependencies' + - script: | + mkdir build + cmake --version + cd build + cmake -DWITH_STATIC=ON -DWITH_NEL_TESTS=OFF -DWITH_NEL_SAMPLES=ON -DWITH_LUA51=OFF -DWITH_LUA52=ON -DWITH_RYZOM=ON -DWITH_RYZOM_SERVER=ON -DWITH_RYZOM_CLIENT=ON -DWITH_RYZOM_TOOLS=ON -DWITH_NEL_TOOLS=ON -DWITH_NELNS=ON -DWITH_NELNS_LOGIN_SYSTEM=ON -DWITH_NELNS_SERVER=ON -DWITH_QT5=ON -DWITH_LIBGSF=ON .. + cat CMakeCache.txt + displayName: 'CMake' + - script: | + cd build + make -j`nproc` + displayName: 'Make' From af16f09d52f3bb21313701450d60994c2f408318 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Mon, 27 Sep 2021 17:37:15 +0800 Subject: [PATCH 03/13] Ubuntu 16.04 is EOL --- azure-pipelines.yml | 41 ----------------------------------------- 1 file changed, 41 deletions(-) diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 71303a253..1885a5dfa 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,45 +1,4 @@ jobs: - - job: ubuntu16 - timeoutInMinutes: 120 - pool: - vmImage: 'Ubuntu-16.04' - steps: - - script: | - sudo apt-get update - sudo apt-get install -y software-properties-common - sudo add-apt-repository ppa:ubuntu-toolchain-r/test - sudo apt-get update - sudo apt-get install cmake build-essential -y - sudo apt-get install gcc-8 g++-8 -y - sudo update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-8 60 - sudo update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-8 60 - sudo apt-get install bison autoconf automake -y - sudo apt-get install libpng12-dev -y - sudo apt-get install libjpeg-dev -y - sudo apt-get install libgif-dev libfreetype6-dev -y - sudo apt-get install freeglut3-dev -y - sudo apt-get install liblua5.1-dev libluabind-dev libcpptest-dev -y - sudo apt-get install libogg-dev libvorbis-dev libopenal-dev -y - sudo apt-get install libavcodec-dev libavformat-dev libavdevice-dev libswscale-dev libpostproc-dev -y - sudo apt-get install libmysqlclient-dev -y - sudo apt-get install libxml2-dev -y - sudo apt-get install libcurl4-openssl-dev libssl-dev -y - sudo apt-get install libsquish-dev -y - sudo apt-get install liblzma-dev -y - sudo apt-get install libgsf-1-dev -y - sudo apt-get install qtbase5-dev qttools5-dev qttools5-dev-tools - displayName: 'Dependencies' - - script: | - mkdir build - cmake --version - cd build - cmake -DWITH_STATIC=ON -DWITH_NEL_TESTS=OFF -DWITH_NEL_SAMPLES=ON -DWITH_LUA51=ON -DWITH_RYZOM=ON -DWITH_RYZOM_SERVER=ON -DWITH_RYZOM_CLIENT=ON -DWITH_RYZOM_TOOLS=ON -DWITH_NEL_TOOLS=ON -DWITH_NELNS=ON -DWITH_NELNS_LOGIN_SYSTEM=ON -DWITH_NELNS_SERVER=ON -DWITH_QT5=ON -DWITH_LIBGSF=ON .. - cat CMakeCache.txt - displayName: 'CMake' - - script: | - cd build - make -j`nproc` - displayName: 'Make' - job: ubuntu18 timeoutInMinutes: 120 pool: From 3d208e024d6806ac2e386787bb2bc114d67add92 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Mon, 27 Sep 2021 22:31:41 +0800 Subject: [PATCH 04/13] Improve c++0x check --- nel/include/nel/misc/types_nl.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/nel/include/nel/misc/types_nl.h b/nel/include/nel/misc/types_nl.h index a257eb293..5af1ce3f3 100644 --- a/nel/include/nel/misc/types_nl.h +++ b/nel/include/nel/misc/types_nl.h @@ -174,10 +174,6 @@ # define NL_COMP_GCC #endif -#if defined(_HAS_CPP0X) || defined(__GXX_EXPERIMENTAL_CXX0X__) || (defined(NL_COMP_VC_VERSION) && NL_COMP_VC_VERSION >= 110) -# define NL_ISO_CPP0X_AVAILABLE -#endif - #if defined(NL_COMP_GCC) && (__cplusplus >= 201103L) # define NL_NO_EXCEPTION_SPECS #endif @@ -233,6 +229,10 @@ # endif #endif +#if defined(_HAS_CPP0X) || defined(__GXX_EXPERIMENTAL_CXX0X__) || (defined(NL_COMP_VC_VERSION) && NL_COMP_VC_VERSION >= 110) || (defined(NL_COMP_GCC) && (GCC_VERSION >= 40400) && (__cplusplus >= 201103L)) +# define NL_ISO_CPP0X_AVAILABLE +#endif + // Remove stupid Visual C++ warnings #ifdef NL_OS_WINDOWS # pragma warning (disable : 4503) // STL: Decorated name length exceeded, name was truncated From 3076b620636df13178896438d44a42ff51e0234d Mon Sep 17 00:00:00 2001 From: kaetemi Date: Mon, 27 Sep 2021 19:10:00 +0800 Subject: [PATCH 05/13] Fix build when using ValyriaTear/luabind (on Ubuntu) --- nel/src/gui/lua_helper.cpp | 6 +++++ nel/src/gui/lua_ihm.cpp | 26 +++++++++++++++---- .../client/src/interface_v3/lua_ihm_ryzom.cpp | 6 +++++ .../variable_parser/lua_helper.cpp | 7 +++++ 4 files changed, 40 insertions(+), 5 deletions(-) diff --git a/nel/src/gui/lua_helper.cpp b/nel/src/gui/lua_helper.cpp index bb5fd5426..ed4106144 100644 --- a/nel/src/gui/lua_helper.cpp +++ b/nel/src/gui/lua_helper.cpp @@ -42,6 +42,12 @@ #define assert(x) #endif +// Always use unique_ptr with ValyriaTear/luabind on Ubuntu 20, +// since the setting is not stored in build_information.hpp +#ifndef LUABIND_USE_CXX11 +#define LUABIND_USE_CXX11 +#endif + #include #include #include diff --git a/nel/src/gui/lua_ihm.cpp b/nel/src/gui/lua_ihm.cpp index cdd87330c..229cd1f0f 100644 --- a/nel/src/gui/lua_ihm.cpp +++ b/nel/src/gui/lua_ihm.cpp @@ -48,6 +48,12 @@ # define assert(x) #endif +// Always use unique_ptr with ValyriaTear/luabind on Ubuntu 20, +// since the setting is not stored in build_information.hpp +#ifndef LUABIND_USE_CXX11 +#define LUABIND_USE_CXX11 +#endif + #include // in luabind > 0.6, LUABIND_MAX_ARITY is set to 10 #if LUABIND_MAX_ARITY == 10 @@ -220,7 +226,9 @@ namespace NLGUI void CLuaIHM::push(CLuaState &ls, const ucstring &value) { //H_AUTO(Lua_CLuaIHM_push) - #if LUABIND_VERSION > 600 + #if defined(LUABIND_STACK_HPP_INCLUDED) + luabind::push(ls.getStatePointer(), value); + #elif (LUABIND_VERSION > 600) luabind::detail::push(ls.getStatePointer(), value); #else luabind::object obj(ls.getStatePointer(), value); @@ -1156,7 +1164,9 @@ namespace NLGUI case CInterfaceExprValue::RGBA: { CRGBA color = value.getRGBA(); - #if LUABIND_VERSION > 600 + #if defined(LUABIND_STACK_HPP_INCLUDED) + luabind::push(ls.getStatePointer(), color); + #elif (LUABIND_VERSION > 600) luabind::detail::push(ls.getStatePointer(), color); #else luabind::object obj(ls.getStatePointer(), color); @@ -1416,7 +1426,9 @@ namespace NLGUI case CReflectedProperty::UCString: { ucstring str = (reflectedObject.*(property.GetMethod.GetUCString))(); - #if LUABIND_VERSION > 600 + #if defined(LUABIND_STACK_HPP_INCLUDED) + luabind::push(ls.getStatePointer(), str); + #elif (LUABIND_VERSION > 600) luabind::detail::push(ls.getStatePointer(), str); #else luabind::object obj(ls.getStatePointer(), str); @@ -1427,7 +1439,9 @@ namespace NLGUI case CReflectedProperty::UCStringRef: { ucstring str = (reflectedObject.*(property.GetMethod.GetUCStringRef))(); - #if LUABIND_VERSION > 600 + #if defined(LUABIND_STACK_HPP_INCLUDED) + luabind::push(ls.getStatePointer(), str); + #elif (LUABIND_VERSION > 600) luabind::detail::push(ls.getStatePointer(), str); #else luabind::object obj(ls.getStatePointer(), str); @@ -1442,7 +1456,9 @@ namespace NLGUI case CReflectedProperty::RGBA: { CRGBA color = (reflectedObject.*(property.GetMethod.GetRGBA))(); - #if LUABIND_VERSION > 600 + #if defined(LUABIND_STACK_HPP_INCLUDED) + luabind::push(ls.getStatePointer(), color); + #elif (LUABIND_VERSION > 600) luabind::detail::push(ls.getStatePointer(), color); #else luabind::object obj(ls.getStatePointer(), color); diff --git a/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp b/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp index c87102c9e..c1c931528 100644 --- a/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp +++ b/ryzom/client/src/interface_v3/lua_ihm_ryzom.cpp @@ -41,6 +41,12 @@ # define assert(x) #endif +// Always use unique_ptr with ValyriaTear/luabind on Ubuntu 20, +// since the setting is not stored in build_information.hpp +#ifndef LUABIND_USE_CXX11 +#define LUABIND_USE_CXX11 +#endif + #include // in luabind > 0.6, LUABIND_MAX_ARITY is set to 10 #if LUABIND_MAX_ARITY == 10 diff --git a/ryzom/tools/leveldesign/variable_parser/lua_helper.cpp b/ryzom/tools/leveldesign/variable_parser/lua_helper.cpp index 2bb462664..bca003d6a 100644 --- a/ryzom/tools/leveldesign/variable_parser/lua_helper.cpp +++ b/ryzom/tools/leveldesign/variable_parser/lua_helper.cpp @@ -30,6 +30,13 @@ extern "C" #include #undef assert #define assert nlassert + +// Always use unique_ptr with ValyriaTear/luabind on Ubuntu 20, +// since the setting is not stored in build_information.hpp +#ifndef LUABIND_USE_CXX11 +#define LUABIND_USE_CXX11 +#endif + #include using namespace std; From 6d60cfee71623017a741558816806f27fbcb3634 Mon Sep 17 00:00:00 2001 From: kaetemi Date: Tue, 28 Sep 2021 11:41:36 +0800 Subject: [PATCH 06/13] Stop sound when patching sound bnp --- ryzom/client/src/init.cpp | 43 ++++++++++++++++++++++ ryzom/client/src/login_patch.cpp | 8 +++- ryzom/tools/client/client_patcher/main.cpp | 4 ++ 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/ryzom/client/src/init.cpp b/ryzom/client/src/init.cpp index 7e4e09521..206122704 100644 --- a/ryzom/client/src/init.cpp +++ b/ryzom/client/src/init.cpp @@ -1456,6 +1456,15 @@ void prelogInit() } } +void stopSoundMngr() +{ + if (SoundMngr) + { + delete SoundMngr; + SoundMngr = NULL; + } +} + // *************************************************************************** void initBotObjectSelection() @@ -1588,6 +1597,40 @@ void postlogInit() // set the primitive context CPrimitiveContext::instance().CurrentLigoConfig = &LigoConfig; + { + H_AUTO(InitRZSound) + + if (!SoundMngr) + { + // Init the sound manager + nmsg = "Initializing sound manager..."; + ProgressBar.newMessage(ClientCfg.buildLoadingString(nmsg)); + if (ClientCfg.SoundOn) + { + SoundMngr = new CSoundManager(&ProgressBar); + try + { + SoundMngr->init(&ProgressBar); + } + catch (const Exception &e) + { + nlwarning("init : Error when creating 'SoundMngr' : %s", e.what()); + delete SoundMngr; + SoundMngr = NULL; + } + + if (SoundMngr) + { + // init the SoundMngr with backuped volume + SoundMngr->setSFXVolume(ClientCfg.SoundSFXVolume); + SoundMngr->setGameMusicVolume(ClientCfg.SoundGameMusicVolume); + } + } + + CPath::memoryCompress(); // Because sound calls addSearchPath + } + } + { H_AUTO(InitRZShIdI) diff --git a/ryzom/client/src/login_patch.cpp b/ryzom/client/src/login_patch.cpp index 4233a23c2..1ecb8bffd 100644 --- a/ryzom/client/src/login_patch.cpp +++ b/ryzom/client/src/login_patch.cpp @@ -2592,7 +2592,7 @@ public: } }; - +void stopSoundMngr(); // **************************************************************************** void CPatchThread::processFile (CPatchManager::SFileToPatch &rFTP) @@ -2605,6 +2605,12 @@ void CPatchThread::processFile (CPatchManager::SFileToPatch &rFTP) // Destination File Name (in writable directory) string DestinationName; + if (NLMISC::startsWith(rFTP.FileName, "sound")) + { + // Stop sound playback + stopSoundMngr(); + } + if (rFTP.ExtractPath.empty()) { DestinationName = pPM->WritableClientDataPath + rFTP.FileName; diff --git a/ryzom/tools/client/client_patcher/main.cpp b/ryzom/tools/client/client_patcher/main.cpp index 9855a6b65..ce6375318 100644 --- a/ryzom/tools/client/client_patcher/main.cpp +++ b/ryzom/tools/client/client_patcher/main.cpp @@ -37,6 +37,10 @@ void quitCrashReport() { } +void stopSoundMngr() +{ +} + /// domain server version for patch string R2ServerVersion; /// name of the version (used to alias many version under the same name), From 5fcaafbc6046cbdd0e8a2b9c8a8bbeb401b010fa Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sun, 3 Oct 2021 12:25:18 +0800 Subject: [PATCH 07/13] Show more useful error on login failure --- nel/include/nel/web/http_client_curl.h | 4 ++++ nel/src/web/http_client_curl.cpp | 8 +++++--- ryzom/client/src/login.cpp | 8 ++++---- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/nel/include/nel/web/http_client_curl.h b/nel/include/nel/web/http_client_curl.h index cfb1ac38a..babd0d7f9 100644 --- a/nel/include/nel/web/http_client_curl.h +++ b/nel/include/nel/web/http_client_curl.h @@ -63,6 +63,8 @@ public: /// Disconnect if connected (otherwise does nothing) void disconnect(); + const char *lastError() { return &m_ErrorBuf[0]; } + protected: /// Helper @@ -78,6 +80,8 @@ private: std::vector _ReceiveBuffer; std::string _Auth; // must be kept here because curl only stores the char pointer + + std::vector m_ErrorBuf; }; extern CCurlHttpClient CurlHttpClient; diff --git a/nel/src/web/http_client_curl.cpp b/nel/src/web/http_client_curl.cpp index b0ea66de3..446491768 100644 --- a/nel/src/web/http_client_curl.cpp +++ b/nel/src/web/http_client_curl.cpp @@ -124,15 +124,17 @@ bool CCurlHttpClient::sendRequest(const std::string& methodWB, const std::string curl_easy_setopt(_Curl, CURLOPT_WRITEFUNCTION, CCurlHttpClient::writeDataFromCurl); curl_easy_setopt(_Curl, CURLOPT_WRITEDATA, this); - char errorbuf [CURL_ERROR_SIZE+1]; - curl_easy_setopt(_Curl, CURLOPT_ERRORBUFFER, errorbuf); + if (!m_ErrorBuf.size()) + m_ErrorBuf.resize(CURL_ERROR_SIZE + 1); + m_ErrorBuf[0] = '\0'; + curl_easy_setopt(_Curl, CURLOPT_ERRORBUFFER, &m_ErrorBuf[0]); // Send CURLcode res = curl_easy_perform(_Curl); if (res != 0) { if (verbose) - nlwarning(errorbuf); + nlwarning(&m_ErrorBuf[0]); return false; } diff --git a/ryzom/client/src/login.cpp b/ryzom/client/src/login.cpp index bedd66f7c..7b0377890 100644 --- a/ryzom/client/src/login.cpp +++ b/ryzom/client/src/login.cpp @@ -2832,7 +2832,7 @@ string checkLogin(const string &login, const string &password, const string &cli { // ask server for salt if(!HttpClient.sendGet(url + "?cmd=ask&cp=2&login=" + login + "&lg=" + ClientCfg.LanguageCode, "", pPM->isVerboseLog())) - return "Can't send (error code 60)"; + return std::string("Can't send (error code 60) ") + HttpClient.lastError(); if(pPM->isVerboseLog()) nlinfo("Sent request for password salt"); @@ -2906,13 +2906,13 @@ string checkLogin(const string &login, const string &password, const string &cli std::string cryptedPassword = CCrypt::crypt(password, Salt); if(!HttpClient.sendGet(url + "?cmd=login&login=" + login + "&password=" + cryptedPassword + "&clientApplication=" + clientApp + "&cp=2" + "&lg=" + ClientCfg.LanguageCode + customParameters)) - return "Can't send (error code 2)"; + return std::string("Can't send (error code 2) ") + HttpClient.lastError(); } else { // don't send login and password if empty if(!HttpClient.sendGet(url + "?cmd=login&clientApplication=" + clientApp + "&cp=2" + "&lg=" + ClientCfg.LanguageCode + customParameters)) - return "Can't send (error code 2)"; + return std::string("Can't send (error code 2) ") + HttpClient.lastError(); } // the response should contains the result code and the cookie value @@ -3022,7 +3022,7 @@ string checkLogin(const string &login, const string &password, const string &cli std::string cryptedPassword = CCrypt::crypt(password, Salt); if(!HttpClient.sendGet(url + "?login=" + login + "&password=" + cryptedPassword + "&clientApplication=" + clientApp + "&cp=2")) - return "Can't send (error code 2)"; + return std::string("Can't send (error code 2) ") + HttpClient.lastError(); /* if(!send(ClientCfg.ConfigFile.getVar("StartupPage").asString()+"?login="+login+"&password="+password+"&clientApplication="+clientApp)) return "Can't send (error code 2)"; From 8f839dc9c75be117b1fd0bc5246614e19af7b72a Mon Sep 17 00:00:00 2001 From: kaetemi Date: Sun, 3 Oct 2021 20:08:36 +0800 Subject: [PATCH 08/13] Properly follow StartupVerify setting --- nel/include/nel/web/http_client_curl.h | 4 +++- nel/src/web/http_client_curl.cpp | 7 ++++--- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/nel/include/nel/web/http_client_curl.h b/nel/include/nel/web/http_client_curl.h index babd0d7f9..0a08b5ac0 100644 --- a/nel/include/nel/web/http_client_curl.h +++ b/nel/include/nel/web/http_client_curl.h @@ -34,7 +34,7 @@ class CCurlHttpClient public: /// Constructor - CCurlHttpClient() : _CurlStruct(NULL) {} + CCurlHttpClient() : _CurlStruct(NULL), m_Verify(true) {} /// Connect to an http server (string by val is intended). If you specify a whole URL, an attempt will be made to determine the server. bool connect(const std::string &server); @@ -82,6 +82,8 @@ private: std::string _Auth; // must be kept here because curl only stores the char pointer std::vector m_ErrorBuf; + bool m_Verify; + }; extern CCurlHttpClient CurlHttpClient; diff --git a/nel/src/web/http_client_curl.cpp b/nel/src/web/http_client_curl.cpp index 446491768..b5e54494c 100644 --- a/nel/src/web/http_client_curl.cpp +++ b/nel/src/web/http_client_curl.cpp @@ -75,8 +75,9 @@ static const std::string CAFilename = "cacert.pem"; // https://curl.haxx.se/docs // *************************************************************************** bool CCurlHttpClient::verifyServer(bool verify) { - curl_easy_setopt(_Curl, CURLOPT_SSL_VERIFYHOST, verify ? 2 : 0); + m_Verify = verify; curl_easy_setopt(_Curl, CURLOPT_SSL_VERIFYPEER, verify ? 1 : 0); + curl_easy_setopt(_Curl, CURLOPT_SSL_VERIFYHOST, verify ? 2 : 0); // specify custom CA certs CCurlCertificates::addCertificateFile(CAFilename); @@ -97,8 +98,8 @@ bool CCurlHttpClient::sendRequest(const std::string& methodWB, const std::string curl_easy_setopt(_Curl, CURLOPT_URL, url.c_str()); if (url.length() > 8 && (url[4] == 's' || url[4] == 'S')) // 01234 https { - curl_easy_setopt(_Curl, CURLOPT_SSL_VERIFYPEER, 1L); - curl_easy_setopt(_Curl, CURLOPT_SSL_VERIFYHOST, 2L); + curl_easy_setopt(_Curl, CURLOPT_SSL_VERIFYPEER, m_Verify ? 1L : 0); + curl_easy_setopt(_Curl, CURLOPT_SSL_VERIFYHOST, m_Verify ? 2L : 0); } // Authentication From 82ef7e5e816552ab8aa53c2faa84365449ffb15e Mon Sep 17 00:00:00 2001 From: kaetemi Date: Mon, 27 Sep 2021 17:36:40 +0800 Subject: [PATCH 09/13] Fix for MySQL 8 client lib support --- nelns/admin_service/admin_service.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/nelns/admin_service/admin_service.cpp b/nelns/admin_service/admin_service.cpp index 9c11347fc..1788ff5ef 100644 --- a/nelns/admin_service/admin_service.cpp +++ b/nelns/admin_service/admin_service.cpp @@ -629,7 +629,11 @@ void sqlInit () nlerror ("mysql_init() failed"); } +#if LIBMYSQL_VERSION_ID < 80000 my_bool opt = true; +#else + bool opt = true; +#endif if (mysql_options (db, MYSQL_OPT_RECONNECT, &opt)) { mysql_close(db); From d893d15daf037dc2d51a99c6393be80663f8071c Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 14 Oct 2021 15:14:51 +0300 Subject: [PATCH 10/13] Remove loading certs from native Windows cert store. --- nel/src/web/curl_certificates.cpp | 41 ------------------------------- 1 file changed, 41 deletions(-) diff --git a/nel/src/web/curl_certificates.cpp b/nel/src/web/curl_certificates.cpp index fdf69604f..52f04fe25 100644 --- a/nel/src/web/curl_certificates.cpp +++ b/nel/src/web/curl_certificates.cpp @@ -131,13 +131,6 @@ namespace NLWEB // only use OpenSSL callback if not using Windows SSPI and using OpenSSL backend if (useOpenSSLBackend && !(data && data->features & CURL_VERSION_SSPI)) { -#ifdef NL_OS_WINDOWS - // load native Windows CA Certs - addCertificatesFrom("CA"); - addCertificatesFrom("AuthRoot"); - addCertificatesFrom("ROOT"); -#endif - isUsingOpenSSLBackend = true; } else @@ -179,40 +172,6 @@ namespace NLWEB return name; } -#ifdef NL_OS_WINDOWS - void addCertificatesFrom(LPCSTR root) - { - HCERTSTORE hStore; - PCCERT_CONTEXT pContext = NULL; - X509 *x509; - hStore = CertOpenSystemStore(NULL, root); - if (hStore) - { - while (pContext = CertEnumCertificatesInStore(hStore, pContext)) - { - x509 = NULL; - x509 = d2i_X509(NULL, (const unsigned char **)&pContext->pbCertEncoded, pContext->cbCertEncoded); - - if (x509) - { - CertEntry entry; - entry.cert = x509; - entry.file = root; - entry.name = getCertName(x509); - - CertList.push_back(entry); - } - } - - CertFreeCertificateContext(pContext); - CertCloseStore(hStore, 0); - } - - // this is called before debug context is set and log ends up in log.log - //nlinfo("Loaded %d certificates from '%s' certificate store", (int)CertList.size(), root); - } -#endif - void addCertificatesFromFile(const std::string &cert) { if (!isInitialized) From 5064f0417ba6586a874f2d7780e45f4cab8d8093 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 14 Oct 2021 15:16:46 +0300 Subject: [PATCH 11/13] Fix UI restore when window is resized while in loading screen --- ryzom/client/src/connection.cpp | 12 ------------ ryzom/client/src/interface_v3/interface_manager.cpp | 9 ++++++--- 2 files changed, 6 insertions(+), 15 deletions(-) diff --git a/ryzom/client/src/connection.cpp b/ryzom/client/src/connection.cpp index d7eaa2969..ce887e48e 100644 --- a/ryzom/client/src/connection.cpp +++ b/ryzom/client/src/connection.cpp @@ -1290,19 +1290,7 @@ TInterfaceState globalMenu() // Restore video mode if (ClientCfg.SelectCharacter == -1) - { - if (ClientCfg.Windowed) - { - // if used changed window resolution in char select - // if we don't update ClientCfg, then UI from icfg is restored wrong - uint32 width, height; - Driver->getWindowSize(width, height); - ClientCfg.Width = width; - ClientCfg.Height = height; - } - connectionRestoreVideoMode (); - } // Skip intro next time ClientCfg.writeBool("SkipIntro", true); diff --git a/ryzom/client/src/interface_v3/interface_manager.cpp b/ryzom/client/src/interface_v3/interface_manager.cpp index ab015e0d6..04b94faaf 100644 --- a/ryzom/client/src/interface_v3/interface_manager.cpp +++ b/ryzom/client/src/interface_v3/interface_manager.cpp @@ -1899,9 +1899,12 @@ bool CInterfaceManager::loadConfig (const string &filename) // NB: we are typically InGame here (even though the _InGame flag is not yet set) // Use the screen size of the config file. Don't update current UI, just _Modes // - // ClientCfg has W/H set to screen size, but interface expects scaled size - sint32 scaledW = ClientCfg.Width / ClientCfg.InterfaceScale; - sint32 scaledH = ClientCfg.Height / ClientCfg.InterfaceScale; + uint32 width, height; + // get non-scaled width/height + Driver->getWindowSize(width, height); + // convert to scaled width/height for ui + sint32 scaledW = width / ClientCfg.InterfaceScale; + sint32 scaledH = height / ClientCfg.InterfaceScale; CWidgetManager::getInstance()->moveAllWindowsToNewScreenSize(scaledW, scaledH, false); updateDesktops(scaledW, scaledH); } From 2efc16ce5279c91e23986b3615ccc260391d6a57 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Wed, 20 Oct 2021 15:04:11 +0300 Subject: [PATCH 12/13] Use configured resolution for login/outgame/ingame --- ryzom/client/src/connection.cpp | 29 ------------- ryzom/client/src/init.cpp | 72 +++++++++++++-------------------- 2 files changed, 28 insertions(+), 73 deletions(-) diff --git a/ryzom/client/src/connection.cpp b/ryzom/client/src/connection.cpp index ce887e48e..8163ac6cb 100644 --- a/ryzom/client/src/connection.cpp +++ b/ryzom/client/src/connection.cpp @@ -195,38 +195,9 @@ bool hasPrivilegeEG() { return (UserPrivileges.find(":EG:") != std::string::npos // Restore the video mode (fullscreen for example) after the connection (done in a window) void connectionRestoreVideoMode () { - // Setup full screen if we have to - UDriver::CMode mode; - Driver->getCurrentScreenMode(mode); - - if (mode.Windowed) - { - uint32 width, height; - Driver->getWindowSize(width, height); - mode.Width = width; - mode.Height = height; - } - - // don't allow sizes smaller than 1024x768 - if (ClientCfg.Width < 1024) ClientCfg.Width = 1024; - if (ClientCfg.Height < 768) ClientCfg.Height = 768; - if (StereoDisplay) StereoDisplayAttached = StereoDisplay->attachToDisplay(); - if (!StereoDisplayAttached && ( - (ClientCfg.Windowed != mode.Windowed) || - (ClientCfg.Width != mode.Width) || - (ClientCfg.Height != mode.Height))) - { - mode.Windowed = ClientCfg.Windowed; - mode.Depth = uint8(ClientCfg.Depth); - mode.Width = ClientCfg.Width; - mode.Height = ClientCfg.Height; - mode.Frequency = ClientCfg.Frequency; - setVideoMode(mode); - } - // And setup hardware mouse if we have to InitMouseWithCursor (ClientCfg.HardwareCursor && !StereoDisplayAttached); SetMouseFreeLook (); diff --git a/ryzom/client/src/init.cpp b/ryzom/client/src/init.cpp index 206122704..87b16d1bf 100644 --- a/ryzom/client/src/init.cpp +++ b/ryzom/client/src/init.cpp @@ -1061,43 +1061,45 @@ void prelogInit() return; } - // used to determine screen default resolution - if (ClientCfg.Width < 800 || ClientCfg.Height < 600) + UDriver::CMode mode; + // first run (no client.cfg) + if (ClientCfg.Width == 0 || ClientCfg.Height == 0) { - UDriver::CMode mode; - - CConfigFile::CVar *varPtr = NULL; - - if (!ClientCfg.Windowed && Driver->getCurrentScreenMode(mode)) + if (Driver->getCurrentScreenMode(mode)) { + // fullscreen, using monitor resolution + mode.Windowed = false; + + ClientCfg.Windowed = mode.Windowed; ClientCfg.Width = mode.Width; ClientCfg.Height = mode.Height; ClientCfg.Depth = mode.Depth; ClientCfg.Frequency = mode.Frequency; - - // update client.cfg with detected depth and frequency - varPtr = ClientCfg.ConfigFile.getVarPtr("Depth"); - if(varPtr) - varPtr->forceAsInt(ClientCfg.Depth); - - varPtr = ClientCfg.ConfigFile.getVarPtr("Frequency"); - if(varPtr) - varPtr->forceAsInt(ClientCfg.Frequency); } else { + // fallback + ClientCfg.Windowed = true; ClientCfg.Width = 1024; ClientCfg.Height = 768; } // update client.cfg with detected resolution - varPtr = ClientCfg.ConfigFile.getVarPtr("Width"); - if(varPtr) - varPtr->forceAsInt(ClientCfg.Width); + ClientCfg.writeBool("FullScreen", !ClientCfg.Windowed, true); + ClientCfg.writeInt("Width", ClientCfg.Width, true); + ClientCfg.writeInt("Height", ClientCfg.Height, true); + ClientCfg.writeInt("Depth", ClientCfg.Depth, true); + ClientCfg.writeInt("Frequency", ClientCfg.Frequency, true); - varPtr = ClientCfg.ConfigFile.getVarPtr("Height"); - if(varPtr) - varPtr->forceAsInt(ClientCfg.Height); + ClientCfg.ConfigFile.save(); + } + else + { + mode.Windowed = ClientCfg.Windowed; + mode.Width = ClientCfg.Width; + mode.Height = ClientCfg.Height; + mode.Depth = ClientCfg.Depth; + mode.Frequency = ClientCfg.Frequency; } CLoginProgressPostThread::getInstance().step(CLoginStep(LoginStep_VideoModeSetup, "login_step_video_mode_setup")); @@ -1107,25 +1109,6 @@ void prelogInit() // Check the driver is not is 16 bits checkDriverDepth (); - UDriver::CMode mode; - - if (Driver->getCurrentScreenMode(mode)) - { - // use current mode if its smaller than 1024x768 - // mode should be windowed already, but incase its not, use the mode as is - if (mode.Windowed && (mode.Width > 1024 && mode.Height > 768)) - { - mode.Width = 1024; - mode.Height = 768; - } - } - else - { - mode.Width = 1024; - mode.Height = 768; - mode.Windowed = true; - } - // Disable Hardware Vertex Program. if(ClientCfg.DisableVtxProgram) Driver->disableHardwareVertexProgram(); @@ -1260,10 +1243,11 @@ void prelogInit() else { // position is not saved in config so center the window - if (Driver->getCurrentScreenMode(mode)) + UDriver::CMode tmp; + if (Driver->getCurrentScreenMode(tmp)) { - posX = (mode.Width - Driver->getWindowWidth())/2; - posY = (mode.Height - Driver->getWindowHeight())/2; + posX = (tmp.Width - Driver->getWindowWidth())/2; + posY = (tmp.Height - Driver->getWindowHeight())/2; } } From d8deff3f2347825d5651b02c0c72bb088cf12939 Mon Sep 17 00:00:00 2001 From: Nimetu Date: Thu, 14 Oct 2021 15:09:56 +0300 Subject: [PATCH 13/13] Linux multi-monitor fullscreen support --- nel/src/3d/driver/opengl/driver_opengl.h | 3 + .../3d/driver/opengl/driver_opengl_window.cpp | 354 +++++++++++++++++- nel/src/3d/driver_user.cpp | 1 + ryzom/client/src/client_cfg.cpp | 8 + ryzom/client/src/client_cfg.h | 2 + ryzom/client/src/init.cpp | 3 + .../src/interface_v3/action_handler_game.cpp | 8 + ryzom/client/src/login.cpp | 1 + ryzom/client/src/main_loop_utilities.cpp | 7 +- ryzom/client/src/misc.cpp | 4 + 10 files changed, 378 insertions(+), 13 deletions(-) diff --git a/nel/src/3d/driver/opengl/driver_opengl.h b/nel/src/3d/driver/opengl/driver_opengl.h index 4941a98d1..ec9b59345 100644 --- a/nel/src/3d/driver/opengl/driver_opengl.h +++ b/nel/src/3d/driver/opengl/driver_opengl.h @@ -999,6 +999,9 @@ private: bool createWindow(const GfxMode& mode); bool destroyWindow(); + // Return monitor info and positon in multi monitor setup or false if monitor not found. + bool getMonitorByName(const std::string &name, sint32 &x, sint32 &y, uint32 &w, uint32 &h) const; + enum EWindowStyle { EWSWindowed, EWSFullscreen }; void setWindowSize(uint32 width, uint32 height); diff --git a/nel/src/3d/driver/opengl/driver_opengl_window.cpp b/nel/src/3d/driver/opengl/driver_opengl_window.cpp index 06f95c38c..35dc433a8 100644 --- a/nel/src/3d/driver/opengl/driver_opengl_window.cpp +++ b/nel/src/3d/driver/opengl/driver_opengl_window.cpp @@ -650,8 +650,6 @@ bool CDriverGL::setDisplay(nlWindow wnd, const GfxMode &mode, bool show, bool re _win = EmptyWindow; - _CurrentMode = mode; - _WindowVisible = false; _Resizable = resizeable; _DestroyWindow = false; @@ -1194,6 +1192,8 @@ bool CDriverGL::saveScreenMode() #ifdef HAVE_XRANDR + // TODO: if using mode switching, save current xrandr mode to _OldSizeID + res = true; if (!res && _xrandr_version > 0) { XRRScreenConfiguration *screen_config = XRRGetScreenInfo(_dpy, RootWindow(_dpy, screen)); @@ -1254,6 +1254,8 @@ bool CDriverGL::restoreScreenMode() #ifdef HAVE_XRANDR + // TODO: if using mode switching, then restore mode from _OldSizeID + res = true; if (!res && _xrandr_version > 0) { Window root = RootWindow(_dpy, screen); @@ -1348,7 +1350,8 @@ bool CDriverGL::setScreenMode(const GfxMode &mode) && mode.Width == previousMode.Width && mode.Height == previousMode.Height && mode.Depth == previousMode.Depth - && mode.Frequency == previousMode.Frequency) + && mode.Frequency == previousMode.Frequency + && mode.DisplayDevice == previousMode.DisplayDevice) return true; #if defined(NL_OS_WINDOWS) @@ -1388,6 +1391,8 @@ bool CDriverGL::setScreenMode(const GfxMode &mode) bool found = false; #ifdef HAVE_XRANDR + // TODO: implement mode switching using xrandr crts + found = true; if (!found && _xrandr_version > 0) { @@ -1911,8 +1916,92 @@ bool CDriverGL::setWindowStyle(EWindowStyle windowStyle) return true; } +bool CDriverGL::getMonitorByName(const std::string &name, sint32 &x, sint32 &y, uint32 &w, uint32 &h) const +{ + bool found = false; + +#if HAVE_XRANDR + int screen = DefaultScreen(_dpy); + + // xrandr 1.5+ + if (_xrandr_version >= 105) + { + int nmonitors = 0; + XRRMonitorInfo *monitor = XRRGetMonitors(_dpy, RootWindow(_dpy, screen), 1, &nmonitors); + if (!monitor) + return false; + + for(sint i = 0; i< nmonitors; ++i) + { + char* pname = XGetAtomName(_dpy, monitor[i].name); + found = (nlstricmp(pname, name) == 0); + XFree(pname); + + if (found) + { + x = monitor[i].x; + y = monitor[i].y; + w = monitor[i].width; + h = monitor[i].height; + + break; + } + } + + XRRFreeMonitors(monitor); + } + else + { + XRRScreenResources *resources = XRRGetScreenResourcesCurrent(_dpy, RootWindow(_dpy, screen)); + if (!resources) + resources = XRRGetScreenResources(_dpy, RootWindow(_dpy, screen)); + + for(uint i = 0; i < resources->noutput; ++i) + { + XRROutputInfo *output = XRRGetOutputInfo(_dpy, resources, resources->outputs[i]); + if (!output) + continue; + + if (output->crtc && output->connection == RR_Connected && nlstricmp(name, output->name) == 0) + { + // physical monitor + XRRCrtcInfo *crtc = XRRGetCrtcInfo(_dpy, resources, output->crtc); + if (crtc) + { + found = true; + x = crtc->x; + y = crtc->y; + + // TODO: test rotation + if (crtc->rotation == RR_Rotate_0 || crtc->rotation == RR_Rotate_180) + { + w = crtc->width; + h = crtc->height; + } + else + { + w = crtc->height; + h = crtc->width; + } + + XRRFreeCrtcInfo(crtc); + } + } + + XRRFreeOutputInfo(output); + + if (found) + break; + } + + XRRFreeScreenResources(resources); + } +#endif + return found; +} + // -------------------------------------------------- -bool CDriverGL::setMode(const GfxMode& mode) +bool CDriverGL::setMode(const GfxMode& amode) { H_AUTO_OGL(CDriverGL_setMode); @@ -1920,6 +2009,10 @@ bool CDriverGL::setMode(const GfxMode& mode) if (!_DestroyWindow) return true; +#if !(HAVE_XRANDR) + const GfxMode &mode = amode; +#endif + #if defined(NL_OS_WINDOWS) // save relative cursor POINT cursorPos; @@ -1929,21 +2022,89 @@ bool CDriverGL::setMode(const GfxMode& mode) BOOL cursorPosOk = isSystemCursorInClientArea() && GetCursorPos(&cursorPos) && ScreenToClient(_win, &cursorPos); + + // FIXME: this probably needs to use _CurrentMode instead of mode sint curX = (sint)cursorPos.x * (sint)mode.Width; sint curY = (sint)cursorPos.y * (sint)mode.Height; #endif +#if HAVE_XRANDR + GfxMode mode = amode; + + if (!mode.Windowed) + { + GfxMode current; + if (!getCurrentScreenMode(current)) + nlinfo("3D: XrandR: Reading active monitor info failed"); + + sint newX = _WindowX; + sint newY = _WindowY; + + // make sure resolution matches requested or currently active monitor's resolution + mode.Width = current.Width; + mode.Height = current.Height; + if (!mode.DisplayDevice.empty()) + { + uint newW = current.Width; + uint newH = current.Height; + if (getMonitorByName(mode.DisplayDevice, newX, newY, newW, newH)) + { + mode.Width = newW; + mode.Height = newH; + } + else + { + nlinfo("3D: XrandR: Reading requested monitor '%s' info failed, using '%s'", mode.DisplayDevice.c_str(), current.DisplayDevice.c_str()); + mode.DisplayDevice = current.DisplayDevice; + } + } + + // switching monitors. + // first move mouse pointer to target monitor and then move window. + // if window is visible, then also restore mouse relative position. + if (!mode.DisplayDevice.empty() && mode.DisplayDevice != current.DisplayDevice) + { + int screen = DefaultScreen(_dpy); + Window root = RootWindow(_dpy, screen); + uint mouseX = mode.Width / 2; + uint mouseY = mode.Height / 2; + + XWindowAttributes xwa; + XGetWindowAttributes(_dpy, _win, &xwa); + if (xwa.map_state != IsUnmapped) + { + Window root_win; + Window child_win; + sint root_x, root_y, win_x, win_y; + uint mask; + + Bool res = XQueryPointer(_dpy, _win, &root_win, &child_win, &root_x, &root_y, &win_x, &win_y, &mask); + if (res) + { + mouseX = (uint)((float)win_x * mode.Width / current.Width); + mouseY = (uint)((float)win_y * mode.Height / current.Height); + } + } + + XWarpPointer(_dpy, None, root, None, None, None, None, newX + mouseX, newY + mouseY); + XMoveWindow(_dpy, _win, newX, newY); + _WindowX = newX; + _WindowY = newY; + } + } +#endif + if (!setScreenMode(mode)) return false; + _CurrentMode.Depth = mode.Depth; + _CurrentMode.Frequency = mode.Frequency; + _CurrentMode.DisplayDevice = mode.DisplayDevice; + // when changing window style, it's possible system change window size too setWindowStyle(mode.Windowed ? EWSWindowed : EWSFullscreen); - - if (!mode.Windowed) - _CurrentMode.Depth = mode.Depth; - - setWindowSize(mode.Width, mode.Height); setWindowPos(_WindowX, _WindowY); + setWindowSize(mode.Width, mode.Height); switch (_CurrentMode.Depth) { @@ -2120,6 +2281,66 @@ bool CDriverGL::getModes(std::vector &modes) int screen = DefaultScreen(_dpy); #if defined(HAVE_XRANDR) + if (_xrandr_version >= 105) + { + int nmonitors = 0; + // virtual monitors + XRRMonitorInfo *monitor = XRRGetMonitors(_dpy, RootWindow(_dpy, screen), 1, &nmonitors); + for(sint i = 0; i < nmonitors; ++i) + { + char * name = XGetAtomName(_dpy, monitor[i].name); + GfxMode mode; + mode.DisplayDevice = name; + mode.Width = monitor[i].width; + mode.Height = monitor[i].height; + mode.Frequency = 0; + modes.push_back(mode); + XFree(name); + } + XRRFreeMonitors(monitor); + } + else + { + XRRScreenResources *resources = XRRGetScreenResourcesCurrent(_dpy, RootWindow(_dpy, screen)); + if (!resources) + resources = XRRGetScreenResources(_dpy, RootWindow(_dpy, screen)); + + std::map resourceModeMap; + for(sint i = 0; i< resources->nmode; ++i) + resourceModeMap.insert(std::make_pair(resources->modes[i].id, i)); + + for(sint i = 0; i < resources->noutput; ++i) + { + XRROutputInfo *output = XRRGetOutputInfo(_dpy, resources, resources->outputs[i]); + if (!output) + continue; + + if (output->crtc && output->connection == RR_Connected) + { + // physical monitor + XRRCrtcInfo *crtc = XRRGetCrtcInfo(_dpy, resources, output->crtc); + if (crtc) + { + std::map::const_iterator it = resourceModeMap.find(crtc->mode); + if (it != resourceModeMap.end()) + { + GfxMode mode; + mode.DisplayDevice = output->name; + mode.Width = resources->modes[it->second].width; + mode.Height = resources->modes[it->second].height; + mode.Frequency = 0; + + modes.push_back(mode); + } + XRRFreeCrtcInfo(crtc); + } + } + XRRFreeOutputInfo(output); + } + + XRRFreeScreenResources(resources); + } + found = modes.size() > 0; if (!found && _xrandr_version >= 100) { XRRScreenConfiguration *screen_config = XRRGetScreenInfo(_dpy, RootWindow(_dpy, screen)); @@ -2255,6 +2476,120 @@ bool CDriverGL::getCurrentScreenMode(GfxMode &mode) int screen = DefaultScreen(_dpy); #ifdef HAVE_XRANDR + int x = 0; + int y = 0; + Window child; + + // get window position so we can compare monitors (or mouse position if window not visible yet) + XWindowAttributes xwa; + XGetWindowAttributes(_dpy, _win, &xwa); + if (xwa.map_state != IsUnmapped) + { + XTranslateCoordinates(_dpy, _win, xwa.root, xwa.x, xwa.y, &x, &y, &child); + } + else + { + sint rx, ry, wx, wy; + uint mask; + Bool res = XQueryPointer(_dpy, RootWindow(_dpy, screen), &child, &child, &rx, &ry, &wx, &wy, &mask); + if (res) + { + x = rx; + y = ry; + } + } + + if (_xrandr_version >= 105) + { + int nmonitors = 0; + XRRMonitorInfo *monitor = XRRGetMonitors(_dpy, RootWindow(_dpy, screen), 1, &nmonitors); + if (monitor) + { + sint bestMatch = -1; + for(sint i = 0; i< nmonitors; ++i) + { + if ((x >= monitor[i].x && x < (monitor[i].x + monitor[i].width) && + y >= monitor[i].y && y < (monitor[i].y + monitor[i].height)) || + (monitor[i].primary && bestMatch == -1)) + { + bestMatch = i; + } + } + + // best match or primary monitor + if (bestMatch != -1) + { + found = true; + char* pname = XGetAtomName(_dpy, monitor[bestMatch].name); + mode.DisplayDevice = pname; + mode.Width = monitor[bestMatch].width; + mode.Height = monitor[bestMatch].height; + mode.Windowed = _CurrentMode.Windowed; + mode.OffScreen = false; + mode.Depth = (uint) DefaultDepth(_dpy, screen); + mode.Frequency = 0; + XFree(pname); + } + + XRRFreeMonitors(monitor); + } + } + else + { + XRRScreenResources *resources = XRRGetScreenResourcesCurrent(_dpy, RootWindow(_dpy, screen)); + if (!resources) + resources = XRRGetScreenResources(_dpy, RootWindow(_dpy, screen)); + + for(uint i = 0; i < resources->noutput; ++i) + { + XRROutputInfo *output = XRRGetOutputInfo(_dpy, resources, resources->outputs[i]); + if (!output) + continue; + + if (output->crtc && output->connection == RR_Connected) + { + XRRCrtcInfo *crtc = XRRGetCrtcInfo(_dpy, resources, output->crtc); + if (crtc) + { + sint width, height; + bool match = false; + + // TODO: test rotation + if (crtc->rotation == RR_Rotate_0 || crtc->rotation == RR_Rotate_180) + { + width = crtc->width; + height = crtc->height; + } + else + { + width = crtc->height; + height = crtc->width; + } + + if (x >= crtc->x && y >= crtc->y && x < (crtc->x + width) && y < (crtc->y + height)) + { + found = true; + mode.DisplayDevice = output->name; + mode.Width = width; + mode.Height = height; + mode.Windowed = _CurrentMode.Windowed; + mode.OffScreen = false; + mode.Depth = (uint) DefaultDepth(_dpy, screen); + mode.Frequency = 0; + } + + XRRFreeCrtcInfo(crtc); + } + } + + XRRFreeOutputInfo(output); + + if (found) + break; + } + + XRRFreeScreenResources(resources); + } if (!found && _xrandr_version > 0) { @@ -2432,7 +2767,6 @@ void CDriverGL::setWindowPos(sint32 x, sint32 y) _DecorationWidth = -1; _DecorationHeight = -1; } - XMoveWindow(_dpy, _win, x, y); } diff --git a/nel/src/3d/driver_user.cpp b/nel/src/3d/driver_user.cpp index a7bd7a332..757d2183f 100644 --- a/nel/src/3d/driver_user.cpp +++ b/nel/src/3d/driver_user.cpp @@ -331,6 +331,7 @@ bool CDriverUser::getCurrentScreenMode(CMode &mode) GfxMode gfxMode; bool res= _Driver->getCurrentScreenMode(gfxMode); mode.Windowed= gfxMode.Windowed; + mode.DisplayDevice= gfxMode.DisplayDevice; mode.Width= gfxMode.Width; mode.Height= gfxMode.Height; mode.Depth= gfxMode.Depth; diff --git a/ryzom/client/src/client_cfg.cpp b/ryzom/client/src/client_cfg.cpp index f67c4e1db..a5034d7ac 100644 --- a/ryzom/client/src/client_cfg.cpp +++ b/ryzom/client/src/client_cfg.cpp @@ -302,6 +302,7 @@ CClientConfig::CClientConfig() SelectedSlot = 0; // Default is slot 0 Windowed = false; // Default is windowed mode. + MonitorName = ""; Width = 0; // Default Width for the window (0 = current screen resolution). Height = 0; // Default Height for the window (0 = current screen resolution). Depth = 32; // Default Bit per Pixel. @@ -847,6 +848,8 @@ void CClientConfig::setValues() } else cfgWarning("Default value used for 'Fullscreen'"); + + READ_STRING_FV(MonitorName); // Width READ_INT_FV(Width) // Height @@ -1941,6 +1944,11 @@ void CClientConfig::serial(NLMISC::IStream &f) f.serial(Light); f.xmlPop(); + f.xmlPushBegin("MonitorName"); + f.xmlPushEnd(); + f.serial(MonitorName); + f.xmlPop(); + f.xmlPushBegin("Windowed"); f.xmlPushEnd(); f.serial(Windowed); diff --git a/ryzom/client/src/client_cfg.h b/ryzom/client/src/client_cfg.h index 22fe46f61..b08843b3b 100644 --- a/ryzom/client/src/client_cfg.h +++ b/ryzom/client/src/client_cfg.h @@ -137,6 +137,8 @@ struct CClientConfig TDriver3D Driver3D; /// Application start in a window or in fullscreen. bool Windowed; + /// Monitor to use for fullscreen + std::string MonitorName; /// Width for the Application. uint16 Width; /// Height for the Application. diff --git a/ryzom/client/src/init.cpp b/ryzom/client/src/init.cpp index 87b16d1bf..a8c9c9837 100644 --- a/ryzom/client/src/init.cpp +++ b/ryzom/client/src/init.cpp @@ -1070,6 +1070,7 @@ void prelogInit() // fullscreen, using monitor resolution mode.Windowed = false; + ClientCfg.MonitorName = mode.DisplayDevice; ClientCfg.Windowed = mode.Windowed; ClientCfg.Width = mode.Width; ClientCfg.Height = mode.Height; @@ -1086,6 +1087,7 @@ void prelogInit() // update client.cfg with detected resolution ClientCfg.writeBool("FullScreen", !ClientCfg.Windowed, true); + ClientCfg.writeString("MonitorName", ClientCfg.MonitorName, true); ClientCfg.writeInt("Width", ClientCfg.Width, true); ClientCfg.writeInt("Height", ClientCfg.Height, true); ClientCfg.writeInt("Depth", ClientCfg.Depth, true); @@ -1095,6 +1097,7 @@ void prelogInit() } else { + mode.DisplayDevice = ClientCfg.MonitorName; mode.Windowed = ClientCfg.Windowed; mode.Width = ClientCfg.Width; mode.Height = ClientCfg.Height; diff --git a/ryzom/client/src/interface_v3/action_handler_game.cpp b/ryzom/client/src/interface_v3/action_handler_game.cpp index f3b5d42ab..0486c2efd 100644 --- a/ryzom/client/src/interface_v3/action_handler_game.cpp +++ b/ryzom/client/src/interface_v3/action_handler_game.cpp @@ -3458,6 +3458,7 @@ class CHandlerGameConfigApply : public IActionHandler { // Get W, H sint w = 1024, h = 768; + string name; { CDBGroupComboBox *pCB = dynamic_cast(CWidgetManager::getInstance()->getElementFromId( GAME_CONFIG_VIDEO_MODES_COMBO )); if( pCB != NULL ) @@ -3467,6 +3468,11 @@ class CHandlerGameConfigApply : public IActionHandler fromString(tmp, w); tmp = vidModeStr.substr(vidModeStr.find('x')+2,vidModeStr.size()); fromString(tmp, h); + + // extract monitor "1024x768 (VGA-1)" + string::size_type pos = vidModeStr.find('('); + if (pos != std::string::npos) + name = vidModeStr.substr(pos + 1, vidModeStr.find(")") - pos - 1); } } @@ -3509,6 +3515,7 @@ class CHandlerGameConfigApply : public IActionHandler ClientCfg.Width = w; ClientCfg.Height = h; + ClientCfg.MonitorName = name; // Write the modified client.cfg ClientCfg.writeBool("FullScreen", bFullscreen); @@ -3517,6 +3524,7 @@ class CHandlerGameConfigApply : public IActionHandler if (bFullscreen) { + ClientCfg.writeString("MonitorName", name, true); ClientCfg.writeInt("Depth", screenMode.Depth); ClientCfg.writeInt("Frequency", freq); } diff --git a/ryzom/client/src/login.cpp b/ryzom/client/src/login.cpp index 7b0377890..da038cdd2 100644 --- a/ryzom/client/src/login.cpp +++ b/ryzom/client/src/login.cpp @@ -2208,6 +2208,7 @@ class CAHLessLod : public IActionHandler REGISTER_ACTION_HANDLER (CAHLessLod, "less_lod"); // *************************************************************************** +// TODO: remove resolution change from login screen class CAHUninitResLod : public IActionHandler { virtual void execute (CCtrlBase * /* pCaller */, const string &/* sParams */) diff --git a/ryzom/client/src/main_loop_utilities.cpp b/ryzom/client/src/main_loop_utilities.cpp index d93e24481..95dcf82c8 100644 --- a/ryzom/client/src/main_loop_utilities.cpp +++ b/ryzom/client/src/main_loop_utilities.cpp @@ -76,7 +76,7 @@ void updateFromClientCfg() // set latest config display mode if not attached if (!StereoDisplayAttached) setVideoMode(UDriver::CMode(ClientCfg.Width, ClientCfg.Height, (uint8)ClientCfg.Depth, - ClientCfg.Windowed, ClientCfg.Frequency)); + ClientCfg.Windowed, ClientCfg.Frequency, -1, ClientCfg.MonitorName)); // force software cursor when attached InitMouseWithCursor(ClientCfg.HardwareCursor && !StereoDisplayAttached); } @@ -87,12 +87,13 @@ void updateFromClientCfg() (ClientCfg.Width != LastClientCfg.Width) || (ClientCfg.Height != LastClientCfg.Height) || (ClientCfg.Depth != LastClientCfg.Depth) || - (ClientCfg.Frequency != LastClientCfg.Frequency)) + (ClientCfg.Frequency != LastClientCfg.Frequency)|| + (ClientCfg.MonitorName != LastClientCfg.MonitorName)) { if (!StereoDisplayAttached) { setVideoMode(UDriver::CMode(ClientCfg.Width, ClientCfg.Height, (uint8)ClientCfg.Depth, - ClientCfg.Windowed, ClientCfg.Frequency)); + ClientCfg.Windowed, ClientCfg.Frequency, -1, ClientCfg.MonitorName)); } } diff --git a/ryzom/client/src/misc.cpp b/ryzom/client/src/misc.cpp index 2653c0e45..7cbeeebc2 100644 --- a/ryzom/client/src/misc.cpp +++ b/ryzom/client/src/misc.cpp @@ -1408,6 +1408,7 @@ bool getRyzomModes(std::vector &videoModes, std::vectorgetModes(videoModes); + // TODO: for resolutions below 1024x768, could use automatic UI scaling like in login/outgame // Remove modes under 1024x768 (outgame ui limitation) and get the unique strings sint i, j; for (i = 0; i < (sint)videoModes.size(); ++i) @@ -1424,6 +1425,9 @@ bool getRyzomModes(std::vector &videoModes, std::vector