Browse Source

Merge remote-tracking branch 'PredatorMF/master'

Lasse Öörni 8 years ago
parent
commit
4e30d6f522

+ 11 - 5
Source/Urho3D/AngelScript/GraphicsAPI.cpp

@@ -1838,9 +1838,14 @@ static void RegisterTerrain(asIScriptEngine* engine)
 }
 }
 
 
 
 
-static CScriptArray* GraphicsGetResolutions(Graphics* ptr)
+static CScriptArray* GraphicsGetResolutions(int monitor, Graphics* ptr)
 {
 {
-    return VectorToArray<IntVector2>(ptr->GetResolutions(), "Array<IntVector2>");
+    return VectorToArray<IntVector3>(ptr->GetResolutions(monitor), "Array<IntVector3>");
+}
+
+static int GraphicsGetMonitorCount(Graphics* ptr)
+{
+    return ptr->GetMonitorCount();
 }
 }
 
 
 static CScriptArray* GraphicsGetMultiSampleLevels(Graphics* ptr)
 static CScriptArray* GraphicsGetMultiSampleLevels(Graphics* ptr)
@@ -1867,7 +1872,7 @@ static Graphics* GetGraphics()
 static void RegisterGraphics(asIScriptEngine* engine)
 static void RegisterGraphics(asIScriptEngine* engine)
 {
 {
     RegisterObject<Graphics>(engine, "Graphics");
     RegisterObject<Graphics>(engine, "Graphics");
-    engine->RegisterObjectMethod("Graphics", "bool SetMode(int, int, bool, bool, bool, bool, bool, bool, int)", asMETHODPR(Graphics, SetMode, (int, int, bool, bool, bool, bool, bool, bool, int), bool), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Graphics", "bool SetMode(int, int, bool, bool, bool, bool, bool, bool, int, int, int)", asMETHODPR(Graphics, SetMode, (int, int, bool, bool, bool, bool, bool, bool, int, int, int), bool), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "bool SetMode(int, int)", asMETHODPR(Graphics, SetMode, (int, int), bool), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "bool SetMode(int, int)", asMETHODPR(Graphics, SetMode, (int, int), bool), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "void SetWindowPosition(int, int)", asMETHODPR(Graphics, SetWindowPosition, (int, int), void), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "void SetWindowPosition(int, int)", asMETHODPR(Graphics, SetWindowPosition, (int, int), void), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "bool ToggleFullscreen()", asMETHOD(Graphics, ToggleFullscreen), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "bool ToggleFullscreen()", asMETHOD(Graphics, ToggleFullscreen), asCALL_THISCALL);
@@ -1915,9 +1920,10 @@ static void RegisterGraphics(asIScriptEngine* engine)
     engine->RegisterObjectMethod("Graphics", "bool get_readableDepthSupport() const", asMETHOD(Graphics, GetReadableDepthSupport), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "bool get_readableDepthSupport() const", asMETHOD(Graphics, GetReadableDepthSupport), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "bool get_sRGBSupport() const", asMETHOD(Graphics, GetSRGBSupport), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "bool get_sRGBSupport() const", asMETHOD(Graphics, GetSRGBSupport), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "bool get_sRGBWriteSupport() const", asMETHOD(Graphics, GetSRGBWriteSupport), asCALL_THISCALL);
     engine->RegisterObjectMethod("Graphics", "bool get_sRGBWriteSupport() const", asMETHOD(Graphics, GetSRGBWriteSupport), asCALL_THISCALL);
-    engine->RegisterObjectMethod("Graphics", "Array<IntVector2>@ get_resolutions() const", asFUNCTION(GraphicsGetResolutions), asCALL_CDECL_OBJLAST);
+    engine->RegisterObjectMethod("Graphics", "Array<IntVector3>@ get_resolutions(int) const", asFUNCTION(GraphicsGetResolutions), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Graphics", "Array<int>@ get_multiSampleLevels() const", asFUNCTION(GraphicsGetMultiSampleLevels), asCALL_CDECL_OBJLAST);
     engine->RegisterObjectMethod("Graphics", "Array<int>@ get_multiSampleLevels() const", asFUNCTION(GraphicsGetMultiSampleLevels), asCALL_CDECL_OBJLAST);
-    engine->RegisterObjectMethod("Graphics", "IntVector2 get_desktopResolution() const", asMETHOD(Graphics, GetDesktopResolution), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Graphics", "IntVector2 get_desktopResolution(int) const", asMETHOD(Graphics, GetDesktopResolution), asCALL_THISCALL);
+    engine->RegisterObjectMethod("Graphics", "int get_monitorCount() const", asFUNCTION(GraphicsGetMonitorCount), asCALL_CDECL_OBJLAST);
     engine->RegisterGlobalFunction("Graphics@+ get_graphics()", asFUNCTION(GetGraphics), asCALL_CDECL);
     engine->RegisterGlobalFunction("Graphics@+ get_graphics()", asFUNCTION(GetGraphics), asCALL_CDECL);
 }
 }
 
 

+ 11 - 1
Source/Urho3D/Engine/Engine.cpp

@@ -248,7 +248,9 @@ bool Engine::Initialize(const VariantMap& parameters)
             GetParameter(parameters, EP_HIGH_DPI, true).GetBool(),
             GetParameter(parameters, EP_HIGH_DPI, true).GetBool(),
             GetParameter(parameters, EP_VSYNC, false).GetBool(),
             GetParameter(parameters, EP_VSYNC, false).GetBool(),
             GetParameter(parameters, EP_TRIPLE_BUFFER, false).GetBool(),
             GetParameter(parameters, EP_TRIPLE_BUFFER, false).GetBool(),
-            GetParameter(parameters, EP_MULTI_SAMPLE, 1).GetInt()
+            GetParameter(parameters, EP_MULTI_SAMPLE, 1).GetInt(),
+            GetParameter(parameters, EP_MONITOR, 0).GetInt(),
+            GetParameter(parameters, EP_REFRESH_RATE, 0).GetInt()
         ))
         ))
             return false;
             return false;
 
 
