# HG changeset patch
# User Nicolas Hake <isilkor@openclonk.org>
# Date 1256262796 -7200
# Node ID daf1795462c39ee3a71a3234d087629c45430429
# Parent  6ce8431bce9bb45f6c1da4983d8d81cd19801981
win32: Allow windowed mode

diff --git a/src/C4FullScreen.cpp b/src/C4FullScreen.cpp
--- a/src/C4FullScreen.cpp
+++ b/src/C4FullScreen.cpp
@@ -43,7 +43,8 @@
 #ifdef _WIN32
 
 LRESULT APIENTRY FullScreenWinProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
-	{
+{
+	static bool NativeCursorShown = true;
 	// Process message
 	switch (uMsg)
 		{
@@ -120,8 +121,34 @@ LRESULT APIENTRY FullScreenWinProc(HWND 
 		case WM_RBUTTONUP: ::GraphicsSystem.MouseMove(C4MC_Button_RightUp,LOWORD(lParam),HIWORD(lParam),wParam, NULL); break;
 		case WM_LBUTTONDBLCLK: ::GraphicsSystem.MouseMove(C4MC_Button_LeftDouble,LOWORD(lParam),HIWORD(lParam),wParam, NULL); break;
 		case WM_RBUTTONDBLCLK: ::GraphicsSystem.MouseMove(C4MC_Button_RightDouble,LOWORD(lParam),HIWORD(lParam),wParam, NULL); break;
-		case WM_MOUSEMOVE: ::GraphicsSystem.MouseMove(C4MC_Button_None,LOWORD(lParam),HIWORD(lParam),wParam, NULL); break;
 		case WM_MOUSEWHEEL: ::GraphicsSystem.MouseMove(C4MC_Button_Wheel,LOWORD(lParam),HIWORD(lParam),wParam, NULL); break;
+		case WM_MOUSEMOVE:
+			::GraphicsSystem.MouseMove(C4MC_Button_None,LOWORD(lParam),HIWORD(lParam),wParam, NULL);
+			// Hide cursor in client area
+			if (NativeCursorShown)
+			{
+				NativeCursorShown = false;
+				ShowCursor(FALSE);
+			}
+			break;
+		case WM_NCMOUSEMOVE:
+			// Show cursor on window frame
+			if (!NativeCursorShown)
+			{
+				NativeCursorShown = true;
+				ShowCursor(TRUE);
+			}
+			break;
+		case WM_SIZE:
+			// Notify app about render window size change
+			switch (wParam)
+			{
+			case SIZE_RESTORED:
+			case SIZE_MAXIMIZED:
+				::Application.OnResolutionChanged(LOWORD(lParam), HIWORD(lParam));
+				break;
+			}
+			break;
 		}
 	return DefWindowProc(hwnd, uMsg, wParam, lParam);
 	}
diff --git a/src/gui/C4StartupOptionsDlg.cpp b/src/gui/C4StartupOptionsDlg.cpp
--- a/src/gui/C4StartupOptionsDlg.cpp
+++ b/src/gui/C4StartupOptionsDlg.cpp
@@ -827,9 +827,6 @@ C4StartupOptionsDlg::C4StartupOptionsDlg
 	pCheck->SetOnChecked(new C4GUI::CallbackHandler<C4StartupOptionsDlg>(this, &C4StartupOptionsDlg::OnFullscreenChange));
 	pCheck->SetToolTip(LoadResStr("IDS_MSG_FULLSCREEN_DESC"));
 	pCheck->SetFont(pUseFont, C4StartupFontClr, C4StartupFontClrDisabled);
-#ifdef _WIN32
-	pCheck->SetEnabled(false);
-#endif
 	pGroupResolution->AddElement(pCheck);
 	// --subgroup troubleshooting
 	pGroupTrouble = new C4GUI::GroupBox(caSheetGraphics.GetGridCell(0,1,1,3));
diff --git a/src/platform/StdD3D.cpp b/src/platform/StdD3D.cpp
--- a/src/platform/StdD3D.cpp
+++ b/src/platform/StdD3D.cpp
@@ -451,49 +451,37 @@ bool CStdD3D::CreatePrimarySurfaces(bool
 	HWND hWindow = pApp->pWindow->hWindow;
 	DebugLog("  Create Device...");
 	if (Fullscreen)
-		{
+	{
 		// fullscreen mode
 		// pick a display mode
-#ifndef _DEBUG
 		if (DDrawCfg.Windowed)
-#else
-		if (true)
-#endif
-			{
+		{
 			// "Windowed fullscreen"
 			if (lpD3D->GetAdapterDisplayMode(iMonitor, &dspMode) != D3D_OK)
 				if (lpD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dspMode) != D3D_OK)
 					return Error("Could not get current display mode");
-			}
+			SetWindowPos(hWindow, HWND_TOP, 0, 0, iXRes,iYRes, SWP_NOOWNERZORDER | SWP_SHOWWINDOW | SWP_NOMOVE);
+			d3dpp.Windowed = true;
+		}
 		else
-			{
+		{
 			// true fullscreen
 			if (!FindDisplayMode(iXRes, iYRes, iColorDepth, iMonitor))
 				return Error("Display mode not supported");
-			}
+		}
 		// fill present structure
-#ifndef _DEBUG
-		if (DDrawCfg.Windowed)
-#endif
-			{
-			SetWindowPos(hWindow, HWND_TOP, /*pApp->MonitorRect.left*/0, /*pApp->MonitorRect.top*/0,
-				iXRes,iYRes, SWP_NOOWNERZORDER | SWP_SHOWWINDOW);
-			SetWindowLong(hWindow, GWL_STYLE, (WS_VISIBLE | WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX));
-			d3dpp.Windowed = true;
-			}
 		d3dpp.BackBufferWidth = iXRes;
 		d3dpp.BackBufferHeight= iYRes;
 		d3dpp.BackBufferFormat= dspMode.Format;
 		d3dpp.BackBufferCount = 0;
-		d3dpp.SwapEffect			= D3DSWAPEFFECT_FLIP;
-		d3dpp.Flags						= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
-		// create primary surface
+		d3dpp.SwapEffect      = D3DSWAPEFFECT_FLIP;
+		d3dpp.Flags           = D3DPRESENTFLAG_LOCKABLE_BACKBUFFER;
 		hr = lpD3D->CreateDevice(iMonitor, fSoftware ? D3DDEVTYPE_REF : D3DDEVTYPE_HAL, hWindow,
-                        D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE,
-                        &d3dpp, &lpDevice);
-		}
+			D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE,
+			&d3dpp, &lpDevice);
+	}
 	else
-		{
+	{
 		// windowed mode
 		// get current display mode
 		if (lpD3D->GetAdapterDisplayMode(iMonitor, &dspMode) != D3D_OK)
@@ -515,16 +503,17 @@ bool CStdD3D::CreatePrimarySurfaces(bool
 			hr = lpD3D->CreateDevice(D3DADAPTER_DEFAULT, fSoftware ? D3DDEVTYPE_REF : D3DDEVTYPE_HAL, hWindow,
                         D3DCREATE_SOFTWARE_VERTEXPROCESSING | D3DCREATE_FPU_PRESERVE,
                         &d3dpp, &lpDevice);
-		}
+	}
 	switch (hr)
-		{
-		case D3DERR_INVALIDCALL: return Error("CreateDevice: D3DERR_INVALIDCALL");
-		case D3DERR_NOTAVAILABLE: return Error("CreateDevice: D3DERR_NOTAVAILABLE");
-		case D3DERR_OUTOFVIDEOMEMORY: return Error("CreateDevice: D3DERR_OUTOFVIDEOMEMORY");
-		case D3DERR_DRIVERINTERNALERROR: return Error("CreateDevice: D3DERR_DRIVERINTERNALERROR");
-		case D3D_OK: break;
-		default: return Error("CreateDevice: unknown error");
-		}
+	{
+	case D3DERR_INVALIDCALL: return Error("CreateDevice: D3DERR_INVALIDCALL");
+	case D3DERR_NOTAVAILABLE: return Error("CreateDevice: D3DERR_NOTAVAILABLE");
+	case D3DERR_OUTOFVIDEOMEMORY: return Error("CreateDevice: D3DERR_OUTOFVIDEOMEMORY");
+	case D3DERR_DRIVERINTERNALERROR: return Error("CreateDevice: D3DERR_DRIVERINTERNALERROR");
+	case D3D_OK: break;
+	default: return Error("CreateDevice: unknown error");
+	}
+	
 	// device successfully created?
 	if (!lpDevice) return Error("CreateDevice: unreported error");
 	// store color depth
@@ -553,9 +542,21 @@ bool CStdD3D::CreatePrimarySurfaces(bool
 	}
 
 bool CStdD3D::OnResolutionChanged(unsigned int iXRes, unsigned int iYRes)
-	{
-	return true;
-	}
+{
+	assert(lpDevice);
+	// If fullscreen: SetVideoMode will have handled this.
+	if (fFullscreen && !DDrawCfg.Windowed) return true;
+
+	// FIXME: This should be replaced by using a desktop-size video buffer and
+	// just clipping to the current resolution
+	d3dpp.BackBufferWidth = iXRes;
+	d3dpp.BackBufferHeight = iYRes;
+	DeleteDeviceObjects();
+	HRESULT hr = lpDevice->Reset(&d3dpp);
+	InitDeviceObjects();
+	RestoreDeviceObjects();
+	return hr == D3D_OK;
+}
 
 bool CStdD3D::SetVideoMode(unsigned int iXRes, unsigned int iYRes, unsigned int iColorDepthFIXME, unsigned int iMonitor, bool fFullScreen)
 	{
@@ -568,16 +569,14 @@ bool CStdD3D::SetVideoMode(unsigned int 
 	HRESULT hr;
 	HWND hWindow = pApp->pWindow->hWindow;
 	// pick a display mode
-#ifndef _DEBUG
 	if (DDrawCfg.Windowed)
-#else
-	if (true)
-#endif
 		{
 		// "Windowed fullscreen"
 		if (lpD3D->GetAdapterDisplayMode(iMonitor, &dspMode) != D3D_OK)
 			if (lpD3D->GetAdapterDisplayMode(D3DADAPTER_DEFAULT, &dspMode) != D3D_OK)
 				return Error("Could not get current display mode");
+		SetWindowPos(hWindow, HWND_TOP, 0, 0, iXRes, iYRes, SWP_NOOWNERZORDER | SWP_SHOWWINDOW | SWP_NOMOVE);
+		d3dpp.Windowed = true;
 		}
 	else
 		{
@@ -586,15 +585,6 @@ bool CStdD3D::SetVideoMode(unsigned int 
 			return Error("Display mode not supported");
 		}
 	// fill present structure
-#ifndef _DEBUG
-	if (DDrawCfg.Windowed)
-#endif
-		{
-		SetWindowPos(hWindow, HWND_TOP, /*pApp->MonitorRect.left*/0, /*pApp->MonitorRect.top*/0,
-			iXRes, iYRes, SWP_NOOWNERZORDER | SWP_SHOWWINDOW);
-		SetWindowLong(hWindow, GWL_STYLE, (WS_VISIBLE | WS_POPUP | WS_SYSMENU | WS_CAPTION | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | WS_SIZEBOX));
-		d3dpp.Windowed = true;
-		}
 	d3dpp.BackBufferWidth = iXRes;
 	d3dpp.BackBufferHeight= iYRes;
 	d3dpp.BackBufferFormat= dspMode.Format;
diff --git a/src/platform/StdWindow.cpp b/src/platform/StdWindow.cpp
--- a/src/platform/StdWindow.cpp
+++ b/src/platform/StdWindow.cpp
@@ -59,19 +59,15 @@ CStdWindow::~CStdWindow () {
 }
 
 BOOL CStdWindow::RegisterWindowClass(HINSTANCE hInst) {
-  WNDCLASSEX WndClass;
-	WndClass.cbSize=sizeof(WNDCLASSEX);
-  WndClass.style         = CS_DBLCLKS;
-  WndClass.lpfnWndProc   = FullScreenWinProc;
-  WndClass.cbClsExtra    = 0;
-  WndClass.cbWndExtra    = 0;
-  WndClass.hInstance     = hInst;
-  WndClass.hCursor       = NULL;
-  WndClass.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
-  WndClass.lpszMenuName  = NULL;
-  WndClass.lpszClassName = C4FullScreenClassName;
+	WNDCLASSEX WndClass = {0};
+	WndClass.cbSize        = sizeof(WNDCLASSEX);
+	WndClass.style         = CS_DBLCLKS;
+	WndClass.lpfnWndProc   = FullScreenWinProc;
+	WndClass.hInstance     = hInst;
+	WndClass.hbrBackground = (HBRUSH) COLOR_BACKGROUND;
+	WndClass.lpszClassName = C4FullScreenClassName;
 	WndClass.hIcon         = LoadIcon (hInst, MAKEINTRESOURCE (IDI_00_C4X) );
-  WndClass.hIconSm       = LoadIcon (hInst, MAKEINTRESOURCE (IDI_00_C4X) );
+	WndClass.hIconSm       = LoadIcon (hInst, MAKEINTRESOURCE (IDI_00_C4X) );
 	return RegisterClassEx(&WndClass);
 }
 
@@ -82,11 +78,11 @@ CStdWindow * CStdWindow::Init(CStdApp * 
 	if (!RegisterWindowClass(pApp->hInstance)) return NULL;
 
 	// Create window
-	hWindow = CreateWindowEx	(
+	hWindow = CreateWindowEx(
 							0,
 							C4FullScreenClassName,
 							C4ENGINENAME,
-							WS_POPUP,
+							WS_OVERLAPPEDWINDOW,
 							CW_USEDEFAULT,CW_USEDEFAULT,0,0,
 							NULL,NULL,pApp->hInstance,NULL);
 
@@ -94,7 +90,6 @@ CStdWindow * CStdWindow::Init(CStdApp * 
 	// Show & focus
 	ShowWindow(hWindow,SW_SHOWNORMAL);
 	SetFocus(hWindow);
-	ShowCursor(false);
 #endif
 
 	return this;
@@ -126,8 +121,16 @@ bool CStdWindow::GetSize(RECT * pRect) {
 }
 
 void CStdWindow::SetSize(unsigned int cx, unsigned int cy) {
-	// resize
 	if (hWindow) {
+		// If bordered, add border size
+		if (GetWindowLong(hWindow, GWL_STYLE) & WS_THICKFRAME)
+		{
+			NONCLIENTMETRICS ncm = {0};
+			ncm.cbSize = sizeof(ncm);
+			SystemParametersInfo(SPI_GETNONCLIENTMETRICS, ncm.cbSize, &ncm, 0);
+			cx += ncm.iBorderWidth * 2;
+			cy += ncm.iBorderWidth * 2 + ncm.iCaptionHeight;
+		}
 		::SetWindowPos(hWindow, NULL, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOCOPYBITS | SWP_NOREDRAW | SWP_NOZORDER);
 	}
 }
@@ -358,7 +361,7 @@ bool CStdApp::SetVideoMode(unsigned int 
 	// change mode
 	if (fFullScreen == fDspModeSet) return true;
 #ifdef _DEBUG
-	SetWindowPos(pWindow->hWindow, HWND_TOP, MonitorRect.left, MonitorRect.top, dspMode.dmPelsWidth, dspMode.dmPelsHeight, SWP_NOOWNERZORDER | SWP_SHOWWINDOW);
+	pWindow->SetSize(iXRes, iYRes);
 	OnResolutionChanged(iXRes, iYRes);
 	return true;
 #else
