--- 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
!