@@ -865,6 +867,14 @@ VariantMap Engine::ParseParameters(const Vector<String>& arguments)
                 ret[EP_WINDOW_HEIGHT] = ToInt(value);
                 ret[EP_WINDOW_HEIGHT] = ToInt(value);
                 ++i;
                 ++i;
             }
             }
+            else if (argument == "monitor" && !value.Empty()) {
+                ret[EP_MONITOR] = ToInt(value);
+                ++i;
+            }
+            else if (argument == "hz" && !value.Empty()) {
+                ret[EP_REFRESH_RATE] = ToInt(value);
+                ++i;
+            }
             else if (argument == "m" && !value.Empty())
             else if (argument == "m" && !value.Empty())
             {
             {
                 ret[EP_MULTI_SAMPLE] = ToInt(value);
                 ret[EP_MULTI_SAMPLE] = ToInt(value);

+ 2 - 0
Source/Urho3D/Engine/EngineDefs.h

@@ -42,10 +42,12 @@ static const String EP_LOG_NAME = "LogName";
 static const String EP_LOG_QUIET = "LogQuiet";
 static const String EP_LOG_QUIET = "LogQuiet";
 static const String EP_LOW_QUALITY_SHADOWS = "LowQualityShadows";
 static const String EP_LOW_QUALITY_SHADOWS = "LowQualityShadows";
 static const String EP_MATERIAL_QUALITY = "MaterialQuality";
 static const String EP_MATERIAL_QUALITY = "MaterialQuality";
+static const String EP_MONITOR = "Monitor";
 static const String EP_MULTI_SAMPLE = "MultiSample";
 static const String EP_MULTI_SAMPLE = "MultiSample";
 static const String EP_ORIENTATIONS = "Orientations";
 static const String EP_ORIENTATIONS = "Orientations";
 static const String EP_PACKAGE_CACHE_DIR = "PackageCacheDir";
 static const String EP_PACKAGE_CACHE_DIR = "PackageCacheDir";
 static const String EP_RENDER_PATH = "RenderPath";
 static const String EP_RENDER_PATH = "RenderPath";
+static const String EP_REFRESH_RATE = "RefreshRate";
 static const String EP_RESOURCE_PACKAGES = "ResourcePackages";
 static const String EP_RESOURCE_PACKAGES = "ResourcePackages";
 static const String EP_RESOURCE_PATHS = "ResourcePaths";
 static const String EP_RESOURCE_PATHS = "ResourcePaths";
 static const String EP_RESOURCE_PREFIX_PATHS = "ResourcePrefixPaths";
 static const String EP_RESOURCE_PREFIX_PATHS = "ResourcePrefixPaths";

+ 26 - 8
Source/Urho3D/Graphics/Direct3D11/D3D11Graphics.cpp

@@ -298,7 +298,7 @@ Graphics::~Graphics()
 }
 }
 
 
 bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless, bool resizable, bool highDPI, bool vsync, bool tripleBuffer,
 bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless, bool resizable, bool highDPI, bool vsync, bool tripleBuffer,
