#REFACTORING by stefan
authorStefan Vogel <sv@exept.de>
Wed, 26 Feb 2020 17:05:17 +0100
changeset 9012 a49af25f3407
parent 9011 b80fbe026ed5
child 9013 60f67817f21c
#REFACTORING by stefan Move methods to instance size where they belong! class: WinWorkstation added: #convertTargetValue:targetMonitorInfo:minScaleFactor:monitorInfoTopOrLeftFetch: #convertVirtualResolutionPointToCurrentResolutionPoint: #isHighDpiAware #monitorBounds #monitorDeviceNameForPoint: #monitorInfoForName: #monitorRealResolutionByMonitorDeviceName: #monitorRealResolutionByPoint: #monitorScaleFactorFor: #monitorScaleFactorForView: #openViewWithBlock:view:at: #scaleFactorForRootViewTranslationOnMonitorNamed: #thisAppVirtualResolutionByMonitorDeviceName: #usableWidthAt: removed: #monitorHandleForName: comment/format in: #monitorInfoForPoint: #monitorInfos changed: #monitorHandleForView: #smallestMonitorHeight #translatePoint:from:to: class: WinWorkstation class removed: #isHighDpiAware #monitorRealResolutionByPoint: #monitorScaleFactorFor: #openViewWithBlock:view:at: comment/format in: #thisAppVirtualResolutionByMonitorDeviceName: changed: #convertVirtualResolutionPointToCurrentResolutionPoint: category of: #convertTargetValue:targetMonitorInfo:minScaleFactor:monitorInfoTopOrLeftFetch: #convertVirtualResolutionPointToCurrentResolutionPoint: #monitorDeviceNameForPoint: #monitorRealResolutionByMonitorDeviceName: #scaleFactorForRootViewTranslationOnMonitorNamed: #thisAppVirtualResolutionByMonitorDeviceName: class: WinWorkstation::MonitorInfo comment/format in: #isPrimary changed: #isCenterMonitor
WinWorkstation.st
--- a/WinWorkstation.st	Wed Feb 26 17:04:42 2020 +0100
+++ b/WinWorkstation.st	Wed Feb 26 17:05:17 2020 +0100
@@ -6283,61 +6283,6 @@
     "
 ! !
 
-!WinWorkstation class methodsFor:'converting'!
-
-convertVirtualResolutionPointToCurrentResolutionPoint:aPoint
-    "this is required when you want to access the root display coordinates correctly,
-     because may the os did scale the application (when the app is not high DPI aware),
-     and if the os do scale the application, the application gets a virtual display
-     with a diffrent resolution"
-
-    "
-	self convertVirtualResolutionPointToCurrentResolutionPoint:2000@400
-	self convertVirtualResolutionPointToCurrentResolutionPoint:2000@500
-    "
-
-    |centerMonitorDeviceName targetMonitorInfo minScaleFactor
-     scaledX scaledY|
-
-    centerMonitorDeviceName := Screen monitorDeviceNameForPoint:0@0.
-    centerMonitorDeviceName isNil ifTrue:[
-	self halt. "/ should not happen?
-	^ aPoint
-    ].
-
-    targetMonitorInfo := Display monitorInfoForPoint:aPoint.
-    (targetMonitorInfo isNil
-    or:[targetMonitorInfo isCenterMonitor]) ifTrue:[
-	"the point is not inside any monitor
-	 or is inside the center monitor
-	 use the center monitor scale factor"
-	^ (aPoint * (Screen scaleFactorForRootViewTranslationOnMonitorNamed:centerMonitorDeviceName)) rounded
-    ].
-
-    minScaleFactor := (Display monitorInfos
-	collect:[:eachMonitorInfo |
-	    Screen scaleFactorForRootViewTranslationOnMonitorNamed:eachMonitorInfo name
-	])
-	    min.
-
-    scaledX := self
-	convertTargetValue:aPoint x
-	targetMonitorInfo:targetMonitorInfo
-	minScaleFactor:minScaleFactor
-	monitorInfoTopOrLeftFetch:[:monitorInfo | monitorInfo screenX].
-
-    scaledY := self
-	convertTargetValue:aPoint y
-	targetMonitorInfo:targetMonitorInfo
-	minScaleFactor:minScaleFactor
-	monitorInfoTopOrLeftFetch:[:monitorInfo | monitorInfo screenY].
-
-    ^ scaledX@scaledY
-
-    "Created: / 22-11-2019 / 10:09:49 / Stefan Reise"
-    "Modified (comment): / 25-11-2019 / 14:23:47 / Stefan Reise"
-! !
-
 !WinWorkstation class methodsFor:'debugging'!
 
 bitmapHandleCounts
@@ -6645,85 +6590,7 @@
 %}
 ! !
 
-!WinWorkstation class methodsFor:'multi monitor support'!
-
-openViewWithBlock:openAction
-    view:aView
-    at:origin
-
-    "
-	HACK for multi monitor support.
-	sub views needs to be opened on the same monitor as their top view,
-	so that Windows create/place them into the same virtual resolution/display.
-	after the sub views are opened we can move them within the same virtual resolution/display.
-	to their actually origin
-    "
-
-    |application monitorInfo
-     originX originY
-     screenX screenY
-     tmpOriginX tmpOriginY
-     topView|
-
-    aView isNil ifTrue:[
-	^ super
-	    openViewWithBlock:openAction
-	    view:aView
-	    at:origin
-    ].
-
-    aView isMenu ifTrue:[
-	application := aView application.
-	application isNil ifTrue:[
-	    ^ super
-		openViewWithBlock:openAction
-		view:aView
-		at:origin
-	].
-
-	topView := application topView.
-    ] ifFalse:[
-	self halt. "/ find the real top view
-	topView := aView topView.
-    ].
-
-    topView isNil ifTrue:[
-	^ super
-	    openViewWithBlock:openAction
-	    view:aView
-	    at:origin
-    ].
-
-    monitorInfo := Display monitorInfoForView:topView.
-    monitorInfo isNil ifTrue:[
-	^ super
-	    openViewWithBlock:openAction
-	    view:aView
-	    at:origin
-    ].
-
-    originX := origin x.
-    originY := origin y.
-    screenX := monitorInfo screenX.
-    screenY := monitorInfo screenY.
-    tmpOriginX := originX.
-    tmpOriginY := originY.
-
-    origin x < screenX ifTrue:[
-	tmpOriginX := screenX.
-    ].
-    origin y < screenY ifTrue:[
-	tmpOriginY := screenY.
-    ].
-
-    aView origin:tmpOriginX@tmpOriginY.
-    openAction value.
-    aView origin:origin.
-
-    "Created: / 28-11-2019 / 17:54:32 / Stefan Reise"
-! !
-
-!WinWorkstation class methodsFor:'private'!
+!WinWorkstation class methodsFor:'obsolete private'!
 
 convertTargetValue:targetValue
     targetMonitorInfo:targetMonitorInfo
