Browse Source

Going back from fullscreen to windowed in DX9 restores the window style properly

Marko Pintera 11 years ago
parent
commit
a95b2215e7

+ 1 - 1
BansheeEditorExec/BsEditorExec.cpp

@@ -11,7 +11,7 @@ int CALLBACK WinMain(
 	_In_  int nCmdShow
 	)
 {
-	EditorApplication::startUp(RenderSystemPlugin::OpenGL);
+	EditorApplication::startUp(RenderSystemPlugin::DX9);
 	EditorApplication::instance().runMainLoop();
 	EditorApplication::shutDown();
 

+ 16 - 17
CamelotD3D9Renderer/Include/CmD3D9RenderWindow.h

@@ -142,22 +142,21 @@ namespace BansheeEngine
 		void destroy_internal();
 
 	protected:
-		HINSTANCE					mInstance;				// Process instance
-		D3D9Device* 				mDevice;				// D3D9 device wrapper class.
-		bool						mDeviceValid;			// Device was validation succeeded.
-		HWND						mHWnd;					// Win32 Window handle		
-		bool						mIsExternal;			// window not created by Ogre
-		bool						mClosed;				// Is this window destroyed.			
-		D3DMULTISAMPLE_TYPE			mMultisampleType;		// AA type.
-		DWORD						mMultisampleQuality;	// AA quality.
-		UINT						mDisplayFrequency;		// Display frequency.
-		bool						mVSync;					// Use vertical sync or not.
-		unsigned int				mVSyncInterval;		
-		DWORD						mStyle;					// Window style currently used for this window.
-		bool						mIsDepthBuffered;
-		bool						mIsChild;
-		// Desired width / height after resizing
-		unsigned int mDesiredWidth;
-		unsigned int mDesiredHeight;
+		HINSTANCE mInstance;
+		D3D9Device* mDevice;
+		bool mDeviceValid;
+		HWND mHWnd;
+		bool mIsExternal;
+		bool mClosed;		
+		D3DMULTISAMPLE_TYPE	mMultisampleType;
+		DWORD mMultisampleQuality;
+		UINT mDisplayFrequency;
+		bool mVSync;
+		unsigned int mVSyncInterval;		
+		DWORD mStyle;	
+		DWORD mWindowedStyle;
+		DWORD mWindowedStyleEx;
+		bool mIsDepthBuffered;
+		bool mIsChild;
 	};
 }

+ 51 - 40
CamelotD3D9Renderer/Source/CmD3D9RenderWindow.cpp