-    int multiSample)
+    int multiSample, int monitor, int refreshRate)
 {
 {
     URHO3D_PROFILE(SetScreenMode);
     URHO3D_PROFILE(SetScreenMode);
 
 
@@ -306,9 +306,14 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
 
 
     bool maximize = false;
     bool maximize = false;
 
 
+    // make sure monitor index is not bigger than the currently detected monitors
+    int monitors = SDL_GetNumVideoDisplays();
+    if (monitor >= monitors || monitor < 0)
+        monitor = 0; // this monitor is not present, use first monitor
+
     // Find out the full screen mode display format (match desktop color depth)
     // Find out the full screen mode display format (match desktop color depth)
     SDL_DisplayMode mode;
     SDL_DisplayMode mode;
-    SDL_GetDesktopDisplayMode(0, &mode);
+    SDL_GetDesktopDisplayMode(monitor, &mode);
     DXGI_FORMAT fullscreenFormat = SDL_BITSPERPIXEL(mode.format) == 16 ? DXGI_FORMAT_B5G6R5_UNORM : DXGI_FORMAT_R8G8B8A8_UNORM;
     DXGI_FORMAT fullscreenFormat = SDL_BITSPERPIXEL(mode.format) == 16 ? DXGI_FORMAT_B5G6R5_UNORM : DXGI_FORMAT_R8G8B8A8_UNORM;
 
 
     // If zero dimensions in windowed mode, set windowed mode to maximize and set a predefined default restored window size. If zero in fullscreen, use desktop mode
     // If zero dimensions in windowed mode, set windowed mode to maximize and set a predefined default restored window size. If zero in fullscreen, use desktop mode
@@ -351,7 +356,7 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
     // Check fullscreen mode validity. Use a closest match if not found
     // Check fullscreen mode validity. Use a closest match if not found
     if (fullscreen)
     if (fullscreen)
     {
     {
-        PODVector<IntVector2> resolutions = GetResolutions();
+        PODVector<IntVector3> resolutions = GetResolutions(monitor);
         if (resolutions.Size())
         if (resolutions.Size())
         {
         {
             unsigned best = 0;
             unsigned best = 0;
@@ -369,10 +374,12 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
 
 
             width = resolutions[best].x_;
             width = resolutions[best].x_;
             height = resolutions[best].y_;
             height = resolutions[best].y_;
+            refreshRate = resolutions[best].z_;
         }
         }
     }
     }
 
 
-    AdjustWindow(width, height, fullscreen, borderless);
+    AdjustWindow(width, height, fullscreen, borderless, monitor);
+    monitor_ = monitor;
 
 
     if (maximize)
     if (maximize)
     {
     {
@@ -397,7 +404,7 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
 
 
 #ifdef URHO3D_LOGGING
 #ifdef URHO3D_LOGGING
     String msg;
     String msg;
-    msg.AppendWithFormat("Set screen mode %dx%d %s", width_, height_, (fullscreen_ ? "fullscreen" : "windowed"));
+    msg.AppendWithFormat("Set screen mode %dx%d %s monitor %d", width_, height_, (fullscreen_ ? "fullscreen" : "windowed"), monitor_);
     if (borderless_)
     if (borderless_)
         msg.Append(" borderless");
         msg.Append(" borderless");
     if (resizable_)
     if (resizable_)
@@ -416,6 +423,8 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
     eventData[P_BORDERLESS] = borderless_;
     eventData[P_BORDERLESS] = borderless_;
     eventData[P_RESIZABLE] = resizable_;
     eventData[P_RESIZABLE] = resizable_;
     eventData[P_HIGHDPI] = highDPI_;
     eventData[P_HIGHDPI] = highDPI_;
+    eventData[P_MONITOR] = monitor_;
+    eventData[P_REFRESHRATE] = refreshRate_;
     SendEvent(E_SCREENMODE, eventData);
     SendEvent(E_SCREENMODE, eventData);
 
 
     return true;
     return true;
@@ -423,7 +432,7 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
 
 
 bool Graphics::SetMode(int width, int height)
 bool Graphics::SetMode(int width, int height)
 {
 {
-    return SetMode(width, height, fullscreen_, borderless_, resizable_, highDPI_, vsync_, tripleBuffer_, multiSample_);
+    return SetMode(width, height, fullscreen_, borderless_, resizable_, highDPI_, vsync_, tripleBuffer_, multiSample_, monitor_, refreshRate_);
 }
 }
 
 
 void Graphics::SetSRGB(bool enable)
 void Graphics::SetSRGB(bool enable)
@@ -2082,7 +2091,7 @@ bool Graphics::OpenWindow(int width, int height, bool resizable, bool borderless
     return true;
     return true;
 }
 }
 
 
-void Graphics::AdjustWindow(int& newWidth, int& newHeight, bool& newFullscreen, bool& newBorderless)
+void Graphics::AdjustWindow(int& newWidth, int& newHeight, bool& newFullscreen, bool& newBorderless, int& monitor)
 {
 {
     if (!externalWindow_)
     if (!externalWindow_)
     {
     {
@@ -2091,8 +2100,17 @@ void Graphics::AdjustWindow(int& newWidth, int& newHeight, bool& newFullscreen,
             SDL_MaximizeWindow(window_);
             SDL_MaximizeWindow(window_);
             SDL_GetWindowSize(window_, &newWidth, &newHeight);
             SDL_GetWindowSize(window_, &newWidth, &newHeight);
         }
         }
-        else
+        else 
+        {
+            if (newFullscreen || newBorderless) 
+            {
+                // reposition the window on the specified monitor
+                SDL_Rect display_rect;
+                SDL_GetDisplayBounds(monitor, &display_rect);
+                SDL_SetWindowPosition(window_, display_rect.x, display_rect.y);
+            }
             SDL_SetWindowSize(window_, newWidth, newHeight);
             SDL_SetWindowSize(window_, newWidth, newHeight);
+        }
 
 
         // Hack fix: on SDL 2.0.4 a fullscreen->windowed transition results in a maximized window when the D3D device is reset, so hide before
         // Hack fix: on SDL 2.0.4 a fullscreen->windowed transition results in a maximized window when the D3D device is reset, so hide before
         SDL_HideWindow(window_);
         SDL_HideWindow(window_);

+ 32 - 11
Source/Urho3D/Graphics/Direct3D9/D3D9Graphics.cpp

@@ -264,6 +264,8 @@ Graphics::Graphics(Context* context) :
     resizable_(false),
     resizable_(false),
     highDPI_(false),
     highDPI_(false),
     vsync_(false),
     vsync_(false),
+    monitor_(0),
+    refreshRate_(0),
     tripleBuffer_(false),
     tripleBuffer_(false),
     flushGPU_(false),
     flushGPU_(false),
     sRGB_(false),
     sRGB_(false),
@@ -328,7 +330,7 @@ Graphics::~Graphics()
 }
 }
 
 
 bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless, bool resizable, bool highDPI, bool vsync,
 bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless, bool resizable, bool highDPI, bool vsync,
-    bool tripleBuffer, int multiSample)
+    bool tripleBuffer, int multiSample, int monitor, int refreshRate)
 {
 {
     URHO3D_PROFILE(SetScreenMode);
     URHO3D_PROFILE(SetScreenMode);
 
 
@@ -336,9 +338,14 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
 
 
     bool maximize = false;
     bool maximize = false;
 
 
+    // make sure monitor index is not bigger than the currently detected monitors
+    int monitors = SDL_GetNumVideoDisplays();
+    if (monitor >= monitors || monitor < 0)
+        monitor = 0; // this monitor is not present, use first monitor
+
     // Find out the full screen mode display format (match desktop color depth)
     // Find out the full screen mode display format (match desktop color depth)
     SDL_DisplayMode mode;
     SDL_DisplayMode mode;
-    SDL_GetDesktopDisplayMode(0, &mode);
+    SDL_GetDesktopDisplayMode(monitor, &mode);
     D3DFORMAT fullscreenFormat = SDL_BITSPERPIXEL(mode.format) == 16 ? D3DFMT_R5G6B5 : D3DFMT_X8R8G8B8;
     D3DFORMAT fullscreenFormat = SDL_BITSPERPIXEL(mode.format) == 16 ? D3DFMT_R5G6B5 : D3DFMT_X8R8G8B8;
 
 
     // If zero dimensions in windowed mode, set windowed mode to maximize and set a predefined default restored window size. If zero in fullscreen, use desktop mode
     // If zero dimensions in windowed mode, set windowed mode to maximize and set a predefined default restored window size. If zero in fullscreen, use desktop mode
@@ -394,7 +401,7 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
     // Check fullscreen mode validity. Use a closest match if not found
     // Check fullscreen mode validity. Use a closest match if not found
     if (fullscreen)
     if (fullscreen)
     {
     {
-        PODVector<IntVector2> resolutions = GetResolutions();
+        PODVector<IntVector3> resolutions = GetResolutions(monitor);
         if (resolutions.Size())
         if (resolutions.Size())
         {
         {
             unsigned best = 0;
             unsigned best = 0;
@@ -412,6 +419,7 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
 
 
             width = resolutions[best].x_;
             width = resolutions[best].x_;
             height = resolutions[best].y_;
             height = resolutions[best].y_;
+            refreshRate = resolutions[best].z_;
         }
         }
     }
     }
 
 
@@ -422,7 +430,7 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
             multiSample = 1;
             multiSample = 1;
     }
     }
 
 
-    AdjustWindow(width, height, fullscreen, borderless);
+    AdjustWindow(width, height, fullscreen, borderless, monitor);
 
 
     if (maximize)
     if (maximize)
     {
     {
@@ -451,7 +459,7 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
     impl_->presentParams_.EnableAutoDepthStencil = TRUE;
     impl_->presentParams_.EnableAutoDepthStencil = TRUE;
     impl_->presentParams_.AutoDepthStencilFormat = D3DFMT_D24S8;
     impl_->presentParams_.AutoDepthStencilFormat = D3DFMT_D24S8;
     impl_->presentParams_.Flags = D3DPRESENT_LINEAR_CONTENT;
     impl_->presentParams_.Flags = D3DPRESENT_LINEAR_CONTENT;
-    impl_->presentParams_.FullScreen_RefreshRateInHz = D3DPRESENT_RATE_DEFAULT;
+    impl_->presentParams_.FullScreen_RefreshRateInHz = fullscreen ? refreshRate : D3DPRESENT_RATE_DEFAULT;
 
 
     if (vsync)
     if (vsync)
         impl_->presentParams_.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
         impl_->presentParams_.PresentationInterval = D3DPRESENT_INTERVAL_ONE;
@@ -466,10 +474,12 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
     highDPI_ = highDPI;
     highDPI_ = highDPI;
     vsync_ = vsync;
     vsync_ = vsync;
     tripleBuffer_ = tripleBuffer;
     tripleBuffer_ = tripleBuffer;
+    monitor_ = monitor;
+    refreshRate_ = refreshRate;
 
 
     if (!impl_->device_)
     if (!impl_->device_)
     {
     {
-        unsigned adapter = D3DADAPTER_DEFAULT;
+        unsigned adapter = monitor;
         unsigned deviceType = D3DDEVTYPE_HAL;
         unsigned deviceType = D3DDEVTYPE_HAL;
 
 
         // Check for PerfHUD adapter
         // Check for PerfHUD adapter
@@ -500,7 +510,7 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
 
 
 #ifdef URHO3D_LOGGING
 #ifdef URHO3D_LOGGING
     String msg;
     String msg;
-    msg.AppendWithFormat("Set screen mode %dx%d %s", width_, height_, (fullscreen_ ? "fullscreen" : "windowed"));
+    msg.AppendWithFormat("Set screen mode %dx%d %s monitor %d", width_, height_, (fullscreen_ ? "fullscreen" : "windowed"), monitor_);
     if (borderless_)
     if (borderless_)
         msg.Append(" borderless");
         msg.Append(" borderless");
     if (resizable_)
     if (resizable_)
@@ -519,6 +529,8 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
     eventData[P_BORDERLESS] = borderless_;
     eventData[P_BORDERLESS] = borderless_;
     eventData[P_RESIZABLE] = resizable_;
     eventData[P_RESIZABLE] = resizable_;
     eventData[P_HIGHDPI] = highDPI_;
     eventData[P_HIGHDPI] = highDPI_;
+    eventData[P_MONITOR] = monitor_;
+    eventData[P_REFRESHRATE] = refreshRate_;
     SendEvent(E_SCREENMODE, eventData);
     SendEvent(E_SCREENMODE, eventData);
 
 
     return true;
     return true;
@@ -526,7 +538,7 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
 
 
 bool Graphics::SetMode(int width, int height)
 bool Graphics::SetMode(int width, int height)
 {
 {
-    return SetMode(width, height, fullscreen_, borderless_, resizable_, highDPI_, vsync_, tripleBuffer_, multiSample_);
+    return SetMode(width, height, fullscreen_, borderless_, resizable_, highDPI_, vsync_, tripleBuffer_, multiSample_, monitor_, refreshRate_);
 }
 }
 
 
 void Graphics::SetSRGB(bool enable)
 void Graphics::SetSRGB(bool enable)
@@ -586,7 +598,7 @@ bool Graphics::TakeScreenShot(Image& destImage)
         // If windowed and multisampled, must still capture the whole screen
         // If windowed and multisampled, must still capture the whole screen
         if (!fullscreen_)
         if (!fullscreen_)
         {
         {
-            IntVector2 desktopSize = GetDesktopResolution();
+            IntVector2 desktopSize = GetDesktopResolution(monitor_);
             surfaceWidth = (unsigned)desktopSize.x_;
             surfaceWidth = (unsigned)desktopSize.x_;
             surfaceHeight = (unsigned)desktopSize.y_;
             surfaceHeight = (unsigned)desktopSize.y_;
         }
         }
@@ -2330,7 +2342,7 @@ bool Graphics::OpenWindow(int width, int height, bool resizable, bool borderless
     return true;
     return true;
 }
 }
 
 
-void Graphics::AdjustWindow(int& newWidth, int& newHeight, bool& newFullscreen, bool& newBorderless)
+void Graphics::AdjustWindow(int& newWidth, int& newHeight, bool& newFullscreen, bool& newBorderless, int& monitor)
 {
 {
     if (!externalWindow_)
     if (!externalWindow_)
     {
     {
@@ -2339,8 +2351,17 @@ void Graphics::AdjustWindow(int& newWidth, int& newHeight, bool& newFullscreen,
             SDL_MaximizeWindow(window_);
             SDL_MaximizeWindow(window_);
             SDL_GetWindowSize(window_, &newWidth, &newHeight);
             SDL_GetWindowSize(window_, &newWidth, &newHeight);
         }
         }
-        else
+        else {
+            if (newFullscreen || newBorderless) 
+            {
+                // reposition the window on the specified monitor
+                SDL_Rect display_rect;
+                SDL_GetDisplayBounds(monitor, &display_rect);
+                SDL_SetWindowPosition(window_, display_rect.x, display_rect.y);
+            }
+
             SDL_SetWindowSize(window_, newWidth, newHeight);
             SDL_SetWindowSize(window_, newWidth, newHeight);
+        }
 
 
         // Hack fix: on SDL 2.0.4 a fullscreen->windowed transition results in a maximized window when the D3D device is reset, so hide before
         // Hack fix: on SDL 2.0.4 a fullscreen->windowed transition results in a maximized window when the D3D device is reset, so hide before
         SDL_HideWindow(window_);
         SDL_HideWindow(window_);

+ 15 - 9
Source/Urho3D/Graphics/Graphics.cpp

@@ -103,7 +103,7 @@ void Graphics::SetOrientations(const String& orientations)
 
 
 bool Graphics::ToggleFullscreen()
 bool Graphics::ToggleFullscreen()
 {
 {
-    return SetMode(width_, height_, !fullscreen_, borderless_, resizable_, highDPI_, vsync_, tripleBuffer_, multiSample_);
+    return SetMode(width_, height_, !fullscreen_, borderless_, resizable_, highDPI_, vsync_, tripleBuffer_, multiSample_, monitor_, refreshRate_);
 }
 }
 
 
 void Graphics::SetShaderParameter(StringHash param, const Variant& value)
 void Graphics::SetShaderParameter(StringHash param, const Variant& value)
@@ -172,25 +172,26 @@ IntVector2 Graphics::GetWindowPosition() const
     return IntVector2::ZERO;
     return IntVector2::ZERO;
 }
 }
 
 
-PODVector<IntVector2> Graphics::GetResolutions() const
+PODVector<IntVector3> Graphics::GetResolutions(int monitor) const
 {
 {
-    PODVector<IntVector2> ret;
+    PODVector<IntVector3> ret;
     // Emscripten is not able to return a valid list
     // Emscripten is not able to return a valid list
 #ifndef __EMSCRIPTEN__
 #ifndef __EMSCRIPTEN__
-    unsigned numModes = (unsigned)SDL_GetNumDisplayModes(0);
+    unsigned numModes = (unsigned)SDL_GetNumDisplayModes(monitor);
 
 
     for (unsigned i = 0; i < numModes; ++i)
     for (unsigned i = 0; i < numModes; ++i)
     {
     {
         SDL_DisplayMode mode;
         SDL_DisplayMode mode;
-        SDL_GetDisplayMode(0, i, &mode);
+        SDL_GetDisplayMode(monitor, i, &mode);
         int width = mode.w;
         int width = mode.w;
         int height = mode.h;
         int height = mode.h;
+        int rate = mode.refresh_rate;
 
 
         // Store mode if unique
         // Store mode if unique
         bool unique = true;
         bool unique = true;
         for (unsigned j = 0; j < ret.Size(); ++j)
         for (unsigned j = 0; j < ret.Size(); ++j)
         {
         {
-            if (ret[j].x_ == width && ret[j].y_ == height)
+            if (ret[j].x_ == width && ret[j].y_ == height && ret[j].z_ == rate)
             {
             {
                 unique = false;
                 unique = false;
                 break;
                 break;
@@ -198,18 +199,18 @@ PODVector<IntVector2> Graphics::GetResolutions() const
         }
         }
 
 
         if (unique)
         if (unique)
-            ret.Push(IntVector2(width, height));
+            ret.Push(IntVector3(width, height, rate));
     }
     }
 #endif
 #endif
 
 
     return ret;
     return ret;
 }
 }
 
 
-IntVector2 Graphics::GetDesktopResolution() const
+IntVector2 Graphics::GetDesktopResolution(int monitor) const
 {
 {
 #if !defined(__ANDROID__) && !defined(IOS)
 #if !defined(__ANDROID__) && !defined(IOS)
     SDL_DisplayMode mode;
     SDL_DisplayMode mode;
-    SDL_GetDesktopDisplayMode(0, &mode);
+    SDL_GetDesktopDisplayMode(monitor, &mode);
     return IntVector2(mode.w, mode.h);
     return IntVector2(mode.w, mode.h);
 #else
 #else
     // SDL_GetDesktopDisplayMode() may not work correctly on mobile platforms. Rather return the window size
     // SDL_GetDesktopDisplayMode() may not work correctly on mobile platforms. Rather return the window size
@@ -217,6 +218,11 @@ IntVector2 Graphics::GetDesktopResolution() const
 #endif
 #endif
 }
 }
 
 
+int Graphics::GetMonitorCount() const
+{
+    return SDL_GetNumVideoDisplays();
+}
+
 void Graphics::Maximize()
 void Graphics::Maximize()
 {
 {
     if (!window_)
     if (!window_)

+ 17 - 5
Source/Urho3D/Graphics/Graphics.h

@@ -101,7 +101,7 @@ public:
     /// Set screen mode. Return true if successful.
     /// Set screen mode. Return true if successful.
     bool SetMode
     bool SetMode
         (int width, int height, bool fullscreen, bool borderless, bool resizable, bool highDPI, bool vsync, bool tripleBuffer,
         (int width, int height, bool fullscreen, bool borderless, bool resizable, bool highDPI, bool vsync, bool tripleBuffer,
-            int multiSample);
+            int multiSample, int monitor, int refreshRate);
     /// Set screen resolution only. Return true if successful.
     /// Set screen resolution only. Return true if successful.
     bool SetMode(int width, int height);
     bool SetMode(int width, int height);
     /// Set whether the main window uses sRGB conversion on write.
     /// Set whether the main window uses sRGB conversion on write.
@@ -300,6 +300,12 @@ public:
     /// Return whether vertical sync is on.
     /// Return whether vertical sync is on.
     bool GetVSync() const { return vsync_; }
     bool GetVSync() const { return vsync_; }
 
 
+    /// Return refresh rate when using vsync in fullscreen
+    int GetRefreshRate() const { return refreshRate_; }
+
+    /// Return the current monitor index. Effective on in fullscreen
+    int GetMonitor() const { return monitor_; }
+
     /// Return whether triple buffering is enabled.
     /// Return whether triple buffering is enabled.
     bool GetTripleBuffer() const { return tripleBuffer_; }
     bool GetTripleBuffer() const { return tripleBuffer_; }
 
 
@@ -360,12 +366,14 @@ public:
     /// Return whether sRGB conversion on rendertarget writing is supported.
     /// Return whether sRGB conversion on rendertarget writing is supported.
     bool GetSRGBWriteSupport() const { return sRGBWriteSupport_; }
     bool GetSRGBWriteSupport() const { return sRGBWriteSupport_; }
 
 
-    /// Return supported fullscreen resolutions. Will be empty if listing the resolutions is not supported on the platform (e.g. Web).
-    PODVector<IntVector2> GetResolutions() const;
+    /// Return supported fullscreen resolutions (third component is refreshRate). Will be empty if listing the resolutions is not supported on the platform (e.g. Web).
+    PODVector<IntVector3> GetResolutions(int monitor) const;
     /// Return supported multisampling levels.
     /// Return supported multisampling levels.
     PODVector<int> GetMultiSampleLevels() const;
     PODVector<int> GetMultiSampleLevels() const;
     /// Return the desktop resolution.
     /// Return the desktop resolution.
-    IntVector2 GetDesktopResolution() const;
+    IntVector2 GetDesktopResolution(int monitor) const;
+    /// Return the number of currently connected monitors
+    int GetMonitorCount() const;
     /// Return hardware format for a compressed image format, or 0 if unsupported.
     /// Return hardware format for a compressed image format, or 0 if unsupported.
     unsigned GetFormat(CompressedFormat format) const;
     unsigned GetFormat(CompressedFormat format) const;
     /// Return a shader variation by name and defines.
     /// Return a shader variation by name and defines.
@@ -560,7 +568,7 @@ private:
     /// Create the application window icon.
     /// Create the application window icon.
     void CreateWindowIcon();
     void CreateWindowIcon();
     /// Adjust the window for new resolution and fullscreen mode.
     /// Adjust the window for new resolution and fullscreen mode.
-    void AdjustWindow(int& newWidth, int& newHeight, bool& newFullscreen, bool& newBorderless);
+    void AdjustWindow(int& newWidth, int& newHeight, bool& newFullscreen, bool& newBorderless, int& monitor);
     /// Create the Direct3D11 device and swap chain. Requires an open window. Can also be called again to recreate swap chain. Return true on success.
     /// Create the Direct3D11 device and swap chain. Requires an open window. Can also be called again to recreate swap chain. Return true on success.
     bool CreateDevice(int width, int height, int multiSample);
     bool CreateDevice(int width, int height, int multiSample);
     /// Update Direct3D11 swap chain state for a new mode and create views for the backbuffer & default depth buffer. Return true on success.
     /// Update Direct3D11 swap chain state for a new mode and create views for the backbuffer & default depth buffer. Return true on success.
@@ -640,6 +648,10 @@ private:
     bool highDPI_;
     bool highDPI_;
     /// Vertical sync flag.
     /// Vertical sync flag.
     bool vsync_;
     bool vsync_;
+    /// Refresh rate in Hz. Only used in fullscreen, 0 when windowed
+    int refreshRate_;
+    /// Monitor index. Only used in fullscreen, 0 when windowed
+    int monitor_;
     /// Triple buffering flag.
     /// Triple buffering flag.
     bool tripleBuffer_;
     bool tripleBuffer_;
     /// Flush GPU command buffer flag.
     /// Flush GPU command buffer flag.

+ 2 - 0
Source/Urho3D/Graphics/GraphicsEvents.h

@@ -36,6 +36,8 @@ URHO3D_EVENT(E_SCREENMODE, ScreenMode)
     URHO3D_PARAM(P_BORDERLESS, Borderless);        // bool
     URHO3D_PARAM(P_BORDERLESS, Borderless);        // bool
     URHO3D_PARAM(P_RESIZABLE, Resizable);          // bool
     URHO3D_PARAM(P_RESIZABLE, Resizable);          // bool
     URHO3D_PARAM(P_HIGHDPI, HighDPI);              // bool
     URHO3D_PARAM(P_HIGHDPI, HighDPI);              // bool
+    URHO3D_PARAM(P_MONITOR, Monitor);              // int
+    URHO3D_PARAM(P_REFRESHRATE, RefreshRate);      // int
 }
 }
 
 
 /// Window position changed.
 /// Window position changed.

+ 20 - 7
Source/Urho3D/Graphics/OpenGL/OGLGraphics.cpp

@@ -284,7 +284,7 @@ Graphics::~Graphics()
 }
 }
 
 
 bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless, bool resizable, bool highDPI, bool vsync,
 bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless, bool resizable, bool highDPI, bool vsync,
-    bool tripleBuffer, int multiSample)
+    bool tripleBuffer, int multiSample, int monitor, int refreshRate)
 {
 {
     URHO3D_PROFILE(SetScreenMode);
     URHO3D_PROFILE(SetScreenMode);
 
 
@@ -295,6 +295,11 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
     fullscreen = true;
     fullscreen = true;
 #endif
 #endif
 
 
+    // make sure monitor index is not bigger than the currently detected monitors
+    int monitors = SDL_GetNumVideoDisplays();
+    if (monitor >= monitors || monitor < 0)
+        monitor = 0; // this monitor is not present, use first monitor
+
     // Fullscreen or Borderless can not be resizable
     // Fullscreen or Borderless can not be resizable
     if (fullscreen || borderless)
     if (fullscreen || borderless)
         resizable = false;
         resizable = false;
@@ -325,7 +330,7 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
         if (fullscreen || borderless)
         if (fullscreen || borderless)
         {
         {
             SDL_DisplayMode mode;
             SDL_DisplayMode mode;
-            SDL_GetDesktopDisplayMode(0, &mode);
+            SDL_GetDesktopDisplayMode(monitor, &mode);
             width = mode.w;
             width = mode.w;
             height = mode.h;
             height = mode.h;
         }
         }
@@ -341,7 +346,7 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
 #ifdef DESKTOP_GRAPHICS
 #ifdef DESKTOP_GRAPHICS
     if (fullscreen)
     if (fullscreen)
     {
     {
-        PODVector<IntVector2> resolutions = GetResolutions();
+        PODVector<IntVector3> resolutions = GetResolutions(monitor);
         if (resolutions.Size())
         if (resolutions.Size())
         {
         {
             unsigned best = 0;
             unsigned best = 0;
@@ -359,6 +364,7 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
 
 
             width = resolutions[best].x_;
             width = resolutions[best].x_;
             height = resolutions[best].y_;
             height = resolutions[best].y_;
+            refreshRate = resolutions[best].z_;
         }
         }
     }
     }
 #endif
 #endif
@@ -417,8 +423,13 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
             SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
             SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
         }
         }
 
 
-        int x = fullscreen ? 0 : position_.x_;
-        int y = fullscreen ? 0 : position_.y_;
+        // reposition the window on the specified monitor
+        SDL_Rect display_rect;
+        SDL_GetDisplayBounds(monitor, &display_rect);
+        SDL_SetWindowPosition(window_, display_rect.x, display_rect.y);
+
+        int x = fullscreen || borderless ? display_rect.x : position_.x_;
+        int y = fullscreen || borderless ? display_rect.y : position_.y_;
 
 
         unsigned flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
         unsigned flags = SDL_WINDOW_OPENGL | SDL_WINDOW_SHOWN;
         if (fullscreen)
         if (fullscreen)
@@ -511,7 +522,7 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
 
 
 #ifdef URHO3D_LOGGING
 #ifdef URHO3D_LOGGING
     String msg;
     String msg;
-    msg.AppendWithFormat("Set screen mode %dx%d %s", width_, height_, (fullscreen_ ? "fullscreen" : "windowed"));
+    msg.AppendWithFormat("Set screen mode %dx%d %s monitor %d", width_, height_, (fullscreen_ ? "fullscreen" : "windowed"), monitor_);
     if (borderless_)
     if (borderless_)
         msg.Append(" borderless");
         msg.Append(" borderless");
     if (resizable_)
     if (resizable_)
@@ -530,6 +541,8 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
     eventData[P_BORDERLESS] = borderless_;
     eventData[P_BORDERLESS] = borderless_;
     eventData[P_RESIZABLE] = resizable_;
     eventData[P_RESIZABLE] = resizable_;
     eventData[P_HIGHDPI] = highDPI_;
     eventData[P_HIGHDPI] = highDPI_;
+    eventData[P_MONITOR] = monitor_;
+    eventData[P_REFRESHRATE] = refreshRate_;
     SendEvent(E_SCREENMODE, eventData);
     SendEvent(E_SCREENMODE, eventData);
 
 
     return true;
     return true;
@@ -537,7 +550,7 @@ bool Graphics::SetMode(int width, int height, bool fullscreen, bool borderless,
 
 
 bool Graphics::SetMode(int width, int height)
 bool Graphics::SetMode(int width, int height)
 {
 {
-    return SetMode(width, height, fullscreen_, borderless_, resizable_, highDPI_, vsync_, tripleBuffer_, multiSample_);
+    return SetMode(width, height, fullscreen_, borderless_, resizable_, highDPI_, vsync_, tripleBuffer_, multiSample_, monitor_, refreshRate_);
 }
 }
 
 
 void Graphics::SetSRGB(bool enable)
 void Graphics::SetSRGB(bool enable)

+ 8 - 3
Source/Urho3D/LuaScript/pkgs/Graphics/Graphics.pkg

@@ -8,7 +8,7 @@ class Graphics : public Object
     void SetWindowPosition(const IntVector2& position);
     void SetWindowPosition(const IntVector2& position);
     void SetWindowPosition(int x, int y);
     void SetWindowPosition(int x, int y);
 
 
-    bool SetMode(int width, int height, bool fullscreen, bool borderless, bool resizable, bool highDPI, bool vsync, bool tripleBuffer, int multiSample);
+    bool SetMode(int width, int height, bool fullscreen, bool borderless, bool resizable, bool highDPI, bool vsync, bool tripleBuffer, int multiSample, int monitor, int refreshRate);
     bool SetMode(int width, int height);
     bool SetMode(int width, int height);
 
 
     void SetSRGB(bool enable);
     void SetSRGB(bool enable);
@@ -39,6 +39,8 @@ class Graphics : public Object
     bool GetResizable() const;
     bool GetResizable() const;
     bool GetBorderless() const;
     bool GetBorderless() const;
     bool GetVSync() const;
     bool GetVSync() const;
+    int GetMonitor() const;
+    int GetRefreshRate() const;
     bool GetTripleBuffer() const;
     bool GetTripleBuffer() const;
     bool GetSRGB() const;
     bool GetSRGB() const;
     bool GetDither() const;
     bool GetDither() const;
@@ -57,7 +59,8 @@ class Graphics : public Object
     bool GetReadableDepthSupport() const;
     bool GetReadableDepthSupport() const;
     bool GetSRGBSupport() const;
     bool GetSRGBSupport() const;
     bool GetSRGBWriteSupport() const;
     bool GetSRGBWriteSupport() const;
-    IntVector2 GetDesktopResolution() const;
+    IntVector2 GetDesktopResolution(int monitor) const;
+    int GetMonitorCount() const;
     const String GetShaderCacheDir() const;
     const String GetShaderCacheDir() const;
 
 
     static unsigned GetAlphaFormat();
     static unsigned GetAlphaFormat();
@@ -91,6 +94,8 @@ class Graphics : public Object
     tolua_readonly tolua_property__get_set bool resizable;
     tolua_readonly tolua_property__get_set bool resizable;
     tolua_readonly tolua_property__get_set bool borderless;
     tolua_readonly tolua_property__get_set bool borderless;
     tolua_readonly tolua_property__get_set bool vSync;
     tolua_readonly tolua_property__get_set bool vSync;
+    tolua_readonly tolua_property__get_set int refreshRate;
+    tolua_readonly tolua_property__get_set int monitor;
     tolua_readonly tolua_property__get_set bool tripleBuffer;
     tolua_readonly tolua_property__get_set bool tripleBuffer;
     tolua_property__get_set bool sRGB;
     tolua_property__get_set bool sRGB;
     tolua_property__get_set bool dither;
     tolua_property__get_set bool dither;
@@ -109,7 +114,7 @@ class Graphics : public Object
     tolua_readonly tolua_property__get_set bool readableDepthSupport;
     tolua_readonly tolua_property__get_set bool readableDepthSupport;
     tolua_readonly tolua_property__get_set bool sRGBSupport;
     tolua_readonly tolua_property__get_set bool sRGBSupport;
     tolua_readonly tolua_property__get_set bool sRGBWriteSupport;
     tolua_readonly tolua_property__get_set bool sRGBWriteSupport;
-    tolua_readonly tolua_property__get_set IntVector2 desktopResolution;
+    tolua_readonly tolua_property__get_set int monitorCount;
     tolua_property__get_set String shaderCacheDir;
     tolua_property__get_set String shaderCacheDir;
 };
 };