@@ -6759,107 +6626,59 @@
     "Created: / 25-11-2019 / 13:56:58 / Stefan Reise"
 !
 
-scaleFactorForRootViewTranslationOnMonitorNamed:aMonitorDeviceName
-    "this is the scale factor, we have to use,
-     when we work directly with the root view (desktop)
-
-     because we may have a virtual display,
-     but the screen (from which we take a screenshot for e.g.)
-     does always have the current resoltion,
-     therefor we have to translate from virtual to current resolution"
-
-    "
-	Screen scaleFactorForRootViewTranslationOnMonitorNamed:'\\.\DISPLAY1'.
-	Screen scaleFactorForRootViewTranslationOnMonitorNamed:'\\.\DISPLAY2'.
-    "
-
-    |currentMonitorResolution thisAppVirtualResolution|
-
-    currentMonitorResolution := Screen monitorRealResolutionByMonitorDeviceName:aMonitorDeviceName.
-    currentMonitorResolution isNil ifTrue:[
-	^ 1
-    ].
-
-    thisAppVirtualResolution := self thisAppVirtualResolutionByMonitorDeviceName:aMonitorDeviceName.
-    thisAppVirtualResolution isNil ifTrue:[
-	^ 1
-    ].
-
-    ^ currentMonitorResolution x / thisAppVirtualResolution x
-
-    "Created: / 21-11-2019 / 12:33:11 / Stefan Reise"
-    "Modified: / 25-11-2019 / 14:18:09 / Stefan Reise"
-! !
-
-!WinWorkstation class methodsFor:'queries'!
-
-isHighDpiAware
-    "answers if this app is high dpi aware"
-
-    "
-        Screen isHighDpiAware.
-    "
-
-    |isHighDpiAware|
-
-    isHighDpiAware := false.
-
-    (OperatingSystem isWin7Like
-    and:[OperatingSystem isWin8Like not]) ifTrue:[
-        "win 7 does not include Shcore.dll"    
-        ^ isHighDpiAware
-    ].
-
-%{
-        HINSTANCE hShcore = LoadLibrary("Shcore.dll");
-
-        if (hShcore) {
-            static HRESULT (__stdcall *P_GetProcessDpiAwareness)(HANDLE, VOID*);
-            P_GetProcessDpiAwareness = (HRESULT (__stdcall *)(HANDLE, VOID*))GetProcAddress(hShcore, "GetProcessDpiAwareness");
-
-            if (P_GetProcessDpiAwareness) {
-                UINT processDpiAwarness = 0;
-
-                if ((*P_GetProcessDpiAwareness)(NULL, &processDpiAwarness) == S_OK) {
-                    if (processDpiAwarness == 0) {
-                        isHighDpiAware = false;
-                    } else {
-                        isHighDpiAware = true;
-                    }
-                } else {
-                    console_fprintf(stderr, "Call \"GetProcessDpiAwareness()\" failed\n");
-                };
-            } else {
-                console_fprintf(stderr, "Loading \"GetProcessDpiAwareness()\" failed\n");
-            }
-        } else {
-            console_fprintf(stderr, "Loading \"Shcore.dll\" failed\n");
-        }
-%}.
-
-    ^ isHighDpiAware
-
-    "Created: / 27-11-2019 / 13:40:04 / Stefan Reise"
-    "Modified: / 11-02-2020 / 11:46:49 / Stefan Reise"
-!
-
-isWindowsPlatform
-    "return true, if this device is a windows screen"
-
-    ^ true
-!
-
-platformName
-    "ST-80 compatibility.
-     Return a string describing the display systems platform.
-     WinWorkstation always returns 'WIN32'."
-
-    ^ 'WIN32'
-
-    "Modified: 26.5.1996 / 15:32:46 / cg"
-! !
-
-!WinWorkstation class methodsFor:'queries - monitor'!
+convertVirtualResolutionPointToCurrentResolutionPoint:aPoint
+    "this is required when you want to access the root display coordinates correctly,
+     because may the os did scale the application (when the app is not high DPI aware),
+     and if the os do scale the application, the application gets a virtual display
+     with a different resolution"
+
+    |centerMonitorDeviceName targetMonitorInfo minScaleFactor
+     scaledX scaledY|
+
+    centerMonitorDeviceName := self monitorDeviceNameForPoint:0@0.
+    centerMonitorDeviceName isNil ifTrue:[
+        self halt. "/ should not happen?
+        ^ aPoint
+    ].
+
+    targetMonitorInfo := Display monitorInfoForPoint:aPoint.
+    (targetMonitorInfo isNil
+     or:[targetMonitorInfo isCenterMonitor]) ifTrue:[
+        "the point is not inside any monitor
+         or is inside the center monitor
+         use the center monitor scale factor"
+        ^ (aPoint * (self scaleFactorForRootViewTranslationOnMonitorNamed:centerMonitorDeviceName)) rounded
+    ].
+
+    minScaleFactor := (Display monitorInfos
+        collect:[:eachMonitorInfo |
+            self scaleFactorForRootViewTranslationOnMonitorNamed:eachMonitorInfo name
+        ])
+            min.
+
+    scaledX := self
+        convertTargetValue:aPoint x
+        targetMonitorInfo:targetMonitorInfo
+        minScaleFactor:minScaleFactor
+        monitorInfoTopOrLeftFetch:[:monitorInfo | monitorInfo screenX].
+
+    scaledY := self
+        convertTargetValue:aPoint y
+        targetMonitorInfo:targetMonitorInfo
+        minScaleFactor:minScaleFactor
+        monitorInfoTopOrLeftFetch:[:monitorInfo | monitorInfo screenY].
+
+    ^ scaledX@scaledY
+
+   "
+        self convertVirtualResolutionPointToCurrentResolutionPoint:2000@400
+        self convertVirtualResolutionPointToCurrentResolutionPoint:2000@500
+    "
+
+
+    "Created: / 22-11-2019 / 10:09:49 / Stefan Reise"
+    "Modified (comment): / 25-11-2019 / 14:23:47 / Stefan Reise"
+!
 
 monitorDeviceNameForPoint:aPoint
     "given a point, return its monitor device name or nil if failed"
