From 0f9f537040bdca074feb52226050e3c680c3003c Mon Sep 17 00:00:00 2001 From: joten Date: Mon, 25 Mar 2019 15:04:26 +0100 Subject: [PATCH] Added per-monitor display scaling awareness ... possibly mitigating issues #122 , #155 and #194 --- src/Bar.ahk | 12 +++---- src/Main.ahk | 1 + src/Manager.ahk | 5 +++ src/MonitorManager.ahk | 79 ++++++++++++++++++++++++++++++++++++++++++ src/Window.ahk | 3 +- 5 files changed, 93 insertions(+), 7 deletions(-) create mode 100644 src/MonitorManager.ahk diff --git a/src/Bar.ahk b/src/Bar.ahk index 05cb311..cfb5a88 100644 --- a/src/Bar.ahk +++ b/src/Bar.ahk @@ -22,10 +22,10 @@ Bar_init(m) { } Else wndWidth := Config_barWidth - wndWidth := Round(wndWidth * Config_scalingFactor) + wndWidth := Round(wndWidth / mmngr1.monitors[m].scaleX) If (Config_verticalBarPos = "tray" And Monitor_#%m%_taskBarClass) { - Bar_ctrlHeight := Round(Bar_ctrlHeight * Config_scalingFactor) - Bar_height := Round(Bar_height * Config_scalingFactor) + Bar_ctrlHeight := Round(Bar_ctrlHeight / mmngr1.monitors[m].scaleY) + Bar_height := Round(Bar_height / mmngr1.monitors[m].scaleY) } Monitor_#%m%_barWidth := wndWidth @@ -116,13 +116,13 @@ Bar_init(m) { If (Config_horizontalBarPos = "left") x1 := 0 Else If (Config_horizontalBarPos = "right") - x1 := Monitor_#%m%_width - wndWidth / Config_scalingFactor + x1 := Monitor_#%m%_width - wndWidth * mmngr1.monitors[m].scaleX Else If (Config_horizontalBarPos = "center") - x1 := (Monitor_#%m%_width - wndWidth / Config_scalingFactor) / 2 + x1 := (Monitor_#%m%_width - wndWidth * mmngr1.monitors[m].scaleX) / 2 Else If (Config_horizontalBarPos >= 0) x1 := Config_horizontalBarPos Else If (Config_horizontalBarPos < 0) - x1 := Monitor_#%m%_width - wndWidth / Config_scalingFactor + Config_horizontalBarPos + x1 := Monitor_#%m%_width - wndWidth * mmngr1.monitors[m].scaleX + Config_horizontalBarPos If Not (Config_verticalBarPos = "tray" And Monitor_#%m%_taskBarClass) x1 += Monitor_#%m%_x x1 := Round(x1) diff --git a/src/Main.ahk b/src/Main.ahk index 1bfe2ab..0813cfd 100644 --- a/src/Main.ahk +++ b/src/Main.ahk @@ -191,3 +191,4 @@ Return #Include Tiler.ahk #Include View.ahk #Include Window.ahk +#Include %A_ScriptDir%\MonitorManager.ahk diff --git a/src/Manager.ahk b/src/Manager.ahk index d370715..9fb1808 100644 --- a/src/Manager.ahk +++ b/src/Manager.ahk @@ -38,12 +38,15 @@ Manager_init() doRestore := 1 } + mmngr1 := New MonitorManager() + mmngr2 := "" SysGet, Manager_monitorCount, MonitorCount Debug_logMessage("DEBUG[0] Manager_init: Found " . Manager_monitorCount . " monitor" . (Manager_monitorCount != 1 ? "s" . "") . ".", 0) Loop, % Manager_monitorCount { Sleep, % Config_shellMsgDelay Monitor_init(A_Index, doRestore) + Debug_logMessage("DEBUG[6] MonitorW: " . Monitor_#%A_Index%_width . ", MMW1: " . mmngr1.monitors[A_Index].width . ", MM1dpiX: " . mmngr1.monitors[A_Index].dpiX . ", MM1scaleX: " . mmngr1.monitors[A_Index].scaleX, 6) } Bar_initCmdGui() @@ -736,8 +739,10 @@ Manager_resetMonitorConfiguration() { } } Else { ;; Has the resolution of a monitor been changed? + mmngr2 := New MonitorManager() Loop, % Manager_monitorCount { Monitor_getWorkArea(A_Index) + Debug_logMessage("DEBUG[6] MonitorW: " . Monitor_#%A_Index%_width . ", MMW1: " . mmngr1.monitors[A_Index].width . ", MM1dpiX: " . mmngr1.monitors[A_Index].dpiX . ", MM1scaleX: " . mmngr1.monitors[A_Index].scaleX . ", MMW2: " . mmngr2.monitors[A_Index].width . ", MM2dpiX: " . mmngr2.monitors[A_Index].dpiX . ", MM2scaleX: " . mmngr2.monitors[A_Index].scaleX, 6) Bar_init(A_Index) } } diff --git a/src/MonitorManager.ahk b/src/MonitorManager.ahk new file mode 100644 index 0000000..a63a9a2 --- /dev/null +++ b/src/MonitorManager.ahk @@ -0,0 +1,79 @@ +/* +:title: bug.n/monitormanager +:copyright: (c) 2019 by joten +:license: GNU General Public License version 3 + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. +*/ + +class MonitorManager { + __New() { + ;; enum _PROCESS_DPI_AWARENESS + PROCESS_DPI_UNAWARE := 0 + PROCESS_SYSTEM_DPI_AWARE := 1 + PROCESS_PER_MONITOR_DPI_AWARE := 2 + ; DllCall("SHcore\SetProcessDpiAwareness", "UInt", PROCESS_PER_MONITOR_DPI_AWARE) + ;; InnI: Get per-monitor DPI scaling factor (https://www.autoitscript.com/forum/topic/189341-get-per-monitor-dpi-scaling-factor/?tab=comments#comment-1359832) + DPI_AWARENESS_CONTEXT_UNAWARE := -1 + DPI_AWARENESS_CONTEXT_SYSTEM_AWARE := -2 + DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE := -3 + DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2 := -4 + DllCall("User32\SetProcessDpiAwarenessContext", "UInt" , DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE_V2) + ;; pneumatic: -DPIScale not working properly (https://www.autohotkey.com/boards/viewtopic.php?p=241869&sid=abb2db983d2b3966bc040c3614c0971e#p241869) + + ptr := A_PtrSize ? "Ptr" : "UInt" + this.monitors := [] + DllCall("EnumDisplayMonitors", ptr, 0, ptr, 0, ptr, RegisterCallback("MonitorEnumProc", "", 4, &this), "UInt", 0) + ;; Solar: SysGet incorrectly identifies monitors (https://autohotkey.com/board/topic/66536-sysget-incorrectly-identifies-monitors/) + } +} + +MonitorEnumProc(hMonitor, hdcMonitor, lprcMonitor, dwData) { + l := NumGet(lprcMonitor + 0, 0, "UInt") + t := NumGet(lprcMonitor + 0, 4, "UInt") + r := NumGet(lprcMonitor + 0, 8, "UInt") + b := NumGet(lprcMonitor + 0, 12, "UInt") + + this := Object(A_EventInfo) + ;; Helgef: Allow RegisterCallback with BoundFunc objects (https://www.autohotkey.com/boards/viewtopic.php?p=235243#p235243) + this.monitors.push(New Monitor(hMonitor, l, t, r, b)) + + Return, 1 +} + +class Monitor { + __New(handle, left, top, right, bottom) { + this.handle := handle + this.left := left + this.top := top + this.right := right + this.bottom := bottom + + this.x := left + this.y := top + this.width := right - left + this.height := bottom - top + + dpi := this.getDpiForMonitor() + this.dpiX := dpi.x + this.dpiY := dpi.y + this.scaleX := this.dpiX / 96 + this.scaleY := this.dpiY / 96 + } + + getDpiForMonitor() { + ;; enum _MONITOR_DPI_TYPE + MDT_EFFECTIVE_DPI := 0 + MDT_ANGULAR_DPI := 1 + MDT_RAW_DPI := 2 + MDT_DEFAULT := MDT_EFFECTIVE_DPI + ptr := A_PtrSize ? "Ptr" : "UInt" + dpiX := dpiY := 0 + DllCall("SHcore\GetDpiForMonitor", ptr, this.handle, "Int", MDT_DEFAULT, "UInt*", dpiX, "UInt*", dpiY) + + Return, {x: dpiX, y: dpiY} + } + ;; InnI: Get per-monitor DPI scaling factor (https://www.autoitscript.com/forum/topic/189341-get-per-monitor-dpi-scaling-factor/?tab=comments#comment-1359832) +} diff --git a/src/Window.ahk b/src/Window.ahk index 68c8f20..bb277cd 100644 --- a/src/Window.ahk +++ b/src/Window.ahk @@ -271,6 +271,7 @@ Window_move(wndId, x, y, width, height) { Sleep, % Config_shellMsgDelay } ;If Not (wndMinMax = 1) Or Not Window_#%wndId%_isDecorated Or Manager_windowNotMaximized(width, height) { + If (mmngr2 == "") { If Window_getPosEx(wndId, wndX, wndY, wndW, wndH) And (Abs(wndX - x) > 1 Or Abs(wndY - y) > 1 Or Abs(wndW - width) > 1 Or Abs(wndH - height) > 1) { x -= wndX - x y -= wndY - y @@ -278,7 +279,7 @@ Window_move(wndId, x, y, width, height) { height += height - wndH - 1 WinMove, ahk_id %wndId%, , %x%, %y%, %width%, %height% } - ;} + } SendMessage, WM_EXITSIZEMOVE, , , , ahk_id %wndId% Return, 0