Skip to content

Commit

Permalink
Dpi unaware placement bug - multimontior with same DPI settings fix (#…
Browse files Browse the repository at this point in the history
…2156)

* Dpi unaware placement bug - multimontior with same DPI settings fix

* Using different enumerating method

* Changed AllMonitorHaveSameDpiScaling method

* Removed accidental file

* small rename

* Changed some methods to CamelCase

* Review comments fixes
  • Loading branch information
PrzemyslawTusinski committed Apr 20, 2020
1 parent af4678f commit dcee505
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 54 deletions.
68 changes: 24 additions & 44 deletions src/common/monitors.cpp
Original file line number Diff line number Diff line change
@@ -1,84 +1,64 @@
#include "pch.h"

#include "common.h"
#include "monitors.h"

#include "common.h"

bool operator==(const ScreenSize& lhs, const ScreenSize& rhs)
{
auto lhs_tuple = std::make_tuple(lhs.rect.left, lhs.rect.right, lhs.rect.top, lhs.rect.bottom);
auto rhs_tuple = std::make_tuple(rhs.rect.left, rhs.rect.right, rhs.rect.top, rhs.rect.bottom);
return lhs_tuple == rhs_tuple;
}

static BOOL CALLBACK get_displays_enum_cb(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM data)
static BOOL CALLBACK GetDisplaysEnumCb(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM data)
{
MONITORINFOEX monitor_info;
monitor_info.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(monitor, &monitor_info);
reinterpret_cast<std::vector<MonitorInfo>*>(data)->emplace_back(monitor, monitor_info.rcWork);
MONITORINFOEX monitorInfo;
monitorInfo.cbSize = sizeof(MONITORINFOEX);
if (GetMonitorInfo(monitor, &monitorInfo))
{
reinterpret_cast<std::vector<MonitorInfo>*>(data)->emplace_back(monitor, monitorInfo.rcWork);
}
return true;
};

static BOOL CALLBACK get_displays_enum_cb_with_toolbar(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM data)
static BOOL CALLBACK GetDisplaysEnumCbWithNonWorkingArea(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM data)
{
MONITORINFOEX monitor_info;
monitor_info.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(monitor, &monitor_info);
reinterpret_cast<std::vector<MonitorInfo>*>(data)->emplace_back(monitor, monitor_info.rcMonitor);
MONITORINFOEX monitorInfo;
monitorInfo.cbSize = sizeof(MONITORINFOEX);
if (GetMonitorInfo(monitor, &monitorInfo))
{
reinterpret_cast<std::vector<MonitorInfo>*>(data)->emplace_back(monitor, monitorInfo.rcMonitor);
}
return true;
};

std::vector<MonitorInfo> MonitorInfo::GetMonitors(bool include_toolbar)
std::vector<MonitorInfo> MonitorInfo::GetMonitors(bool includeNonWorkingArea)
{
std::vector<MonitorInfo> monitors;
EnumDisplayMonitors(NULL, NULL, include_toolbar ? get_displays_enum_cb_with_toolbar : get_displays_enum_cb, reinterpret_cast<LPARAM>(&monitors));
EnumDisplayMonitors(NULL, NULL, includeNonWorkingArea ? GetDisplaysEnumCbWithNonWorkingArea : GetDisplaysEnumCb, reinterpret_cast<LPARAM>(&monitors));
std::sort(begin(monitors), end(monitors), [](const MonitorInfo& lhs, const MonitorInfo& rhs) {
return lhs.rect < rhs.rect;
});
return monitors;
}

int MonitorInfo::GetMonitorsCount()
static BOOL CALLBACK GetPrimaryDisplayEnumCb(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM data)
{
return GetMonitors(true).size();
}
MONITORINFOEX monitorInfo;
monitorInfo.cbSize = sizeof(MONITORINFOEX);