@@ -6944,101 +6763,36 @@
     "Modified (format): / 25-11-2019 / 14:25:31 / Stefan Reise"
 !
 
-monitorRealResolutionByPoint:aPoint
-    "this is the real resolution of the display,
-     without any effect of os scaling
-
-     for e.g.
-	real resolution -> 1080p
-	os scaling 150%
-	virtual resolution -> 720p
-
-	real resolution -> 1080p
-	os scaling 100%
-	virtual resolution -> 1080p"
-
-    "
-	Screen monitorRealResolutionByPoint:nil.
-	Screen monitorRealResolutionByPoint:0@0.
-	Screen monitorRealResolutionByPoint:500@0.
-	Screen monitorRealResolutionByPoint:2000@0.
-    "
-
-    |monitorName|
-
-    aPoint isNil ifTrue:[
-	^ super monitorRealResolutionByPoint:aPoint
-    ].
-
-    monitorName := self monitorDeviceNameForPoint:aPoint.
-    monitorName isNil ifTrue:[
-	^ super monitorRealResolutionByPoint:aPoint
-    ].
-
-    ^ self monitorRealResolutionByMonitorDeviceName:monitorName
-
-    "Created: / 25-11-2019 / 12:19:40 / Stefan Reise"
-    "Modified (comment): / 25-11-2019 / 14:25:43 / Stefan Reise"
-!
-
-monitorScaleFactorFor:aMonitorHandle
-    "this method always returns the os scale factor,
-     regardless if the app is high dpi aware or not.
-
-     this is the scale factor the user did enter in the os settings,
-     for e.g. the user can choose between 100, 125, 150 etc.
-     here we return 1, 1.25 1.5"
-
-    "
-        Screen monitorScaleFactorFor:(Display monitorHandleForName:'\\.\DISPLAY1').
-        Screen monitorScaleFactorFor:(Display monitorHandleForName:'\\.\DISPLAY2').
-    "
-
-    |scaleFactor|
-
-    (OperatingSystem isWin7Like
-    and:[OperatingSystem isWin8Like not]) ifTrue:[
-        "win 7 does not include Shcore.dll"    
-        ^ super monitorScaleFactorFor:aMonitorHandle
-    ].
-
-%{
-    if (__isExternalAddress(aMonitorHandle)) {
-        HMONITOR hMonitor = (HMONITOR)(_HWNDVal(aMonitorHandle));
-        HINSTANCE hShcore = LoadLibrary("Shcore.dll");
-
-        if (hShcore) {
-            static HRESULT (__stdcall *P_GetScaleFactorForMonitor)(HMONITOR, VOID*);
-            P_GetScaleFactorForMonitor = (HRESULT (__stdcall *)(HMONITOR, VOID*))GetProcAddress(hShcore, "GetScaleFactorForMonitor");
-
-            if (P_GetScaleFactorForMonitor) {
-                UINT displayScaleFactor = 0;
-
-                if ((*P_GetScaleFactorForMonitor)(hMonitor, &displayScaleFactor) == S_OK) {
-                    scaleFactor = __MKSMALLINT(displayScaleFactor);
-                } else {
-                    console_fprintf(stderr, "Call \"GetScaleFactorForMonitor()\" failed\n");
-                };
-            } else {
-                console_fprintf(stderr, "Loading \"GetScaleFactorForMonitor()\" failed\n");
-            }
-        } else {
-            console_fprintf(stderr, "Loading \"Shcore.dll\" failed\n");
-        }
-    }
-%}.
-
-    scaleFactor isNil ifTrue:[
-        ^ super monitorScaleFactorFor:aMonitorHandle
-    ].
-    scaleFactor == 0 ifTrue:[
-        ^ super monitorScaleFactorFor:aMonitorHandle
-    ].
-
-    ^ scaleFactor / 100
-
-    "Created: / 25-11-2019 / 11:52:42 / Stefan Reise"
-    "Modified: / 11-02-2020 / 11:47:10 / Stefan Reise"
+scaleFactorForRootViewTranslationOnMonitorNamed:aMonitorDeviceName
+    "this is the scale factor, we have to use,
+     when we work directly with the root view (desktop)
+
+     because we may have a virtual display,
+     but the screen (from which we take a screenshot for e.g.)
+     does always have the current resoltion,
+     therefor we have to translate from virtual to current resolution"
+
+    "
+	Screen scaleFactorForRootViewTranslationOnMonitorNamed:'\\.\DISPLAY1'.
+	Screen scaleFactorForRootViewTranslationOnMonitorNamed:'\\.\DISPLAY2'.
+    "
+
+    |currentMonitorResolution thisAppVirtualResolution|
+
+    currentMonitorResolution := Screen monitorRealResolutionByMonitorDeviceName:aMonitorDeviceName.
+    currentMonitorResolution isNil ifTrue:[
+	^ 1
+    ].
+
+    thisAppVirtualResolution := self thisAppVirtualResolutionByMonitorDeviceName:aMonitorDeviceName.
+    thisAppVirtualResolution isNil ifTrue:[
+	^ 1
+    ].
+
+    ^ currentMonitorResolution x / thisAppVirtualResolution x
+
+    "Created: / 21-11-2019 / 12:33:11 / Stefan Reise"
+    "Modified: / 25-11-2019 / 14:18:09 / Stefan Reise"
 !
 
 thisAppVirtualResolutionByMonitorDeviceName:aMonitorDeviceName
@@ -7046,38 +6800,52 @@
      may (when a os scaling is defined and this app is not high dpi aware) effected by os scaling
 
      for e.g.
