2019-09-05 00:26:26 +08:00
|
|
|
#include "pch.h"
|
|
|
|
|
2020-04-21 00:09:10 +08:00
|
|
|
|
|
|
|
#include <Shellscalingapi.h>
|
|
|
|
|
2019-12-17 17:34:45 +08:00
|
|
|
#include <common/dpi_aware.h>
|
|
|
|
#include <common/monitors.h>
|
2019-12-17 16:21:46 +08:00
|
|
|
#include "Zone.h"
|
|
|
|
#include "Settings.h"
|
2020-04-10 22:09:08 +08:00
|
|
|
#include "util.h"
|
2019-12-17 16:21:46 +08:00
|
|
|
|
2020-04-15 18:34:11 +08:00
|
|
|
#include "common/monitors.h"
|
|
|
|
|
2019-09-05 00:26:26 +08:00
|
|
|
struct Zone : winrt::implements<Zone, IZone>
|
|
|
|
{
|
|
|
|
public:
|
|
|
|
Zone(RECT zoneRect) :
|
|
|
|
m_zoneRect(zoneRect)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
|
|
|
IFACEMETHODIMP_(RECT) GetZoneRect() noexcept { return m_zoneRect; }
|
|
|
|
IFACEMETHODIMP_(void) SetId(size_t id) noexcept { m_id = id; }
|
|
|
|
IFACEMETHODIMP_(size_t) Id() noexcept { return m_id; }
|
2020-04-10 22:09:08 +08:00
|
|
|
IFACEMETHODIMP_(RECT) ComputeActualZoneRect(HWND window, HWND zoneWindow) noexcept;
|
2019-09-05 00:26:26 +08:00
|
|
|
|
|
|
|
private:
|
|
|
|
RECT m_zoneRect{};
|
|
|
|
size_t m_id{};
|
|
|
|
std::map<HWND, RECT> m_windows{};
|
|
|
|
};
|
|
|
|
|
2020-04-21 00:09:10 +08:00
|
|
|
static BOOL CALLBACK saveDisplayToVector(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM data)
|
|
|
|
{
|
|
|
|
reinterpret_cast<std::vector<HMONITOR>*>(data)->emplace_back(monitor);
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool allMonitorsHaveSameDpiScaling()
|
|
|
|
{
|
|
|
|
std::vector<HMONITOR> monitors;
|
|
|
|
EnumDisplayMonitors(NULL, NULL, saveDisplayToVector, reinterpret_cast<LPARAM>(&monitors));
|
|
|
|
|
|
|
|
if (monitors.size() < 2)
|
|
|
|
{
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
UINT firstMonitorDpiX;
|
|
|
|
UINT firstMonitorDpiY;
|
|
|
|
|
|
|
|
if (S_OK != GetDpiForMonitor(monitors[0], MDT_EFFECTIVE_DPI, &firstMonitorDpiX, &firstMonitorDpiY))
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 1; i < monitors.size(); i++)
|
|
|
|
{
|
|
|
|
UINT iteratedMonitorDpiX;
|
|
|
|
UINT iteratedMonitorDpiY;
|
|
|
|
|
|
|
|
if (S_OK != GetDpiForMonitor(monitors[i], MDT_EFFECTIVE_DPI, &iteratedMonitorDpiX, &iteratedMonitorDpiY) ||
|
|
|
|
iteratedMonitorDpiX != firstMonitorDpiX)
|
|
|
|
{
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
2020-04-10 22:09:08 +08:00
|
|
|
RECT Zone::ComputeActualZoneRect(HWND window, HWND zoneWindow) noexcept
|
|
|
|
{
|
2019-09-05 00:26:26 +08:00
|
|
|
// Take care of 1px border
|
2020-04-09 00:22:43 +08:00
|
|
|
RECT newWindowRect = m_zoneRect;
|
2019-09-05 00:26:26 +08:00
|
|
|
|
|
|
|
RECT windowRect{};
|
|
|
|
::GetWindowRect(window, &windowRect);
|
|
|
|
|
|
|
|
RECT frameRect{};
|
2019-12-17 17:34:45 +08:00
|
|
|
|
|
|
|
const auto level = DPIAware::GetAwarenessLevel(GetWindowDpiAwarenessContext(window));
|
|
|
|
const bool accountForUnawareness = level < DPIAware::PER_MONITOR_AWARE;
|
2020-04-15 18:34:11 +08:00
|
|
|
|
2019-09-05 00:26:26 +08:00
|
|
|
if (SUCCEEDED(DwmGetWindowAttribute(window, DWMWA_EXTENDED_FRAME_BOUNDS, &frameRect, sizeof(frameRect))))
|
|
|
|
{
|
2020-04-15 18:34:11 +08:00
|
|
|
LONG leftMargin = frameRect.left - windowRect.left;
|
|
|
|
LONG rightMargin = frameRect.right - windowRect.right;
|
|
|
|
LONG bottomMargin = frameRect.bottom - windowRect.bottom;
|
|
|
|
newWindowRect.left -= leftMargin;
|
|
|
|
newWindowRect.right -= rightMargin;
|
|
|
|
newWindowRect.bottom -= bottomMargin;
|
2019-09-05 00:26:26 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
// Map to screen coords
|
2020-04-09 00:22:43 +08:00
|
|
|
MapWindowRect(zoneWindow, nullptr, &newWindowRect);
|
2019-09-17 20:36:59 +08:00
|
|
|
|
2020-04-09 00:22:43 +08:00
|
|
|
MONITORINFO mi{ sizeof(mi) };
|
2019-10-15 03:17:55 +08:00
|
|
|
if (GetMonitorInfoW(MonitorFromWindow(zoneWindow, MONITOR_DEFAULTTONEAREST), &mi))
|
|
|
|
{
|
2019-12-17 17:34:45 +08:00
|
|
|
const auto taskbar_left_size = std::abs(mi.rcMonitor.left - mi.rcWork.left);
|
|
|
|
const auto taskbar_top_size = std::abs(mi.rcMonitor.top - mi.rcWork.top);
|
2020-04-09 00:22:43 +08:00
|
|
|
OffsetRect(&newWindowRect, -taskbar_left_size, -taskbar_top_size);
|
2020-04-15 18:34:11 +08:00
|
|
|
|
2020-04-21 00:09:10 +08:00
|
|
|
if (accountForUnawareness && !allMonitorsHaveSameDpiScaling())
|
2019-12-17 17:34:45 +08:00
|
|
|
{
|
2020-04-09 00:22:43 +08:00
|
|
|
newWindowRect.left = max(mi.rcMonitor.left, newWindowRect.left);
|
|
|
|
newWindowRect.right = min(mi.rcMonitor.right - taskbar_left_size, newWindowRect.right);
|
|
|
|
newWindowRect.top = max(mi.rcMonitor.top, newWindowRect.top);
|
|
|
|
newWindowRect.bottom = min(mi.rcMonitor.bottom - taskbar_top_size, newWindowRect.bottom);
|
2019-12-17 17:34:45 +08:00
|
|
|
}
|
2019-10-15 03:17:55 +08:00
|
|
|
}
|
|
|
|
|
2020-04-09 00:22:43 +08:00
|
|
|
if ((::GetWindowLong(window, GWL_STYLE) & WS_SIZEBOX) == 0)
|
|
|
|
{
|
|
|
|
newWindowRect.right = newWindowRect.left + (windowRect.right - windowRect.left);
|
|
|
|
newWindowRect.bottom = newWindowRect.top + (windowRect.bottom - windowRect.top);
|
|
|
|
}
|
|
|
|
|
2020-04-10 22:09:08 +08:00
|
|
|
return newWindowRect;
|
2019-09-05 00:26:26 +08:00
|
|
|
}
|
|
|
|
|
2020-02-10 21:59:51 +08:00
|
|
|
winrt::com_ptr<IZone> MakeZone(const RECT& zoneRect) noexcept
|
2019-09-05 00:26:26 +08:00
|
|
|
{
|
|
|
|
return winrt::make_self<Zone>(zoneRect);
|
2019-12-17 17:34:45 +08:00
|
|
|
}
|