static BOOL CALLBACK get_primary_display_enum_cb(HMONITOR monitor, HDC hdc, LPRECT rect, LPARAM data)
{
MONITORINFOEX monitor_info;
monitor_info.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(monitor, &monitor_info);
if (monitor_info.dwFlags & MONITORINFOF_PRIMARY)
if (GetMonitorInfo(monitor, &monitorInfo) && (monitorInfo.dwFlags & MONITORINFOF_PRIMARY))
{
reinterpret_cast<MonitorInfo*>(data)->handle = monitor;
reinterpret_cast<MonitorInfo*>(data)->rect = monitor_info.rcWork;
reinterpret_cast<MonitorInfo*>(data)->rect = monitorInfo.rcWork;
}
return true;
};

MonitorInfo MonitorInfo::GetPrimaryMonitor()
{
MonitorInfo primary({}, {});
EnumDisplayMonitors(NULL, NULL, get_primary_display_enum_cb, reinterpret_cast<LPARAM>(&primary));
EnumDisplayMonitors(NULL, NULL, GetPrimaryDisplayEnumCb, reinterpret_cast<LPARAM>(&primary));
return primary;
}

MonitorInfo MonitorInfo::GetFromWindow(HWND hwnd)
{
auto monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
return GetFromHandle(monitor);
}

MonitorInfo MonitorInfo::GetFromPoint(POINT p)
{
auto monitor = MonitorFromPoint(p, MONITOR_DEFAULTTONEAREST);
return GetFromHandle(monitor);
}

MonitorInfo MonitorInfo::GetFromHandle(HMONITOR monitor)
{
MONITORINFOEX monitor_info;
monitor_info.cbSize = sizeof(MONITORINFOEX);
GetMonitorInfo(monitor, &monitor_info);
return MonitorInfo(monitor, monitor_info.rcWork);
}
10 changes: 1 addition & 9 deletions src/common/monitors.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,8 @@ struct MonitorInfo : ScreenSize
HMONITOR handle;

// Returns monitor rects ordered from left to right
static std::vector<MonitorInfo> GetMonitors(bool include_toolbar);
static int GetMonitorsCount();
// Return primary display
static std::vector<MonitorInfo> GetMonitors(bool includeNonWorkingArea);
static MonitorInfo GetPrimaryMonitor();
// Return monitor on which hwnd window is displayed
static MonitorInfo GetFromWindow(HWND hwnd);
// Return monitor nearest to a point
static MonitorInfo GetFromPoint(POINT p);
// Return monitor info given a HMONITOR
static MonitorInfo GetFromHandle(HMONITOR monitor);
};

bool operator==(const ScreenSize& lhs, const ScreenSize& rhs);
44 changes: 43 additions & 1 deletion src/modules/fancyzones/lib/Zone.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
#include "pch.h"


#include <Shellscalingapi.h>

#include <common/dpi_aware.h>
#include <common/monitors.h>
#include "Zone.h"
Expand Down Expand Up @@ -68,6 +71,45 @@ void Zone::SizeWindowToZone(HWND window, HWND zoneWindow) noexcept
SizeWindowToRect(window, ComputeActualZoneRect(window, zoneWindow));
}

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;
}

RECT Zone::ComputeActualZoneRect(HWND window, HWND zoneWindow) noexcept
{
// Take care of 1px border
Expand Down Expand Up @@ -101,7 +143,7 @@ RECT Zone::ComputeActualZoneRect(HWND window, HWND zoneWindow) noexcept
const auto taskbar_top_size = std::abs(mi.rcMonitor.top - mi.rcWork.top);
OffsetRect(&newWindowRect, -taskbar_left_size, -taskbar_top_size);

if (accountForUnawareness && MonitorInfo::GetMonitorsCount() > 1)
if (accountForUnawareness && !allMonitorsHaveSameDpiScaling())
{
newWindowRect.left = max(mi.rcMonitor.left, newWindowRect.left);
newWindowRect.right = min(mi.rcMonitor.right - taskbar_left_size, newWindowRect.right);
Expand Down

0 comments on commit dcee505

Please sign in to comment.