-	real current resolution -> 1080p
-	scaling 150%
-	virtual resolution -> 720p
-
-	real current resolution -> 1080p
-	scaling 100%
-	virtual resolution -> 1080p"
-
-    "
-	Screen thisAppVirtualResolutionByMonitorDeviceName:nil.
-	Screen thisAppVirtualResolutionByMonitorDeviceName:'ereswt'.
-	Screen thisAppVirtualResolutionByMonitorDeviceName:'\\.\DISPLAY1'.
-	Screen thisAppVirtualResolutionByMonitorDeviceName:'\\.\DISPLAY2'.
-    "
-
-    |monitorHandle monitorInfo|
-
-    monitorHandle := Display monitorHandleForName:aMonitorDeviceName.
-    monitorHandle isNil ifTrue:[
-	^ super thisAppVirtualResolutionByMonitorDeviceName:aMonitorDeviceName
-    ].
-
-    monitorInfo := Display monitorInfoFor:monitorHandle.
+        real current resolution -> 1080p
+        scaling 150%
+        virtual resolution -> 720p
+
+        real current resolution -> 1080p
+        scaling 100%
+        virtual resolution -> 1080p"
+
+    |monitorInfo|
+
+    monitorInfo := Display monitorInfoForName:aMonitorDeviceName.
     monitorInfo isNil ifTrue:[
-	^ super thisAppVirtualResolutionByMonitorDeviceName:aMonitorDeviceName
+        ^ Display extent
     ].
 
     ^ (monitorInfo screenWidth)@(monitorInfo screenHeight)
 
+    "
+        Screen thisAppVirtualResolutionByMonitorDeviceName:nil.
+        Screen thisAppVirtualResolutionByMonitorDeviceName:'ereswt'.
+        Screen thisAppVirtualResolutionByMonitorDeviceName:'\\.\DISPLAY1'.
+        Screen thisAppVirtualResolutionByMonitorDeviceName:'\\.\DISPLAY2'.
+    "
+
+
     "Created: / 25-11-2019 / 14:17:05 / Stefan Reise"
 ! !
 
+!WinWorkstation class methodsFor:'queries'!
+
+isWindowsPlatform
+    "return true, if this device is a windows screen"
+
+    ^ true
+!
+
+platformName
+    "ST-80 compatibility.
+     Return a string describing the display systems platform.
+     WinWorkstation always returns 'WIN32'."
+
+    ^ 'WIN32'
+
+    "Modified: 26.5.1996 / 15:32:46 / cg"
+! !
+
 !WinWorkstation methodsFor:'accessing & queries'!
 
 activateOnClick:aBoolean
@@ -8048,10 +7816,10 @@
      in aPoint and returns a device coordinate relative to the 2nd views origin.
      - use to xlate points from a window to rootwindow"
 
-    |x1 y1 x2 y2 ret|
-
-    x1 := x2 := aPoint x truncated.
-    y1 := y2 := aPoint y truncated.
+    |x1 y1 ret|
+
+    x1 := aPoint x truncated.
+    y1 := aPoint y truncated.
 
 %{
     HWND w1, w2;
@@ -8060,19 +7828,19 @@
     if (__isExternalAddress(windowId1)
      && __isExternalAddress(windowId2)
      && __bothSmallInteger(x1, y1)) {
-	w1 = _HWNDVal(windowId1);
-	w2 = _HWNDVal(windowId2);
-	point.x = __intVal(x1);
-	point.y = __intVal(y1);
-	CPRINTF(("TransPoint %x %d/%d ->", w1, point.x, point.y));
-	if (ClientToScreen(w1, &point) == FALSE) {
-	    RETURN (nil);
-	}
-	if (ScreenToClient(w2, &point) == FALSE) {
-	    RETURN (nil);
-	}
-	CPRINTF((" %x %d/%d\n", w2, point.x, point.y));
-	ret = __MKPOINT_INT(point.x, point.y);
+        w1 = _HWNDVal(windowId1);
+        w2 = _HWNDVal(windowId2);
+        point.x = __intVal(x1);
+        point.y = __intVal(y1);
+        CPRINTF(("TransPoint %x %d/%d ->", w1, point.x, point.y));
+        if (ClientToScreen(w1, &point) == FALSE) {
+            RETURN (nil);
+        }
+        if (ScreenToClient(w2, &point) == FALSE) {
+            RETURN (nil);
+        }
+        CPRINTF((" %x %d/%d\n", w2, point.x, point.y));
+        ret = __MKPOINT_INT(point.x, point.y);
     }
 %}.
     ^ ret
@@ -8167,6 +7935,16 @@
     "Modified: / 08-09-2006 / 15:40:18 / cg"
 !
 
+monitorBounds
+    ^ self monitorInfos collect:[:each| each bounds].
+
+    "
+        Screen current monitorBounds
+    "
+
+    "Created: / 21-11-2019 / 13:35:22 / Stefan Reise"
+!
+
 monitorBoundsAt:aPoint
     "answer the bounds of the monitor the point is contained in"
 
@@ -8192,27 +7970,6 @@
     "Modified: / 22-11-2019 / 10:14:50 / Stefan Reise"
 !
 
-monitorHandleForName:aMonitorDeviceName
-    "given a name, return a handle to the monitor"
-
-    "
-	Display monitorHandleForName:'some nonsense'.
-	Display monitorInfoFor:(Display monitorHandleForName:'\\.\DISPLAY1')
-	Display monitorInfoFor:(Display monitorHandleForName:'\\.\DISPLAY2')
-    "
-
-    self monitorHandles do:[:eachMonitorHandle |
-	(self monitorInfoFor:eachMonitorHandle) name = aMonitorDeviceName ifTrue:[
-	    ^ eachMonitorHandle
-	].
-    ].
-
-    ^ nil
-
-    "Created: / 21-11-2019 / 12:13:33 / Stefan Reise"
-    "Modified: / 21-11-2019 / 13:32:11 / Stefan Reise"
-!
-
 monitorHandleForPoint:aPoint
     "given a point, return a handle to the monitor"
 
@@ -8263,56 +8020,52 @@
 monitorHandleForView:aViewOrViewId
     "given a window ID, return a handle to the monitor"
 
