mirror of
https://github.com/microsoft/PowerToys.git
synced 2024-11-27 14:59:16 +08:00
[Workspaces]Fix Steam repositioning (#35101)
* moved and simplified logic * address PR comment
This commit is contained in:
parent
ff17e3dec9
commit
6bab73777b
@ -2,8 +2,9 @@
|
||||
#include "AppUtils.h"
|
||||
|
||||
#include <atlbase.h>
|
||||
#include <ShlObj.h>
|
||||
#include <propvarutil.h>
|
||||
#include <ShlObj.h>
|
||||
#include <TlHelp32.h>
|
||||
|
||||
#include <filesystem>
|
||||
|
||||
@ -28,6 +29,7 @@ namespace Utils
|
||||
constexpr const wchar_t* PowerToys = L"PowerToys.exe";
|
||||
constexpr const wchar_t* PowerToysSettingsUpper = L"POWERTOYS.SETTINGS.EXE";
|
||||
constexpr const wchar_t* PowerToysSettings = L"PowerToys.Settings.exe";
|
||||
constexpr const wchar_t* ApplicationFrameHost = L"APPLICATIONFRAMEHOST.EXE";
|
||||
}
|
||||
|
||||
AppList IterateAppsFolder()
|
||||
@ -184,11 +186,39 @@ namespace Utils
|
||||
return IterateAppsFolder();
|
||||
}
|
||||
|
||||
std::optional<AppData> GetApp(const std::wstring& appPath, const AppList& apps)
|
||||
DWORD GetParentPid(DWORD pid)
|
||||
{
|
||||
DWORD res = 0;
|
||||
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
PROCESSENTRY32 pe = { 0 };
|
||||
pe.dwSize = sizeof(PROCESSENTRY32);
|
||||
|
||||
if (Process32First(h, &pe))
|
||||
{
|
||||
do
|
||||
{
|
||||
if (pe.th32ProcessID == pid)
|
||||
{
|
||||
res = pe.th32ParentProcessID;
|
||||
}
|
||||
} while (Process32Next(h, &pe));
|
||||
}
|
||||
|
||||
CloseHandle(h);
|
||||
return res;
|
||||
}
|
||||
|
||||
std::optional<AppData> GetApp(const std::wstring& appPath, DWORD pid, const AppList& apps)
|
||||
{
|
||||
std::wstring appPathUpper(appPath);
|
||||
std::transform(appPathUpper.begin(), appPathUpper.end(), appPathUpper.begin(), towupper);
|
||||
|
||||
// filter out ApplicationFrameHost.exe
|
||||
if (appPathUpper.ends_with(NonLocalizable::ApplicationFrameHost))
|
||||
{
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
// edge case, "Windows Software Development Kit" has the same app path as "File Explorer"
|
||||
if (appPathUpper == NonLocalizable::FileExplorerPath)
|
||||
{
|
||||
@ -217,6 +247,7 @@ namespace Utils
|
||||
}
|
||||
}
|
||||
|
||||
// search in apps list
|
||||
for (const auto& appData : apps)
|
||||
{
|
||||
if (!appData.installPath.empty())
|
||||
@ -251,11 +282,43 @@ namespace Utils
|
||||
|
||||
if (appNameUpper == exeNameUpper)
|
||||
{
|
||||
return appData;
|
||||
auto result = appData;
|
||||
result.installPath = appPath;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// try with parent process (fix for Steam)
|
||||
auto parentPid = GetParentPid(pid);
|
||||
auto parentProcessPath = get_process_path(parentPid);
|
||||
|
||||
if (!parentProcessPath.empty())
|
||||
{
|
||||
std::wstring parentDirUpper = std::filesystem::path(parentProcessPath).parent_path().c_str();
|
||||
std::transform(parentDirUpper.begin(), parentDirUpper.end(), parentDirUpper.begin(), towupper);
|
||||
|
||||
if (appPathUpper.starts_with(parentDirUpper))
|
||||
{
|
||||
Logger::info(L"original process is in the subfolder of the parent process");
|
||||
|
||||
for (const auto& appData : apps)
|
||||
{
|
||||
if (!appData.installPath.empty())
|
||||
{
|
||||
std::wstring installDirUpper = std::filesystem::path(appData.installPath).parent_path().c_str();
|
||||
std::transform(installDirUpper.begin(), installDirUpper.end(), installDirUpper.begin(), towupper);
|
||||
|
||||
if (installDirUpper == parentDirUpper)
|
||||
{
|
||||
return appData;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return AppData{
|
||||
.name = std::filesystem::path(appPath).stem(),
|
||||
.installPath = appPath
|
||||
};
|
||||
}
|
||||
@ -263,7 +326,11 @@ namespace Utils
|
||||
std::optional<AppData> GetApp(HWND window, const AppList& apps)
|
||||
{
|
||||
std::wstring processPath = get_process_path(window);
|
||||
return Utils::Apps::GetApp(processPath, apps);
|
||||
|
||||
DWORD pid{};
|
||||
GetWindowThreadProcessId(window, &pid);
|
||||
|
||||
return Utils::Apps::GetApp(processPath, pid, apps);
|
||||
}
|
||||
}
|
||||
}
|
@ -19,7 +19,7 @@ namespace Utils
|
||||
const std::wstring& GetCurrentFolderUpper();
|
||||
|
||||
AppList GetAppsList();
|
||||
std::optional<AppData> GetApp(const std::wstring& appPath, const AppList& apps);
|
||||
std::optional<AppData> GetApp(const std::wstring& appPath, DWORD pid, const AppList& apps);
|
||||
std::optional<AppData> GetApp(HWND window, const AppList& apps);
|
||||
}
|
||||
}
|
@ -12,22 +12,12 @@
|
||||
#include <workspaces-common/WindowFilter.h>
|
||||
|
||||
#include <WorkspacesLib/AppUtils.h>
|
||||
#include <TlHelp32.h>
|
||||
|
||||
namespace SnapshotUtils
|
||||
{
|
||||
namespace NonLocalizable
|
||||
{
|
||||
const std::wstring ApplicationFrameHost = L"ApplicationFrameHost.exe";
|
||||
|
||||
namespace FileManagers
|
||||
{
|
||||
const std::wstring FileExplorer = L"EXPLORER"; // windows explorer
|
||||
const std::wstring TotalCommander = L"TOTALCMD"; // total commander
|
||||
const std::wstring DirectoryOpus = L"DOPUS"; // directory opus
|
||||
const std::wstring QDir = L"Q-DIR"; // Q-Dir
|
||||
const std::wstring Xplorer2 = L"XPLORER2"; // Xplorer2
|
||||
}
|
||||
}
|
||||
|
||||
class WbemHelper
|
||||
@ -178,39 +168,6 @@ namespace SnapshotUtils
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD GetParentPid(DWORD pid)
|
||||
{
|
||||
DWORD res = 0;
|
||||
HANDLE h = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||
PROCESSENTRY32 pe = { 0 };
|
||||
pe.dwSize = sizeof(PROCESSENTRY32);
|
||||
|
||||
if (Process32First(h, &pe))
|
||||
{
|
||||
do
|
||||
{
|
||||
if (pe.th32ProcessID == pid)
|
||||
{
|
||||
res = pe.th32ParentProcessID;
|
||||
}
|
||||
} while (Process32Next(h, &pe));
|
||||
}
|
||||
|
||||
CloseHandle(h);
|
||||
return res;
|
||||
}
|
||||
|
||||
bool IsFileManagerApp(std::wstring processPath)
|
||||
{
|
||||
std::wstring appName = std::filesystem::path(processPath).stem();
|
||||
std::transform(appName.begin(), appName.end(), appName.begin(), towupper);
|
||||
return ((appName == NonLocalizable::FileManagers::FileExplorer) // windows explorer
|
||||
|| (appName.starts_with(NonLocalizable::FileManagers::TotalCommander)) // total commander
|
||||
|| (appName == NonLocalizable::FileManagers::DirectoryOpus) // directory opus
|
||||
|| (appName == NonLocalizable::FileManagers::QDir) // Q-Dir
|
||||
|| (appName.starts_with(NonLocalizable::FileManagers::Xplorer2))); // Xplorer2
|
||||
}
|
||||
|
||||
std::vector<WorkspacesData::WorkspacesProject::Application> GetApps(const std::function<unsigned int(HWND)> getMonitorNumberFromWindowHandle)
|
||||
{
|
||||
std::vector<WorkspacesData::WorkspacesProject::Application> apps{};
|
||||
@ -285,83 +242,17 @@ namespace SnapshotUtils
|
||||
continue;
|
||||
}
|
||||
|
||||
auto data = Utils::Apps::GetApp(processPath, installedApps);
|
||||
auto data = Utils::Apps::GetApp(processPath, pid, installedApps);
|
||||
if (!data.has_value() || data->name.empty())
|
||||
{
|
||||
Logger::info(L"Installed app not found: {}, try parent process", processPath);
|
||||
|
||||
bool standaloneApp = false;
|
||||
bool steamLikeApp = false;
|
||||
|
||||
// try with parent process (fix for Steam)
|
||||
auto parentPid = GetParentPid(pid);
|
||||
auto parentProcessPath = get_process_path(parentPid);
|
||||
|
||||
// check if original process is in the subfolder of the parent process which is a sign of an steam-like app
|
||||
std::wstring processDir = std::filesystem::path(processPath).parent_path().c_str();
|
||||
std::wstring parentProcessDir = std::filesystem::path(parentProcessPath).parent_path().c_str();
|
||||
|
||||
if (parentProcessPath == L"")
|
||||
{
|
||||
if (processPath.ends_with(NonLocalizable::ApplicationFrameHost))
|
||||
{
|
||||
// filter out ApplicationFrameHost.exe
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::info(L"parent process unknown, the parent app is an already closed file manager app, it is a standalone app");
|
||||
standaloneApp = true;
|
||||
}
|
||||
}
|
||||
else if (processDir.starts_with(parentProcessDir))
|
||||
{
|
||||
Logger::info(L"parent process: {}, original process is in the subfolder of the parent process, it is a steam-like app", parentProcessPath);
|
||||
steamLikeApp = true;
|
||||
}
|
||||
else if (IsFileManagerApp(parentProcessPath))
|
||||
{
|
||||
Logger::info(L"parent process: {}, The parent process is a known file manager app, it is a standalone app", parentProcessPath);
|
||||
standaloneApp = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::info(L"parent process: {}, The parent process is NOT a known file manager app, it is a steam-like app", parentProcessPath);
|
||||
steamLikeApp = true;
|
||||
}
|
||||
|
||||
if (standaloneApp)
|
||||
{
|
||||
data = Utils::Apps::AppData{
|
||||
.name = std::filesystem::path(processPath).stem(),
|
||||
.installPath = processPath,
|
||||
};
|
||||
}
|
||||
else if (steamLikeApp)
|
||||
{
|
||||
if (!parentProcessPath.empty())
|
||||
{
|
||||
data = Utils::Apps::GetApp(parentProcessPath, installedApps);
|
||||
if (!data.has_value() || data->name.empty())
|
||||
{
|
||||
Logger::info(L"Installed parent app not found: {}", processPath);
|
||||
continue;
|
||||
}
|
||||
|
||||
processPath = parentProcessPath;
|
||||
}
|
||||
else
|
||||
{
|
||||
Logger::info(L"Parent process path not found");
|
||||
continue;
|
||||
}
|
||||
}
|
||||
Logger::info(L"Installed app not found: {}", processPath);
|
||||
continue;
|
||||
}
|
||||
|
||||
WorkspacesData::WorkspacesProject::Application app{
|
||||
.name = data.value().name,
|
||||
.title = title,
|
||||
.path = processPath,
|
||||
.path = data.value().installPath,
|
||||
.packageFullName = data.value().packageFullName,
|
||||
.appUserModelId = data.value().appUserModelId,
|
||||
.commandLineArgs = L"", // GetCommandLineArgs(pid, wbemHelper),
|
||||
|
@ -161,19 +161,16 @@ void WindowArranger::processWindow(HWND window)
|
||||
return;
|
||||
}
|
||||
|
||||
std::wstring title = WindowUtils::GetWindowTitle(window);
|
||||
if (title.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::wstring processPath = get_process_path(window);
|
||||
if (processPath.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto data = Utils::Apps::GetApp(processPath, m_installedApps);
|
||||
DWORD pid{};
|
||||
GetWindowThreadProcessId(window, &pid);
|
||||
|
||||
auto data = Utils::Apps::GetApp(processPath, pid, m_installedApps);
|
||||
if (!data.has_value())
|
||||
{
|
||||
return;
|
||||
@ -189,7 +186,6 @@ void WindowArranger::processWindow(HWND window)
|
||||
return;
|
||||
}
|
||||
|
||||
Logger::debug(L"Move {}", title);
|
||||
iter->second.window = window;
|
||||
if (moveWindow(window, iter->first))
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user