Files
PowerToys/src/common/Display/DisplayUtils.cpp

144 lines
5.0 KiB
C++
Raw Normal View History

[New Module] Workspaces (#34324) * spell checker * Adding OOBE Projects page * changed the default hotkey * module interface * rename projects editor * bug report tool * installer * gpo * exit event constant * extend search for projects by search over the containing apps' names * [Projects] fix grammatical issue #43 (1 app - many apps) * [Projects] Editor: Main page: fix layout if there are many apps, launch button not disappearing on the right side * dsc * github * pipeline * guid prefix * [Projects] fixing general settings gpo handling in runner + minor changes * arm build fix * Do not allow saving project if name or applist is empty. Also minor UI changes * version * editor version * spellcheck * editor dll signing * update projects names to filter them out * shortcut saving fix * [Projects] Editor: brining the highlighted app's icon into the foreground. + minor UI fixes * spell checker * spellcheck * [Projects] re-implementing icon size calculation to have similar sized icons for every app. * [projects] Adding info message for cases: there are no projects or no results for the search * [Projects] Adding Edit button to the popup. + minor changes * [Projects] Making popup having rounded corners * changed "no projects" text color and position * remove opening the first proj * fix placing windows of the same app in the project * [Projects] bringing back the breadcrumb on the editor page. Make it clickable. * [Projects] optimizing click handlers * [Projects] Removing not selected apps on save * moved on thread executor to common * moved display utils * added convert rect * unsigned monitor number * set awareness * app placement * [Projects] Re-implementing preview drawing - one common image * [Projects] fix boundary calculation, use DPI aware values * fix launching with command line args * Fix ARM64 CI build * launch packaged apps using names when possible * spell-check * update packaged apps path * projects editor single instance * [Projects] Add Select all checkbox, Delete selected button * Add Checkbox for per monitor selection * modifying highlight in preview * spell checker * logs * exclude help windows https://github.com/JaneaSystems/PowerToys-DevProjects/issues/49 * Add intermediate step to project creation * minor bugfix * mutex fix * modifying highlight for minimized apps * Fixing bug: re-draw the preview on app deletion in the editor * Adding helper class for getting the right bounds for screens * spell checker * spell checker * Minor fixes in the capture dialog * get dpi unaware screen bounds * refactoring: added utils * changed window filter https://github.com/JaneaSystems/PowerToys-DevProjects/issues/2 * clean up * refactoring * projects common lib * localizable default project prefix * launcher resources * clean up * change snapshot project saving https://github.com/JaneaSystems/PowerToys-DevProjects/issues/14 * changed project data https://github.com/JaneaSystems/PowerToys-DevProjects/issues/14 * changed project creation save-cancel handles https://github.com/JaneaSystems/PowerToys-DevProjects/issues/14 * spell-check * Remove checkboxes, delete feature * remove unused from the project * get command line args in the snapshot * minimized settings snap fix * set window property after launching * FZ: ignore projects launched windows * Implementing major new features: remove button, position manipulation, arguments, admin, minimized, maximized * modifying colors * launcher project filters * clean up * Hide Admin checkbox * hide WIP * spell-check * Revert "Hide Admin checkbox" This reverts commit 3036df9d7fe48de6418b0ebeff6422d535cb25e2. * get app elevated property * Implementing Launch and Edit feature * fixing: update of listed projects on the main page after hitting save in editor * Fix for packaged app's icons * fixing scroll speed issue * change scroll speed to 15 * launch elevated apps * minor fixes * minor fix * enhancing shortcut handling * can-launch-elevated check * projects module interface telemetry * Implementing store of setting "order by". * minor string correction * moved projects data parsing * telemetry * add move apps checkbox * notification about elevated apps * restart unelevated * move existing windows * keep opened windows at the same positions * handle powertoys settings * use common theme * fix corrupted data: project id and monitor id * project launch on "launch and edit" * clean up * show screen numbers instead of monitor names * launcher error messages * fix default shortcut * Adding launch button to projects settings, dashboard and flyout * Adding new app which is launched when launching a project. It shows the status of the launch process * spell checker * Renaming Projects to App Layouts. Replacing only string values, not the variable names * Re-ordering modules after Renaming Projects + spell checker * setting window size according to the screen (making it bigger) * commenting out feature "move apps if exist" * spell checker * Add ProjectsLauncherUI to signing * opening apps in minimized state which are placed on a monitor, which is not found at the moment of launching * consistent file name * removed unused sln * telemetry: create event * WindowPosition comparison * telemetry: edit event * fix muted Launch as admin checkbox * telemetry: delete event * updated Edit telemetry event * added invoke point to launcher args * added utils * parse invoke point * replaced tuple with struct * telemetry: launch event * MonitorRect comparison * resources * rename: folders * remove outdated * rename: window property * rename: files and folders * rename: common data structures * rename: telemetry namespace * rename: workspaces data * rename ProjectsLib -> WorkspacesLib * rename: gpo * rename: settings * rename: launcher UI * rename: other * rename: pt run * rename: fz * rename: module interface * rename: icon * rename: snapshot tool * rename: editor * rename: common files * rename: launcher * rename: editor resources * fix empty file crash * rename: json * rename: module interface * fix custom actions build * added launch editor event constant * xaml formatting * Add missing method defition to interop::Constants idl Remove Any CPU config * more .sln cleanup * [Run][PowerToys] Fix Workspaces utility (#34336) polished workspaces utility * build fix - align CppWinRT version * address PR comment: fix isdigit * indentation * address PR comment: rename function * address PR comment: changed version for workspaces and revision * added supported version definition * addressPR comment: use BringToForeground * address PR comments: updated projects * address PR comment: uncomment gpo in settings * address PR comment: rename oobe view * update OOBE image with current module name * moved AppUtils * launching with AppUserModel.ID * fixed module order in settings * fix xaml formatting * [Workspaces] Close launcher if there are failed launches. Plus adding new spinner gif * fix topmost LauncherUI * clean up * UI closing * BugReportTool - omit cmd arg data * Delete icon on workspace removal * Adding cancellation to launcher UI. * reordered launching * fix terminating UI * Removing old shortcut on workspace renaming * Sentence case labels * get process path without waiting * comment out unused * remove unused argument * logs * New icon * fix launch and edit for the new project * fix launch and edit: save new project * Update exe icons --------- Co-authored-by: donlaci <laszlo@janeasystems.com> Co-authored-by: Jaime Bernardo <jaime@janeasystems.com> Co-authored-by: Stefan Markovic <stefan@janeasystems.com> Co-authored-by: Davide Giacometti <davide.giacometti@outlook.it> Co-authored-by: Niels Laute <niels.laute@live.nl>
2024-08-23 09:28:13 +02:00
#include "DisplayUtils.h"
#include <algorithm>
#include <cwctype>
#include <iterator>
#include <dpi_aware.h>
#include <MonitorEnumerator.h>
#include <utils/OnThreadExecutor.h>
namespace DisplayUtils
{
std::wstring remove_non_digits(const std::wstring& input)
{
std::wstring result;
std::copy_if(input.begin(), input.end(), std::back_inserter(result), [](wchar_t ch) { return std::iswdigit(ch); });
return result;
}
std::pair<std::wstring, std::wstring> SplitDisplayDeviceId(const std::wstring& str) noexcept
{
// format: \\?\DISPLAY#{device id}#{instance id}#{some other id}
// example: \\?\DISPLAY#GSM1388#4&125707d6&0&UID8388688#{e6f07b5f-ee97-4a90-b076-33f57bf4eaa7}
// output: { GSM1388, 4&125707d6&0&UID8388688 }
size_t nameStartPos = str.find_first_of('#');
size_t uidStartPos = str.find('#', nameStartPos + 1);
size_t uidEndPos = str.find('#', uidStartPos + 1);
if (nameStartPos == std::string::npos || uidStartPos == std::string::npos || uidEndPos == std::string::npos)
{
return { str, L"" };
}
return { str.substr(nameStartPos + 1, uidStartPos - nameStartPos - 1), str.substr(uidStartPos + 1, uidEndPos - uidStartPos - 1) };
}
std::pair<bool, std::vector<DisplayUtils::DisplayData>> GetDisplays()
{
bool success = true;
std::vector<DisplayUtils::DisplayData> result{};
auto allMonitors = MonitorEnumerator::Enumerate();
OnThreadExecutor dpiUnawareThread;
dpiUnawareThread.submit(OnThreadExecutor::task_t{ [&] {
SetThreadDpiAwarenessContext(DPI_AWARENESS_CONTEXT_UNAWARE);
SetThreadDpiHostingBehavior(DPI_HOSTING_BEHAVIOR_MIXED);
} }).wait();
for (auto& monitorData : allMonitors)
{
MONITORINFOEX monitorInfo = monitorData.second;
MONITORINFOEX dpiUnawareMonitorInfo{};
dpiUnawareThread.submit(OnThreadExecutor::task_t{ [&] {
dpiUnawareMonitorInfo.cbSize = sizeof(dpiUnawareMonitorInfo);
if (!GetMonitorInfo(monitorData.first, &dpiUnawareMonitorInfo))
{
return;
}
} }).wait();
UINT dpi = 0;
if (DPIAware::GetScreenDPIForMonitor(monitorData.first, dpi) != S_OK)
{
success = false;
break;
}
DisplayUtils::DisplayData data{
.monitor = monitorData.first,
.dpi = dpi,
.monitorRectDpiAware = monitorInfo.rcMonitor,
.monitorRectDpiUnaware = dpiUnawareMonitorInfo.rcMonitor,
};
bool foundActiveMonitor = false;
DISPLAY_DEVICE displayDevice{ .cb = sizeof(displayDevice) };
DWORD displayDeviceIndex = 0;
while (EnumDisplayDevicesW(monitorInfo.szDevice, displayDeviceIndex, &displayDevice, EDD_GET_DEVICE_INTERFACE_NAME))
{
/*
* if (WI_IsFlagSet(displayDevice.StateFlags, DISPLAY_DEVICE_ACTIVE) &&
WI_IsFlagClear(displayDevice.StateFlags, DISPLAY_DEVICE_MIRRORING_DRIVER))
*/
if (((displayDevice.StateFlags & DISPLAY_DEVICE_ACTIVE) == DISPLAY_DEVICE_ACTIVE) &&
(displayDevice.StateFlags & DISPLAY_DEVICE_MIRRORING_DRIVER) == 0)
{
// Find display devices associated with the display.
foundActiveMonitor = true;
break;
}
displayDeviceIndex++;
}
if (foundActiveMonitor)
{
auto deviceId = SplitDisplayDeviceId(displayDevice.DeviceID);
data.id = deviceId.first;
data.instanceId = deviceId.second;
try
{
std::wstring numberStr = displayDevice.DeviceName; // \\.\DISPLAY1\Monitor0
numberStr = numberStr.substr(0, numberStr.find_last_of('\\')); // \\.\DISPLAY1
numberStr = remove_non_digits(numberStr);
data.number = std::stoi(numberStr);
}
catch (...)
{
success = false;
break;
}
}
else
{
success = false;
// Use the display name as a fallback value when no proper device was found.
data.id = monitorInfo.szDevice;
data.instanceId = L"";
try
{
std::wstring numberStr = monitorInfo.szDevice; // \\.\DISPLAY1
numberStr = remove_non_digits(numberStr);
data.number = std::stoi(numberStr);
}
catch (...)
{
success = false;
break;
}
}
result.push_back(data);
}
return { success, result };
}
}