-    "
-	Display monitorHandleForView:Transcript topView.
-	Display monitorHandleForView:Transcript topView id.
-    "
-
     |windowId|
 
     aViewOrViewId isNil ifTrue:[
-	^ nil
+        ^ nil
     ].
 
     aViewOrViewId isExternalAddress ifTrue:[
-	windowId := aViewOrViewId.
+        windowId := aViewOrViewId.
     ] ifFalse:[
-	windowId := aViewOrViewId id.
+        windowId := aViewOrViewId id.
     ].
 
 %{
     if (__isExternalAddress(windowId)) {
-	HWND hWnd = _HWNDVal(windowId);
-	HMONITOR hMonitor;
-#if 0
-	/* the following is only needed when we want
-	 * to support very old NT/W95/W98 systems; we don't !
-	 */
-	static HMONITOR (__stdcall *P_MonitorFromWindow)(HWND, int);
-
-	if (P_MonitorFromWindow == 0) {
-	    HINSTANCE hUser = LoadLibrary("user32.dll");
-	    // console_printf("hUser: %x\n", hUser);
-	    if (hUser) {
-		P_MonitorFromWindow = (HMONITOR (__stdcall *)(HWND, int ))
-				    GetProcAddress(hUser, "MonitorFromWindow");
-	    }
-	}
-	// console_printf("P_MonitorFromWindow: %x\n", P_MonitorFromWindow);
-	hMonitor = (*P_MonitorFromWindow)(hWnd, MONITOR_DEFAULTTONULL);
-#else
-	hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONULL);
-#endif
-	if (hMonitor == 0) {
-	    RETURN(nil);
-	}
-	RETURN ( __MKEXTERNALADDRESS(hMonitor) );
+        HWND hWnd = _HWNDVal(windowId);
+        HMONITOR hMonitor;
+#if 0
+        /* the following is only needed when we want
+         * to support very old NT/W95/W98 systems; we don't !
+         */
+        static HMONITOR (__stdcall *P_MonitorFromWindow)(HWND, int);
+
+        if (P_MonitorFromWindow == 0) {
+            HINSTANCE hUser = LoadLibrary("user32.dll");
+            // console_printf("hUser: %x\n", hUser);
+            if (hUser) {
+                P_MonitorFromWindow = (HMONITOR (__stdcall *)(HWND, int ))
+                                    GetProcAddress(hUser, "MonitorFromWindow");
+            }
+        }
+        // console_printf("P_MonitorFromWindow: %x\n", P_MonitorFromWindow);
+        hMonitor = (*P_MonitorFromWindow)(hWnd, MONITOR_DEFAULTTONULL);
+#else
+        hMonitor = MonitorFromWindow(hWnd, MONITOR_DEFAULTTONULL);
+#endif
+        if (hMonitor == 0) {
+            RETURN(nil);
+        }
+        RETURN ( __MKEXTERNALADDRESS(hMonitor) );
     }
 %}.
 
     ^ nil
 
     "
+     Screen current monitorHandleForView:Transcript topView.
      Screen current monitorHandleForView:(Transcript topView id)
      Screen current monitorHandleForPoint:(0@0)
     "
@@ -8342,24 +8095,42 @@
     "Modified (comment): / 28-01-2012 / 10:26:55 / cg"
 !
 
+monitorInfoForName:aMonitorDeviceName
+    "given a name, return the info for the monitor"
+
+    ^ self monitorInfos detect:[:eachMonitorInfo |
+                            eachMonitorInfo name = aMonitorDeviceName
+                        ] ifNone:[].
+
+    "
+        Screen current monitorInfoForName:'some nonsense'.
+        Screen current monitorInfoForName:'\\.\DISPLAY1'.
+        Screen current monitorInfoForName:'\\.\DISPLAY2'.
+    "
+
+
+    "Created: / 21-11-2019 / 12:13:33 / Stefan Reise"
+    "Modified: / 21-11-2019 / 13:32:11 / Stefan Reise"
+!
+
 monitorInfoForPoint:aPoint
     "answer the bounds of the monitor the point is contained in"
 
-    "
-	Display monitorInfoForPoint:100@100
-	Display monitorInfoForPoint:2000@100
-	Display monitorInfoForPoint:-200@100
-    "
-
     |monitorHandle|
 
     monitorHandle := self monitorHandleForPoint:aPoint.
     monitorHandle notNil ifTrue:[
-	^ self monitorInfoFor:monitorHandle
+        ^ self monitorInfoFor:monitorHandle
     ].
 
     ^ nil
 
+    "
+        Screen current monitorInfoForPoint:100@100
+        Screen current monitorInfoForPoint:2000@100
+        Screen current monitorInfoForPoint:-200@100
+    "
+
     "Created: / 21-11-2019 / 11:11:47 / Stefan Reise"
     "Modified: / 22-11-2019 / 09:57:05 / Stefan Reise"
 !
@@ -8385,9 +8156,13 @@
 
 monitorInfos
     ^ self monitorHandles
-	collect:[:eachMonitorHandle |
-	    self monitorInfoFor:eachMonitorHandle
-	].
+        collect:[:eachMonitorHandle |
+            self monitorInfoFor:eachMonitorHandle
+        ].
+
+    "
+        Screen current monitorInfos
+    "
 
     "Created: / 21-11-2019 / 13:35:22 / Stefan Reise"
 !
@@ -8439,12 +8214,11 @@
 smallestMonitorHeight
     "returns the usable height of the smallest monitor in a mult-monitor setup"
 
-    |info minH|
+    |minH|
 
     minH := self usableHeight.
