1 /*
2  * COPYRIGHT:       See COPYING in the top level directory
3  * PROJECT:         ReactOS Console Server DLL
4  * FILE:            consrv/frontends/gui/fullscreen.c
5  * PURPOSE:         GUI Terminal Full-screen Mode
6  * PROGRAMMERS:     Hermes Belusca-Maito (hermes.belusca@sfr.fr)
7  */
8 
9 /* INCLUDES *******************************************************************/
10 
11 #include <consrv.h>
12 
13 #define NDEBUG
14 #include <debug.h>
15 
16 #include "guiterm.h"
17 
18 /* FUNCTIONS ******************************************************************/
19 
20 BOOL
21 EnterFullScreen(PGUI_CONSOLE_DATA GuiData)
22 {
23     DEVMODEW DevMode;
24 
25     ZeroMemory(&DevMode, sizeof(DevMode));
26     DevMode.dmSize = sizeof(DevMode);
27 
28     DevMode.dmDisplayFixedOutput = DMDFO_CENTER; // DMDFO_STRETCH // DMDFO_DEFAULT
29     // DevMode.dmDisplayFlags = DMDISPLAYFLAGS_TEXTMODE;
30     DevMode.dmPelsWidth  = 640; // GuiData->ActiveBuffer->ViewSize.X * GuiData->CharWidth;
31     DevMode.dmPelsHeight = 480; // GuiData->ActiveBuffer->ViewSize.Y * GuiData->CharHeight;
32     // DevMode.dmBitsPerPel = 32;
33     DevMode.dmFields     = DM_DISPLAYFIXEDOUTPUT | /* DM_DISPLAYFLAGS | DM_BITSPERPEL | */ DM_PELSWIDTH | DM_PELSHEIGHT;
34 
35     return (ChangeDisplaySettingsW(&DevMode, CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL);
36 }
37 
38 VOID
39 LeaveFullScreen(PGUI_CONSOLE_DATA GuiData)
40 {
41     ChangeDisplaySettingsW(NULL, CDS_RESET);
42 }
43 
44 
45 // static VOID
46 // GuiConsoleResize(PGUI_CONSOLE_DATA GuiData, WPARAM wParam, LPARAM lParam);
47 
48 VOID
49 SwitchFullScreen(PGUI_CONSOLE_DATA GuiData, BOOL FullScreen)
50 {
51     PCONSRV_CONSOLE Console = GuiData->Console;
52 
53     /*
54      * See:
55      * http://stackoverflow.com/questions/2382464/win32-full-screen-and-hiding-taskbar
56      * http://stackoverflow.com/questions/3549148/fullscreen-management-with-winapi
57      * http://blogs.msdn.com/b/oldnewthing/archive/2010/04/12/9994016.aspx
58      * http://blogs.msdn.com/b/oldnewthing/archive/2005/05/05/414910.aspx
59      * http://stackoverflow.com/questions/1400654/how-do-i-put-my-opengl-app-into-fullscreen-mode
60      * http://nehe.gamedev.net/tutorial/creating_an_opengl_window_win32/13001/
61      * http://www.reocities.com/pcgpe/dibs.html
62      */
63 
64     /* If we are already in the given state, just bail out */
65     if (FullScreen == GuiData->GuiInfo.FullScreen) return;
66 
67     /* Save the current window state if we are not already full-screen */
68     if (!GuiData->GuiInfo.FullScreen)
69     {
70         GuiData->IsWndMax = IsZoomed(GuiData->hWindow);
71         if (GuiData->IsWndMax)
72             SendMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_RESTORE, 0);
73 
74         /* Save its old position and size and show state */
75         GuiData->WndPl.length = sizeof(WINDOWPLACEMENT);
76         GetWindowPlacement(GuiData->hWindow, &GuiData->WndPl);
77 
78         /* Save the old window styles */
79         GuiData->WndStyle   = GetWindowLongPtr(GuiData->hWindow, GWL_STYLE  );
80         GuiData->WndStyleEx = GetWindowLongPtr(GuiData->hWindow, GWL_EXSTYLE);
81     }
82 
83     if (FullScreen)
84     {
85         SendMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_MINIMIZE, 0);
86 
87         /* Switch to full screen */
88         if (EnterFullScreen(GuiData))
89         {
90             /* Save the new state */
91             Console->FixedSize = TRUE;
92             GuiData->GuiInfo.FullScreen = TRUE;
93 
94             GuiData->ActiveBuffer->OldViewSize = GuiData->ActiveBuffer->ViewSize;
95             // GuiData->ActiveBuffer->OldScreenBufferSize = GuiData->ActiveBuffer->ScreenBufferSize;
96 
97             /* Change the window styles */
98             SetWindowLongPtr(GuiData->hWindow, GWL_STYLE,
99                              WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN);
100             SetWindowLongPtr(GuiData->hWindow, GWL_EXSTYLE,
101                              WS_EX_APPWINDOW);
102             // SetWindowPos(GuiData->hWindow, NULL, 0, 0, 0, 0,
103                          // SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
104                          // SWP_FRAMECHANGED | SWP_SHOWWINDOW);
105 
106             /* Reposition the window to the upper-left corner */
107             SetWindowPos(GuiData->hWindow, HWND_TOPMOST, 0, 0, 0, 0,
108                          SWP_NOSIZE | SWP_FRAMECHANGED | SWP_SHOWWINDOW);
109 
110             /* Make it the foreground window */
111             SetForegroundWindow(GuiData->hWindow);
112 
113             /* Resize it */
114             // // GuiConsoleResizeWindow(GuiData);
115             // GuiConsoleResize(GuiData, SIZE_RESTORED, MAKELPARAM(640, 480));
116 
117             PostMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
118             // SendMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_MAXIMIZE, 0);
119         }
120 
121         PostMessageW(GuiData->hWindow, WM_SYSCOMMAND,
122                      GuiData->GuiInfo.FullScreen || GuiData->IsWndMax
123                         ? SC_MAXIMIZE : SC_RESTORE,
124                      0);
125         // ShowWindowAsync(GuiData->hWindow, SW_RESTORE);
126     }
127     else
128     {
129         SendMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_MINIMIZE, 0);
130 
131         /* Restore windowing mode */
132         LeaveFullScreen(GuiData);
133 
134         /* Save the new state */
135         GuiData->GuiInfo.FullScreen = FALSE;
136         Console->FixedSize = FALSE;
137 
138         /*
139          * Restore possible saved dimensions
140          * of the active screen buffer view.
141          */
142         GuiData->ActiveBuffer->ViewSize = GuiData->ActiveBuffer->OldViewSize;
143         // GuiData->ActiveBuffer->ScreenBufferSize = GuiData->ActiveBuffer->OldScreenBufferSize;
144 
145         /* Restore the window styles */
146         SetWindowLongPtr(GuiData->hWindow, GWL_STYLE,
147                          GuiData->WndStyle);
148         SetWindowLongPtr(GuiData->hWindow, GWL_EXSTYLE,
149                          GuiData->WndStyleEx);
150         SetWindowPos(GuiData->hWindow, NULL, 0, 0, 0, 0,
151                      SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER |
152                      SWP_FRAMECHANGED /*| SWP_SHOWWINDOW*/);
153 
154 
155         /* Restore the window to its original position */
156         SetWindowPlacement(GuiData->hWindow, &GuiData->WndPl);
157 
158         PostMessageW(GuiData->hWindow, WM_SYSCOMMAND,
159                      GuiData->IsWndMax ? SC_MAXIMIZE : SC_RESTORE,
160                      0);
161         // ShowWindowAsync(GuiData->hWindow, SW_RESTORE);
162 
163         /* Make it the foreground window */
164         SetForegroundWindow(GuiData->hWindow);
165 
166         /* Resize it */
167         // GuiConsoleResizeWindow(GuiData);
168 
169         // PostMessageW(GuiData->hWindow, WM_SYSCOMMAND, SC_RESTORE, 0);
170         // // ShowWindowAsync(GuiData->hWindow, SW_RESTORE);
171     }
172 }
173 
174 VOID
175 GuiConsoleSwitchFullScreen(PGUI_CONSOLE_DATA GuiData)
176 {
177     PCONSRV_CONSOLE Console = GuiData->Console;
178     BOOL FullScreen;
179 
180     if (!ConDrvValidateConsoleUnsafe((PCONSOLE)Console, CONSOLE_RUNNING, TRUE)) return;
181 
182     /* Switch to full-screen or to windowed mode */
183     FullScreen = !GuiData->GuiInfo.FullScreen;
184     DPRINT("GuiConsoleSwitchFullScreen - Switch to %s ...\n",
185             (FullScreen ? "full-screen" : "windowed mode"));
186 
187     SwitchFullScreen(GuiData, FullScreen);
188 
189     LeaveCriticalSection(&Console->Lock);
190 }
191 
192 /* EOF */
193