--- a/WinWorkstation.st Fri Nov 22 02:25:28 2019 +0100
+++ b/WinWorkstation.st Fri Nov 22 10:43:26 2019 +0100
@@ -22,8 +22,8 @@
classVariableNames:'BeepDuration NativeDialogs NativeFileDialogs NativeWidgets
NativeWidgetClassTable StandardColorValues IgnoreSysColorChanges
IgnoreFontChanges SystemColorValues CanEndSession
- VerboseNativeDialogs CurrentDisplayResolutionFromTool
- VirtualDisplayResolutionFromTool'
+ VerboseNativeDialogs MonitorNameToCurrentResolution
+ MonitorNameToVirtualResolution MonitorNameDictionariesSema'
poolDictionaries:''
category:'Interface-Graphics'
!
@@ -5423,25 +5423,31 @@
IgnoreSysColorChanges := false.
SystemColorValues := IdentityDictionary new.
+ "/ cache information we get from support/win32/displayResolutionTools
+ MonitorNameToCurrentResolution := Dictionary new.
+ MonitorNameToVirtualResolution := Dictionary new.
+ MonitorNameDictionariesSema := Semaphore forMutualExclusion.
+
"/ translation table from ST/X windowType symbol (system-independent)
"/ to Windows windowClass (windows-specific).
NativeWidgetClassTable := IdentityDictionary
- withKeysAndValues:#(
- ScrollBar SCROLLBAR
- HorizontalScrollBar SCROLLBAR
- VerticalScrollBar SCROLLBAR
- CheckBox BUTTON
- RadioButton BUTTON
- Button BUTTON
- DefaultButton BUTTON
- OwnerDrawButton BUTTON
- ComboBox COMBOBOX
- EditField EDIT
- ListBox LISTBOX
- ).
+ withKeysAndValues:#(
+ ScrollBar SCROLLBAR
+ HorizontalScrollBar SCROLLBAR
+ VerticalScrollBar SCROLLBAR
+ CheckBox BUTTON
+ RadioButton BUTTON
+ Button BUTTON
+ DefaultButton BUTTON
+ OwnerDrawButton BUTTON
+ ComboBox COMBOBOX
+ EditField EDIT
+ ListBox LISTBOX
+ ).
"Modified: / 24-08-2010 / 16:42:23 / sr"
+ "Modified: / 21-11-2019 / 10:04:42 / Stefan Reise"
!
initializeStandardColorNames
@@ -6266,6 +6272,59 @@
"
! !
+!WinWorkstation class methodsFor:'converting'!
+
+convertVirtualResolutionPointToCurrentResolutionPoint:aPoint
+ "
+ self convertVirtualResolutionPointToCurrentResolutionPoint:2000@400
+ self convertVirtualResolutionPointToCurrentResolutionPoint:2000@500
+ "
+
+ |centerMonitorInfo centerMonitorScaleFactor
+ targetMonitorInfo minScaleFactor
+ scaledX scaledY|
+
+ centerMonitorInfo := Display monitorInfoForPoint:0@0.
+ centerMonitorInfo isNil ifTrue:[
+ self halt. "/ should not happen?
+ ^ aPoint
+ ].
+
+ centerMonitorScaleFactor := Screen scaleFactorForMonitorNamed:centerMonitorInfo name.
+ 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 * centerMonitorScaleFactor) rounded
+ ].
+
+ minScaleFactor := (Display monitorInfos
+ collect:[:eachMonitorInfo |
+ Screen scaleFactorForRootViewTranslationOnMonitorNamed:eachMonitorInfo name
+ ])
+ min.
+
+ scaledX := self
+ convertTargetValue:aPoint x
+ targetMonitorInfo:targetMonitorInfo
+ minScaleFactor:minScaleFactor x
+ pointValueFetch:[:eachPoint | eachPoint x]
+ monitorInfoTopOrLeftFetch:[:monitorInfo | monitorInfo screenX].
+
+ scaledY := self
+ convertTargetValue:aPoint y
+ targetMonitorInfo:targetMonitorInfo
+ minScaleFactor:minScaleFactor y
+ pointValueFetch:[:eachPoint | eachPoint y]
+ monitorInfoTopOrLeftFetch:[:monitorInfo | monitorInfo screenY].
+
+ ^ scaledX@scaledY
+
+ "Created: / 22-11-2019 / 10:09:49 / Stefan Reise"
+! !
+
!WinWorkstation class methodsFor:'debugging'!
bitmapHandleCounts
@@ -6575,79 +6634,45 @@
!WinWorkstation class methodsFor:'private'!
-commonDisplayResolutionBinaryFromPackageSubPath:packageSubPath
- binaryBaseNameWithoutSuffix:binaryBaseNameWithoutSuffix
-
- "
- Screen
- commonDisplayResolutionBinaryFromPackageSubPath:'currentDisplayResolution'
- binaryBaseNameWithoutSuffix:'cdr'
- "
-
- |packageId directory|
-
- packageId := 'stx:support/win32/', packageSubPath, '/bin'.
- directory := Smalltalk packageDirectoryForPackageId:packageId.
- directory isNil ifTrue:[
- 'package "', packageId, '" is missing"' errorPrintCR.
- ^ nil
- ].
-
- ^ directory / (binaryBaseNameWithoutSuffix, '.exe')
-
- "Created: / 19-11-2019 / 11:58:44 / Stefan Reise"
-!
-
-currentDisplayResolutionBinary
- "
- Screen currentDisplayResolutionBinary
- "
-
- ^ self
- commonDisplayResolutionBinaryFromPackageSubPath:'currentDisplayResolution'
- binaryBaseNameWithoutSuffix:'cdr'
-
- "Created: / 15-11-2019 / 09:32:22 / Stefan Reise"
- "Modified (comment): / 19-11-2019 / 11:59:34 / Stefan Reise"
-!
-
-displayResolutionFromTool:aFilenameOrNil
- "
- self displayResolutionFromTool:self currentDisplayResolutionBinary
- self displayResolutionFromTool:self virtualDisplayResolutionBinary
- "
-
- |output pointValues|
-
- aFilenameOrNil isNil ifTrue:[
- ^ nil
- ].
- aFilenameOrNil exists ifFalse:[
- 'tool binary "', aFilenameOrNil nameString, '" is missing"' errorPrintCR.
- ^ nil
- ].
-
- output := '' writeStream.
-
- OperatingSystem
- executeCommand:aFilenameOrNil pathName
- outputTo:output
- errorTo:output.
-
- pointValues := output contents subStrings:$x.
-
- ^ pointValues first asInteger@pointValues second asInteger
-
- "Created: / 15-11-2019 / 09:37:01 / Stefan Reise"
- "Modified: / 19-11-2019 / 12:03:00 / Stefan Reise"
-!
-
-virtualDisplayResolution
- "ATTENTION: can return nil if the package or the tool is missing:
- stx:support/win32/virtualDisplayResolution/bin/vdr.exe
-
- this is the resolution of a virtual display,
- this resolution is effected by the scaling
+convertTargetValue:targetValue
+ targetMonitorInfo:targetMonitorInfo
+ minScaleFactor:minScaleFactor
+ pointValueFetch:pointValueFetch
+ monitorInfoTopOrLeftFetch:monitorInfoTopOrLeftFetch
+
+ |scaleFactorInTargetMonitor targetMonitorVirtualTopOrLeft
+ targetMonitorRealTopOrLeft remainingVirtual remainingReal
+ returnValue|
+
+ scaleFactorInTargetMonitor := pointValueFetch
+ value:(Screen
+ scaleFactorForRootViewTranslationOnMonitorNamed:targetMonitorInfo name).
+
+ "check if target moinitor is the center monitor"
+ targetMonitorVirtualTopOrLeft := monitorInfoTopOrLeftFetch value:targetMonitorInfo.
+ targetMonitorVirtualTopOrLeft == 0 ifTrue:[
+ returnValue := (targetValue * scaleFactorInTargetMonitor) rounded.
+ ^ returnValue
+ ].
+
+ "targte 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: / 22-11-2019 / 10:37:55 / Stefan Reise"
+!
+
+primResolutionForMonitorNamed:aMonitorDeviceNameOrNil
+ trueForVirtualResolutionOrFalseForCurrentResolution:trueForVirtualResolutionOrFalseForCurrentResolution
+
+ "ATTENTION: can return nil if the package or the tools are missing:
+ stx:support/win32/displayResolutionTools/bin/cdr.exe
+ stx:support/win32/displayResolutionTools/bin/vdr.exe
for e.g.
real current display resolution -> 1080p
@@ -6656,57 +6681,87 @@
real current display resolution -> 1080p
scaling 100%
- virtual display resolution -> 1080p"
-
- "
- VirtualDisplayResolutionFromTool := nil.
- self virtualDisplayResolution
- "
-
- |tmp|
-
- VirtualDisplayResolutionFromTool isNil ifTrue:[
- tmp := self displayResolutionFromTool:self virtualDisplayResolutionBinary.
- tmp isNil ifTrue:[
- "use 0 to indicate nil,
- avoid recalling of #displayResolutionFromTool:"
- VirtualDisplayResolutionFromTool := 0.
- ] ifFalse:[
- VirtualDisplayResolutionFromTool := tmp.
- ].
- ].
-
- VirtualDisplayResolutionFromTool == 0 ifTrue:[
+ virtual display resolution -> 1080p"
+
+ "
+ self
+ primResolutionForMonitorNamed:nil
+ trueForVirtualResolutionOrFalseForCurrentResolution:true.
+
+ self
+ primResolutionForMonitorNamed:'some nonsense'
+ trueForVirtualResolutionOrFalseForCurrentResolution:true.
+
+ self
+ primResolutionForMonitorNamed:'\\.\DISPLAY1'
+ trueForVirtualResolutionOrFalseForCurrentResolution:false.
+
+ self
+ primResolutionForMonitorNamed:'\\.\DISPLAY1'
+ trueForVirtualResolutionOrFalseForCurrentResolution:true.
+
+ self
+ primResolutionForMonitorNamed:'\\.\DISPLAY2'
+ trueForVirtualResolutionOrFalseForCurrentResolution:false.
+
+ self
+ primResolutionForMonitorNamed:'\\.\DISPLAY2'
+ trueForVirtualResolutionOrFalseForCurrentResolution:true.
+ "
+
+ |packageId directory toolBaseNameWithoutSuffix
+ filenameOrNil output pointValues|
+
+ aMonitorDeviceNameOrNil isNil ifTrue:[
+ ^ nil
+ ].
+
+ packageId := 'stx:support/win32/displayResolutionTools/bin'.
+ directory := Smalltalk packageDirectoryForPackageId:packageId.
+ directory isNil ifTrue:[
+ 'package "', packageId, '" is missing"' errorPrintCR.
^ nil
].
- ^ VirtualDisplayResolutionFromTool
-
- "Created: / 15-11-2019 / 09:37:48 / Stefan Reise"
- "Modified (format): / 19-11-2019 / 12:17:02 / Stefan Reise"
-!
-
-virtualDisplayResolutionBinary
- "
- Screen virtualDisplayResolutionBinary
- "
-
- ^ self
- commonDisplayResolutionBinaryFromPackageSubPath:'virtualDisplayResolution'
- binaryBaseNameWithoutSuffix:'vdr'
-
- "Created: / 15-11-2019 / 09:32:51 / Stefan Reise"
- "Modified (comment): / 19-11-2019 / 11:59:52 / Stefan Reise"
-! !
-
-!WinWorkstation class methodsFor:'queries'!
-
-currentDisplayResolution
- "ATTENTION: can return nil if the package or the tool is missing:
- stx:support/win32/currentDisplayResolution/bin/cdr.exe
-
- this is the current resolution of the display,
- without any effect of scaling
+ trueForVirtualResolutionOrFalseForCurrentResolution ifTrue:[
+ toolBaseNameWithoutSuffix := 'vdr'.
+ ] ifFalse:[
+ toolBaseNameWithoutSuffix := 'cdr'.
+ ].
+
+ filenameOrNil := directory / (toolBaseNameWithoutSuffix, '.exe').
+ filenameOrNil isNil ifTrue:[
+ ^ nil
+ ].
+ filenameOrNil exists ifFalse:[
+ 'tool binary "', filenameOrNil nameString, '" is missing"' errorPrintCR.
+ ^ nil
+ ].
+
+ output := '' writeStream.
+
+ (OperatingSystem
+ executeCommand:('"%1" %2'
+ bindWith:filenameOrNil pathName
+ with:aMonitorDeviceNameOrNil)
+ outputTo:output
+ errorTo:output) ifFalse:[
+ ^ nil
+ ].
+
+ pointValues := output contents subStrings:$x.
+
+ ^ pointValues first asInteger@pointValues second asInteger
+
+ "Created: / 21-11-2019 / 10:07:34 / Stefan Reise"
+!
+
+resolutionForMonitorNamed:aMonitorDeviceName
+ trueForVirtualResolutionOrFalseForCurrentResolution:trueForVirtualResolutionOrFalseForCurrentResolution
+
+ "ATTENTION: can return nil if the package or the tools are missing:
+ stx:support/win32/displayResolutionTools/bin/cdr.exe
+ stx:support/win32/displayResolutionTools/bin/vdr.exe
for e.g.
real current display resolution -> 1080p
@@ -6715,68 +6770,69 @@
real current display resolution -> 1080p
scaling 100%
- virtual display resolution -> 1080p"
-
- "
- CurrentDisplayResolutionFromTool := nil.
- self currentDisplayResolution
+ virtual display resolution -> 1080p"
+
+ "
+ MonitorNameToCurrentResolution := Dictionary new.
+ MonitorNameToVirtualResolution := Dictionary new.
+
+ self
+ resolutionForMonitorNamed:'\\.\DISPLAY1'
+ trueForVirtualResolutionOrFalseForCurrentResolution:false.
+
+ self
+ resolutionForMonitorNamed:'\\.\DISPLAY1'
+ trueForVirtualResolutionOrFalseForCurrentResolution:true.
+
+ self
+ resolutionForMonitorNamed:'\\.\DISPLAY2'
+ trueForVirtualResolutionOrFalseForCurrentResolution:false.
+
+ self
+ resolutionForMonitorNamed:'\\.\DISPLAY2'
+ trueForVirtualResolutionOrFalseForCurrentResolution:true.
"
- |tmp|
-
- CurrentDisplayResolutionFromTool isNil ifTrue:[
- tmp := self displayResolutionFromTool:self currentDisplayResolutionBinary.
- tmp isNil ifTrue:[
- "use 0 to indicate nil,
- avoid recalling of #displayResolutionFromTool:"
- CurrentDisplayResolutionFromTool := 0.
- ] ifFalse:[
- CurrentDisplayResolutionFromTool := tmp.
- ].
- ].
-
- CurrentDisplayResolutionFromTool == 0 ifTrue:[
+ |cacheDictionary currentResolution|
+
+ aMonitorDeviceName isNil ifTrue:[
^ nil
].
- ^ CurrentDisplayResolutionFromTool
-
- "Created: / 15-11-2019 / 09:37:53 / Stefan Reise"
- "Modified (comment): / 19-11-2019 / 12:17:27 / Stefan Reise"
-!
-
-displayScaleFactor
- "ATTENTION: returns the may wrong default 1@1 if the package or the tool is missing:
- stx:support/win32/currrentDisplayResolution/bin/cdr.exe
- stx:support/win32/virtualDisplayResolution/bin/vdr.exe
-
- this is the scale factor the user did enter within the windows settings,
- for e.g. the user can choose between 100, 125, 150 etc.
- here we return 1, 1.25 1.5"
-
- "
- self displayScaleFactor
- "
-
- |currentDisplayResolution virtualDisplayResolution|
-
- currentDisplayResolution := self currentDisplayResolution.
- currentDisplayResolution isNil ifTrue:[
- "may the tool binary is missing (this is already catched in #displayResolutionFromTool:)"
- ^ 1@1
- ].
-
- virtualDisplayResolution := self virtualDisplayResolution.
- virtualDisplayResolution isNil ifTrue:[
- "may the tool binary is missing (this is already catched in #displayResolutionFromTool:)"
- ^ 1@1
- ].
-
- ^ currentDisplayResolution / virtualDisplayResolution
-
- "Created: / 15-11-2019 / 09:43:53 / Stefan Reise"
- "Modified (comment): / 19-11-2019 / 12:07:55 / Stefan Reise"
-!
+ trueForVirtualResolutionOrFalseForCurrentResolution ifTrue:[
+ cacheDictionary := MonitorNameToVirtualResolution.
+ ] ifFalse:[
+ cacheDictionary := MonitorNameToCurrentResolution.
+ ].
+
+ currentResolution := cacheDictionary
+ at:aMonitorDeviceName
+ ifAbsent:nil.
+
+ currentResolution isNil ifTrue:[
+ MonitorNameDictionariesSema critical:[
+ currentResolution := cacheDictionary
+ at:aMonitorDeviceName
+ ifAbsentPut:[
+ (self
+ primResolutionForMonitorNamed:aMonitorDeviceName
+ trueForVirtualResolutionOrFalseForCurrentResolution:trueForVirtualResolutionOrFalseForCurrentResolution)
+ ? 0 "/ use 0 to indicate nil, avoid recalling of #displayResolutionForDisplayWithDeviceName:...
+ ].
+ ].
+ ].
+
+ currentResolution == 0 ifTrue:[
+ ^ nil
+ ].
+
+ ^ currentResolution
+
+ "Created: / 21-11-2019 / 10:06:51 / Stefan Reise"
+ "Modified: / 22-11-2019 / 10:41:38 / Stefan Reise"
+! !
+
+!WinWorkstation class methodsFor:'queries'!
isWindowsPlatform
"return true, if this device is a windows screen"
@@ -6792,31 +6848,245 @@
^ 'WIN32'
"Modified: 26.5.1996 / 15:32:46 / cg"
-!
-
-scaleFactorForRootDisplayCoordinates
- "ATTENTION: returns the may wrong default 1@1 (from super) if the package or the tool is missing:
- stx:support/win32/currrentDisplayResolution/bin/cdr.exe
-
- this is the factor we need to adopt for the root display coordinates,
- if windows did scale the application (when the app is not high DPI aware)"
-
- "
- self scaleFactorForRootDisplayCoordinates
- "
-
- |currentDisplayResolution|
-
- currentDisplayResolution := self currentDisplayResolution.
- currentDisplayResolution isNil ifTrue:[
- "may the tool binary is missing (this is already catched in #displayResolutionFromTool:)"
- ^ super scaleFactorForRootDisplayCoordinates
- ].
-
- ^ currentDisplayResolution / Display extent
-
- "Created: / 14-11-2019 / 13:36:59 / Stefan Reise"
- "Modified (comment): / 19-11-2019 / 12:08:26 / Stefan Reise"
+! !
+
+!WinWorkstation class methodsFor:'queries - monitor'!
+
+currentResolutionForMonitorNamed:aMonitorDeviceName
+ "ATTENTION: can return nil if the package or the tool is missing:
+ stx:support/win32/displayResolutionTools/bin/cdr.exe
+
+ this is the current resolution of the display,
+ without any effect of scaling
+
+ for e.g.
+ real current display resolution -> 1080p
+ scaling 150%
+ virtual display resolution -> 720p
+
+ real current display resolution -> 1080p
+ scaling 100%
+ virtual display resolution -> 1080p"
+
+ "
+ MonitorNameToCurrentResolution := Dictionary new.
+ self currentResolutionForMonitorNamed:'\\.\DISPLAY1'.
+ self currentResolutionForMonitorNamed:'\\.\DISPLAY2'.
+ "
+
+ |currentResolution|
+
+ currentResolution := self
+ resolutionForMonitorNamed:aMonitorDeviceName
+ trueForVirtualResolutionOrFalseForCurrentResolution:false.
+
+ currentResolution isNil ifTrue:[
+ ^ super currentResolutionForMonitorNamed:aMonitorDeviceName
+ ].
+
+ ^ currentResolution
+
+ "Created: / 21-11-2019 / 10:10:16 / Stefan Reise"
+ "Modified (comment): / 22-11-2019 / 10:22:06 / Stefan Reise"
+!
+
+monitorDeviceNameForPoint:aPoint
+ "given a point, return its monitor device name or nil if failed"
+
+ "
+ Screen monitorDeviceNameForPoint:0@0
+ Screen monitorDeviceNameForPoint:2000@0
+ "
+
+ |incomingX incomingY|
+
+ incomingX := aPoint x.
+ incomingY := aPoint y.
+
+%{
+ POINT pt;
+ HMONITOR hMonitor;
+ MONITORINFOEX monitorInfo;
+
+ pt.x = __intVal(incomingX);
+ pt.y = __intVal(incomingY);
+
+ hMonitor = MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
+ if (hMonitor == 0) {
+ RETURN(nil);
+ }
+
+ monitorInfo.cbSize = sizeof(MONITORINFOEX);
+ if (GetMonitorInfo(hMonitor, &monitorInfo) == 0){
+ RETURN(nil);
+ }
+
+ RETURN(__MKSTRING(monitorInfo.szDevice));
+%}
+
+ "Created: / 21-11-2019 / 09:13:57 / Stefan Reise"
+ "Modified (comment): / 21-11-2019 / 12:36:21 / Stefan Reise"
+!
+
+monitorDeviceNameForView:aView
+ "given a window ID, return its monitor device name or nil if failed"
+
+ "
+ Screen monitorDeviceNameForView:Transcript topView
+ "
+
+ |windowId|
+
+ windowId := aView id.
+
+%{
+ if (__isExternalAddress(windowId)) {
+ HMONITOR hMonitor;
+ MONITORINFOEX monitorInfo;
+
+ hMonitor = MonitorFromWindow(_HWNDVal(windowId), MONITOR_DEFAULTTOPRIMARY);
+ if (hMonitor == 0) {
+ RETURN(nil);
+ }
+
+ monitorInfo.cbSize = sizeof(MONITORINFOEX);
+ if (GetMonitorInfo(hMonitor, &monitorInfo) == 0){
+ RETURN(nil);
+ }
+
+ RETURN(__MKSTRING(monitorInfo.szDevice));
+ }
+%}
+
+ "Created: / 20-11-2019 / 14:52:59 / Stefan Reise"
+ "Modified: / 21-11-2019 / 18:04:50 / Stefan Reise"
+ "Modified (comment): / 22-11-2019 / 10:22:49 / Stefan Reise"
+!
+
+scaleFactorForMonitorNamed:aMonitorDeviceName
+ "ATTENTION: returns the may wrong default 1@1 if the package or the tools are missing:
+ stx:support/win32/displayResolutionTools/bin/cdr.exe
+ stx:support/win32/displayResolutionTools/bin/vdr.exe
+
+ ATTENTION: this method always returns the scale factor set by os,
+ REGARDLESS if the application (stx, expecco) has a virtual resolution or not
+ use #scaleFactorForRootViewTranslationOnMonitorNamed: which is dependent on the
+ application's (stx, expecco) high dpi awareness (if the application has a virtual
+ resolution or not).
+
+ this is the scale factor the user did enter within the windows settings,
+ for e.g. the user can choose between 100, 125, 150 etc.
+ here we return 1, 1.25 1.5"
+
+ "
+ self scaleFactorForMonitorNamed:'\\.\DISPLAY1'
+ self scaleFactorForMonitorNamed:'\\.\DISPLAY2'
+ "
+
+ |currentMonitorResolution virtualMonitorResolution|
+
+ currentMonitorResolution := self currentResolutionForMonitorNamed:aMonitorDeviceName.
+ currentMonitorResolution isNil ifTrue:[
+ "may the tool binary is missing"
+ ^ super scaleFactorForMonitorNamed:aMonitorDeviceName
+ ].
+
+ virtualMonitorResolution := self virtualResolutionForMonitorNamed:aMonitorDeviceName.
+ virtualMonitorResolution isNil ifTrue:[
+ "may the tool binary is missing"
+ ^ 1@1
+ ].
+
+ ^ currentMonitorResolution / virtualMonitorResolution
+
+ "Created: / 21-11-2019 / 10:12:00 / Stefan Reise"
+ "Modified: / 22-11-2019 / 10:01:09 / Stefan Reise"
+!
+
+scaleFactorForRootViewTranslationOnMonitorNamed:aMonitorDeviceName
+ "ATTENTION: returns the may wrong default 1@1 if the package or the tool is missing:
+ stx:support/win32/displayResolutionTools/bin/cdr.exe
+
+ 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"
+
+ "
+ self scaleFactorForRootViewTranslationOnMonitorNamed:'\\.\DISPLAY1'
+ self scaleFactorForRootViewTranslationOnMonitorNamed:'\\.\DISPLAY2'
+ "
+
+ |currentMonitorResolution monitorHandle monitorInfo|
+
+ currentMonitorResolution := Screen currentResolutionForMonitorNamed:aMonitorDeviceName.
+ currentMonitorResolution isNil ifTrue:[
+ "may the tool binary is missing"
+ ^ super scaleFactorForRootViewTranslationOnMonitorNamed:aMonitorDeviceName
+ ].
+
+ monitorHandle := Display monitorHandleForName:aMonitorDeviceName.
+ monitorHandle isNil ifTrue:[
+ ^ super scaleFactorForRootViewTranslationOnMonitorNamed:aMonitorDeviceName
+ ].
+
+ monitorInfo := Display monitorInfoFor:monitorHandle.
+ monitorInfo isNil ifTrue:[
+ "something wrong with the monitor name?"
+ ^ super scaleFactorForRootViewTranslationOnMonitorNamed:aMonitorDeviceName
+ ].
+
+ "the #monitorInfo contains the virtual resolution,
+ if the application is not high dpi aware.
+ otherwise the current resolution"
+ ^ currentMonitorResolution / ((monitorInfo screenWidth)@(monitorInfo screenHeight))
+
+ "Created: / 21-11-2019 / 12:33:11 / Stefan Reise"
+ "Modified (format): / 22-11-2019 / 10:23:16 / Stefan Reise"
+!
+
+virtualResolutionForMonitorNamed:aMonitorDeviceName
+ "ATTENTION: can return nil if the package or the tool is missing:
+ stx:support/win32/displayResolutionTools/bin/vdr.exe
+
+ ATTENTION: this method always returns the virtual resolution,
+ REGARDLESS if the application (stx, expecco) has a virtual resolution or not
+
+ this is the resolution of a virtual display,
+ this resolution is effected by the scaling
+
+ for e.g.
+ real current display resolution -> 1080p
+ scaling 150%
+ virtual display resolution -> 720p
+
+ real current display resolution -> 1080p
+ scaling 100%
+ virtual display resolution -> 1080p"
+
+ "
+ MonitorNameToVirtualResolution := Dictionary new.
+ self virtualResolutionForMonitorNamed:'\\.\DISPLAY1'
+ self virtualResolutionForMonitorNamed:'\\.\DISPLAY2'
+ "
+
+ |virtualResolution|
+
+ virtualResolution := self
+ resolutionForMonitorNamed:aMonitorDeviceName
+ trueForVirtualResolutionOrFalseForCurrentResolution:true.
+
+ virtualResolution isNil ifTrue:[
+ ^ 1@1
+ ].
+
+ ^ virtualResolution
+
+ "Created: / 21-11-2019 / 10:13:54 / Stefan Reise"
+ "Modified: / 22-11-2019 / 10:00:35 / Stefan Reise"
! !
!WinWorkstation methodsFor:'accessing & queries'!
@@ -7877,18 +8147,16 @@
monitorBoundsAt:aPoint
"answer the bounds of the monitor the point is contained in"
- |monitorHandle monitorInfo|
+ |monitorInfo|
self numberOfMonitors > 1 ifTrue:[
- "/ ******* MULTI SCREEN ******
- monitorHandle := self monitorHandleForPoint:aPoint.
- monitorHandle notNil ifTrue:[
- monitorInfo := self monitorInfoFor:monitorHandle.
- monitorInfo notNil ifTrue:[
- ^ monitorInfo bounds
- ].
- ].
- ].
+ "/ ******* MULTI SCREEN ******
+ monitorInfo := self monitorInfoForPoint:aPoint.
+ monitorInfo notNil ifTrue:[
+ ^ monitorInfo bounds
+ ].
+ ].
+
^ super monitorBoundsAt:aPoint
"
@@ -7898,6 +8166,166 @@
"
"Modified: / 22-10-2010 / 10:55:59 / cg"
+ "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"
+
+ |pX pY|
+
+ pX := aPoint x.
+ pY := aPoint y.
+%{
+ if (__bothSmallInteger(pX, pY)) {
+ POINT p;
+ HMONITOR hMonitor;
+ p.x = __intVal(pX);
+ p.y = __intVal(pY);
+#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_MonitorFromPoint)(POINT, int);
+
+ if (P_MonitorFromPoint == 0) {
+ HINSTANCE hUser = LoadLibrary("user32.dll");
+ // console_printf("hUser: %x\n", hUser);
+ if (hUser) {
+ P_MonitorFromPoint = (HMONITOR (__stdcall *)(POINT, int ))
+ GetProcAddress(hUser, "MonitorFromPoint");
+ }
+ }
+ // console_printf("P_MonitorFromPoint: %x\n", P_MonitorFromPoint);
+
+ hMonitor = (*P_MonitorFromPoint)(p, MONITOR_DEFAULTTONULL);
+#else
+ hMonitor = MonitorFromPoint(p, MONITOR_DEFAULTTONULL);
+#endif
+ if (hMonitor == 0) {
+ RETURN(nil);
+ }
+ RETURN ( __MKEXTERNALADDRESS(hMonitor) );
+ }
+%}
+ "
+ Screen current monitorHandleForPoint:(0@0)
+ Screen current monitorHandleForPoint:(1500@0)
+ Screen current monitorHandleForPoint:(3000@0)
+ Screen current monitorHandleForPoint:(Display pointFromUser)
+ "
+!
+
+monitorHandleForView:aWindowId
+ "given a window ID, return a handle to the monitor"
+
+%{
+ if (__isExternalAddress(aWindowId)) {
+ HWND hWnd = _HWNDVal(aWindowId);
+ 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) );
+ }
+%}
+ "
+ Screen current monitorHandleForView:(Transcript topView id)
+ Screen current monitorHandleForPoint:(0@0)
+ "
+!
+
+monitorHandles
+ "retrieve a list of monitor handles"
+
+ |handleArray|
+
+ handleArray := Array new:(self numberOfMonitors).
+%{
+ struct EnumDisplayMonitorsProcData data;
+
+ data.hArray = handleArray;
+ data.index = 0;
+ EnumDisplayMonitors(NULL, NULL, EnumDisplayMonitorsProc, (INT)&data);
+%}.
+ ^ handleArray
+
+ "
+ Screen default monitorHandles
+ "
+
+ "Modified (comment): / 28-01-2012 / 10:26:55 / cg"
+!
+
+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
+ ].
+
+ ^ nil
+
+ "Created: / 21-11-2019 / 11:11:47 / Stefan Reise"
+ "Modified: / 22-11-2019 / 09:57:05 / Stefan Reise"
+!
+
+monitorInfos
+ ^ self monitorHandles
+ collect:[:eachMonitorHandle |
+ self monitorInfoFor:eachMonitorHandle
+ ].
+
+ "Created: / 21-11-2019 / 13:35:22 / Stefan Reise"
!
numberOfMonitors
@@ -8093,20 +8521,20 @@
On multi-display systems with different sized screens, this should care for
which display is at the given x-position"
- |info fullHeight usableHeight delta|
+ |info|
true "(self numberOfMonitors) > 1" ifTrue:[
- "/ ******* MULTI SCREEN ******
- info := self monitorInfoFor:(self monitorHandleForPoint:aPoint).
- info notNil ifTrue:[
- ^ info workHeight
-
- "/ only works with single screen..
+ "/ ******* MULTI SCREEN ******
+ info := self monitorInfoForPoint:aPoint.
+ info notNil ifTrue:[
+ ^ info workHeight
+
+ "/ only works with single screen..
"/ fullHeight := self getSystemMetrics:#SM_CYVIRTUALSCREEN.
"/ usableHeight := self getSystemMetrics:#SM_CYFULLSCREEN. "/ without any start-menu bar
"/ delta := fullHeight - usableHeight.
"/ ^ info workHeight - delta
- ].
+ ].
].
^ self usableHeight
@@ -8121,21 +8549,19 @@
"
"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"
- |monitorHandle monitorInfo|
+ |monitorInfo|
"/ ******* MULTI SCREEN ******
- monitorHandle := self monitorHandleForPoint:aPoint.
- monitorHandle notNil ifTrue:[
- monitorInfo := self monitorInfoFor:monitorHandle.
- monitorInfo notNil ifTrue:[
- ^ monitorInfo workableAreaBounds
- ].
+ monitorInfo := self monitorInfoForPoint:aPoint.
+ monitorInfo notNil ifTrue:[
+ ^ monitorInfo workableAreaBounds
].
^ super workableAreaBoundsAt:aPoint
@@ -8147,6 +8573,7 @@
"
"Created: / 23-05-2019 / 11:10:06 / Stefan Vogel"
+ "Modified: / 22-11-2019 / 10:15:40 / Stefan Reise"
! !
!WinWorkstation methodsFor:'bitmap/window creation'!
@@ -16076,142 +16503,6 @@
%}
!
-monitorDeviceNameForView:aWindowId
- "given a window ID, return its monitor device name or nil if failed"
-
- "
- Screen current monitorDeviceNameForView:Transcript topView id
- "
-
-%{
- if (__isExternalAddress(aWindowId)) {
- HMONITOR hMonitor;
- MONITORINFOEX monitorInfo;
-
- hMonitor = MonitorFromWindow(_HWNDVal(aWindowId), MONITOR_DEFAULTTOPRIMARY);
- if (hMonitor == 0) {
- RETURN(nil);
- }
-
- monitorInfo.cbSize = sizeof(MONITORINFOEX);
- if (GetMonitorInfo(hMonitor, &monitorInfo) == 0){
- RETURN(nil);
- }
-
- RETURN(__MKSTRING(monitorInfo.szDevice));
- }
-%}
-
- "Created: / 20-11-2019 / 14:52:59 / Stefan Reise"
-!
-
-monitorHandleForPoint:aPoint
- "given a point, return a handle to the monitor"
-
- |pX pY|
-
- pX := aPoint x.
- pY := aPoint y.
-%{
- if (__bothSmallInteger(pX, pY)) {
- POINT p;
- HMONITOR hMonitor;
- p.x = __intVal(pX);
- p.y = __intVal(pY);
-#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_MonitorFromPoint)(POINT, int);
-
- if (P_MonitorFromPoint == 0) {
- HINSTANCE hUser = LoadLibrary("user32.dll");
- // console_printf("hUser: %x\n", hUser);
- if (hUser) {
- P_MonitorFromPoint = (HMONITOR (__stdcall *)(POINT, int ))
- GetProcAddress(hUser, "MonitorFromPoint");
- }
- }
- // console_printf("P_MonitorFromPoint: %x\n", P_MonitorFromPoint);
-
- hMonitor = (*P_MonitorFromPoint)(p, MONITOR_DEFAULTTONULL);
-#else
- hMonitor = MonitorFromPoint(p, MONITOR_DEFAULTTONULL);
-#endif
- if (hMonitor == 0) {
- RETURN(nil);
- }
- RETURN ( __MKEXTERNALADDRESS(hMonitor) );
- }
-%}
- "
- Screen current monitorHandleForPoint:(0@0)
- Screen current monitorHandleForPoint:(1500@0)
- Screen current monitorHandleForPoint:(3000@0)
- Screen current monitorHandleForPoint:(Display pointFromUser)
- "
-!
-
-monitorHandleForView:aWindowId
- "given a window ID, return a handle to the monitor"
-
-%{
- if (__isExternalAddress(aWindowId)) {
- HWND hWnd = _HWNDVal(aWindowId);
- 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) );
- }
-%}
- "
- Screen current monitorHandleForView:(Transcript topView id)
- Screen current monitorHandleForPoint:(0@0)
- "
-!
-
-monitorHandles
- "retrieve a list of monitor handles"
-
- |handleArray|
-
- handleArray := Array new:(self numberOfMonitors).
-%{
- struct EnumDisplayMonitorsProcData data;
-
- data.hArray = handleArray;
- data.index = 0;
- EnumDisplayMonitors(NULL, NULL, EnumDisplayMonitorsProc, (INT)&data);
-%}.
- ^ handleArray
-
- "
- Screen default monitorHandles
- "
-
- "Modified (comment): / 28-01-2012 / 10:26:55 / cg"
-!
-
setInputFocusTo:aWindowId
self setInputFocusTo:aWindowId revertTo:nil
!
@@ -20714,10 +21005,6 @@
height:workH - 1
!
-isPrimary
- ^ isPrimary
-!
-
name
^ name
!
@@ -20784,6 +21071,53 @@
"Created: / 23-05-2019 / 11:06:15 / Stefan Vogel"
! !
+!WinWorkstation::MonitorInfo methodsFor:'printing'!
+
+printOn:aStream
+ aStream nextPutAll:self class nameWithoutPrefix.
+ aStream nextPutAll:'[origin:'.
+ aStream nextPutAll:(screenX@screenY) printString.
+ aStream nextPutAll:'|extent:'.
+ aStream nextPutAll:(screenW@screenH) printString.
+ aStream nextPutAll:']'.
+
+ "Created: / 21-11-2019 / 16:39:12 / Stefan Reise"
+! !
+
+!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
+
+ "Created: / 22-11-2019 / 10:31:16 / Stefan Reise"
+!
+
+isPrimary
+ ^ isPrimary
+!
+
+screenBottom
+ ^ screenY + screenH
+
+ "Created: / 21-11-2019 / 13:38:25 / Stefan Reise"
+!
+
+screenRight
+ ^ screenX + screenW
+
+ "Created: / 21-11-2019 / 13:38:17 / Stefan Reise"
+! !
+
!WinWorkstation::NativeFileDialogCreationData methodsFor:'accessing'!
dataAddress