-    self monitorHandles do:[:eachHandle |
-	info := self monitorInfoFor:eachHandle.
-	info notNil ifTrue:[ minH := minH min: info workHeight ].
+    self monitorInfos do:[:eachInfo |
+        minH := minH min:eachInfo workHeight.
     ].
     ^ minH
 
@@ -8616,6 +8390,34 @@
     "Modified: / 22-11-2019 / 10:15:17 / Stefan Reise"
 !
 
+usableWidthAt:aPoint
+    "returns the usable width of the display (in pixels) at a given point.
+     On multi-display systems with different sized screens, this should care for
+     which display is at the given x-position"
+
+    |info|
+
+    "/ ******* MULTI SCREEN ******
+    info := self monitorInfoForPoint:aPoint.
+    info notNil ifTrue:[
+        ^ info workWidth.
+    ].
+    ^ self usableWidth
+
+    "
+     Display numberOfMonitors
+
+     Display usableHeight
+
+     Display usableHeightAt:100@100
+     Display usableHeightAt:2000@100
+     Display usableHeightAt:-200@100
+    "
+
+    "Modified (comment): / 27-10-2012 / 13:34:32 / cg"
+    "Modified: / 22-11-2019 / 10:15:17 / Stefan Reise"
+!
+
 workableAreaBoundsAt:aPoint
     "return a rectangle representing the displays bounding box
      of the workable area (without TaskBar etc.) of the monitor"
@@ -10494,6 +10296,62 @@
     "Modified: 30.1.1998 / 09:30:22 / md"
 ! !
 
+!WinWorkstation methodsFor:'converting'!
+
+convertVirtualResolutionPointToCurrentResolutionPoint:aPoint
+    "this is required when you want to access the root display coordinates correctly,
+     because may the os did scale the application (when the app is not high DPI aware),
+     and if the os do scale the application, the application gets a virtual display
+     with a different resolution"
+
+    |centerMonitorDeviceName targetMonitorInfo minScaleFactor
+     scaledX scaledY|
+
+    centerMonitorDeviceName := self monitorDeviceNameForPoint:0@0.
+    centerMonitorDeviceName isNil ifTrue:[
+        self halt. "/ should not happen?
+        ^ aPoint
+    ].
+
+    targetMonitorInfo := Display monitorInfoForPoint:aPoint.
+    (targetMonitorInfo isNil
+     or:[targetMonitorInfo isCenterMonitor]) ifTrue:[
+        "the point is not inside any monitor
+         or is inside the center monitor
+         use the center monitor scale factor"
+        ^ (aPoint * (self scaleFactorForRootViewTranslationOnMonitorNamed:centerMonitorDeviceName)) rounded
+    ].
+
+    minScaleFactor := (Display monitorInfos
+        collect:[:eachMonitorInfo |
+            self scaleFactorForRootViewTranslationOnMonitorNamed:eachMonitorInfo name
+        ])
+            min.
+
+    scaledX := self
+        convertTargetValue:aPoint x
+        targetMonitorInfo:targetMonitorInfo
+        minScaleFactor:minScaleFactor
+        monitorInfoTopOrLeftFetch:[:monitorInfo | monitorInfo screenX].
+
+    scaledY := self
+        convertTargetValue:aPoint y
+        targetMonitorInfo:targetMonitorInfo
+        minScaleFactor:minScaleFactor
+        monitorInfoTopOrLeftFetch:[:monitorInfo | monitorInfo screenY].
+
+    ^ scaledX@scaledY
+
+   "
+        self convertVirtualResolutionPointToCurrentResolutionPoint:2000@400
+        self convertVirtualResolutionPointToCurrentResolutionPoint:2000@500
+    "
+
+
+    "Created: / 22-11-2019 / 10:09:49 / Stefan Reise"
+    "Modified (comment): / 25-11-2019 / 14:23:47 / Stefan Reise"
+! !
+
 !WinWorkstation methodsFor:'cursor stuff'!
 
 builtInCursorShapes
@@ -16635,6 +16493,76 @@
 %}
 ! !
 
+!WinWorkstation methodsFor:'multi monitor support'!
+
+openViewWithBlock:openAction view:aView at:origin
+    " HACK for multi monitor support.
+        sub views needs to be opened on the same monitor as their top view,
+        so that Windows create/place them into the same virtual resolution/display.
+        after the sub views are opened we can move them within the same virtual resolution/display.
+        to their actually origin."
+
+    |application monitorInfo
+     originX originY
+     screenX screenY
+     tmpOriginX tmpOriginY
+     topView|
+
+    aView isNil ifTrue:[
+        ^ self. "/ nothing to open
+    ].
+
+    aView isMenu ifTrue:[
+        application := aView application.
+        application isNil ifTrue:[
+            ^ super
+                openViewWithBlock:openAction
+                view:aView
+                at:origin
+        ].
+
+        topView := application topView.
+    ] ifFalse:[
+        self halt. "/ find the real top view
+        topView := aView topView.
+    ].
+
+    topView isNil ifTrue:[
+        ^ super
+            openViewWithBlock:openAction
+            view:aView
+            at:origin
+    ].
+
+    monitorInfo := self monitorInfoForView:topView.
+    monitorInfo isNil ifTrue:[
+        ^ super
+            openViewWithBlock:openAction
+            view:aView
+            at:origin
+    ].
+
+    originX := origin x.
+    originY := origin y.
+    screenX := monitorInfo screenX.
+    screenY := monitorInfo screenY.
+    tmpOriginX := originX.
+    tmpOriginY := originY.
+
+    originX < screenX ifTrue:[
+        tmpOriginX := screenX.
+    ].
+    originY < screenY ifTrue:[
+        tmpOriginY := screenY.
+    ].
+
+    aView origin:tmpOriginX@tmpOriginY.
+    openAction value.
+    aView origin:origin.
+
+    "Created: / 28-11-2019 / 17:54:32 / Stefan Reise"
+! !
+
 !WinWorkstation methodsFor:'native dialogs'!
 
 nativeConfirm:aString title:titleString flags:flags initialAnswer:trueOrFalse
@@ -18306,6 +18234,42 @@
 "/    self setCursorPosition:(self translatePoint:newPosition from:aWindowId to:self rootView id).
 ! !
 
+!WinWorkstation methodsFor:'private'!
+
+convertTargetValue:targetValue
+    targetMonitorInfo:targetMonitorInfo
+    minScaleFactor:minScaleFactor
+    monitorInfoTopOrLeftFetch:monitorInfoTopOrLeftFetch
+
+    "helper function,
+     take a look at the caller"
+
+    |scaleFactorInTargetMonitor targetMonitorVirtualTopOrLeft
+     targetMonitorRealTopOrLeft remainingVirtual remainingReal
+     returnValue|
+
+    scaleFactorInTargetMonitor := self
+        scaleFactorForRootViewTranslationOnMonitorNamed:targetMonitorInfo name.
+
+    "check if target moinitor is the center monitor"
+    targetMonitorVirtualTopOrLeft := monitorInfoTopOrLeftFetch value:targetMonitorInfo.
+    targetMonitorVirtualTopOrLeft == 0 ifTrue:[
+        returnValue := (targetValue * scaleFactorInTargetMonitor) rounded.
+        ^ returnValue
+    ].
+
+    "target monitor is not the center monitor,
+     scale the x of the monitor with the min. scale factor
+     and the remaining stuff with the target monitor scale factor"
+    targetMonitorRealTopOrLeft := (targetMonitorVirtualTopOrLeft * minScaleFactor) rounded.
+    remainingVirtual := targetValue - targetMonitorVirtualTopOrLeft.
+    remainingReal := (remainingVirtual * scaleFactorInTargetMonitor) rounded.
+
+    ^ targetMonitorRealTopOrLeft + remainingReal
+
+    "Created: / 25-11-2019 / 13:56:58 / Stefan Reise"
+! !
+
 !WinWorkstation methodsFor:'private error handling'!
 
 textOutFailed
