From 4826072e24eb7393cc2564d0da9d95f471cb14c9 Mon Sep 17 00:00:00 2001 From: "John F. Fay" Date: Fri, 29 Jan 2010 05:05:14 +0000 Subject: [PATCH] Implementing Windows multiple-display patch per e-mail from Eero Paharre dated 1/25/10, 11:54 AM git-svn-id: svn+ssh://svn.code.sf.net/p/freeglut/code/trunk/freeglut/freeglut@872 7f0cb862-5218-0410-a997-914c9d46530a --- src/freeglut_gamemode.c | 12 ++++--- src/freeglut_init.c | 25 ++++++++++++-- src/freeglut_internal.h | 1 + src/freeglut_window.c | 83 +++++++++++++++++++++++++++++++++++++++-------- 4 files changed, 101 insertions(+), 20 deletions(-) diff --git a/src/freeglut_gamemode.c b/src/freeglut_gamemode.c index 67159e1..3172dfc 100644 --- a/src/freeglut_gamemode.c +++ b/src/freeglut_gamemode.c @@ -110,7 +110,7 @@ static void fghRememberState( void ) /* hack to get around my stupid cross-gcc headers */ #define FREEGLUT_ENUM_CURRENT_SETTINGS -1 - EnumDisplaySettings( NULL, FREEGLUT_ENUM_CURRENT_SETTINGS, + EnumDisplaySettings( fgDisplay.DisplayName, FREEGLUT_ENUM_CURRENT_SETTINGS, &fgDisplay.DisplayMode ); /* Make sure we will be restoring all settings needed */ @@ -205,7 +205,7 @@ static void fghRestoreState( void ) #elif TARGET_HOST_MS_WINDOWS /* Restore the previously rememebered desktop display settings */ - ChangeDisplaySettings( &fgDisplay.DisplayMode, 0 ); + ChangeDisplaySettingsEx( fgDisplay.DisplayName,&fgDisplay.DisplayMode, 0,0,0 ); #endif } @@ -323,7 +323,7 @@ static GLboolean fghChangeDisplayMode( GLboolean haveToTest ) success = GL_FALSE; - EnumDisplaySettings( NULL, -1, &devMode ); + EnumDisplaySettings( fgDisplay.DisplayName, -1, &devMode ); devMode.dmFields |= DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY; devMode.dmPelsWidth = fgState.GameModeSize.X; @@ -332,13 +332,13 @@ static GLboolean fghChangeDisplayMode( GLboolean haveToTest ) devMode.dmDisplayFrequency = fgState.GameModeRefresh; devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT | DM_BITSPERPEL | DM_DISPLAYFREQUENCY; - switch ( ChangeDisplaySettingsEx(NULL, &devMode, NULL, haveToTest ? CDS_TEST : CDS_FULLSCREEN , NULL) ) + switch ( ChangeDisplaySettingsEx(fgDisplay.DisplayName, &devMode, NULL, haveToTest ? CDS_TEST : CDS_FULLSCREEN , NULL) ) { case DISP_CHANGE_SUCCESSFUL: success = GL_TRUE; /* update vars in case if windows switched to proper mode */ - EnumDisplaySettings( NULL, FREEGLUT_ENUM_CURRENT_SETTINGS, &devMode ); + EnumDisplaySettings( fgDisplay.DisplayName, FREEGLUT_ENUM_CURRENT_SETTINGS, &devMode ); fgState.GameModeSize.X = devMode.dmPelsWidth; fgState.GameModeSize.Y = devMode.dmPelsHeight; fgState.GameModeDepth = devMode.dmBitsPerPel; @@ -410,6 +410,8 @@ void FGAPIENTRY glutGameModeString( const char* string ) fgState.GameModeRefresh = refresh; } + + /* * Enters the game mode */ diff --git a/src/freeglut_init.c b/src/freeglut_init.c index 8b9d34d..c96ca10 100644 --- a/src/freeglut_init.c +++ b/src/freeglut_init.c @@ -311,7 +311,7 @@ static void fghInitialize( const char* displayName ) /* What we need to do is to initialize the fgDisplay global structure here. */ fgDisplay.Instance = GetModuleHandle( NULL ); - + fgDisplay.DisplayName=strdup(displayName); atom = GetClassInfo( fgDisplay.Instance, _T("FREEGLUT"), &wc ); if( atom == 0 ) @@ -363,7 +363,23 @@ static void fghInitialize( const char* displayName ) ReleaseDC( desktop, context ); } - + /* If we have a DisplayName try to use it for metrics */ + if( fgDisplay.DisplayName ) + { + HDC context = CreateDC(fgDisplay.DisplayName,0,0,0); + if( context ) + { + fgDisplay.ScreenWidth = GetDeviceCaps( context, HORZRES ); + fgDisplay.ScreenHeight = GetDeviceCaps( context, VERTRES ); + fgDisplay.ScreenWidthMM = GetDeviceCaps( context, HORZSIZE ); + fgDisplay.ScreenHeightMM = GetDeviceCaps( context, VERTSIZE ); + DeleteDC(context); + } + else + fgWarning("fghInitialize: " + "CreateDC failed, Screen size info may be incorrect"); + + } /* Set the timer granularity to 1 ms */ timeBeginPeriod ( 1 ); @@ -489,6 +505,11 @@ void fgDeinitialize( void ) XCloseDisplay( fgDisplay.Display ); #elif TARGET_HOST_MS_WINDOWS + if( fgDisplay.DisplayName ) + { + free( fgDisplay.DisplayName ); + fgDisplay.DisplayName = NULL; + } /* Reset the timer granularity */ timeEndPeriod ( 1 ); diff --git a/src/freeglut_internal.h b/src/freeglut_internal.h index 74e454a..4172112 100644 --- a/src/freeglut_internal.h +++ b/src/freeglut_internal.h @@ -362,6 +362,7 @@ struct tagSFG_Display #elif TARGET_HOST_MS_WINDOWS HINSTANCE Instance; /* The application's instance */ DEVMODE DisplayMode; /* Desktop's display settings */ + char *DisplayName; /* Display name for multi display support*/ #endif diff --git a/src/freeglut_window.c b/src/freeglut_window.c index 232f4ea..6244c61 100644 --- a/src/freeglut_window.c +++ b/src/freeglut_window.c @@ -825,6 +825,55 @@ void fgSetWindow ( SFG_Window *window ) fgStructure.CurrentWindow = window; } +#if TARGET_HOST_MS_WINDOWS + +typedef struct { + int *x; + int *y; + const char *name; +}m_proc_t ; + +static BOOL CALLBACK m_proc(HMONITOR mon, + HDC hdc, + LPRECT rect, + LPARAM data) +{ + m_proc_t *dp=(m_proc_t *)data; + MONITORINFOEX info; + BOOL res; + info.cbSize=sizeof(info); + res=GetMonitorInfo(mon,(LPMONITORINFO)&info); + if( res ) + { + if( !strcmp(dp->name,info.szDevice) ) + { + *(dp->x)=info.rcMonitor.left; + *(dp->y)=info.rcMonitor.top; + return FALSE; + } + } + return TRUE; +} + +/* + * this function is only used in fgOpenWindow. Currently it only sets + * its output parameters, if the DisplayName is set in fgDisplay + * (and if it is able to recognize the display) +*/ + +static void get_display_origin(int *xp,int *yp) +{ + if( fgDisplay.DisplayName ) + { + m_proc_t st; + st.x=xp; + st.y=yp; + st.name=fgDisplay.DisplayName; + EnumDisplayMonitors(0,0,m_proc,(LPARAM)&st); + } +} +#endif + /* @@ -1137,17 +1186,24 @@ void fgOpenWindow( SFG_Window* window, const char* title, UpdateWindow(window->Window.Handle); } #else - window->Window.Handle = CreateWindowEx( - exFlags, - _T("FREEGLUT"), - title, - flags, - x, y, w, h, - (HWND) window->Parent == NULL ? NULL : window->Parent->Window.Handle, - (HMENU) NULL, - fgDisplay.Instance, - (LPVOID) window - ); + { + /* xoff and yoff are used to place window relative to current display */ + /* The operation of gamemode also depends on this */ + int xoff=0,yoff=0; + get_display_origin(&xoff,&yoff); + + window->Window.Handle = CreateWindowEx( + exFlags, + _T("FREEGLUT"), + title, + flags, + x+xoff, y+yoff, w, h, + (HWND) window->Parent == NULL ? NULL : window->Parent->Window.Handle, + (HMENU) NULL, + fgDisplay.Instance, + (LPVOID) window + ); + } #endif /* defined(_WIN32_WCE) */ if( !( window->Window.Handle ) ) @@ -1680,8 +1736,9 @@ void FGAPIENTRY glutFullScreen( void ) rect.left = 0; rect.top = 0; - rect.right = fgDisplay.ScreenWidth; - rect.bottom = fgDisplay.ScreenHeight; + get_display_origin(&rect.left,&rect.top); + rect.right = fgDisplay.ScreenWidth+rect.left; + rect.bottom = fgDisplay.ScreenHeight+rect.top; AdjustWindowRect ( &rect, WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN, FALSE ); -- 1.7.10.4