Compare commits

...

7 Commits

Author SHA1 Message Date
Dustin L. Howett
aad3855287 Work around a compiler bug w/ coroutines and exceptions (#9893)
There is a bug in the compiler that we trip over when we handle the
exception generated by Package::Current inside a coroutine. It appears
to destruct an invalid instance of winrt::factory_guard_count.

Learned from the compiler folks: "coroutine frame pointer wasn't being
stored ... properly".

Fixes #9821

(cherry picked from commit 21b2e01643)
2021-04-19 16:15:35 -05:00
Kayla Cinnamon
4c09a235cc doc: Add tabColor to JSON schema (#9843)
(cherry picked from commit 8bcb47339d)
2021-04-15 12:32:42 -05:00
Dustin L. Howett
8078db5fd5 Only update render appearance settings if there's a renderer (#9798)
I ran into this crash when I just opened a new tab.

Fixes MSFT-32485023

(cherry picked from commit dab52c46a2)
2021-04-13 16:17:52 -05:00
Evan Koschik
f2afb223f5 Fix restore window position when exiting fullscreen (#9737)
<!-- Enter a brief description/summary of your PR here. What does it fix/what does it change/how was it tested (even manually, if necessary)? -->
## Summary of the Pull Request

This change cleans up the Fullscreen implementation for both conhost and Terminal, improving the restore position (where the window goes when exiting fullscreen).

Prior to this change the window wasn't guaranteed to restore somewhere on the window's current monitor when exiting fullscreen. With this change the window will restore always to its current monitor, at a reasonable location (and will 'double restore' (to fullscreen->maximize->restore) after monitor changes while fullscreen, which is the expected user behavior.

<!-- Other than the issue solved, is this relevant to any other issues/existing PRs? -->
## References

<!-- Please review the items on the PR checklist before submitting-->
## PR Checklist
* [x] Closes #9746
* [x] CLA signed. If not, go over [here](https://cla.opensource.microsoft.com/microsoft/Terminal) and sign the CLA
* [ ] Tests added/passed
* [ ] Documentation updated. If checked, please file a pull request on [our docs repo](https://github.com/MicrosoftDocs/terminal) and link it here: #xxx
* [ ] Schema updated.
* [ ] I've discussed this with core contributors already. If not checked, I'm ready to accept this work might be rejected in favor of a different grand plan. Issue number where discussion took place: #xxx

<!-- Provide a more detailed description of the PR, other things fixed or any additional comments/features here -->
## Detailed Description of the Pull Request / Additional comments

A fullscreen window's monitor can change.
 - Win+Shift+left/right migrates a window between monitors.
 - User could open settings, display, and move the monitor or change its DPI.
 - The monitor could be unplugged.
 - The session could be remote and be disconnected.

A fullscreen window stores a 'restore position' when entering fullscreen, used to move the window back 'where it was'. BUT, its unexpected for the window to exit fullscreen and jump to another monitor. This means its previous position must be migrated from the old monitor's work area to the new monitor's work area.

If a window is maximized, it is sized to the work area. Like with fullscreen, a maximized window has a 'restore position', though unlike with fullscreen the restore position for maximized is stored by the system itself. Migration in cases where a maximized (or fullscreen) window's monitor changes is also taken care of by the system. To restore 'safely' to maximized (after changing window styles) a window must only `SetWindowPos(SWP_FRAMECHANGED)`. While technically a maximized window that becomes fullscreen 'is still maximized' (from Win32's perspective), its prudent to also `ShowWindow(SW_MAXIMIZED)` prior to `SWP_FRAMECHANGED` (to explicitly make the window maximized).

If not restoring to maximized, the restore position is adjusted by the new/ old work area. Additionally, the new/ old window DPI is used to adjust the size of the window by the DPI change (keeping the window's logical size the same).
 - The work area origin is checked first (shifting window rect by the change in origin)
 - The DPI is checked next, changing right/ bottom (size only)
 - Each edge of the window is compared against the corresponding edge of the work area, nudging the window back on-screen if hanging offscreen. By shifting right before left, bottom before top, the top-left is guaranteed on-screen.

<!-- Describe how you validated the behavior. Add automated tests wherever possible, but list manual validation steps taken as well -->
## Validation Steps Performed

Tried it out. Seemed to work on my machine.
Jk, ran conhost/ terminal on mixed DPI system, max (or not), fullscreen, win+shift+left/ exit fullscreen/ maximize. Monitor unplug, etc.

(cherry picked from commit bc1ff0b71a)
(cherry picked from commit 14a7e45280)
2021-04-13 15:44:42 -05:00
Dustin L. Howett
9882e9f835 Remove the splash screen (to save 100kb (compressed!)) (#9795)
We're a Centennial application; we can't even _use_ the splash screen.

(cherry picked from commit ab6f41f4bd)
2021-04-13 12:52:42 -05:00
Dustin L. Howett
6072be5436 [RELEASE ONLY] Remove the close submenu (#9102)
There's a platform issue that causes it to crash.
Fixes #8944.

(cherry picked from commit 5fdd1560fd)
(cherry picked from commit c951a70208)
2021-04-13 09:14:05 -05:00
Dustin Howett
bc368b7c29 Disable handoff registration (only) for preview in 1.8
Handoff will still be accepted if the registry is set up properly.
2021-04-13 09:11:21 -05:00
59 changed files with 263 additions and 123 deletions

View File

@@ -28,6 +28,7 @@ GETHIGHCONTRAST
Hashtable
HIGHCONTRASTON
HIGHCONTRASTW
hotkeys
href
IActivation
IApp

View File

@@ -1347,6 +1347,11 @@
"type": "boolean",
"default": false
},
"tabColor": {
"$ref": "#/definitions/Color",
"description": "Sets the color of the profile's tab. Using the tab color picker will override this color.",
"type": ["string", "null"]
},
"tabTitle": {
"description": "If set, will replace the name as the title to pass to the shell on startup. Some shells (like bash) may choose to ignore this initial value, while others (cmd, powershell) may use this value over the lifetime of the application.",
"type": ["string", "null"]

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

View File

@@ -54,7 +54,6 @@
<uap:ShowOn Tile="square310x310Logo"/>
</uap:ShowNameOnTiles>
</uap:DefaultTile>
<uap:SplashScreen Image="Images\SplashScreen.png"/>
</uap:VisualElements>
<Extensions>

View File

@@ -55,7 +55,6 @@
<uap:ShowOn Tile="square310x310Logo"/>
</uap:ShowNameOnTiles>
</uap:DefaultTile>
<uap:SplashScreen Image="Images\SplashScreen.png"/>
</uap:VisualElements>
<Extensions>
@@ -75,6 +74,7 @@
Enabled="false"
DisplayName="ms-resource:AppNamePre" />
</uap5:Extension>
<!-- DISABLED FOR 1.8
<uap3:Extension Category="windows.appExtension">
<uap3:AppExtension Name="com.microsoft.windows.console.host"
Id="OpenConsole-Pre"
@@ -97,6 +97,7 @@
</uap3:Properties>
</uap3:AppExtension>
</uap3:Extension>
-->
<com:Extension Category="windows.comInterface">
<com:ComInterface>
<com:ProxyStub Id="1833E661-CC81-4DD0-87C6-C2F74BD39EFA" DisplayName="OpenConsoleHandoffProxy" Path="OpenConsoleProxy.dll"/>

View File

@@ -55,7 +55,6 @@
<uap:ShowOn Tile="square310x310Logo"/>
</uap:ShowNameOnTiles>
</uap:DefaultTile>
<uap:SplashScreen Image="Images\SplashScreen.png"/>
</uap:VisualElements>
<Extensions>

View File

@@ -919,12 +919,32 @@ namespace winrt::TerminalApp::implementation
_ApplyTheme(_settings.GlobalSettings().Theme());
}
// Function Description:
// Returns the current app package or nullptr.
// TRANSITIONAL
// Exists to work around a compiler bug. This function encapsulates the
// exception handling that we used to keep around calls to Package::Current,
// so that when it's called inside a coroutine and fails it doesn't explode
// terribly.
static winrt::Windows::ApplicationModel::Package GetCurrentPackageNoThrow() noexcept
{
try
{
return winrt::Windows::ApplicationModel::Package::Current();
}
catch (...)
{
// discard any exception -- literally pretend we're not in a package
}
return nullptr;
}
fire_and_forget AppLogic::_ApplyStartupTaskStateChange()
try
{
// First, make sure we're running in a packaged context. This method
// won't work, and will crash mysteriously if we're running unpackaged.
const auto package{ winrt::Windows::ApplicationModel::Package::Current() };
const auto package{ GetCurrentPackageNoThrow() };
if (package == nullptr)
{
return;

View File

@@ -62,7 +62,6 @@ namespace winrt::TerminalApp::implementation
// Build the menu
Controls::MenuFlyout newTabFlyout;
newTabFlyout.Items().Append(_CreateCloseSubMenu());
newTabFlyout.Items().Append(closeTabMenuItem);
TabViewItem().ContextFlyout(newTabFlyout);
}

View File

@@ -870,7 +870,6 @@ namespace winrt::TerminalApp::implementation
newTabFlyout.Items().Append(renameTabMenuItem);
newTabFlyout.Items().Append(duplicateTabMenuItem);
newTabFlyout.Items().Append(menuSeparator);
newTabFlyout.Items().Append(_CreateCloseSubMenu());
newTabFlyout.Items().Append(closeTabMenuItem);
TabViewItem().ContextFlyout(newTabFlyout);
}

View File

@@ -481,11 +481,14 @@ namespace winrt::Microsoft::Terminal::Control::implementation
// Update the terminal core with its new Core settings
_terminal->UpdateAppearance(newAppearance);
// Update DxEngine settings under the lock
_renderEngine->SetSelectionBackground(til::color{ newAppearance.SelectionBackground() });
_renderEngine->SetRetroTerminalEffect(newAppearance.RetroTerminalEffect());
_renderEngine->SetPixelShaderPath(newAppearance.PixelShaderPath());
_renderer->TriggerRedrawAll();
if (_renderEngine)
{
// Update DxEngine settings under the lock
_renderEngine->SetSelectionBackground(til::color{ newAppearance.SelectionBackground() });
_renderEngine->SetRetroTerminalEffect(newAppearance.RetroTerminalEffect());
_renderEngine->SetPixelShaderPath(newAppearance.PixelShaderPath());
_renderer->TriggerRedrawAll();
}
}
// Method Description:

View File

@@ -758,6 +758,91 @@ void IslandWindow::_SetIsBorderless(const bool borderlessEnabled)
SWP_SHOWWINDOW | SWP_FRAMECHANGED | SWP_NOACTIVATE);
}
// Method Description:
// - Called when entering fullscreen, with the window's current monitor rect and work area.
// - The current window position, dpi, work area, and maximized state are stored, and the
// window is positioned to the monitor rect.
void IslandWindow::_SetFullscreenPosition(const RECT rcMonitor, const RECT rcWork)
{
HWND const hWnd = GetHandle();
::GetWindowRect(hWnd, &_rcWindowBeforeFullscreen);
_dpiBeforeFullscreen = GetDpiForWindow(hWnd);
_fWasMaximizedBeforeFullscreen = IsZoomed(hWnd);
_rcWorkBeforeFullscreen = rcWork;
SetWindowPos(hWnd,
HWND_TOP,
rcMonitor.left,
rcMonitor.top,
rcMonitor.right - rcMonitor.left,
rcMonitor.bottom - rcMonitor.top,
SWP_FRAMECHANGED);
}
// Method Description:
// - Called when exiting fullscreen, with the window's current monitor work area.
// - The window is restored to its previous position, migrating that previous position to the
// window's current monitor (if the current work area or window DPI have changed).
// - A fullscreen window's monitor can be changed by win+shift+left/right hotkeys or monitor
// topology changes (for example unplugging a monitor or disconnecting a remote session).
void IslandWindow::_RestoreFullscreenPosition(const RECT rcWork)
{
HWND const hWnd = GetHandle();
// If the window was previously maximized, re-maximize the window.
if (_fWasMaximizedBeforeFullscreen)
{
ShowWindow(hWnd, SW_SHOWMAXIMIZED);
SetWindowPos(hWnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
return;
}
// Start with the stored window position.
RECT rcRestore = _rcWindowBeforeFullscreen;
// If the window DPI has changed, re-size the stored position by the change in DPI. This
// ensures the window restores to the same logical size (even if to a monitor with a different
// DPI/ scale factor).
UINT dpiWindow = GetDpiForWindow(hWnd);
rcRestore.right = rcRestore.left + MulDiv(rcRestore.right - rcRestore.left, dpiWindow, _dpiBeforeFullscreen);
rcRestore.bottom = rcRestore.top + MulDiv(rcRestore.bottom - rcRestore.top, dpiWindow, _dpiBeforeFullscreen);
// Offset the stored position by the difference in work area.
OffsetRect(&rcRestore,
rcWork.left - _rcWorkBeforeFullscreen.left,
rcWork.top - _rcWorkBeforeFullscreen.top);
// Enforce that our position is entirely within the bounds of our work area.
// Prefer the top-left be on-screen rather than bottom-right (right before left, bottom before top).
if (rcRestore.right > rcWork.right)
{
OffsetRect(&rcRestore, rcWork.right - rcRestore.right, 0);
}
if (rcRestore.left < rcWork.left)
{
OffsetRect(&rcRestore, rcWork.left - rcRestore.left, 0);
}
if (rcRestore.bottom > rcWork.bottom)
{
OffsetRect(&rcRestore, 0, rcWork.bottom - rcRestore.bottom);
}
if (rcRestore.top < rcWork.top)
{
OffsetRect(&rcRestore, 0, rcWork.top - rcRestore.top);
}
// Show the window at the computed position.
SetWindowPos(hWnd,
HWND_TOP,
rcRestore.left,
rcRestore.top,
rcRestore.right - rcRestore.left,
rcRestore.bottom - rcRestore.top,
SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
}
// Method Description:
// - Controls setting us into or out of fullscreen mode. Largely taken from
// Window::SetIsFullscreen in conhost.
@@ -773,7 +858,7 @@ void IslandWindow::_SetIsFullscreen(const bool fullscreenEnabled)
// It is possible to enter _SetIsFullscreen even if we're already in full
// screen. Use the old is in fullscreen flag to gate checks that rely on the
// current state.
const auto oldIsInFullscreen = _fullscreen;
const bool fChangingFullscreen = (fullscreenEnabled != _fullscreen);
_fullscreen = fullscreenEnabled;
HWND const hWnd = GetHandle();
@@ -789,61 +874,27 @@ void IslandWindow::_SetIsFullscreen(const bool fullscreenEnabled)
WI_UpdateFlag(exWindowStyle, WS_EX_WINDOWEDGE, !_fullscreen);
_SetWindowLongWHelper(hWnd, GWL_EXSTYLE, exWindowStyle);
// When entering/exiting fullscreen mode, we also need to backup/restore the
// current window size, and resize the window to match the new state.
_BackupWindowSizes(oldIsInFullscreen);
_ApplyWindowSize();
}
// Method Description:
// - Used in entering/exiting fullscreen mode. Saves the current window size,
// and the full size of the monitor, for use in _ApplyWindowSize.
// - Taken from conhost's Window::_BackupWindowSizes
// Arguments:
// - fCurrentIsInFullscreen: true if we're currently in fullscreen mode.
// Return Value:
// - <none>
void IslandWindow::_BackupWindowSizes(const bool fCurrentIsInFullscreen)
{
if (_fullscreen)
// Only change the window position if changing fullscreen state.
if (fChangingFullscreen)
{
// Note: the current window size depends on the current state of the
// window. So don't back it up if we're already in full screen.
if (!fCurrentIsInFullscreen)
{
_nonFullscreenWindowSize = GetWindowRect();
}
// Get the monitor info for the window's current monitor.
MONITORINFO mi = {};
mi.cbSize = sizeof(mi);
GetMonitorInfo(MonitorFromWindow(hWnd, MONITOR_DEFAULTTONEAREST), &mi);
// get and back up the current monitor's size
HMONITOR const hCurrentMonitor = MonitorFromWindow(GetHandle(), MONITOR_DEFAULTTONEAREST);
MONITORINFO currMonitorInfo;
currMonitorInfo.cbSize = sizeof(currMonitorInfo);
if (GetMonitorInfo(hCurrentMonitor, &currMonitorInfo))
if (_fullscreen)
{
_fullscreenWindowSize = currMonitorInfo.rcMonitor;
// Store the window's current position and size the window to the monitor.
_SetFullscreenPosition(mi.rcMonitor, mi.rcWork);
}
else
{
// Restore the stored window position.
_RestoreFullscreenPosition(mi.rcWork);
}
}
}
// Method Description:
// - Applies the appropriate window size for transitioning to/from fullscreen mode.
// - Taken from conhost's Window::_ApplyWindowSize
// Arguments:
// - <none>
// Return Value:
// - <none>
void IslandWindow::_ApplyWindowSize()
{
const auto newSize = _fullscreen ? _fullscreenWindowSize : _nonFullscreenWindowSize;
LOG_IF_WIN32_BOOL_FALSE(SetWindowPos(GetHandle(),
HWND_TOP,
newSize.left,
newSize.top,
newSize.right - newSize.left,
newSize.bottom - newSize.top,
SWP_FRAMECHANGED | SWP_NOACTIVATE));
}
// Method Description:
// - Force activate this window. This method will bring us to the foreground and
// activate us. If the window is minimized, it will restore the window. If the

View File

@@ -68,15 +68,17 @@ protected:
[[nodiscard]] LRESULT _OnSizing(const WPARAM wParam, const LPARAM lParam);
bool _borderless{ false };
bool _fullscreen{ false };
bool _alwaysOnTop{ false };
RECT _fullscreenWindowSize;
RECT _nonFullscreenWindowSize;
bool _fullscreen{ false };
bool _fWasMaximizedBeforeFullscreen{ false };
RECT _rcWindowBeforeFullscreen;
RECT _rcWorkBeforeFullscreen;
UINT _dpiBeforeFullscreen;
virtual void _SetIsBorderless(const bool borderlessEnabled);
virtual void _SetIsFullscreen(const bool fullscreenEnabled);
void _BackupWindowSizes(const bool currentIsInFullscreen);
void _ApplyWindowSize();
void _RestoreFullscreenPosition(const RECT rcWork);
void _SetFullscreenPosition(const RECT rcMonitor, const RECT rcWork);
LONG _getDesiredWindowStyle() const;

View File

@@ -60,11 +60,13 @@ Window::Window() :
_fIsInFullscreen(false),
_pSettings(nullptr),
_hWnd(nullptr),
_pUiaProvider(nullptr)
_pUiaProvider(nullptr),
_fWasMaximizedBeforeFullscreen(false),
_dpiBeforeFullscreen(0)
{
ZeroMemory((void*)&_rcClientLast, sizeof(_rcClientLast));
ZeroMemory((void*)&_rcNonFullscreenWindowSize, sizeof(_rcNonFullscreenWindowSize));
ZeroMemory((void*)&_rcFullscreenWindowSize, sizeof(_rcFullscreenWindowSize));
ZeroMemory((void*)&_rcWindowBeforeFullscreen, sizeof(_rcWindowBeforeFullscreen));
ZeroMemory((void*)&_rcWorkBeforeFullscreen, sizeof(_rcWorkBeforeFullscreen));
}
Window::~Window()
@@ -1095,11 +1097,90 @@ bool Window::IsInFullscreen() const
return _fIsInFullscreen;
}
// Routine Description:
// - Called when entering fullscreen, with the window's current monitor rect and work area.
// - The current window position, dpi, work area, and maximized state are stored, and the
// window is positioned to the monitor rect.
void Window::_SetFullscreenPosition(const RECT rcMonitor, const RECT rcWork)
{
::GetWindowRect(GetWindowHandle(), &_rcWindowBeforeFullscreen);
_dpiBeforeFullscreen = GetDpiForWindow(GetWindowHandle());
_fWasMaximizedBeforeFullscreen = IsZoomed(GetWindowHandle());
_rcWorkBeforeFullscreen = rcWork;
SetWindowPos(GetWindowHandle(),
HWND_TOP,
rcMonitor.left,
rcMonitor.top,
rcMonitor.right - rcMonitor.left,
rcMonitor.bottom - rcMonitor.top,
SWP_FRAMECHANGED);
}
// Routine Description:
// - Called when exiting fullscreen, with the window's current monitor work area.
// - The window is restored to its previous position, migrating that previous position to the
// window's current monitor (if the current work area or window DPI have changed).
// - A fullscreen window's monitor can be changed by win+shift+left/right hotkeys or monitor
// topology changes (for example unplugging a monitor or disconnecting a remote session).
void Window::_RestoreFullscreenPosition(const RECT rcWork)
{
// If the window was previously maximized, re-maximize the window.
if (_fWasMaximizedBeforeFullscreen)
{
ShowWindow(GetWindowHandle(), SW_SHOWMAXIMIZED);
SetWindowPos(GetWindowHandle(), HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
return;
}
// Start with the stored window position.
RECT rcRestore = _rcWindowBeforeFullscreen;
// If the window DPI has changed, re-size the stored position by the change in DPI. This
// ensures the window restores to the same logical size (even if to a monitor with a different
// DPI/ scale factor).
UINT dpiWindow = GetDpiForWindow(GetWindowHandle());
rcRestore.right = rcRestore.left + MulDiv(rcRestore.right - rcRestore.left, dpiWindow, _dpiBeforeFullscreen);
rcRestore.bottom = rcRestore.top + MulDiv(rcRestore.bottom - rcRestore.top, dpiWindow, _dpiBeforeFullscreen);
// Offset the stored position by the difference in work area.
OffsetRect(&rcRestore,
rcWork.left - _rcWorkBeforeFullscreen.left,
rcWork.top - _rcWorkBeforeFullscreen.top);
// Enforce that our position is entirely within the bounds of our work area.
// Prefer the top-left be on-screen rather than bottom-right (right before left, bottom before top).
if (rcRestore.right > rcWork.right)
{
OffsetRect(&rcRestore, rcWork.right - rcRestore.right, 0);
}
if (rcRestore.left < rcWork.left)
{
OffsetRect(&rcRestore, rcWork.left - rcRestore.left, 0);
}
if (rcRestore.bottom > rcWork.bottom)
{
OffsetRect(&rcRestore, 0, rcWork.bottom - rcRestore.bottom);
}
if (rcRestore.top < rcWork.top)
{
OffsetRect(&rcRestore, 0, rcWork.top - rcRestore.top);
}
// Show the window at the computed position.
SetWindowPos(GetWindowHandle(),
HWND_TOP,
rcRestore.left,
rcRestore.top,
rcRestore.right - rcRestore.left,
rcRestore.bottom - rcRestore.top,
SWP_SHOWWINDOW | SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
}
void Window::SetIsFullscreen(const bool fFullscreenEnabled)
{
// It is possible to enter SetIsFullScreen even if we're already in full screen.
// Use the old is in fullscreen flag to gate checks that rely on the current state.
bool fOldIsInFullscreen = _fIsInFullscreen;
const bool fChangingFullscreen = (fFullscreenEnabled != _fIsInFullscreen);
_fIsInFullscreen = fFullscreenEnabled;
HWND const hWnd = GetWindowHandle();
@@ -1135,48 +1216,30 @@ void Window::SetIsFullscreen(const bool fFullscreenEnabled)
}
SetWindowLongW(hWnd, GWL_EXSTYLE, dwExWindowStyle);
_BackupWindowSizes(fOldIsInFullscreen);
_ApplyWindowSize();
}
void Window::_BackupWindowSizes(const bool fCurrentIsInFullscreen)
{
if (_fIsInFullscreen)
// Only change the window position if changing fullscreen state.
if (fChangingFullscreen)
{
// Note: the current window size depends on the current state of the window.
// So don't back it up if we're already in full screen.
if (!fCurrentIsInFullscreen)
{
_rcNonFullscreenWindowSize = GetWindowRect();
}
// Get the monitor info for the window's current monitor.
MONITORINFO mi = {};
mi.cbSize = sizeof(mi);
GetMonitorInfo(MonitorFromWindow(GetWindowHandle(), MONITOR_DEFAULTTONEAREST), &mi);
// get and back up the current monitor's size
HMONITOR const hCurrentMonitor = MonitorFromWindow(GetWindowHandle(), MONITOR_DEFAULTTONEAREST);
MONITORINFO currMonitorInfo;
currMonitorInfo.cbSize = sizeof(currMonitorInfo);
if (GetMonitorInfo(hCurrentMonitor, &currMonitorInfo))
if (_fIsInFullscreen)
{
_rcFullscreenWindowSize = currMonitorInfo.rcMonitor;
// Store the window's current position and size the window to the monitor.
_SetFullscreenPosition(mi.rcMonitor, mi.rcWork);
}
else
{
// Restore the stored window position.
_RestoreFullscreenPosition(mi.rcWork);
SCREEN_INFORMATION& siAttached = GetScreenInfo();
siAttached.MakeCurrentCursorVisible();
}
}
}
void Window::_ApplyWindowSize()
{
const RECT rcNewSize = _fIsInFullscreen ? _rcFullscreenWindowSize : _rcNonFullscreenWindowSize;
SetWindowPos(GetWindowHandle(),
HWND_TOP,
rcNewSize.left,
rcNewSize.top,
RECT_WIDTH(&rcNewSize),
RECT_HEIGHT(&rcNewSize),
SWP_FRAMECHANGED);
SCREEN_INFORMATION& siAttached = GetScreenInfo();
siAttached.MakeCurrentCursorVisible();
}
void Window::ToggleFullscreen()
{
SetIsFullscreen(!IsInFullscreen());

View File

@@ -147,12 +147,13 @@ namespace Microsoft::Console::Interactivity::Win32
RECT _rcClientLast;
// Full screen
void _BackupWindowSizes(const bool fCurrentIsInFullscreen);
void _ApplyWindowSize();
void _RestoreFullscreenPosition(const RECT rcWork);
void _SetFullscreenPosition(const RECT rcMonitor, const RECT rcWork);
bool _fIsInFullscreen;
RECT _rcFullscreenWindowSize;
RECT _rcNonFullscreenWindowSize;
bool _fWasMaximizedBeforeFullscreen;
RECT _rcWindowBeforeFullscreen;
RECT _rcWorkBeforeFullscreen;
UINT _dpiBeforeFullscreen;
// math helpers
void _CalculateWindowRect(const COORD coordWindowInChars,

View File

@@ -226,18 +226,15 @@ using namespace Microsoft::Console::Types;
_UpdateSystemMetrics();
s_ReinitializeFontsForDPIChange();
if (IsInFullscreen())
{
// If we're a full screen window, completely ignore what the DPICHANGED says as it will be bigger than the monitor and
// instead just ensure that the window is still taking up the full screen.
SetIsFullscreen(true);
}
else
{
// this is the RECT that the system suggests.
RECT* const prcNewScale = (RECT*)lParam;
SetWindowPos(hWnd, HWND_TOP, prcNewScale->left, prcNewScale->top, RECT_WIDTH(prcNewScale), RECT_HEIGHT(prcNewScale), SWP_NOZORDER | SWP_NOACTIVATE);
}
// This is the RECT that the system suggests.
RECT* const prcNewScale = (RECT*)lParam;
SetWindowPos(hWnd,
HWND_TOP,
prcNewScale->left,
prcNewScale->top,
RECT_WIDTH(prcNewScale),
RECT_HEIGHT(prcNewScale),
SWP_NOZORDER | SWP_NOACTIVATE);
_fInDPIChange = false;