@@ -18316,6 +18280,316 @@
     "/ self error:'textOut failed'.
 ! !
 
+!WinWorkstation methodsFor:'queries - monitor'!
+
+isHighDpiAware
+    "answers if this app is high dpi aware"
+
+    |isHighDpiAware|
+
+    OperatingSystem isWin8Like ifFalse:[
+        "win 7 does not include Shcore.dll"    
+        ^ false
+    ].
+
+    isHighDpiAware := false.
+
+%{
+        HINSTANCE hShcore = LoadLibrary("Shcore.dll");
+
+        if (hShcore) {
+            static HRESULT (__stdcall *P_GetProcessDpiAwareness)(HANDLE, VOID*);
+            P_GetProcessDpiAwareness = (HRESULT (__stdcall *)(HANDLE, VOID*))GetProcAddress(hShcore, "GetProcessDpiAwareness");
+
+            if (P_GetProcessDpiAwareness) {
+                UINT processDpiAwarness = 0;
+
+                if ((*P_GetProcessDpiAwareness)(NULL, &processDpiAwarness) == S_OK) {
+                    if (processDpiAwarness == 0) {
+                        isHighDpiAware = false;
+                    } else {
+                        isHighDpiAware = true;
+                    }
+                } else {
+                    console_fprintf(stderr, "Call \"GetProcessDpiAwareness()\" failed\n");
+                };
+            } else {
+                console_fprintf(stderr, "Loading \"GetProcessDpiAwareness()\" failed\n");
+            }
+        } else {
+            console_fprintf(stderr, "Loading \"Shcore.dll\" failed\n");
+        }
+%}.
+
+    ^ isHighDpiAware
+
+    "
+        Screen current isHighDpiAware.
+    "
+
+
+
+    "Created: / 27-11-2019 / 13:40:04 / Stefan Reise"
+    "Modified: / 11-02-2020 / 11:46:49 / Stefan Reise"
+!
+
+monitorDeviceNameForPoint:aPoint
+    "given a point, return its monitor device name or nil if failed"
+
+    |info|
+
+    info := self monitorInfoForPoint:aPoint.
+    info isNil ifTrue:[
+        ^ info
+    ].
+    ^ info name. 
+
+    "
+        Screen current monitorDeviceNameForPoint:0@0
+        Screen current monitorDeviceNameForPoint:2000@0
+    "
+!
+
+monitorRealResolutionByMonitorDeviceName:aMonitorDeviceName
+    "this is the real resolution of the display,
+     without any effect of os scaling
+
+     for e.g.
+	real resolution -> 1080p
+	os scaling 150%
+	virtual resolution -> 720p
+
+	real resolution -> 1080p
+	os scaling 100%
+	virtual resolution -> 1080p"
+
+    "
+	Screen monitorRealResolutionByMonitorDeviceName:nil.
+	Screen monitorRealResolutionByMonitorDeviceName:'ereswt'.
+	Screen monitorRealResolutionByMonitorDeviceName:'\\.\DISPLAY1'.
+	Screen monitorRealResolutionByMonitorDeviceName:'\\.\DISPLAY2'.
+    "
+
+    |currentX currentY|
+
+    aMonitorDeviceName isEmptyOrNil ifTrue:[
+	^ super monitorRealResolutionByMonitorDeviceName:aMonitorDeviceName
+    ].
+
+%{
+    HDC hdc = CreateDCA(__stringVal(aMonitorDeviceName), NULL, NULL, NULL);
+    if (hdc != NULL) {
+	currentX = __MKSMALLINT(GetDeviceCaps(hdc, DESKTOPHORZRES));
+	currentY = __MKSMALLINT(GetDeviceCaps(hdc, DESKTOPVERTRES));
+	DeleteDC(hdc);
+    }
+%}.
+
+    currentX isNil ifTrue:[
+	^ super monitorRealResolutionByMonitorDeviceName:aMonitorDeviceName
+    ].
+
+    ^ currentX@currentY
+
+    "Created: / 25-11-2019 / 12:20:36 / Stefan Reise"
+    "Modified (format): / 25-11-2019 / 14:25:31 / Stefan Reise"
+!
+
+monitorRealResolutionByPoint:aPoint
+    "this is the real resolution of the display,
+     without any effect of os scaling
+
+     for e.g.
+        real resolution -> 1080p
+        os scaling 150%
+        virtual resolution -> 720p
+
+        real resolution -> 1080p
+        os scaling 100%
+        virtual resolution -> 1080p"
+
+    |monitorName|
+
+    aPoint isNil ifTrue:[
+        ^ super monitorRealResolutionByPoint:aPoint
+    ].
+
+    monitorName := self monitorDeviceNameForPoint:aPoint.
+    monitorName isNil ifTrue:[
+        ^ super monitorRealResolutionByPoint:aPoint
+    ].
+
+    ^ self monitorRealResolutionByMonitorDeviceName:monitorName
+
+    "
+        Screen monitorRealResolutionByPoint:nil.
+        Screen monitorRealResolutionByPoint:0@0.
+        Screen monitorRealResolutionByPoint:500@0.
+        Screen monitorRealResolutionByPoint:2000@0.
+    "
+
+
+    "Created: / 25-11-2019 / 12:19:40 / Stefan Reise"
+    "Modified (comment): / 25-11-2019 / 14:25:43 / Stefan Reise"
+!
+
+monitorScaleFactorFor:aMonitorHandle
+    "this method always returns the os scale factor,
+     regardless if the app is high dpi aware or not.
+
+     this is the scale factor the user did enter in the os settings,
+     for e.g. the user can choose between 100, 125, 150 etc.
+     here we return 1, 1.25 1.5"
+
+    |scaleFactor|
+
+    OperatingSystem isWin8Like ifFalse:[
+        "win 7 does not include Shcore.dll"    
+        ^ nil
+    ].
+
+%{
+    if (__isExternalAddress(aMonitorHandle)) {
+        HMONITOR hMonitor = (HMONITOR)(_HWNDVal(aMonitorHandle));
+        HINSTANCE hShcore = LoadLibrary("Shcore.dll");
+
+        if (hShcore) {
+            static HRESULT (__stdcall *P_GetScaleFactorForMonitor)(HMONITOR, VOID*);
+            P_GetScaleFactorForMonitor = (HRESULT (__stdcall *)(HMONITOR, VOID*))GetProcAddress(hShcore, "GetScaleFactorForMonitor");
+
+            if (P_GetScaleFactorForMonitor) {
+                UINT displayScaleFactor = 0;
+
+                if ((*P_GetScaleFactorForMonitor)(hMonitor, &displayScaleFactor) == S_OK) {
+                    scaleFactor = __MKSMALLINT(displayScaleFactor);
+                } else {
+                    console_fprintf(stderr, "Call \"GetScaleFactorForMonitor()\" failed\n");
+                };
+            } else {
+                console_fprintf(stderr, "Loading \"GetScaleFactorForMonitor()\" failed\n");
+            }
+        } else {
+            console_fprintf(stderr, "Loading \"Shcore.dll\" failed\n");
+        }
+    }
+%}.
+
+    (scaleFactor isNil
+     or:[scaleFactor == 0]) ifTrue:[
+        ^ nil
+    ].
+
+    ^ scaleFactor / 100
+
+   "
+        Screen current monitorScaleFactorFor:(Display monitorHandleForName:'\\.\DISPLAY1').
+        Screen current monitorScaleFactorFor:(Display monitorHandleForName:'\\.\DISPLAY2').
+    "
+
+
+
+    "Created: / 25-11-2019 / 11:52:42 / Stefan Reise"
+    "Modified: / 11-02-2020 / 11:47:10 / Stefan Reise"
+!
+
+monitorScaleFactorForView:aView
+    "this method always returns the os scale factor,
+     regardless if the app is high dpi aware or not.
+
+     this is the scale factor the user did enter in the os settings,
+     for e.g. the user can choose between 100, 125, 150 etc.
+     here we return 1, 1.25 1.5"
+
+    |monitorHandle scaleFactor|
+
+    monitorHandle := self monitorHandleForView:aView.
+    monitorHandle isNil ifTrue:[
+        "win 7 does not include Shcore.dll"    
+        ^ super monitorScaleFactorForView:aView
+    ].
+    scaleFactor := self monitorScaleFactorFor:monitorHandle.
+
+    scaleFactor isNil ifTrue:[
+        ^ super monitorScaleFactorForView:aView
+    ].
+
+    ^ scaleFactor / 100
+
+   "
+        Screen current monitorScaleFactorForView:Transcript topView.
+    "
+
+
+
+    "Created: / 25-11-2019 / 11:52:42 / Stefan Reise"
+    "Modified: / 11-02-2020 / 11:47:10 / Stefan Reise"
+!
+
+scaleFactorForRootViewTranslationOnMonitorNamed:aMonitorDeviceName
+    "this is the scale factor, we have to use,
+     when we work directly with the root view (desktop)
+
+     because we may have a virtual display,
+     but the screen (from which we take a screenshot for e.g.)
+     does always have the current resolution,
+     therefore we have to translate from virtual to current resolution"
+
+    |currentMonitorResolution thisAppVirtualResolution|
+
+    currentMonitorResolution := self monitorRealResolutionByMonitorDeviceName:aMonitorDeviceName.
+    currentMonitorResolution isNil ifTrue:[
+        ^ 1
+    ].
+
+    thisAppVirtualResolution := self thisAppVirtualResolutionByMonitorDeviceName:aMonitorDeviceName.
+    thisAppVirtualResolution isNil ifTrue:[
+        ^ 1
+    ].
+
+    ^ currentMonitorResolution x / thisAppVirtualResolution x
+
+    "
+        Screen current scaleFactorForRootViewTranslationOnMonitorNamed:'\\.\DISPLAY1'.
+        Screen current scaleFactorForRootViewTranslationOnMonitorNamed:'\\.\DISPLAY2'.
+    "
+
+    "Created: / 21-11-2019 / 12:33:11 / Stefan Reise"
+    "Modified: / 25-11-2019 / 14:18:09 / Stefan Reise"
+!
+
+thisAppVirtualResolutionByMonitorDeviceName:aMonitorDeviceName
+    "this is the virtual resolution of the display for this app,
+     may (when a os scaling is defined and this app is not high dpi aware) effected by os scaling
+
+     for e.g.
+        real current resolution -> 1080p
+        scaling 150%
+        virtual resolution -> 720p
+
+        real current resolution -> 1080p
+        scaling 100%
+        virtual resolution -> 1080p"
+
+    |monitorInfo|
+
+    monitorInfo := self monitorInfoForName:aMonitorDeviceName.
+    monitorInfo isNil ifTrue:[
+        ^ self extent
+    ].
+
+    ^ (monitorInfo screenWidth)@(monitorInfo screenHeight)
+
+    "
+        Screen thisAppVirtualResolutionByMonitorDeviceName:nil.
+        Screen thisAppVirtualResolutionByMonitorDeviceName:'ereswt'.
+        Screen thisAppVirtualResolutionByMonitorDeviceName:'\\.\DISPLAY1'.
+        Screen thisAppVirtualResolutionByMonitorDeviceName:'\\.\DISPLAY2'.
+    "
+
+
+    "Created: / 25-11-2019 / 14:17:05 / Stefan Reise"
+! !
+
 !WinWorkstation methodsFor:'retrieving pixels'!
 
 getBitsFromId:aDrawableId x:srcX y:srcY width:w height:h into:imageBits
@@ -21184,22 +21458,19 @@
 !WinWorkstation::MonitorInfo methodsFor:'queries'!
 
 isCenterMonitor
-    "maybe the same as #isPrimary,
-     but I am not sure what #isPrimary does indicate exactly"
-
-    screenX == 0 ifFalse:[
-	^ false
-    ].
-    screenY == 0 ifFalse:[
-	^ false
-    ].
-
-    ^ true
+    "answer true, if this monitor is not located
+     at the top or left margin"
+
+    ^ screenX ~~ 0 and:[screenY ~~ 0].
 
     "Created: / 22-11-2019 / 10:31:16 / Stefan Reise"
 !
 
 isPrimary
+    "answer true, if this is the monitor marked as
+     primary monitor (where the Desktop is shown)
+     in thw windows aettings"
+
     ^ isPrimary
 !