@@ -13,7 +13,8 @@
 namespace BansheeEngine
 {
 	D3D9RenderWindow::D3D9RenderWindow(const RENDER_WINDOW_DESC& desc, HINSTANCE instance)
-		: RenderWindow(desc), mInstance(instance), mIsDepthBuffered(true), mIsChild(false)
+		: RenderWindow(desc), mInstance(instance), mIsDepthBuffered(true), mIsChild(false),
+		mStyle(0), mWindowedStyle(0), mWindowedStyleEx(0)
 	{
 		mDevice = NULL;
 		mIsFullScreen = false;		
@@ -53,10 +54,33 @@ namespace BansheeEngine
 
 		mIsChild = parentHWnd != 0;
 
+		mWindowedStyle = WS_VISIBLE | WS_CLIPCHILDREN;
+		mWindowedStyleEx = 0;
+
+		if (!mDesc.fullscreen || mIsChild)
+		{
+			if (parentHWnd)
+			{
+				if (mDesc.toolWindow)
+					mWindowedStyleEx = WS_EX_TOOLWINDOW;
+				else
+					mWindowedStyle |= WS_CHILD;
+			}
+
+			if (!parentHWnd || mDesc.toolWindow)
+			{
+				if (mDesc.border == WindowBorder::None)
+					mWindowedStyle |= WS_POPUP;
+				else if (mDesc.border == WindowBorder::Fixed)
+					mWindowedStyle |= WS_OVERLAPPED | WS_BORDER | WS_CAPTION |
+					WS_SYSMENU | WS_MINIMIZEBOX;
+				else
+					mWindowedStyle |= WS_OVERLAPPEDWINDOW;
+			}
+		}
+
 		if (!externalHandle)
 		{
-			DWORD dwStyle = WS_VISIBLE | WS_CLIPCHILDREN;
-			DWORD dwStyleEx = 0;	
 			MONITORINFO monitorInfo;
 			RECT rc;
 
@@ -121,38 +145,23 @@ namespace BansheeEngine
 				top += monitorInfo.rcWork.top;
 			}
 
-			mWidth = mDesiredWidth = mDesc.videoMode.getWidth();
-			mHeight = mDesiredHeight = mDesc.videoMode.getHeight();
+			mWidth = mDesc.videoMode.getWidth();
+			mHeight =  mDesc.videoMode.getHeight();
 			mTop = top;
 			mLeft = left;
 
+			DWORD dwStyle = 0;
+			DWORD dwStyleEx = 0;
 			if (mDesc.fullscreen && !mIsChild)
 			{
-				dwStyleEx |= WS_EX_TOPMOST;
-				dwStyle |= WS_POPUP;
+				dwStyle = WS_VISIBLE | WS_CLIPCHILDREN | WS_POPUP;
 				mTop = monitorInfo.rcMonitor.top;
 				mLeft = monitorInfo.rcMonitor.left;		
 			}
 			else
 			{
-				if (parentHWnd)
-				{
-					if(mDesc.toolWindow)
-						dwStyleEx = WS_EX_TOOLWINDOW;
-					else
-						dwStyle |= WS_CHILD;
-				}
-
-				if (!parentHWnd || mDesc.toolWindow)
-				{
-					if (mDesc.border == WindowBorder::None)
-						dwStyle |= WS_POPUP;
-					else if (mDesc.border == WindowBorder::Fixed)
-						dwStyle |= WS_OVERLAPPED | WS_BORDER | WS_CAPTION |
-						WS_SYSMENU | WS_MINIMIZEBOX;
-					else
-						dwStyle |= WS_OVERLAPPEDWINDOW;
-				}
+				dwStyle = mWindowedStyle;
+				dwStyleEx = mWindowedStyleEx;
 
 				_adjustWindow(mDesc.videoMode.getWidth(), mDesc.videoMode.getHeight(), dwStyle, &winWidth, &winHeight);
 
@@ -261,7 +270,6 @@ namespace BansheeEngine
 
 		bool oldFullscreen = mIsFullScreen;
 
-		mStyle = WS_VISIBLE | WS_CLIPCHILDREN | WS_POPUP;
 		mWidth = width;
 		mHeight = height;
 		mDisplayFrequency = Math::roundToInt(refreshRate);
@@ -278,17 +286,6 @@ namespace BansheeEngine
 		mTop = monitorInfo.rcMonitor.top;
 		mLeft = monitorInfo.rcMonitor.left;
 
-		if (oldFullscreen) // Was previously fullscreen, just changing the resolution
-		{
-			//SetWindowPos(mHWnd, HWND_TOPMOST, mLeft, mTop, mWidth, mHeight, SWP_NOACTIVATE);
-		}
-		else
-		{
-			//SetWindowPos(mHWnd, HWND_TOPMOST, mLeft, mTop, mWidth, mHeight, SWP_NOACTIVATE);
-			SetWindowLong(mHWnd, GWL_STYLE, mStyle);
-			SetWindowPos(mHWnd, 0, 0, 0, 0, 0, SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
-		}
-
 		// Invalidate device, which resets it
 		mDevice->invalidate(this);
 		mDevice->acquire();
@@ -310,14 +307,28 @@ namespace BansheeEngine
 
 		mIsFullScreen = false;
 
-		mStyle = WS_VISIBLE | WS_CLIPCHILDREN | WS_OVERLAPPEDWINDOW;
+		mStyle = mWindowedStyle;
 
 		unsigned int winWidth, winHeight;
 		_adjustWindow(mWidth, mHeight, mStyle, &winWidth, &winHeight);
 
+		// Deal with centering when switching down to smaller resolution
+		HMONITOR hMonitor = MonitorFromWindow(mHWnd, MONITOR_DEFAULTTONEAREST);
+		MONITORINFO monitorInfo;
+		memset(&monitorInfo, 0, sizeof(MONITORINFO));
+		monitorInfo.cbSize = sizeof(MONITORINFO);
+		GetMonitorInfo(hMonitor, &monitorInfo);
+
+		LONG screenw = monitorInfo.rcWork.right - monitorInfo.rcWork.left;
+		LONG screenh = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;
+
+		int left = screenw > int(winWidth) ? ((screenw - int(winWidth)) / 2) : 0;
+		int top = screenh > int(winHeight) ? ((screenh - int(winHeight)) / 2) : 0;
+
 		SetWindowLong(mHWnd, GWL_STYLE, mStyle);
-		SetWindowPos(mHWnd, HWND_NOTOPMOST, 0, 0, winWidth, winHeight,
-			SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOACTIVATE);
+		SetWindowLong(mHWnd, GWL_EXSTYLE, mWindowedStyleEx);
+		SetWindowPos(mHWnd, HWND_NOTOPMOST, left, top, winWidth, winHeight,
+			SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_NOACTIVATE);
 
 		mDevice->invalidate(this);
 		mDevice->acquire();

+ 1 - 7
Polish.txt

@@ -17,13 +17,7 @@ Finish GPUProfiler:
 
 I should be able to specify resolution when going to windowed mode
  - Maybe just store the windowed and fullscreen resolutions separately and restore automatically?
-
-OpenGL going back from windowed mode doesn't restore window style properly.
-
-Switching from higher to lower resoltuion in DX9 causes an issue where viewport is larger than the render target. (Only with debug runtime - Can probably ignore)
-When toggling fullscreen two times device reset fails
-In DX9 render window I have disabled top most style.
-  - If needed re-enable it, if not remove it from OpenGL as well as I think it disables alt+tab
+ - I have a feeling DX9 might start crashing once I resize to sub-fullscreen res and go back to FS - test it
 
 DISREGARD MONITOR INDEX ON DX9
  - It's not trivial and its not worth wasting time on a deprecated system