setFullscreen Win32Window bugfix

Discussion area about developing or extending OGRE, adding plugins for it or building applications on it. No newbie questions please, use the Help forum for that.
Post Reply
ccamporesi
Gnoblar
Posts: 2
Joined: Wed Oct 24, 2012 12:16 am

setFullscreen Win32Window bugfix

Post by ccamporesi » Wed Oct 24, 2012 5:02 am

Hello everyone,
even though I am working with OGRE since many years this is my first post on the forum!
I am quite sure this is not the right place to post mods and bugfixes. I am aware there is a track system but since
I am not working on the development trunk, please forgive me for this time (and please give directions for future contributions).

I am writing to post a bugfix for the Ogre::Win32Window::setFullscreen(..) method in RenderSystem\GL\src\OgreWin32Windows.cpp.
At the present the function lacks on controlling multiple screen for system with multi monitor and extended desktop (the system RenderWindow for Linux works correctly).
This version handles correctly the fullscreen in a specific display after a window reposition.

Please let me know what you think and if it would work for the community.
Thanks

Code: Select all

	void Win32Window::setFullscreen(bool fullScreen, unsigned int width, unsigned int height)
	{
		if (mIsFullScreen != fullScreen || width != mWidth || height != mHeight)
		{
			mIsFullScreen = fullScreen;

			// Getting current monitor and display info
			HMONITOR hMonitor = MonitorFromWindow(mHWnd, MONITOR_DEFAULTTOPRIMARY);
			MONITORINFOEX monitorInfo;
			memset(&monitorInfo, 0, sizeof(MONITORINFOEX));
			monitorInfo.cbSize = sizeof(MONITORINFOEX);
			GetMonitorInfo(hMonitor, &monitorInfo);

			UINT flag;

			if (mIsFullScreen)
			{
				DEVMODE displayDeviceMode;

				memset(&displayDeviceMode, 0, sizeof(displayDeviceMode));
				displayDeviceMode.dmSize = sizeof(DEVMODE);
				displayDeviceMode.dmBitsPerPel = mColourDepth;
				displayDeviceMode.dmPelsWidth = width;
				displayDeviceMode.dmPelsHeight = height;
				displayDeviceMode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;
				if (mDisplayFrequency)
				{
					displayDeviceMode.dmDisplayFrequency = mDisplayFrequency;
					displayDeviceMode.dmFields |= DM_DISPLAYFREQUENCY;

					if (ChangeDisplaySettingsEx(monitorInfo.szDevice, &displayDeviceMode, NULL, 
						CDS_FULLSCREEN | CDS_TEST, NULL) != DISP_CHANGE_SUCCESSFUL)					
					{
						LogManager::getSingleton().logMessage(LML_NORMAL, "ChangeDisplaySettings with user display frequency failed");
						displayDeviceMode.dmFields ^= DM_DISPLAYFREQUENCY;
					}
				}
				else
				{
					// try a few
					displayDeviceMode.dmDisplayFrequency = 100;
					displayDeviceMode.dmFields |= DM_DISPLAYFREQUENCY;
					if (ChangeDisplaySettingsEx(monitorInfo.szDevice, &displayDeviceMode, NULL, 
						CDS_FULLSCREEN | CDS_TEST, NULL) != DISP_CHANGE_SUCCESSFUL)		
					{
						displayDeviceMode.dmDisplayFrequency = 75;
						if (ChangeDisplaySettingsEx(monitorInfo.szDevice, &displayDeviceMode, NULL, 
							CDS_FULLSCREEN | CDS_TEST, NULL) != DISP_CHANGE_SUCCESSFUL)		
						{
							displayDeviceMode.dmFields ^= DM_DISPLAYFREQUENCY;
						}
					}

				}

				if (ChangeDisplaySettingsEx(monitorInfo.szDevice, &displayDeviceMode, NULL, CDS_FULLSCREEN, NULL) != DISP_CHANGE_SUCCESSFUL) {			
					LogManager::getSingleton().logMessage(LML_CRITICAL, "ChangeDisplaySettings failed");
				}

				SetWindowLongPtr(mHWnd, GWL_STYLE, getWindowStyle(mIsFullScreen));

				// retrieving desktop and current display info
				memset(&monitorInfo, 0, sizeof(MONITORINFO));
				monitorInfo.cbSize = sizeof(MONITORINFO);
				GetMonitorInfo(hMonitor, &monitorInfo);

				mWidth = width;
				mHeight = height;
				mTop = monitorInfo.rcMonitor.top;
				mLeft = monitorInfo.rcMonitor.left;

				flag = SWP_NOACTIVATE;
			}
			else
			{
				// drop out of fullscreen
				ChangeDisplaySettingsEx(monitorInfo.szDevice, NULL, NULL, 0, NULL);

				// calculate overall dimensions for requested client area
				unsigned int winWidth, winHeight;
				adjustWindow(width, height, &winWidth, &winHeight);

				// deal with centering when switching down to smaller resolution
				memset(&monitorInfo, 0, sizeof(MONITORINFO));
				monitorInfo.cbSize = sizeof(MONITORINFO);
				GetMonitorInfo(hMonitor, &monitorInfo);

				// Reset to default style
				SetWindowLongPtr(mHWnd, GWL_STYLE, getWindowStyle(mIsFullScreen));

				LONG screenw = monitorInfo.rcWork.right  - monitorInfo.rcWork.left;
				LONG screenh = monitorInfo.rcWork.bottom - monitorInfo.rcWork.top;

				mWidth = winWidth;
				mHeight = winHeight;
				mLeft = screenw > winWidth ? ((screenw - winWidth) / 2) : 0;
				mTop = screenh > winHeight ? ((screenh - winHeight) / 2) : 0;

				flag = SWP_DRAWFRAME | SWP_FRAMECHANGED | SWP_NOACTIVATE;
			}

			// Notify viewports of resize
			ViewportList::iterator it = mViewportList.begin();
			while( it != mViewportList.end() )
				(*it++).second->_updateDimensions();

			// Window reposition and dim
			SetWindowPos(mHWnd, HWND_NOTOPMOST, mLeft, mTop, mWidth, mHeight, flag);
		}
	}
0 x

bstone
OGRE Expert User
OGRE Expert User
Posts: 1920
Joined: Sun Feb 19, 2012 9:24 pm
Location: Russia

Re: setFullscreen Win32Window bugfix

Post by bstone » Thu Oct 25, 2012 6:26 am

Nice, I'll give that a try when I have time. I remember that I had that problem with OpenGL. Thanks for sharing. Here's the proper way of submitting a patch described in more detail: Submit Patch
0 x

ccamporesi
Gnoblar
Posts: 2
Joined: Wed Oct 24, 2012 12:16 am

Re: setFullscreen Win32Window bugfix

Post by ccamporesi » Thu Oct 25, 2012 7:33 pm

If I recall correctly the OpenGL RW has problem on addressing windows in different screen if multiple X clients are running.
The way I usually overcome this problem is specifying the DISPLAY global var before the application starts.
If the system is configuered as multidisplay with desktop extension setfullscreen works correctly. You just have to reposition
the window in the right monitor then call setfullscreen (1.7.4 and old 1.8.1 not tested yet).
Thanks for the info I will follow the guidelines next time.
0 x

Post Reply