diff --git a/src/cascadia/Remoting/Monarch.cpp b/src/cascadia/Remoting/Monarch.cpp index c35ed452cc8..5bb9693361e 100644 --- a/src/cascadia/Remoting/Monarch.cpp +++ b/src/cascadia/Remoting/Monarch.cpp @@ -705,7 +705,8 @@ namespace winrt::Microsoft::Terminal::Remoting::implementation // If no name was provided, then just summon the MRU window. if (searchedForName.empty()) { - windowId = _getMostRecentPeasantID(true); + // TODO!: let this optionally be true, in the SummonWindowSelectionArgs + windowId = _getMostRecentPeasantID(false); } else { diff --git a/src/cascadia/WindowsTerminal/AppHost.cpp b/src/cascadia/WindowsTerminal/AppHost.cpp index 19acc879ae6..931e911271c 100644 --- a/src/cascadia/WindowsTerminal/AppHost.cpp +++ b/src/cascadia/WindowsTerminal/AppHost.cpp @@ -8,6 +8,7 @@ #include "../types/inc/User32Utils.hpp" #include "../WinRTUtils/inc/WtExeUtils.h" #include "resource.h" +#include "VirtualDesktopUtils.h" using namespace winrt::Windows::UI; using namespace winrt::Windows::UI::Composition; @@ -721,10 +722,52 @@ winrt::fire_and_forget AppHost::_createNewTerminalWindow(Settings::Model::Global co_return; } +GUID _currentlyActiveDesktop() +{ + // // HWND desktop = GetDesktopWindow(); + + // static const wchar_t* const PSEUDO_WINDOW_CLASS = L"Pseudo1ConsoleWindow"; + // WNDCLASS pseudoClass{ 0 }; + // pseudoClass.lpszClassName = PSEUDO_WINDOW_CLASS; + // pseudoClass.lpfnWndProc = DefWindowProc; + // RegisterClass(&pseudoClass); + // // Attempt to create window + // wil::unique_hwnd hwnd{ CreateWindowExW( + // 0, PSEUDO_WINDOW_CLASS, nullptr, WS_OVERLAPPEDWINDOW, 0, 0, 0, 0, HWND_DESKTOP, nullptr, nullptr, nullptr) }; + // HWND h = hwnd.get(); + // GUID currentDesktopGuid{ 0 }; + // try + // { + // const auto manager = winrt::create_instance(__uuidof(VirtualDesktopManager)); + // if (manager) + // { + // DebugBreak(); + // LOG_IF_FAILED(manager->GetWindowDesktopId(h, ¤tDesktopGuid)); + // } + // } + // CATCH_LOG(); + GUID currentDesktopGuid; + VirtualDesktopUtils::GetCurrentVirtualDesktopId(¤tDesktopGuid); + return currentDesktopGuid; +} + void AppHost::_HandleSummon(const winrt::Windows::Foundation::IInspectable& /*sender*/, const winrt::Windows::Foundation::IInspectable& /*args*/) { _window->SummonWindow(); + + const auto currentWindowDesktop{ _CurrentDesktopGuid() }; + const auto currentlyActiveDesktop{ _currentlyActiveDesktop() }; + // DebugBreak(); + try + { + const auto manager = winrt::create_instance(__uuidof(VirtualDesktopManager)); + if (manager) + { + LOG_IF_FAILED(manager->MoveWindowToDesktop(_window->GetHandle(), currentlyActiveDesktop)); + } + } + CATCH_LOG(); } GUID AppHost::_CurrentDesktopGuid() diff --git a/src/cascadia/WindowsTerminal/IslandWindow.cpp b/src/cascadia/WindowsTerminal/IslandWindow.cpp index 2c5612b02ad..aef5192ac73 100644 --- a/src/cascadia/WindowsTerminal/IslandWindow.cpp +++ b/src/cascadia/WindowsTerminal/IslandWindow.cpp @@ -916,7 +916,7 @@ void IslandWindow::UnsetHotkeys(const std::vector(hotkeyList.size()); i++) { LOG_IF_WIN32_BOOL_FALSE(UnregisterHotKey(_window.get(), i)); } diff --git a/src/cascadia/WindowsTerminal/VirtualDesktopUtils.cpp b/src/cascadia/WindowsTerminal/VirtualDesktopUtils.cpp new file mode 100644 index 00000000000..29ff96da18e --- /dev/null +++ b/src/cascadia/WindowsTerminal/VirtualDesktopUtils.cpp @@ -0,0 +1,141 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. +// +// Shamelessly copied from PowerToys + +#include "pch.h" + +#include "VirtualDesktopUtils.h" + +// Non-Localizable strings +namespace NonLocalizable +{ + const wchar_t RegCurrentVirtualDesktop[] = L"CurrentVirtualDesktop"; + const wchar_t RegVirtualDesktopIds[] = L"VirtualDesktopIDs"; + const wchar_t RegKeyVirtualDesktops[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\VirtualDesktops"; + const wchar_t RegKeyVirtualDesktopsFromSession[] = L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\SessionInfo\\%d\\VirtualDesktops"; +} + +namespace VirtualDesktopUtils +{ + bool GetDesktopIdFromCurrentSession(GUID* desktopId) + { + DWORD sessionId; + if (!ProcessIdToSessionId(GetCurrentProcessId(), &sessionId)) + { + return false; + } + + wchar_t sessionKeyPath[256]{}; + if (FAILED(StringCchPrintfW(sessionKeyPath, ARRAYSIZE(sessionKeyPath), NonLocalizable::RegKeyVirtualDesktopsFromSession, sessionId))) + { + return false; + } + + wil::unique_hkey key{}; + if (RegOpenKeyExW(HKEY_CURRENT_USER, sessionKeyPath, 0, KEY_ALL_ACCESS, &key) == ERROR_SUCCESS) + { + GUID value{}; + DWORD size = sizeof(GUID); + if (RegQueryValueExW(key.get(), NonLocalizable::RegCurrentVirtualDesktop, 0, nullptr, reinterpret_cast(&value), &size) == ERROR_SUCCESS) + { + *desktopId = value; + return true; + } + } + return false; + } + + bool GetVirtualDesktopIds(HKEY hKey, std::vector& ids) + { + if (!hKey) + { + return false; + } + DWORD bufferCapacity; + // request regkey binary buffer capacity only + if (RegQueryValueExW(hKey, NonLocalizable::RegVirtualDesktopIds, 0, nullptr, nullptr, &bufferCapacity) != ERROR_SUCCESS) + { + return false; + } + std::unique_ptr buffer = std::make_unique(bufferCapacity); + // request regkey binary content + if (RegQueryValueExW(hKey, NonLocalizable::RegVirtualDesktopIds, 0, nullptr, buffer.get(), &bufferCapacity) != ERROR_SUCCESS) + { + return false; + } + const size_t guidSize = sizeof(GUID); + std::vector temp; + temp.reserve(bufferCapacity / guidSize); + for (size_t i = 0; i < bufferCapacity; i += guidSize) + { + GUID* guid = reinterpret_cast(buffer.get() + i); + temp.push_back(*guid); + } + ids = std::move(temp); + return true; + } + + HKEY OpenVirtualDesktopsRegKey() + { + HKEY hKey{ nullptr }; + if (RegOpenKeyEx(HKEY_CURRENT_USER, NonLocalizable::RegKeyVirtualDesktops, 0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS) + { + return hKey; + } + return nullptr; + } + + HKEY GetVirtualDesktopsRegKey() + { + static wil::unique_hkey virtualDesktopsKey{ OpenVirtualDesktopsRegKey() }; + return virtualDesktopsKey.get(); + } + bool GetVirtualDesktopIds(std::vector& ids) + { + return GetVirtualDesktopIds(GetVirtualDesktopsRegKey(), ids); + } + + bool GetVirtualDesktopIds(std::vector& ids) + { + std::vector guids{}; + if (GetVirtualDesktopIds(guids)) + { + for (auto& guid : guids) + { + wil::unique_cotaskmem_string guidString; + if (SUCCEEDED(StringFromCLSID(guid, &guidString))) + { + ids.push_back(guidString.get()); + } + } + return true; + } + return false; + } + + bool GetCurrentVirtualDesktopId(GUID* desktopId) + { + // Explorer persists current virtual desktop identifier to registry on a per session basis, but only + // after first virtual desktop switch happens. If the user hasn't switched virtual desktops in this + // session, value in registry will be empty. + if (GetDesktopIdFromCurrentSession(desktopId)) + { + return true; + } + // Fallback scenario is to get array of virtual desktops stored in registry, but not kept per session. + // Note that we are taking first element from virtual desktop array, which is primary desktop. + // If user has more than one virtual desktop, previous function should return correct value, as desktop + // switch occurred in current session. + else + { + std::vector ids{}; + if (GetVirtualDesktopIds(ids) && ids.size() > 0) + { + *desktopId = ids[0]; + return true; + } + } + return false; + } +} diff --git a/src/cascadia/WindowsTerminal/VirtualDesktopUtils.h b/src/cascadia/WindowsTerminal/VirtualDesktopUtils.h new file mode 100644 index 00000000000..41ce71d068e --- /dev/null +++ b/src/cascadia/WindowsTerminal/VirtualDesktopUtils.h @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. +// Licensed under the MIT license. + +#pragma once + +namespace VirtualDesktopUtils +{ + bool GetCurrentVirtualDesktopId(GUID* desktopId); +} diff --git a/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj b/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj index fba24855f8e..806c83c0bf3 100644 --- a/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj +++ b/src/cascadia/WindowsTerminal/WindowsTerminal.vcxproj @@ -48,6 +48,7 @@ + @@ -57,6 +58,7 @@ +