mirror of
https://bitbucket.org/CPMADevs/cnq3
synced 2025-01-21 07:40:48 +00:00
with r_mode 1, tabbing out of the game will restore display settings on the desktop
fixed window restore after minimizing when clicking the task bar or using alt-tab fixed r_mode 1 on secondary monitors fixed in_mouse 2 input on secondary monitors fixed the cursor sometimes staying visible and unclipped when restoring the window
This commit is contained in:
parent
d9bacec921
commit
c3ee3f2a4d
6 changed files with 158 additions and 83 deletions
|
@ -38,7 +38,8 @@ typedef struct
|
|||
HGLRC hGLRC;
|
||||
HINSTANCE hinstOpenGL;
|
||||
int desktopBPP;
|
||||
qbool cdsFullscreen;
|
||||
qbool cdsDevModeValid;
|
||||
DEVMODE cdsDevMode; // Custom device mode for full-screen with r_mode 1.
|
||||
qbool pixelFormatSet;
|
||||
int nPendingPF;
|
||||
} glwstate_t;
|
||||
|
|
|
@ -471,7 +471,7 @@ static qbool GLW_CreateWindow( int width, int height, int colorbits )
|
|||
const int w = r.right - r.left;
|
||||
const int h = r.bottom - r.top;
|
||||
|
||||
const RECT monRect = g_wv.monitorRects[g_wv.monitor];
|
||||
const RECT& monRect = g_wv.monitorRects[g_wv.monitor];
|
||||
|
||||
int dx = 0;
|
||||
int dy = 0;
|
||||
|
@ -517,19 +517,72 @@ static qbool GLW_CreateWindow( int width, int height, int colorbits )
|
|||
}
|
||||
|
||||
|
||||
static qbool GLW_Fullscreen( DEVMODE& dm )
|
||||
static const char* GLW_GetCurrentDisplayDeviceName()
|
||||
{
|
||||
int cds = ChangeDisplaySettings( &dm, CDS_FULLSCREEN );
|
||||
static char deviceName[CCHDEVICENAME + 1];
|
||||
|
||||
if (cds == DISP_CHANGE_SUCCESSFUL)
|
||||
const HMONITOR hMonitor = g_wv.hMonitors[g_wv.monitor];
|
||||
if ( hMonitor == NULL )
|
||||
return NULL;
|
||||
|
||||
MONITORINFOEXA info;
|
||||
ZeroMemory( &info, sizeof(info) );
|
||||
info.cbSize = sizeof(info);
|
||||
if ( GetMonitorInfoA(hMonitor, &info) == 0 )
|
||||
return NULL;
|
||||
|
||||
Q_strncpyz( deviceName, info.szDevice, sizeof(deviceName) );
|
||||
|
||||
return deviceName;
|
||||
}
|
||||
|
||||
|
||||
static void GLW_UpdateMonitorRect( const char* deviceName )
|
||||
{
|
||||
if ( deviceName == NULL )
|
||||
return;
|
||||
|
||||
DEVMODEA dm;
|
||||
ZeroMemory( &dm, sizeof(dm) );
|
||||
dm.dmSize = sizeof(dm);
|
||||
if ( EnumDisplaySettingsExA(deviceName, ENUM_CURRENT_SETTINGS, &dm, 0) == 0 )
|
||||
return;
|
||||
|
||||
if ( dm.dmPelsWidth == 0 || dm.dmPelsHeight == 0 )
|
||||
return;
|
||||
|
||||
// Normally, we should check dm.dmFields for the following flags:
|
||||
// DM_POSITION DM_PELSWIDTH DM_PELSHEIGHT
|
||||
// EnumDisplaySettingsExA doesn't always set up the flags properly.
|
||||
|
||||
RECT& rect = g_wv.monitorRects[g_wv.monitor];
|
||||
rect.left = dm.dmPosition.x;
|
||||
rect.top = dm.dmPosition.y;
|
||||
rect.right = dm.dmPosition.x + dm.dmPelsWidth;
|
||||
rect.bottom = dm.dmPosition.y + dm.dmPelsHeight;
|
||||
}
|
||||
|
||||
|
||||
static qbool GLW_SetDisplaySettings( DEVMODE& dm )
|
||||
{
|
||||
const char* deviceName = GLW_GetCurrentDisplayDeviceName();
|
||||
const int ec = ChangeDisplaySettingsExA( deviceName, &dm, NULL, CDS_FULLSCREEN, NULL );
|
||||
if ( ec == DISP_CHANGE_SUCCESSFUL )
|
||||
{
|
||||
glw_state.cdsDevMode = dm;
|
||||
glw_state.cdsDevModeValid = qtrue;
|
||||
GLW_UpdateMonitorRect( deviceName );
|
||||
return qtrue;
|
||||
}
|
||||
|
||||
ri.Printf( PRINT_ALL, "...CDS: %ix%i (C%i) failed: ", dm.dmPelsWidth, dm.dmPelsHeight, dm.dmBitsPerPel );
|
||||
glw_state.cdsDevModeValid = qfalse;
|
||||
|
||||
ri.Printf( PRINT_ALL, "...CDS: %ix%i (C%i) failed: ", (int)dm.dmPelsWidth, (int)dm.dmPelsHeight, (int)dm.dmBitsPerPel );
|
||||
|
||||
#define CDS_ERROR(x) case x: ri.Printf( PRINT_ALL, #x##"\n" ); break;
|
||||
switch (cds) {
|
||||
switch (ec) {
|
||||
default:
|
||||
ri.Printf( PRINT_ALL, "unknown error %d\n", cds );
|
||||
ri.Printf( PRINT_ALL, "unknown error %d\n", ec );
|
||||
break;
|
||||
CDS_ERROR( DISP_CHANGE_RESTART );
|
||||
CDS_ERROR( DISP_CHANGE_BADPARAM );
|
||||
|
@ -544,6 +597,31 @@ static qbool GLW_Fullscreen( DEVMODE& dm )
|
|||
}
|
||||
|
||||
|
||||
static void GLW_ResetDisplaySettings( qbool invalidate )
|
||||
{
|
||||
const char* deviceName = GLW_GetCurrentDisplayDeviceName();
|
||||
ChangeDisplaySettingsEx( deviceName, NULL, NULL, 0, NULL );
|
||||
GLW_UpdateMonitorRect( deviceName );
|
||||
if ( invalidate )
|
||||
glw_state.cdsDevModeValid = qfalse;
|
||||
}
|
||||
|
||||
|
||||
void WIN_SetGameDisplaySettings()
|
||||
{
|
||||
if ( glw_state.cdsDevModeValid )
|
||||
GLW_SetDisplaySettings( glw_state.cdsDevMode );
|
||||
}
|
||||
|
||||
|
||||
void WIN_SetDesktopDisplaySettings()
|
||||
{
|
||||
// We don't invalidate glw_state.cdsDevModeValid so we can
|
||||
// return to the previous mode later.
|
||||
GLW_ResetDisplaySettings( qfalse );
|
||||
}
|
||||
|
||||
|
||||
static qbool GLW_SetMode( qbool cdsFullscreen )
|
||||
{
|
||||
HDC hDC = GetDC( GetDesktopWindow() );
|
||||
|
@ -553,7 +631,7 @@ static qbool GLW_SetMode( qbool cdsFullscreen )
|
|||
glInfo.isFullscreen = cdsFullscreen;
|
||||
WIN_UpdateMonitorIndexFromCvar();
|
||||
if ( !R_GetModeInfo( &glConfig.vidWidth, &glConfig.vidHeight, &glConfig.windowAspect ) ) {
|
||||
const RECT monRect = g_wv.monitorRects[g_wv.monitor];
|
||||
const RECT& monRect = g_wv.monitorRects[g_wv.monitor];
|
||||
glConfig.vidWidth = monRect.right - monRect.left;
|
||||
glConfig.vidHeight = monRect.bottom - monRect.top;
|
||||
glConfig.windowAspect = (float)glConfig.vidWidth / glConfig.vidHeight;
|
||||
|
@ -562,10 +640,10 @@ static qbool GLW_SetMode( qbool cdsFullscreen )
|
|||
//ri.Printf( PRINT_DEVELOPER, "...setting mode %dx%d %s\n", glConfig.vidWidth, glConfig.vidHeight, cdsFullscreen ? "FS" : "W" );
|
||||
|
||||
DEVMODE dm;
|
||||
memset( &dm, 0, sizeof( dm ) );
|
||||
ZeroMemory( &dm, sizeof( dm ) );
|
||||
dm.dmSize = sizeof( dm );
|
||||
|
||||
if (cdsFullscreen != glw_state.cdsFullscreen) {
|
||||
if (cdsFullscreen != glw_state.cdsDevModeValid) {
|
||||
if (cdsFullscreen) {
|
||||
dm.dmPelsWidth = glConfig.vidWidth;
|
||||
dm.dmPelsHeight = glConfig.vidHeight;
|
||||
|
@ -581,25 +659,23 @@ static qbool GLW_SetMode( qbool cdsFullscreen )
|
|||
dm.dmFields |= DM_BITSPERPEL;
|
||||
}
|
||||
|
||||
glInfo.isFullscreen = qtrue;
|
||||
glw_state.cdsFullscreen = qtrue;
|
||||
const RECT& monRect = g_wv.monitorRects[g_wv.monitor];
|
||||
dm.dmPosition.x = monRect.left;
|
||||
dm.dmPosition.y = monRect.top;
|
||||
dm.dmFields |= DM_POSITION;
|
||||
|
||||
if (!GLW_Fullscreen( dm )) {
|
||||
glInfo.isFullscreen = qfalse;
|
||||
glw_state.cdsFullscreen = qfalse;
|
||||
}
|
||||
glInfo.isFullscreen = GLW_SetDisplaySettings( dm );
|
||||
}
|
||||
else
|
||||
{
|
||||
ChangeDisplaySettings( 0, 0 );
|
||||
glw_state.cdsFullscreen = qfalse;
|
||||
GLW_ResetDisplaySettings( qtrue );
|
||||
}
|
||||
}
|
||||
|
||||
if (!GLW_CreateWindow( glConfig.vidWidth, glConfig.vidHeight, glConfig.colorBits ))
|
||||
return qfalse;
|
||||
|
||||
if (EnumDisplaySettings( NULL, ENUM_CURRENT_SETTINGS, &dm ))
|
||||
if (EnumDisplaySettingsA( GLW_GetCurrentDisplayDeviceName(), ENUM_CURRENT_SETTINGS, &dm ))
|
||||
glInfo.displayFrequency = dm.dmDisplayFrequency;
|
||||
|
||||
return qtrue;
|
||||
|
@ -668,7 +744,7 @@ static qbool GLW_LoadOpenGL()
|
|||
// load the driver and bind our function pointers to it
|
||||
if ( QGL_Init( OPENGL_DRIVER_NAME ) ) {
|
||||
// create the window and set up the context
|
||||
if ( GLW_SetMode( (qbool)r_fullscreen->integer ) ) {
|
||||
if ( GLW_SetMode( (qbool)!!r_fullscreen->integer ) ) {
|
||||
return qtrue;
|
||||
}
|
||||
}
|
||||
|
@ -783,11 +859,10 @@ void GLimp_Shutdown()
|
|||
}
|
||||
|
||||
// reset display settings
|
||||
if ( glw_state.cdsFullscreen )
|
||||
if ( glw_state.cdsDevModeValid )
|
||||
{
|
||||
ri.Printf( PRINT_DEVELOPER, "...resetting display\n" );
|
||||
ChangeDisplaySettings( 0, 0 );
|
||||
glw_state.cdsFullscreen = qfalse;
|
||||
GLW_ResetDisplaySettings( qtrue );
|
||||
}
|
||||
|
||||
// shutdown QGL subsystem
|
||||
|
|
|
@ -27,7 +27,6 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
struct Mouse {
|
||||
virtual qbool Init() { return qtrue; }
|
||||
virtual qbool Activate( qbool active );
|
||||
virtual void OnWindowMoved() {}
|
||||
virtual void Shutdown() {}
|
||||
virtual qbool ProcessMessage( UINT msg, WPARAM wParam, LPARAM lParam ) { return qfalse; } // returns true if the event was handled
|
||||
|
||||
|
@ -91,17 +90,14 @@ qbool rawmouse_t::Init()
|
|||
|
||||
qbool rawmouse_t::Activate( qbool active )
|
||||
{
|
||||
// RIDEV_NOLEGACY means we only get WM_INPUT and not WM_LBUTTONDOWN etc
|
||||
RAWINPUTDEVICE rid;
|
||||
rid.usUsagePage = 1;
|
||||
rid.usUsage = 2;
|
||||
rid.dwFlags = active ? RIDEV_NOLEGACY : RIDEV_REMOVE;
|
||||
rid.hwndTarget = NULL;
|
||||
|
||||
rid.usUsagePage = 0x01;
|
||||
rid.usUsage = 0x02; // page 1 item 2 = mouse, gg constants you asswipes >:(
|
||||
if (active)
|
||||
rid.dwFlags = RIDEV_NOLEGACY;
|
||||
else
|
||||
rid.dwFlags = RIDEV_REMOVE;
|
||||
rid.hwndTarget = 0;
|
||||
|
||||
return RegisterRawInputDevices( &rid, 1, sizeof(rid) );
|
||||
return !!RegisterRawInputDevices( &rid, 1, sizeof(rid) );
|
||||
}
|
||||
|
||||
|
||||
|
@ -162,7 +158,6 @@ qbool rawmouse_t::ProcessMessage( UINT msg, WPARAM wParam, LPARAM lParam )
|
|||
|
||||
struct winmouse_t : public Mouse {
|
||||
virtual qbool Activate( qbool active );
|
||||
virtual void OnWindowMoved();
|
||||
virtual qbool ProcessMessage( UINT msg, WPARAM wParam, LPARAM lParam );
|
||||
|
||||
void UpdateWindowCenter();
|
||||
|
@ -176,14 +171,9 @@ static winmouse_t winmouse;
|
|||
|
||||
void winmouse_t::UpdateWindowCenter()
|
||||
{
|
||||
const int sw = GetSystemMetrics( SM_CXSCREEN );
|
||||
const int sh = GetSystemMetrics( SM_CYSCREEN );
|
||||
|
||||
RECT rc;
|
||||
GetWindowRect( g_wv.hWnd, &rc );
|
||||
|
||||
window_center_x = ( max(rc.left, 0) + min(rc.right, sw) ) / 2;
|
||||
window_center_y = ( max(rc.top, 0) + min(rc.bottom, sh) ) / 2;
|
||||
const RECT& rect = g_wv.monitorRects[g_wv.monitor];
|
||||
window_center_x = (int)( rect.left + rect.right ) / 2;
|
||||
window_center_y = (int)( rect.top + rect.bottom ) / 2;
|
||||
}
|
||||
|
||||
|
||||
|
@ -201,17 +191,13 @@ qbool winmouse_t::Activate( qbool _active )
|
|||
}
|
||||
|
||||
|
||||
void winmouse_t::OnWindowMoved()
|
||||
{
|
||||
UpdateWindowCenter();
|
||||
}
|
||||
|
||||
|
||||
qbool winmouse_t::ProcessMessage( UINT msg, WPARAM wParam, LPARAM lParam )
|
||||
{
|
||||
if ( !active )
|
||||
return qfalse;
|
||||
|
||||
UpdateWindowCenter();
|
||||
|
||||
#define QUEUE_WM_BUTTON( qbutton, mask ) \
|
||||
Sys_QueEvent( g_wv.sysMsgTime, SE_KEY, qbutton, (wParam & mask), 0, NULL );
|
||||
|
||||
|
@ -352,14 +338,8 @@ void IN_Shutdown()
|
|||
}
|
||||
|
||||
|
||||
// called when the window gains or loses focus or changes in some way
|
||||
// the window may have been destroyed and recreated between a deactivate and an activate
|
||||
|
||||
void IN_Activate( qbool active )
|
||||
void IN_SetCursorSettings( qbool active )
|
||||
{
|
||||
if ( !mouse || !mouse->Mouse::Activate( active ) )
|
||||
return;
|
||||
|
||||
if (active) {
|
||||
while (ShowCursor(FALSE) >= 0)
|
||||
;
|
||||
|
@ -373,17 +353,20 @@ void IN_Activate( qbool active )
|
|||
ClipCursor( NULL );
|
||||
ReleaseCapture();
|
||||
}
|
||||
|
||||
mouse->Activate( active );
|
||||
}
|
||||
|
||||
|
||||
void IN_WindowMoved()
|
||||
// called when the window gains or loses focus or changes in some way
|
||||
// the window may have been destroyed and recreated between a deactivate and an activate
|
||||
|
||||
void IN_Activate( qbool active )
|
||||
{
|
||||
if (!mouse)
|
||||
if ( !mouse || !mouse->Mouse::Activate( active ) )
|
||||
return;
|
||||
|
||||
mouse->OnWindowMoved();
|
||||
IN_SetCursorSettings( active );
|
||||
|
||||
mouse->Activate( active );
|
||||
}
|
||||
|
||||
|
||||
|
@ -403,12 +386,7 @@ void IN_Frame()
|
|||
if (!mouse)
|
||||
return;
|
||||
|
||||
if (!IN_ShouldBeActive()) {
|
||||
IN_Activate( qfalse );
|
||||
return;
|
||||
}
|
||||
|
||||
IN_Activate( qtrue );
|
||||
IN_Activate( IN_ShouldBeActive() );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -33,8 +33,8 @@ void Conbuf_AppendText( const char *msg );
|
|||
|
||||
|
||||
void IN_Init();
|
||||
void IN_SetCursorSettings( qbool active );
|
||||
void IN_Activate( qbool active );
|
||||
void IN_WindowMoved();
|
||||
qbool IN_ShouldBeActive();
|
||||
qbool IN_ProcessMessage( UINT msg, WPARAM wParam, LPARAM lParam ); // returns true if the event was handled
|
||||
void IN_Frame();
|
||||
|
@ -45,6 +45,8 @@ void WIN_UpdateMonitorIndexFromMainWindow();
|
|||
void WIN_UpdateResolution( int width, int height );
|
||||
void WIN_RegisterLastValidHotKey();
|
||||
void WIN_UnregisterHotKey();
|
||||
void WIN_SetGameDisplaySettings();
|
||||
void WIN_SetDesktopDisplaySettings();
|
||||
|
||||
void SNDDMA_Activate();
|
||||
|
||||
|
@ -62,7 +64,6 @@ typedef struct
|
|||
HWND hWnd;
|
||||
HINSTANCE hInstance;
|
||||
qbool activeApp;
|
||||
qbool isMinimized;
|
||||
|
||||
// when we get a windows message, we store the time off
|
||||
// using Sys_Milliseconds
|
||||
|
|
|
@ -605,7 +605,7 @@ void WIN_UpdateMonitorIndexFromCvar()
|
|||
return;
|
||||
}
|
||||
|
||||
g_wv.monitor = monitor - 1;
|
||||
g_wv.monitor = Com_ClampInt( 0, g_wv.monitorCount - 1, monitor - 1 );
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
|||
|
||||
#include "../client/client.h"
|
||||
#include "win_local.h"
|
||||
#include "glw_win.h"
|
||||
|
||||
|
||||
// Console variables that we need to access from this module
|
||||
|
@ -72,19 +73,19 @@ static void WIN_EnableAltTab()
|
|||
}
|
||||
|
||||
|
||||
static void VID_AppActivate( BOOL fActive, BOOL minimize )
|
||||
static void WIN_AppActivate( BOOL fActive, BOOL fMinimized )
|
||||
{
|
||||
if (r_fullscreen->integer)
|
||||
SetWindowPos( g_wv.hWnd, fActive ? HWND_TOPMOST : HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
|
||||
const qbool active = fActive && !fMinimized;
|
||||
|
||||
g_wv.isMinimized = (minimize == TRUE);
|
||||
if (r_fullscreen->integer)
|
||||
SetWindowPos( g_wv.hWnd, active ? HWND_TOPMOST : HWND_BOTTOM, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE );
|
||||
|
||||
Com_DPrintf("VID_AppActivate: %i\n", fActive );
|
||||
|
||||
Key_ClearStates(); // FIXME!!!
|
||||
|
||||
// we don't want to act like we're active if we're minimized
|
||||
g_wv.activeApp = (fActive && !g_wv.isMinimized);
|
||||
g_wv.activeApp = active;
|
||||
|
||||
IN_Activate( IN_ShouldBeActive() );
|
||||
}
|
||||
|
@ -268,7 +269,7 @@ LRESULT CALLBACK MainWndProc (
|
|||
break;
|
||||
|
||||
case WM_ACTIVATE:
|
||||
VID_AppActivate( (LOWORD(wParam) != WA_INACTIVE), (BOOL)HIWORD(wParam) );
|
||||
WIN_AppActivate( (LOWORD(wParam) != WA_INACTIVE), !!(BOOL)HIWORD(wParam) );
|
||||
SNDDMA_Activate();
|
||||
break;
|
||||
|
||||
|
@ -285,17 +286,13 @@ LRESULT CALLBACK MainWndProc (
|
|||
r.bottom = 1;
|
||||
AdjustWindowRect( &r, GetWindowLong( hWnd, GWL_STYLE ), FALSE );
|
||||
|
||||
const RECT monRect = g_wv.monitorRects[g_wv.monitor];
|
||||
const RECT& monRect = g_wv.monitorRects[g_wv.monitor];
|
||||
const int x = LOWORD( lParam );
|
||||
const int y = HIWORD( lParam );
|
||||
Cvar_SetValue( "vid_xpos", x + r.left - monRect.left );
|
||||
Cvar_SetValue( "vid_ypos", y + r.top - monRect.top );
|
||||
vid_xpos->modified = qfalse;
|
||||
vid_ypos->modified = qfalse;
|
||||
if ( g_wv.activeApp )
|
||||
{
|
||||
IN_WindowMoved();
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -353,6 +350,29 @@ LRESULT CALLBACK MainWndProc (
|
|||
}
|
||||
break;
|
||||
|
||||
case WM_SETFOCUS:
|
||||
if ( glw_state.cdsDevModeValid ) // is there a valid mode to restore?
|
||||
{
|
||||
WIN_SetGameDisplaySettings();
|
||||
if ( glw_state.cdsDevModeValid ) // was the mode successfully restored?
|
||||
{
|
||||
const RECT& rect = g_wv.monitorRects[g_wv.monitor];
|
||||
const DEVMODE& dm = glw_state.cdsDevMode;
|
||||
SetWindowPos( hWnd, NULL, (int)rect.left, (int)rect.top, (int)dm.dmPelsWidth, (int)dm.dmPelsHeight, SWP_NOZORDER );
|
||||
}
|
||||
}
|
||||
g_wv.activeApp = (qbool)!IsIconic( hWnd );
|
||||
IN_SetCursorSettings( IN_ShouldBeActive() );
|
||||
|
||||
break;
|
||||
|
||||
case WM_KILLFOCUS:
|
||||
g_wv.activeApp = qfalse;
|
||||
IN_SetCursorSettings( qfalse );
|
||||
if ( glw_state.cdsDevModeValid )
|
||||
WIN_SetDesktopDisplaySettings();
|
||||
break;
|
||||
|
||||
default:
|
||||
// this is complicated because Win32 seems to pack multiple mouse events into
|
||||
// one update sometimes, so we always check all states and look for events
|
||||
|
|
Loading…
Reference in a new issue