11# A part of NonVisual Desktop Access (NVDA)
22# This file is covered by the GNU General Public License.
33# See the file COPYING for more details.
4- # Copyright (C) 2018-2023 NV Access Limited, Babbage B.V., Leonard de Ruijter
4+ # Copyright (C) 2018-2024 NV Access Limited, Babbage B.V., Leonard de Ruijter
55
66"""Screen curtain implementation based on the windows magnification API.
77The Magnification API has been marked by MS as unsupported for WOW64 applications such as NVDA. (#12491)
1010import os
1111from vision import providerBase
1212from ctypes import Structure , windll , c_float , POINTER , WINFUNCTYPE , WinError
13- from ctypes .wintypes import BOOL
13+ from ctypes .wintypes import BOOL , FLOAT , HWND , RECT , INT
1414from autoSettingsUtils .driverSetting import BooleanDriverSetting
1515from autoSettingsUtils .autoSettings import SupportedSettingType
1616import wx
@@ -30,6 +30,24 @@ class MAGCOLOREFFECT(Structure):
3030 _fields_ = (("transform" , c_float * 5 * 5 ),)
3131
3232
33+ class MAGTRANSFORM (Structure ):
34+ _fields_ = (("v" , c_float * 3 * 3 ),)
35+
36+ def __init__ (self , magnificationFactor : float = 1.0 ):
37+ """
38+ https://learn.microsoft.com/en-us/windows/win32/api/magnification/ns-magnification-magtransform
39+
40+ :param magnificationFactor: defaults to 1.0.
41+ The minimum value of this parameter is 1.0, and the maximum value is 4096.0.
42+ If this value is 1.0, the screen content is not magnified and no offsets are applied.
43+ """
44+ super ().__init__ ()
45+ assert 1.0 <= magnificationFactor <= 4096.0
46+ self .v [0 ][0 ] = magnificationFactor
47+ self .v [1 ][1 ] = magnificationFactor
48+ self .v [2 ][2 ] = 1.0
49+
50+
3351# homogeneous matrix for a 4-space transformation (red, green, blue, opacity).
3452# https://docs.microsoft.com/en-gb/windows/win32/gdiplus/-gdiplus-using-a-color-matrix-to-transform-a-single-color-use
3553TRANSFORM_BLACK = MAGCOLOREFFECT () # empty transformation
@@ -85,6 +103,73 @@ class Magnification:
85103 MagUninitialize = _MagUninitializeFuncType (("MagUninitialize" , _magnification ))
86104 MagUninitialize .errcheck = _errCheck
87105
106+ _MagSetWindowSourceFuncType = WINFUNCTYPE (BOOL , HWND , POINTER (RECT ))
107+ _MagSetWindowSourceArgTypes = ((1 , "hwnd" ), (1 , "rect" ))
108+ MagSetWindowSource = _MagSetWindowSourceFuncType (
109+ ("MagSetWindowSource" , _magnification ),
110+ _MagSetWindowSourceArgTypes ,
111+ )
112+ MagSetWindowSource .errcheck = _errCheck
113+
114+ _MagGetWindowSourceFuncType = WINFUNCTYPE (BOOL , HWND , POINTER (RECT ))
115+ _MagGetWindowSourceArgTypes = ((1 , "hwnd" ), (2 , "rect" ))
116+ MagGetWindowSource = _MagGetWindowSourceFuncType (
117+ ("MagGetWindowSource" , _magnification ),
118+ _MagGetWindowSourceArgTypes ,
119+ )
120+ MagGetWindowSource .errcheck = _errCheck
121+
122+ _MagSetWindowTransformFuncType = WINFUNCTYPE (BOOL , HWND , POINTER (MAGTRANSFORM ))
123+ _MagSetWindowTransformArgTypes = ((1 , "hwnd" ), (1 , "transform" ))
124+ MagSetWindowTransform = _MagSetWindowTransformFuncType (
125+ ("MagSetWindowTransform" , _magnification ),
126+ _MagSetWindowTransformArgTypes ,
127+ )
128+ MagSetWindowTransform .errcheck = _errCheck
129+
130+ # Create transformation window
131+ _MagGetWindowTransformFuncType = WINFUNCTYPE (BOOL , HWND , POINTER (MAGTRANSFORM ))
132+ _MagGetWindowTransformArgTypes = ((1 , "hwnd" ), (2 , "transform" ))
133+ MagGetWindowTransform = _MagGetWindowTransformFuncType (
134+ ("MagGetWindowTransform" , _magnification ),
135+ _MagGetWindowTransformArgTypes ,
136+ )
137+ MagGetWindowTransform .errcheck = _errCheck
138+
139+ _MagSetFullscreenTransformFuncType = WINFUNCTYPE (BOOL , POINTER (FLOAT ), POINTER (INT ), POINTER (INT ))
140+ _MagSetFullscreenTransformArgTypes = ((1 , "magLevel" ), (1 , "offsetX" ), (1 , "offsetY" ))
141+ MagSetFullscreenTransform = _MagSetFullscreenTransformFuncType (
142+ ("MagSetFullscreenTransform" , _magnification ),
143+ _MagSetFullscreenTransformArgTypes ,
144+ )
145+ MagSetFullscreenTransform .errcheck = _errCheck
146+
147+ _MagGetFullscreenTransformFuncType = WINFUNCTYPE (BOOL , POINTER (FLOAT ), POINTER (INT ), POINTER (INT ))
148+ _MagGetFullscreenTransformArgTypes = ((2 , "magLevel" ), (2 , "offsetX" ), (2 , "offsetY" ))
149+ MagGetFullscreenTransform = _MagGetFullscreenTransformFuncType (
150+ ("MagGetFullscreenTransform" , _magnification ),
151+ _MagGetFullscreenTransformArgTypes ,
152+ )
153+ MagGetFullscreenTransform .errcheck = _errCheck
154+
155+ # # Create transformation window
156+ # _MagGetInputTransformFuncType = WINFUNCTYPE(BOOL, POINTER(BOOL), POINTER(RECT), POINTER(RECT))
157+ # _MagGetInputTransformArgTypes = ((2, "enabled"), (2, "src"), (2, "dest"))
158+ # MagGetInputTransform = _MagGetInputTransformFuncType(
159+ # ("MagGetInputTransform", _magnification),
160+ # _MagGetInputTransformArgTypes,
161+ # )
162+ # MagGetInputTransform.errcheck = _errCheck
163+
164+ # # Create transformation window
165+ # _MagSetInputTransformFuncType = WINFUNCTYPE(BOOL, POINTER(BOOL), POINTER(RECT), POINTER(RECT))
166+ # _MagSetInputTransformArgTypes = ((1, "enabled"), (1, "src"), (1, "dest"))
167+ # MagSetInputTransform = _MagGetInputTransformFuncType(
168+ # ("MagSetInputTransform", _magnification),
169+ # _MagSetInputTransformArgTypes,
170+ # )
171+ # MagSetInputTransform.errcheck = _errCheck
172+
88173
89174# Translators: Name for a vision enhancement provider that disables output to the screen,
90175# making it black.
0 commit comments