From 302aba84c596ae6bb1bb71f3353d151d7bf050cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Herm=C3=A8s=20B=C3=A9lusca-Ma=C3=AFto?= Date: Sun, 13 Oct 2013 00:11:38 +0000 Subject: [PATCH] [CONSRV] Implement a basic full-screen mode for the console. Still Work-In-Progress. See r59099 for more details. svn path=/trunk/; revision=60635 --- .../winsrv/consrv/frontends/gui/guisettings.c | 7 +- .../winsrv/consrv/frontends/gui/guisettings.h | 3 + .../winsrv/consrv/frontends/gui/guiterm.c | 188 +++++++++++++++--- .../user/winsrv/consrv/include/conio.h | 2 +- 4 files changed, 169 insertions(+), 31 deletions(-) diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c index 6dac93342aa..c579fb5befe 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c +++ b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.c @@ -19,6 +19,7 @@ VOID GuiConsoleMoveWindow(PGUI_CONSOLE_DATA GuiData); +VOID SwitchFullScreen(PGUI_CONSOLE_DATA GuiData, BOOL FullScreen); /* FUNCTIONS ******************************************************************/ @@ -507,8 +508,10 @@ GuiApplyUserSettings(PGUI_CONSOLE_DATA GuiData, /* * Apply full-screen mode. */ - GuiData->GuiInfo.FullScreen = GuiInfo->FullScreen; - // TODO: Apply it really + if (GuiInfo->FullScreen != GuiData->GuiInfo.FullScreen) + { + SwitchFullScreen(GuiData, GuiInfo->FullScreen); + } } /* diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.h b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.h index 2a3c6163237..9e7627f3d70 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.h +++ b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guisettings.h @@ -49,6 +49,9 @@ typedef struct _GUI_CONSOLE_DATA HICON hIcon; /* Handle to the console's icon (big) */ HICON hIconSm; /* Handle to the console's icon (small) */ + LONG_PTR WndStyle; + LONG_PTR WndStyleEx; + HPALETTE hSysPalette; /* Handle to the original system palette */ /*** The following may be put per-screen-buffer !! ***/ diff --git a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c index fc2a711e7f4..8587d985335 100644 --- a/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c +++ b/reactos/win32ss/user/winsrv/consrv/frontends/gui/guiterm.c @@ -12,7 +12,6 @@ /* INCLUDES *******************************************************************/ #define COBJMACROS -#define NONAMELESSUNION #include "consrv.h" #include "include/conio.h" @@ -468,46 +467,147 @@ GuiConsoleResizeWindow(PGUI_CONSOLE_DATA GuiData) // to: InvalidateRect(GuiData->hWindow, NULL, TRUE); } + + +static BOOL +EnterFullScreen(PGUI_CONSOLE_DATA GuiData) +{ + DEVMODEW DevMode; + + ZeroMemory(&DevMode, sizeof(DevMode)); + DevMode.dmSize = sizeof(DevMode); + + // DevMode.dmDisplayFixedOutput = DMDFO_CENTER; // DMDFO_STRETCH // DMDFO_DEFAULT + // DevMode.dmDisplayFlags = DMDISPLAYFLAGS_TEXTMODE; + DevMode.dmPelsWidth = 640; // GuiData->ActiveBuffer->ViewSize.X * GuiData->CharWidth; + DevMode.dmPelsHeight = 480; // GuiData->ActiveBuffer->ViewSize.Y * GuiData->CharHeight; + // DevMode.dmBitsPerPel = 32; + DevMode.dmFields = /* DM_DISPLAYFIXEDOUTPUT | DM_DISPLAYFLAGS | DM_BITSPERPEL | */ DM_PELSWIDTH | DM_PELSHEIGHT; + + return (ChangeDisplaySettingsW(&DevMode, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL); +} + +static BOOL +LeaveFullScreen(PGUI_CONSOLE_DATA GuiData) +{ + return (ChangeDisplaySettingsW(NULL, CDS_RESET) == DISP_CHANGE_SUCCESSFUL); +} + +static VOID +GuiConsoleResize(PGUI_CONSOLE_DATA GuiData, WPARAM wParam, LPARAM lParam); + +VOID +SwitchFullScreen(PGUI_CONSOLE_DATA GuiData, BOOL FullScreen) +{ + PCONSOLE Console = GuiData->Console; + + /* + * See: + * http://stackoverflow.com/questions/2382464/win32-full-screen-and-hiding-taskbar + * http://stackoverflow.com/questions/3549148/fullscreen-management-with-winapi + * http://blogs.msdn.com/b/oldnewthing/archive/2010/04/12/9994016.aspx + * http://blogs.msdn.com/b/oldnewthing/archive/2005/05/05/414910.aspx + * http://stackoverflow.com/questions/1400654/how-do-i-put-my-opengl-app-into-fullscreen-mode + * http://nehe.gamedev.net/tutorial/creating_an_opengl_window_win32/13001/ + * http://www.reocities.com/pcgpe/dibs.html + */ + + if (FullScreen) + { + SendMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_MINIMIZE, 0); + + /* Switch to full screen */ + if (EnterFullScreen(GuiData)) + { + /* Save the new state */ + GuiData->GuiInfo.FullScreen = TRUE; + Console->FixedSize = TRUE; + + GuiData->ActiveBuffer->OldViewSize = GuiData->ActiveBuffer->ViewSize; + // GuiData->ActiveBuffer->OldScreenBufferSize = GuiData->ActiveBuffer->ScreenBufferSize; + + /* Save the old window styles */ + GuiData->WndStyle = GetWindowLongPtr(GuiData->hWindow, GWL_STYLE ); + GuiData->WndStyleEx = GetWindowLongPtr(GuiData->hWindow, GWL_EXSTYLE); + + /* Change the window styles */ + SetWindowLongPtr(GuiData->hWindow, GWL_STYLE, + WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN); + SetWindowLongPtr(GuiData->hWindow, GWL_EXSTYLE, + WS_EX_APPWINDOW); + + /* Reposition the window to the upper-left corner */ + SetWindowPos(GuiData->hWindow, + HWND_TOPMOST, + 0, 0, + 0, 0, + SWP_NOSIZE | SWP_FRAMECHANGED | SWP_SHOWWINDOW); + /* Make it the foreground window */ + SetForegroundWindow(GuiData->hWindow); + /* Resize it */ + // GuiConsoleResizeWindow(GuiData); + GuiConsoleResize(GuiData, SIZE_RESTORED, MAKELPARAM(640, 480)); + + PostMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_MAXIMIZE, 0); + } + else + { + PostMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_RESTORE, 0); + } + } + else + { + SendMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_MINIMIZE, 0); + + /* Restore windowing mode */ + if (LeaveFullScreen(GuiData)) + { + /* Save the new state */ + GuiData->GuiInfo.FullScreen = FALSE; + Console->FixedSize = FALSE; + + /* + * Restore possible saved dimensions + * of the active screen buffer view. + */ + GuiData->ActiveBuffer->ViewSize = GuiData->ActiveBuffer->OldViewSize; + // GuiData->ActiveBuffer->ScreenBufferSize = GuiData->ActiveBuffer->OldScreenBufferSize; + + /* Restore the window styles */ + SetWindowLongPtr(GuiData->hWindow, GWL_STYLE, + GuiData->WndStyle); + SetWindowLongPtr(GuiData->hWindow, GWL_EXSTYLE, + GuiData->WndStyleEx); + + /* Resize it */ + GuiConsoleResizeWindow(GuiData); + + // PostMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_RESTORE, 0); + } + PostMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_RESTORE, 0); + } +} + static VOID GuiConsoleSwitchFullScreen(PGUI_CONSOLE_DATA GuiData) { PCONSOLE Console = GuiData->Console; - // DEVMODE dmScreenSettings; + BOOL FullScreen; if (!ConDrvValidateConsoleUnsafe(Console, CONSOLE_RUNNING, TRUE)) return; /* Switch to full-screen or to windowed mode */ - GuiData->GuiInfo.FullScreen = !GuiData->GuiInfo.FullScreen; + FullScreen = !GuiData->GuiInfo.FullScreen; DPRINT1("GuiConsoleSwitchFullScreen - Switch to %s ...\n", - (GuiData->GuiInfo.FullScreen ? "full-screen" : "windowed mode")); + (FullScreen ? "full-screen" : "windowed mode")); - // TODO: Change window appearance. - // See: - // http://stackoverflow.com/questions/2382464/win32-full-screen-and-hiding-taskbar - // http://stackoverflow.com/questions/3549148/fullscreen-management-with-NTAPI - // http://blogs.msdn.com/b/oldnewthing/archive/2010/04/12/9994016.aspx - // http://stackoverflow.com/questions/1400654/how-do-i-put-my-opengl-app-into-fullscreen-mode - // http://nehe.gamedev.net/tutorial/creating_an_opengl_window_win32/13001/ -#if 0 - if (GuiData->GuiInfo.FullScreen) - { - memset(&dmScreenSettings, 0, sizeof(dmScreenSettings)); - dmScreenSettings.dmSize = sizeof(dmScreenSettings); - dmScreenSettings.dmDisplayFixedOutput = DMDFO_CENTER; // DMDFO_STRETCH // DMDFO_DEFAULT - dmScreenSettings.dmPelsWidth = 640; // GuiData->ActiveBuffer->ViewSize.X * GuiData->CharWidth; - dmScreenSettings.dmPelsHeight = 480; // GuiData->ActiveBuffer->ViewSize.Y * GuiData->CharHeight; - dmScreenSettings.dmBitsPerPel = 32; - dmScreenSettings.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; - ChangeDisplaySettings(&dmScreenSettings, CDS_FULLSCREEN); - } - else - { - } -#endif + SwitchFullScreen(GuiData, FullScreen); LeaveCriticalSection(&Console->Lock); } + + static BOOL GuiConsoleHandleNcCreate(HWND hWnd, LPCREATESTRUCTW Create) { @@ -1688,7 +1788,31 @@ GuiConsoleWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { case WM_ACTIVATE: { - if (LOWORD(wParam) == WA_CLICKACTIVE) GuiData->IgnoreNextMouseSignal = TRUE; + WORD ActivationState = LOWORD(wParam); + + if ( ActivationState == WA_ACTIVE || + ActivationState == WA_CLICKACTIVE ) + { + if (GuiData->GuiInfo.FullScreen) + { + EnterFullScreen(GuiData); + // // PostMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_RESTORE, 0); + // SendMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_RESTORE, 0); + } + } + else // if (ActivationState == WA_INACTIVE) + { + if (GuiData->GuiInfo.FullScreen) + { + SendMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_MINIMIZE, 0); + LeaveFullScreen(GuiData); + // // PostMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_MINIMIZE, 0); + // SendMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_MINIMIZE, 0); + } + } + + if (ActivationState == WA_CLICKACTIVE) GuiData->IgnoreNextMouseSignal = TRUE; + break; } @@ -2043,6 +2167,8 @@ GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) (PVOID)GuiData); if (NULL != NewWindow) { + ASSERT(NewWindow == GuiData->hWindow); + WindowCount = GetWindowLongW(hWnd, GWL_USERDATA); WindowCount++; SetWindowLongW(hWnd, GWL_USERDATA, WindowCount); @@ -2068,6 +2194,9 @@ GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) GuiConsoleResizeWindow(GuiData); GuiData->WindowSizeLock = FALSE; + /* Switch to full-screen mode if necessary */ + if (GuiData->GuiInfo.FullScreen) SwitchFullScreen(GuiData, TRUE); + // ShowWindow(NewWindow, (int)wParam); ShowWindowAsync(NewWindow, (int)wParam); DPRINT("Window showed\n"); @@ -2080,6 +2209,9 @@ GuiConsoleNotifyWndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { PGUI_CONSOLE_DATA GuiData = (PGUI_CONSOLE_DATA)lParam; + /* Exit the full screen mode if it was already set */ + // LeaveFullScreen(GuiData); + /* * Window creation is done using a PostMessage(), so it's possible * that the window that we want to destroy doesn't exist yet. diff --git a/reactos/win32ss/user/winsrv/consrv/include/conio.h b/reactos/win32ss/user/winsrv/consrv/include/conio.h index 76d4aa2a244..0e8bbc40bc4 100644 --- a/reactos/win32ss/user/winsrv/consrv/include/conio.h +++ b/reactos/win32ss/user/winsrv/consrv/include/conio.h @@ -66,7 +66,7 @@ struct _CONSOLE_SCREEN_BUFFER // PVOID Data; /* Private data for the frontend to use */ - COORD ScreenBufferSize; /* Size of this screen buffer. (Rows, Columns) for text-mode and (Width, Height) for graphics */ + COORD ScreenBufferSize; /* Size of this screen buffer. (Rows, Columns) for text-mode and (Width, Height) for graphics-mode */ COORD ViewSize; /* Associated "view" (i.e. console) size */ COORD OldScreenBufferSize; /* Old size of this screen buffer */