|
| 1 | +import { Orientation } from '@appium/types'; |
1 | 2 | import { |
2 | 3 | load, |
3 | 4 | struct, |
@@ -70,7 +71,7 @@ interface DeviceModeAnsi { |
70 | 71 | dmDeviceName: string | null, |
71 | 72 | dmSpecVersion: number, |
72 | 73 | dmDriverVersion: number, |
73 | | - dmSize: 68, |
| 74 | + dmSize: number, |
74 | 75 | dmDriverExtra: number, |
75 | 76 | dmFields: number, |
76 | 77 | u1: { |
@@ -213,7 +214,7 @@ const INPUT = struct('INPUT', { |
213 | 214 | } satisfies InputUnion) |
214 | 215 | }); |
215 | 216 |
|
216 | | -struct('DEVMODEA', { |
| 217 | +const DEVMODEA = struct('DEVMODEA', { |
217 | 218 | dmDeviceName: array('char', 32, 'String'), |
218 | 219 | dmSpecVersion: 'uint16', |
219 | 220 | dmDriverVersion: 'uint16', |
@@ -291,7 +292,7 @@ const GetSystemMetrics = user32.func(/* c */ `int __stdcall GetSystemMetrics(int |
291 | 292 | const SetProcessDPIAware = user32.func(/* c */ `bool __stdcall SetProcessDPIAware()`) as () => boolean; |
292 | 293 | const GetDpiForSystem = user32.func(/* c */ `unsigned int __stdcall GetDpiForSystem()`) as () => number; |
293 | 294 | const GetCursorPos = user32.func(/* c */ `bool __stdcall GetCursorPos(_Out_ POINT *lpPoint)`) as (lpPoint: Point) => boolean; |
294 | | -const EnumDisplaySettingsA = user32.func(/* c */ `bool __stdcall EnumDisplaySettingsA(str lpszDeviceName, uint iModeNum, _Out_ DEVMODEA *lpDevMode)`) as (lpszDeviceName: string | null, iModeNum: number, lpDevMode: DeviceModeAnsi) => boolean; |
| 295 | +const EnumDisplaySettingsA = user32.func(/* c */ `bool __stdcall EnumDisplaySettingsA(str lpszDeviceName, uint iModeNum, _Out_ DEVMODEA *lpDevMode)`) as (lpszDeviceName: string | null, iModeNum: number, lpDevMode: Buffer) => boolean; |
295 | 296 | // end TODO |
296 | 297 |
|
297 | 298 | const GetWindowThreadProcessId = user32.func(/* c */ `DWORD __stdcall GetWindowThreadProcessId(HWND hWnd, _Out_ LPDWORD lpdwProcessId)`) as (hWnd: HWND, lpdwProcessId: [LPDWORD | null]) => DWORD; |
@@ -654,7 +655,11 @@ async function sendMouseMoveInput(args: { x: number, y: number, relative: boolea |
654 | 655 | const updateInterval = 1000 / refreshRate; |
655 | 656 | const iterations = Math.max(Math.floor(duration / updateInterval), 1); |
656 | 657 |
|
657 | | - const cursorPosition = {} as Point; |
| 658 | + const cursorPosition = { |
| 659 | + x: 0, |
| 660 | + y: 0, |
| 661 | + } satisfies Point; |
| 662 | + |
658 | 663 | if (GetCursorPos(cursorPosition) && iterations > 1) { |
659 | 664 | if (relative) { |
660 | 665 | x += cursorPosition.x; |
@@ -733,15 +738,26 @@ function getResolutionScalingFactor(): number { |
733 | 738 | function getScreenResolutionAndRefreshRate(): [number, number, number] { |
734 | 739 | const width = GetSystemMetrics(SystemMetric.SM_CXSCREEN); |
735 | 740 | const height = GetSystemMetrics(SystemMetric.SM_CYSCREEN); |
| 741 | + let refreshRate: number | null = null; |
736 | 742 |
|
737 | | - const deviceMode = {} as DeviceModeAnsi; |
738 | | - EnumDisplaySettingsA(null, -1, deviceMode); |
| 743 | + const buffer = Buffer.alloc(sizeof(DEVMODEA)); |
| 744 | + EnumDisplaySettingsA(null, -1, buffer); |
| 745 | + const deviceMode = { dmDisplayFrequency: buffer.readUInt32LE(120) } as DeviceModeAnsi; |
| 746 | + refreshRate = deviceMode.dmDisplayFrequency; |
739 | 747 |
|
740 | | - const refreshRate = deviceMode.dmDisplayFrequency; |
741 | 748 | const resolution = [width, height, refreshRate] satisfies ReturnType<typeof getScreenResolutionAndRefreshRate>; |
742 | 749 |
|
743 | | - // @ts-expect-error temporary quick and dirty version of memoization |
744 | | - getScreenResolutionAndRefreshRate = () => resolution; |
| 750 | + const nonMemoizedMethod = getScreenResolutionAndRefreshRate; |
| 751 | + const currentTime = new Date().getTime(); |
| 752 | + |
| 753 | + // @ts-expect-error memoizing the function to prevent repeated calls that might crash Node.js |
| 754 | + getScreenResolutionAndRefreshRate = () => { |
| 755 | + if (new Date().getTime() - currentTime > 1000) { |
| 756 | + // @ts-expect-error reset memoization after 1 second |
| 757 | + getScreenResolutionAndRefreshRate = nonMemoizedMethod; |
| 758 | + } |
| 759 | + return resolution; |
| 760 | + }; |
745 | 761 |
|
746 | 762 | return resolution; |
747 | 763 | } |
@@ -774,12 +790,9 @@ export function mouseUp(button: number = 0): void { |
774 | 790 | sendMouseButtonInput(button, false); |
775 | 791 | } |
776 | 792 |
|
777 | | -export function getDisplayOrientation(): number { |
778 | | - const deviceMode = {} as DeviceModeAnsi; |
779 | | - EnumDisplaySettingsA(null, -1, deviceMode); |
780 | | - |
781 | | - const orientation = deviceMode.u1.s2.dmDisplayOrientation; |
782 | | - return orientation; |
| 793 | +export function getDisplayOrientation(): Orientation { |
| 794 | + const resolution = getScreenResolutionAndRefreshRate(); |
| 795 | + return resolution[0] > resolution[1] ? 'LANDSCAPE' : 'PORTRAIT'; |
783 | 796 | } |
784 | 797 |
|
785 | 798 | export function setDpiAwareness() { |
|
0 commit comments