appium-webdriveragent 16.13.6 → 16.14.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -0
- package/README.md +8 -0
- package/WebDriverAgent.xcodeproj/project.pbxproj +16 -0
- package/WebDriverAgentLib/Categories/XCAXClient_iOS+FBSnapshotReqParams.m +8 -0
- package/WebDriverAgentLib/Categories/XCUIDevice+FBHinge.h +41 -0
- package/WebDriverAgentLib/Categories/XCUIDevice+FBHinge.m +215 -0
- package/WebDriverAgentLib/Commands/FBCustomCommands.m +71 -10
- package/WebDriverAgentLib/Info.plist +2 -2
- package/WebDriverAgentLib/Routing/FBScreenRecordingRequest.m +7 -2
- package/WebDriverAgentLib/Utilities/FBActiveAppDetectionPoint.h +2 -2
- package/WebDriverAgentLib/Utilities/FBActiveAppDetectionPoint.m +20 -0
- package/WebDriverAgentLib/Utilities/FBConfiguration.h +1 -1
- package/WebDriverAgentLib/Utilities/FBMjpegServer.m +3 -3
- package/WebDriverAgentLib/Utilities/FBScreen.m +53 -10
- package/WebDriverAgentLib/WebDriverAgentLib.h +1 -0
- package/WebDriverAgentTests/IntegrationApp/Classes/ViewController.m +15 -0
- package/WebDriverAgentTests/IntegrationTests/FBConfigurationTests.m +52 -0
- package/WebDriverAgentTests/IntegrationTests/FBScreenTests.m +322 -3
- package/WebDriverAgentTests/UnitTests/FBCustomCommandsTests.m +61 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,16 @@
|
|
|
1
|
+
## [16.14.1](https://github.com/appium/WebDriverAgent/compare/v16.14.0...v16.14.1) (2026-10-07)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
* report geometry for the selected display ([#1291](https://github.com/appium/WebDriverAgent/issues/1291)) ([43fa6da](https://github.com/appium/WebDriverAgent/commit/43fa6da647fb8adca21fdbd106d8f73d782d6717))
|
|
6
|
+
* skip accessibility idle checks for WebKit services ([#1293](https://github.com/appium/WebDriverAgent/issues/1293)) ([9d06611](https://github.com/appium/WebDriverAgent/commit/9d06611d1f5d342fd16458f707dca3f3e3ec00fc))
|
|
7
|
+
|
|
8
|
+
## [16.14.0](https://github.com/appium/WebDriverAgent/compare/v16.13.6...v16.14.0) (2026-10-04)
|
|
9
|
+
|
|
10
|
+
### Features
|
|
11
|
+
|
|
12
|
+
* support Duo hinge control and secondary display capture ([#1287](https://github.com/appium/WebDriverAgent/issues/1287)) ([76d6aa0](https://github.com/appium/WebDriverAgent/commit/76d6aa03e2423290bb05c436afc153bd32878ce0))
|
|
13
|
+
|
|
1
14
|
## [16.13.6](https://github.com/appium/WebDriverAgent/compare/v16.13.5...v16.13.6) (2026-09-30)
|
|
2
15
|
|
|
3
16
|
### Bug Fixes
|
package/README.md
CHANGED
|
@@ -26,6 +26,14 @@ and start sending [requests](https://github.com/facebook/WebDriverAgent/wiki/Que
|
|
|
26
26
|
|
|
27
27
|
More about how to start WebDriverAgent [here](https://github.com/facebook/WebDriverAgent/wiki/Starting-WebDriverAgent).
|
|
28
28
|
|
|
29
|
+
## Multiple displays
|
|
30
|
+
|
|
31
|
+
See [Multiple displays](docs/multiple-displays.md) for display selection, capture,
|
|
32
|
+
and active-app detection.
|
|
33
|
+
|
|
34
|
+
See [Hinge angle](docs/hinge-angle.md) for reading angles, sending simulated hinge
|
|
35
|
+
events, runtime requirements, and physical-device testing feedback.
|
|
36
|
+
|
|
29
37
|
## Known Issues
|
|
30
38
|
If you are having some issues please checkout [wiki](https://github.com/facebook/WebDriverAgent/wiki/Common-Issues) first.
|
|
31
39
|
|
|
@@ -245,6 +245,7 @@
|
|
|
245
245
|
57C72DA18039FED310967F8F /* XCTSourceCodeLocation.h in Headers */ = {isa = PBXBuildFile; fileRef = 81BB54ECBFB5B7B680BB5D4F /* XCTSourceCodeLocation.h */; };
|
|
246
246
|
57EAF450031647694B6491F8 /* FBConfiguration.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9B76A21CF7A43900275851 /* FBConfiguration.m */; };
|
|
247
247
|
583AD004FF71CAA305E6DEAF /* XCUIDevice+FBHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = AD6C26971CF2481700F8B5FF /* XCUIDevice+FBHelpers.m */; };
|
|
248
|
+
0460879AD6034130AE0A3DEC /* XCUIDevice+FBHinge.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C8E6FD103A84C908F5746EA /* XCUIDevice+FBHinge.m */; };
|
|
248
249
|
587AA46196BC2C46555C8E44 /* XCUIButtonConsole.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E09842154A44874C4E9CA01 /* XCUIButtonConsole.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
249
250
|
588F51093FD2A5597366C282 /* XCUIElementEventTarget-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 0DC62BF635704E9C72AF533E /* XCUIElementEventTarget-Protocol.h */; };
|
|
250
251
|
5967912A40E807CDBE87E4B2 /* XCTReportingSessionIssueReporter-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 525D62A58488A52AA1BFE94A /* XCTReportingSessionIssueReporter-Protocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
@@ -327,6 +328,7 @@
|
|
|
327
328
|
641EE60A2240C5CA00173FCB /* FBLogger.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9B76A41CF7A43900275851 /* FBLogger.m */; };
|
|
328
329
|
641EE60B2240C5CA00173FCB /* FBCustomCommands.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB7531CAEDF0C008C271F /* FBCustomCommands.m */; };
|
|
329
330
|
641EE60C2240C5CA00173FCB /* XCUIDevice+FBHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = AD6C26971CF2481700F8B5FF /* XCUIDevice+FBHelpers.m */; };
|
|
331
|
+
181F0DBB6D28418680D52128 /* XCUIDevice+FBHinge.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C8E6FD103A84C908F5746EA /* XCUIDevice+FBHinge.m */; };
|
|
330
332
|
641EE60D2240C5CA00173FCB /* XCTestPrivateSymbols.m in Sources */ = {isa = PBXBuildFile; fileRef = EE6B64FC1D0F86EF00E85F5D /* XCTestPrivateSymbols.m */; };
|
|
331
333
|
641EE60E2240C5CA00173FCB /* XCUIElement+FBTyping.m in Sources */ = {isa = PBXBuildFile; fileRef = AD76723C1D6B7CC000610457 /* XCUIElement+FBTyping.m */; };
|
|
332
334
|
641EE60F2240C5CA00173FCB /* XCUIElement+FBAccessibility.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB7461CAEDF0C008C271F /* XCUIElement+FBAccessibility.m */; };
|
|
@@ -433,6 +435,7 @@
|
|
|
433
435
|
641EE6BF2240C5CA00173FCB /* FBKeyboard.h in Headers */ = {isa = PBXBuildFile; fileRef = EE3A18641CDE734B00DE4205 /* FBKeyboard.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
434
436
|
641EE6C02240C5CA00173FCB /* XCUIApplication+FBHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = AD6C269A1CF2494200F8B5FF /* XCUIApplication+FBHelpers.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
435
437
|
641EE6C22240C5CA00173FCB /* XCUIDevice+FBHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = AD6C26961CF2481700F8B5FF /* XCUIDevice+FBHelpers.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
438
|
+
95EF6989BCBE4C548C26B140 /* XCUIDevice+FBHinge.h in Headers */ = {isa = PBXBuildFile; fileRef = E7536267DE094076A4EEE1D7 /* XCUIDevice+FBHinge.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
436
439
|
641EE6C32240C5CA00173FCB /* FBClassChainQueryParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 71A7EAF71E224648001DA4F2 /* FBClassChainQueryParser.h */; };
|
|
437
440
|
641EE6C42240C5CA00173FCB /* FBMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = EE9B76A51CF7A43900275851 /* FBMacros.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
438
441
|
641EE6C52240C5CA00173FCB /* XCTestExpectationDelegate-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = EE35ACD91E3B77D600A02D78 /* XCTestExpectationDelegate-Protocol.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
@@ -887,7 +890,9 @@
|
|
|
887
890
|
AD6C26941CF2379700F8B5FF /* FBAlert.h in Headers */ = {isa = PBXBuildFile; fileRef = AD6C26921CF2379700F8B5FF /* FBAlert.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
888
891
|
AD6C26951CF2379700F8B5FF /* FBAlert.m in Sources */ = {isa = PBXBuildFile; fileRef = AD6C26931CF2379700F8B5FF /* FBAlert.m */; };
|
|
889
892
|
AD6C26981CF2481700F8B5FF /* XCUIDevice+FBHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = AD6C26961CF2481700F8B5FF /* XCUIDevice+FBHelpers.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
893
|
+
210AB789D14D40308B764DD0 /* XCUIDevice+FBHinge.h in Headers */ = {isa = PBXBuildFile; fileRef = E7536267DE094076A4EEE1D7 /* XCUIDevice+FBHinge.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
890
894
|
AD6C26991CF2481700F8B5FF /* XCUIDevice+FBHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = AD6C26971CF2481700F8B5FF /* XCUIDevice+FBHelpers.m */; };
|
|
895
|
+
25C9BDFC65564D78A70231B4 /* XCUIDevice+FBHinge.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C8E6FD103A84C908F5746EA /* XCUIDevice+FBHinge.m */; };
|
|
891
896
|
AD6C269C1CF2494200F8B5FF /* XCUIApplication+FBHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = AD6C269A1CF2494200F8B5FF /* XCUIApplication+FBHelpers.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
|
892
897
|
AD6C269D1CF2494200F8B5FF /* XCUIApplication+FBHelpers.m in Sources */ = {isa = PBXBuildFile; fileRef = AD6C269B1CF2494200F8B5FF /* XCUIApplication+FBHelpers.m */; };
|
|
893
898
|
AD764F10E2F00090AEB802F2 /* XCUIElement+FBIsVisible.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB7481CAEDF0C008C271F /* XCUIElement+FBIsVisible.m */; };
|
|
@@ -987,6 +992,7 @@
|
|
|
987
992
|
D1172A7F53F89B78D8324A13 /* RouteRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = 374BB11AE4E4243BCA444CF8 /* RouteRequest.m */; };
|
|
988
993
|
D1212325FDE77754EE503755 /* FBRouteRequest.m in Sources */ = {isa = PBXBuildFile; fileRef = EE9AB7881CAEDF0C008C271F /* FBRouteRequest.m */; };
|
|
989
994
|
D142183578036F5FD5B9880B /* XCUIDevice+FBHelpers.h in Headers */ = {isa = PBXBuildFile; fileRef = AD6C26961CF2481700F8B5FF /* XCUIDevice+FBHelpers.h */; };
|
|
995
|
+
2E71304F39B64EDC98EE3974 /* XCUIDevice+FBHinge.h in Headers */ = {isa = PBXBuildFile; fileRef = E7536267DE094076A4EEE1D7 /* XCUIDevice+FBHinge.h */; };
|
|
990
996
|
D14718959F7D46949859EEE6 /* FBDebugLogDelegateDecorator.m in Sources */ = {isa = PBXBuildFile; fileRef = EE7E27191D06C69F001BEC7B /* FBDebugLogDelegateDecorator.m */; };
|
|
991
997
|
D1DE06DF54156F744E364B5F /* FBDebugLogDelegateDecorator.h in Headers */ = {isa = PBXBuildFile; fileRef = EE7E27181D06C69F001BEC7B /* FBDebugLogDelegateDecorator.h */; };
|
|
992
998
|
D203F622C7C0D968F3BD2AAF /* XCUIPlatformApplicationServicesProviding-Protocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 3BA71BCF1FDA482419CA8596 /* XCUIPlatformApplicationServicesProviding-Protocol.h */; };
|
|
@@ -1760,7 +1766,9 @@
|
|
|
1760
1766
|
AD6C26921CF2379700F8B5FF /* FBAlert.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FBAlert.h; path = WebDriverAgentLib/FBAlert.h; sourceTree = SOURCE_ROOT; };
|
|
1761
1767
|
AD6C26931CF2379700F8B5FF /* FBAlert.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; name = FBAlert.m; path = WebDriverAgentLib/FBAlert.m; sourceTree = SOURCE_ROOT; xcLanguageSpecificationIdentifier = xcode.lang.objc; };
|
|
1762
1768
|
AD6C26961CF2481700F8B5FF /* XCUIDevice+FBHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XCUIDevice+FBHelpers.h"; sourceTree = "<group>"; };
|
|
1769
|
+
E7536267DE094076A4EEE1D7 /* XCUIDevice+FBHinge.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XCUIDevice+FBHinge.h"; sourceTree = "<group>"; };
|
|
1763
1770
|
AD6C26971CF2481700F8B5FF /* XCUIDevice+FBHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCUIDevice+FBHelpers.m"; sourceTree = "<group>"; };
|
|
1771
|
+
8C8E6FD103A84C908F5746EA /* XCUIDevice+FBHinge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCUIDevice+FBHinge.m"; sourceTree = "<group>"; };
|
|
1764
1772
|
AD6C269A1CF2494200F8B5FF /* XCUIApplication+FBHelpers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XCUIApplication+FBHelpers.h"; sourceTree = "<group>"; };
|
|
1765
1773
|
AD6C269B1CF2494200F8B5FF /* XCUIApplication+FBHelpers.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "XCUIApplication+FBHelpers.m"; sourceTree = "<group>"; };
|
|
1766
1774
|
AD76723B1D6B7CC000610457 /* XCUIElement+FBTyping.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "XCUIElement+FBTyping.h"; sourceTree = "<group>"; };
|
|
@@ -2415,7 +2423,9 @@
|
|
|
2415
2423
|
EEDFE11F1D9C06F800E6FFE5 /* XCUIDevice+FBHealthCheck.h */,
|
|
2416
2424
|
EEDFE1201D9C06F800E6FFE5 /* XCUIDevice+FBHealthCheck.m */,
|
|
2417
2425
|
AD6C26961CF2481700F8B5FF /* XCUIDevice+FBHelpers.h */,
|
|
2426
|
+
E7536267DE094076A4EEE1D7 /* XCUIDevice+FBHinge.h */,
|
|
2418
2427
|
AD6C26971CF2481700F8B5FF /* XCUIDevice+FBHelpers.m */,
|
|
2428
|
+
8C8E6FD103A84C908F5746EA /* XCUIDevice+FBHinge.m */,
|
|
2419
2429
|
A1B2C3D41F001A00A1B0001 /* XCUIDevice+FBVoiceOver.h */,
|
|
2420
2430
|
A1B2C3D41F001A00A1B0002 /* XCUIDevice+FBVoiceOver.m */,
|
|
2421
2431
|
EEE3763D1D59F81400ED88DD /* XCUIDevice+FBRotation.h */,
|
|
@@ -3178,6 +3188,7 @@
|
|
|
3178
3188
|
641EE6C02240C5CA00173FCB /* XCUIApplication+FBHelpers.h in Headers */,
|
|
3179
3189
|
714EAA0E2673FDFE005C5B47 /* FBCapabilities.h in Headers */,
|
|
3180
3190
|
641EE6C22240C5CA00173FCB /* XCUIDevice+FBHelpers.h in Headers */,
|
|
3191
|
+
95EF6989BCBE4C548C26B140 /* XCUIDevice+FBHinge.h in Headers */,
|
|
3181
3192
|
71D3B3D6267FC7260076473D /* XCUIElement+FBResolve.h in Headers */,
|
|
3182
3193
|
641EE6C32240C5CA00173FCB /* FBClassChainQueryParser.h in Headers */,
|
|
3183
3194
|
641EE6C42240C5CA00173FCB /* FBMacros.h in Headers */,
|
|
@@ -3489,6 +3500,7 @@
|
|
|
3489
3500
|
81231F08969740B0C8C67A30 /* XCUIApplication+FBHelpers.h in Headers */,
|
|
3490
3501
|
9AA0E22033281B4EAA78BC51 /* FBCapabilities.h in Headers */,
|
|
3491
3502
|
D142183578036F5FD5B9880B /* XCUIDevice+FBHelpers.h in Headers */,
|
|
3503
|
+
2E71304F39B64EDC98EE3974 /* XCUIDevice+FBHinge.h in Headers */,
|
|
3492
3504
|
09D97BD46764FD8149747723 /* XCUIElement+FBResolve.h in Headers */,
|
|
3493
3505
|
6BF3F57247F59B81B8BCEE7B /* FBClassChainQueryParser.h in Headers */,
|
|
3494
3506
|
8AAA33A5B1943B667B0DB05E /* FBMacros.h in Headers */,
|
|
@@ -3756,6 +3768,7 @@
|
|
|
3756
3768
|
AD6C269C1CF2494200F8B5FF /* XCUIApplication+FBHelpers.h in Headers */,
|
|
3757
3769
|
714D88CC2733FB970074A925 /* FBXMLGenerationOptions.h in Headers */,
|
|
3758
3770
|
AD6C26981CF2481700F8B5FF /* XCUIDevice+FBHelpers.h in Headers */,
|
|
3771
|
+
210AB789D14D40308B764DD0 /* XCUIDevice+FBHinge.h in Headers */,
|
|
3759
3772
|
71A7EAF91E224648001DA4F2 /* FBClassChainQueryParser.h in Headers */,
|
|
3760
3773
|
EE9B76AA1CF7A43900275851 /* FBMacros.h in Headers */,
|
|
3761
3774
|
C8FB547922D4C1FC00B69954 /* FBUnattachedAppLauncher.h in Headers */,
|
|
@@ -4513,6 +4526,7 @@
|
|
|
4513
4526
|
641EE60B2240C5CA00173FCB /* FBCustomCommands.m in Sources */,
|
|
4514
4527
|
71BB58E42B9631F100CB9BFE /* FBScreenRecordingPromise.m in Sources */,
|
|
4515
4528
|
641EE60C2240C5CA00173FCB /* XCUIDevice+FBHelpers.m in Sources */,
|
|
4529
|
+
181F0DBB6D28418680D52128 /* XCUIDevice+FBHinge.m in Sources */,
|
|
4516
4530
|
641EE60D2240C5CA00173FCB /* XCTestPrivateSymbols.m in Sources */,
|
|
4517
4531
|
641EE60E2240C5CA00173FCB /* XCUIElement+FBTyping.m in Sources */,
|
|
4518
4532
|
641EE60F2240C5CA00173FCB /* XCUIElement+FBAccessibility.m in Sources */,
|
|
@@ -4668,6 +4682,7 @@
|
|
|
4668
4682
|
EDC993E0858F89F73D8E9DF8 /* FBCustomCommands.m in Sources */,
|
|
4669
4683
|
45033CF6BD35C16E34BF76CC /* FBScreenRecordingPromise.m in Sources */,
|
|
4670
4684
|
583AD004FF71CAA305E6DEAF /* XCUIDevice+FBHelpers.m in Sources */,
|
|
4685
|
+
0460879AD6034130AE0A3DEC /* XCUIDevice+FBHinge.m in Sources */,
|
|
4671
4686
|
192CACF49EC3825BA6D2EF4F /* XCTestPrivateSymbols.m in Sources */,
|
|
4672
4687
|
53E0F0F38E7847065810FF41 /* XCUIElement+FBTyping.m in Sources */,
|
|
4673
4688
|
A5353D849D394BC630839E59 /* XCUIElement+FBAccessibility.m in Sources */,
|
|
@@ -4787,6 +4802,7 @@
|
|
|
4787
4802
|
EE9B76A91CF7A43900275851 /* FBLogger.m in Sources */,
|
|
4788
4803
|
EE158ABB1CBD456F00A3E3F0 /* FBCustomCommands.m in Sources */,
|
|
4789
4804
|
AD6C26991CF2481700F8B5FF /* XCUIDevice+FBHelpers.m in Sources */,
|
|
4805
|
+
25C9BDFC65564D78A70231B4 /* XCUIDevice+FBHinge.m in Sources */,
|
|
4790
4806
|
716C9E0227315EFF005AD475 /* XCUIApplication+FBUIInterruptions.m in Sources */,
|
|
4791
4807
|
EE6B64FE1D0F86EF00E85F5D /* XCTestPrivateSymbols.m in Sources */,
|
|
4792
4808
|
AD76723E1D6B7CC000610457 /* XCUIElement+FBTyping.m in Sources */,
|
|
@@ -109,6 +109,14 @@ static id swizzledRequestSnapshotForElement(id self, SEL _cmd, id element, id at
|
|
|
109
109
|
return original_requestSnapshotForElement(self, _cmd, element, attributes, parameters, error);
|
|
110
110
|
}
|
|
111
111
|
|
|
112
|
+
// Remote WKWebView elements belong to a WebKit service, not the host app.
|
|
113
|
+
// Sending the idle-check AX action to WebContent can crash it (#1290).
|
|
114
|
+
// Read process metadata only: resolving UI attributes here can reenter
|
|
115
|
+
// snapshotting. Leave these services on the original snapshot path.
|
|
116
|
+
if ([application.bundleID hasPrefix:@"com.apple.WebKit."]) {
|
|
117
|
+
return original_requestSnapshotForElement(self, _cmd, element, attributes, parameters, error);
|
|
118
|
+
}
|
|
119
|
+
|
|
112
120
|
NSNumber *pidKey = @(pid);
|
|
113
121
|
@synchronized (unresponsiveApplicationPidsLock) {
|
|
114
122
|
NSDate *markedUnresponsiveAt = unresponsiveApplicationPids[pidKey];
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2015-present, Facebook, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the BSD-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
#import <XCTest/XCTest.h>
|
|
10
|
+
|
|
11
|
+
NS_ASSUME_NONNULL_BEGIN
|
|
12
|
+
|
|
13
|
+
@interface XCUIDevice (FBHinge)
|
|
14
|
+
|
|
15
|
+
/** Whether a hinge and the CoreMotion angle-reading APIs are available. */
|
|
16
|
+
- (BOOL)fb_supportsHingeAngleReading;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
Whether a hinge and the IOKit APIs needed to attempt injection are available.
|
|
20
|
+
This does not guarantee event acceptance, particularly on physical devices.
|
|
21
|
+
*/
|
|
22
|
+
- (BOOL)fb_canAttemptSimulatedHingeAngleInjection;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
Reads the current hinge angle in degrees, including changes made outside WDA.
|
|
26
|
+
Waits up to 5 seconds for a valid reading. Does not change the hinge angle.
|
|
27
|
+
@return The angle, or nil with an error if unavailable or reading times out.
|
|
28
|
+
*/
|
|
29
|
+
- (nullable NSNumber *)fb_getSimulatedHingeAngle:(NSError **)error;
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
Sends a simulated hinge angle in degrees (0 = closed, 180 = fully open).
|
|
33
|
+
This dispatches the event; the display transition completes asynchronously.
|
|
34
|
+
Verified on the iPhone Duo simulator; physical-device behavior is unverified.
|
|
35
|
+
Does not change currentDisplayId.
|
|
36
|
+
*/
|
|
37
|
+
- (BOOL)fb_setSimulatedHingeAngle:(double)angle error:(NSError **)error;
|
|
38
|
+
|
|
39
|
+
@end
|
|
40
|
+
|
|
41
|
+
NS_ASSUME_NONNULL_END
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) 2015-present, Facebook, Inc.
|
|
3
|
+
* All rights reserved.
|
|
4
|
+
*
|
|
5
|
+
* This source code is licensed under the BSD-style license found in the
|
|
6
|
+
* LICENSE file in the root directory of this source tree.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
#import "XCUIDevice+FBHinge.h"
|
|
10
|
+
|
|
11
|
+
#import <dlfcn.h>
|
|
12
|
+
#import <math.h>
|
|
13
|
+
#import <mach/mach_time.h>
|
|
14
|
+
|
|
15
|
+
#import "FBErrorBuilder.h"
|
|
16
|
+
|
|
17
|
+
#if !TARGET_OS_TV && !TARGET_OS_WATCH
|
|
18
|
+
static const NSTimeInterval FBHingeAngleReadingTimeout = 5.0;
|
|
19
|
+
|
|
20
|
+
typedef CFDataRef (*FBIOCFSerialize)(CFTypeRef object, CFOptionFlags options);
|
|
21
|
+
typedef CFTypeRef (*FBIOHIDEventCreateVendorDefinedEvent)(CFAllocatorRef allocator,
|
|
22
|
+
uint64_t timestamp,
|
|
23
|
+
uint32_t usagePage,
|
|
24
|
+
uint32_t usage,
|
|
25
|
+
uint32_t version,
|
|
26
|
+
uint8_t *data,
|
|
27
|
+
CFIndex length,
|
|
28
|
+
uint32_t options);
|
|
29
|
+
typedef CFTypeRef (*FBIOHIDEventSystemClientCreate)(CFAllocatorRef allocator);
|
|
30
|
+
typedef void (*FBIOHIDEventSystemClientDispatchEvent)(CFTypeRef client, CFTypeRef event);
|
|
31
|
+
|
|
32
|
+
@protocol FBAngle <NSObject>
|
|
33
|
+
- (BOOL)isAngleValid;
|
|
34
|
+
- (float)angleDegrees;
|
|
35
|
+
@end
|
|
36
|
+
|
|
37
|
+
@protocol FBAngleManager <NSObject>
|
|
38
|
+
+ (instancetype)new;
|
|
39
|
+
+ (BOOL)isAvailable;
|
|
40
|
+
+ (BOOL)instancesRespondToSelector:(SEL)selector;
|
|
41
|
+
- (void)startAngleUpdatesToQueue:(NSOperationQueue *)queue handler:(void (^)(id<FBAngle>))handler;
|
|
42
|
+
- (void)stopAngleUpdates;
|
|
43
|
+
@end
|
|
44
|
+
|
|
45
|
+
static Class<FBAngleManager> FBAngleManagerClass(void)
|
|
46
|
+
{
|
|
47
|
+
static Class<FBAngleManager> angleManagerClass;
|
|
48
|
+
static dispatch_once_t onceToken;
|
|
49
|
+
dispatch_once(&onceToken, ^{
|
|
50
|
+
// This path also loads on physical devices (verified on an iPad mini).
|
|
51
|
+
// Framework/class presence does not imply that a hinge sensor is available.
|
|
52
|
+
if (NULL != dlopen("/System/Library/Frameworks/CoreMotion.framework/CoreMotion", RTLD_LAZY)) {
|
|
53
|
+
angleManagerClass = NSClassFromString(@"CMAngleManager");
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
return angleManagerClass;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
static BOOL FBHasAvailableHinge(void)
|
|
60
|
+
{
|
|
61
|
+
Class<FBAngleManager> managerClass = FBAngleManagerClass();
|
|
62
|
+
return [managerClass respondsToSelector:@selector(isAvailable)] && [managerClass isAvailable];
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
typedef struct {
|
|
66
|
+
FBIOCFSerialize serialize;
|
|
67
|
+
FBIOHIDEventCreateVendorDefinedEvent createEvent;
|
|
68
|
+
FBIOHIDEventSystemClientCreate createClient;
|
|
69
|
+
FBIOHIDEventSystemClientDispatchEvent dispatchEvent;
|
|
70
|
+
} FBHingeInjectionAPI;
|
|
71
|
+
|
|
72
|
+
// Loads and caches the injection APIs; NULL means at least one is unavailable.
|
|
73
|
+
// Resolving these functions does not dispatch an event or confirm its acceptance.
|
|
74
|
+
static const FBHingeInjectionAPI *FBHingeInjectionFunctions(void)
|
|
75
|
+
{
|
|
76
|
+
static FBHingeInjectionAPI api;
|
|
77
|
+
static dispatch_once_t onceToken;
|
|
78
|
+
dispatch_once(&onceToken, ^{
|
|
79
|
+
void *handle = dlopen("/System/Library/Frameworks/IOKit.framework/IOKit", RTLD_LAZY);
|
|
80
|
+
if (NULL != handle) {
|
|
81
|
+
api.serialize = (FBIOCFSerialize)dlsym(handle, "IOCFSerialize");
|
|
82
|
+
api.createEvent = (FBIOHIDEventCreateVendorDefinedEvent)dlsym(handle, "IOHIDEventCreateVendorDefinedEvent");
|
|
83
|
+
api.createClient = (FBIOHIDEventSystemClientCreate)dlsym(handle, "IOHIDEventSystemClientCreate");
|
|
84
|
+
api.dispatchEvent = (FBIOHIDEventSystemClientDispatchEvent)dlsym(handle, "IOHIDEventSystemClientDispatchEvent");
|
|
85
|
+
}
|
|
86
|
+
});
|
|
87
|
+
return NULL != api.serialize && NULL != api.createEvent
|
|
88
|
+
&& NULL != api.createClient && NULL != api.dispatchEvent ? &api : NULL;
|
|
89
|
+
}
|
|
90
|
+
#endif
|
|
91
|
+
|
|
92
|
+
@implementation XCUIDevice (FBHinge)
|
|
93
|
+
|
|
94
|
+
- (BOOL)fb_supportsHingeAngleReading
|
|
95
|
+
{
|
|
96
|
+
#if !TARGET_OS_TV && !TARGET_OS_WATCH
|
|
97
|
+
Class<FBAngleManager> managerClass = FBAngleManagerClass();
|
|
98
|
+
return FBHasAvailableHinge()
|
|
99
|
+
&& [managerClass instancesRespondToSelector:@selector(startAngleUpdatesToQueue:handler:)]
|
|
100
|
+
&& [managerClass instancesRespondToSelector:@selector(stopAngleUpdates)];
|
|
101
|
+
#else
|
|
102
|
+
return NO;
|
|
103
|
+
#endif
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
- (BOOL)fb_canAttemptSimulatedHingeAngleInjection
|
|
107
|
+
{
|
|
108
|
+
#if !TARGET_OS_TV && !TARGET_OS_WATCH
|
|
109
|
+
// Sensor presence and local APIs permit an attempt, not proof that the
|
|
110
|
+
// device's receiver accepts the vendor event. Physical devices are unverified.
|
|
111
|
+
return FBHasAvailableHinge() && NULL != FBHingeInjectionFunctions();
|
|
112
|
+
#else
|
|
113
|
+
return NO;
|
|
114
|
+
#endif
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
- (nullable NSNumber *)fb_getSimulatedHingeAngle:(NSError **)error
|
|
118
|
+
{
|
|
119
|
+
if (!self.fb_supportsHingeAngleReading) {
|
|
120
|
+
[[FBErrorBuilder.builder withDescription:@"Hinge angle reading is unavailable on this device"] buildError:error];
|
|
121
|
+
return nil;
|
|
122
|
+
}
|
|
123
|
+
#if !TARGET_OS_TV && !TARGET_OS_WATCH
|
|
124
|
+
id<FBAngleManager> manager = [FBAngleManagerClass() new];
|
|
125
|
+
NSOperationQueue *queue = [NSOperationQueue new];
|
|
126
|
+
queue.maxConcurrentOperationCount = 1;
|
|
127
|
+
NSCondition *condition = [NSCondition new];
|
|
128
|
+
__block NSNumber *reading = nil;
|
|
129
|
+
NSNumber *result;
|
|
130
|
+
@try {
|
|
131
|
+
[manager startAngleUpdatesToQueue:queue handler:^(id<FBAngle> angle) {
|
|
132
|
+
if (![angle respondsToSelector:@selector(isAngleValid)]
|
|
133
|
+
|| ![angle respondsToSelector:@selector(angleDegrees)] || !angle.isAngleValid) {
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
float degrees = angle.angleDegrees;
|
|
137
|
+
if (!isfinite(degrees)) {
|
|
138
|
+
return;
|
|
139
|
+
}
|
|
140
|
+
[condition lock];
|
|
141
|
+
if (nil == reading) {
|
|
142
|
+
reading = @(degrees);
|
|
143
|
+
[condition signal];
|
|
144
|
+
}
|
|
145
|
+
[condition unlock];
|
|
146
|
+
}];
|
|
147
|
+
NSDate *deadline = [NSDate dateWithTimeIntervalSinceNow:FBHingeAngleReadingTimeout];
|
|
148
|
+
[condition lock];
|
|
149
|
+
while (nil == reading) {
|
|
150
|
+
if (![condition waitUntilDate:deadline]) {
|
|
151
|
+
break;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
result = reading;
|
|
155
|
+
[condition unlock];
|
|
156
|
+
} @finally {
|
|
157
|
+
[manager stopAngleUpdates];
|
|
158
|
+
}
|
|
159
|
+
if (nil == result) {
|
|
160
|
+
[[FBErrorBuilder.builder withDescriptionFormat:@"Timed out after %g seconds waiting for a valid hinge angle",
|
|
161
|
+
FBHingeAngleReadingTimeout] buildError:error];
|
|
162
|
+
}
|
|
163
|
+
return result;
|
|
164
|
+
#else
|
|
165
|
+
return nil;
|
|
166
|
+
#endif
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
- (BOOL)fb_setSimulatedHingeAngle:(double)angle error:(NSError **)error
|
|
170
|
+
{
|
|
171
|
+
if (!isfinite(angle) || angle < 0 || angle > 180) {
|
|
172
|
+
return [[FBErrorBuilder.builder withDescription:@"Hinge angle must be a finite number between 0 and 180 degrees"] buildError:error];
|
|
173
|
+
}
|
|
174
|
+
if (!self.fb_canAttemptSimulatedHingeAngleInjection) {
|
|
175
|
+
return [[FBErrorBuilder.builder withDescription:@"Hinge angle injection requires an available hinge and the IOKit HID APIs"] buildError:error];
|
|
176
|
+
}
|
|
177
|
+
#if !TARGET_OS_TV && !TARGET_OS_WATCH
|
|
178
|
+
// WDA's fb_performIOHIDEventWithPage:usage:duration:error: uses XCDeviceEvent
|
|
179
|
+
// with page, usage, and duration only. The XCDeviceEvent interfaces checked
|
|
180
|
+
// in Xcode 27.1 provide no way to attach the vendor payload containing the
|
|
181
|
+
// hinge angle, so this command creates and dispatches an IOKit event directly.
|
|
182
|
+
const FBHingeInjectionAPI *api = FBHingeInjectionFunctions();
|
|
183
|
+
// Matches Device Hub's hinge-slider-control payload (Xcode 27.1). It is an
|
|
184
|
+
// IOCF binary serialization, not an NSPropertyListSerialization binary plist.
|
|
185
|
+
NSDictionary *payload = @{
|
|
186
|
+
@"provider": @"com.apple.Virtualization.VirtualMachines",
|
|
187
|
+
@"source": @"hinge-slider-control",
|
|
188
|
+
@"type": @"range",
|
|
189
|
+
@"value": @(angle),
|
|
190
|
+
};
|
|
191
|
+
CFDataRef data = api->serialize((__bridge CFTypeRef)payload, 1);
|
|
192
|
+
if (NULL == data) {
|
|
193
|
+
return [[FBErrorBuilder.builder withDescription:@"Cannot serialize the simulated hinge event"] buildError:error];
|
|
194
|
+
}
|
|
195
|
+
CFTypeRef event = api->createEvent(kCFAllocatorDefault, mach_absolute_time(), 0xff61, 0x5b, 0,
|
|
196
|
+
(uint8_t *)CFDataGetBytePtr(data), CFDataGetLength(data), 0);
|
|
197
|
+
CFRelease(data);
|
|
198
|
+
CFTypeRef client = api->createClient(kCFAllocatorDefault);
|
|
199
|
+
BOOL canDispatch = NULL != event && NULL != client;
|
|
200
|
+
if (canDispatch) {
|
|
201
|
+
api->dispatchEvent(client, event);
|
|
202
|
+
}
|
|
203
|
+
if (NULL != event) {
|
|
204
|
+
CFRelease(event);
|
|
205
|
+
}
|
|
206
|
+
if (NULL != client) {
|
|
207
|
+
CFRelease(client);
|
|
208
|
+
}
|
|
209
|
+
return canDispatch || [[FBErrorBuilder.builder withDescription:@"Cannot create the simulated hinge HID event or client"] buildError:error];
|
|
210
|
+
#else
|
|
211
|
+
return NO;
|
|
212
|
+
#endif
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
@end
|
|
@@ -29,10 +29,12 @@
|
|
|
29
29
|
#import "XCUIApplication.h"
|
|
30
30
|
#import "XCUIApplication+FBHelpers.h"
|
|
31
31
|
#import "XCUIDevice+FBHelpers.h"
|
|
32
|
+
#import "XCUIDevice+FBHinge.h"
|
|
32
33
|
#import "XCUIDevice+FBVoiceOver.h"
|
|
33
34
|
#import "XCUIElement.h"
|
|
34
35
|
#import "XCUIElement+FBIsVisible.h"
|
|
35
36
|
#import "XCUIElementQuery.h"
|
|
37
|
+
#import "XCUIScreen.h"
|
|
36
38
|
#import "FBUnattachedAppLauncher.h"
|
|
37
39
|
|
|
38
40
|
@implementation FBCustomCommands
|
|
@@ -74,6 +76,10 @@
|
|
|
74
76
|
[[FBRoute POST:@"/wda/expectNotification"] respondWithTarget:self action:@selector(handleExpectNotification:)],
|
|
75
77
|
[[FBRoute POST:@"/wda/siri/activate"] respondWithTarget:self action:@selector(handleActivateSiri:)],
|
|
76
78
|
[[FBRoute POST:@"/wda/apps/launchUnattached"].withoutSession respondWithTarget:self action:@selector(handleLaunchUnattachedApp:)],
|
|
79
|
+
[[FBRoute GET:@"/wda/device/hingeAngle"] respondWithTarget:self action:@selector(handleGetSimulatedHingeAngle:)],
|
|
80
|
+
[[FBRoute GET:@"/wda/device/hingeAngle"].withoutSession respondWithTarget:self action:@selector(handleGetSimulatedHingeAngle:)],
|
|
81
|
+
[[FBRoute POST:@"/wda/device/hingeAngle"] respondWithTarget:self action:@selector(handleSetSimulatedHingeAngle:)],
|
|
82
|
+
[[FBRoute POST:@"/wda/device/hingeAngle"].withoutSession respondWithTarget:self action:@selector(handleSetSimulatedHingeAngle:)],
|
|
77
83
|
[[FBRoute GET:@"/wda/device/info"] respondWithTarget:self action:@selector(handleGetDeviceInfo:)],
|
|
78
84
|
[[FBRoute POST:@"/wda/resetAppAuth"] respondWithTarget:self action:@selector(handleResetAppAuth:)],
|
|
79
85
|
[[FBRoute GET:@"/wda/device/info"].withoutSession respondWithTarget:self action:@selector(handleGetDeviceInfo:)],
|
|
@@ -157,17 +163,41 @@
|
|
|
157
163
|
|
|
158
164
|
+ (id<FBResponsePayload>)handleGetScreen:(FBRouteRequest *)request
|
|
159
165
|
{
|
|
166
|
+
NSError *error = nil;
|
|
167
|
+
XCUIScreen *screen = [FBScreen currentScreenWithError:&error];
|
|
168
|
+
if (nil == screen) {
|
|
169
|
+
return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:error.localizedDescription
|
|
170
|
+
traceback:nil]);
|
|
171
|
+
}
|
|
160
172
|
XCUIApplication *app = XCUIApplication.fb_systemApplication;
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
CGSize screenSize = app.frame.size;
|
|
167
|
-
#else
|
|
168
|
-
CGSize screenSize = FBAdjustDimensionsForApplication(app.wdFrame.size, app.interfaceOrientation);
|
|
173
|
+
CGSize screenSize = CGSizeMake(CGRectGetWidth(screen.bounds) / screen.scale,
|
|
174
|
+
CGRectGetHeight(screen.bounds) / screen.scale);
|
|
175
|
+
#if !TARGET_OS_TV && !TARGET_OS_WATCH
|
|
176
|
+
XCUIApplication *activeApp = request.session ? request.session.activeApplication : XCUIApplication.fb_activeApplication;
|
|
177
|
+
screenSize = FBAdjustDimensionsForApplication(screenSize, activeApp.interfaceOrientation);
|
|
169
178
|
#endif
|
|
170
179
|
|
|
180
|
+
// SpringBoard can expose hidden status bars belonging to other displays, and
|
|
181
|
+
// Duo also exposes full-screen containers for its side-mounted status UI.
|
|
182
|
+
// Only a visible horizontal bar at the top of this display can be subtracted
|
|
183
|
+
// from a rectangular viewport.
|
|
184
|
+
CGSize statusBarSize = CGSizeZero;
|
|
185
|
+
for (XCUIElement *statusBar in app.statusBars.allElementsBoundByIndex) {
|
|
186
|
+
// Resolve the element before reading its screen: displayID can be zero on
|
|
187
|
+
// an unresolved query result even when the bar belongs to the main screen.
|
|
188
|
+
CGRect frame = statusBar.frame;
|
|
189
|
+
if (statusBar.screen.displayID != screen.displayID || !statusBar.fb_isVisible) {
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
if (fabs(CGRectGetMinY(frame)) <= 1 && fabs(CGRectGetMinX(frame)) <= 1
|
|
193
|
+
&& fabs(CGRectGetWidth(frame) - screenSize.width) <= 1
|
|
194
|
+
&& CGRectGetHeight(frame) > 0 && CGRectGetHeight(frame) < screenSize.height
|
|
195
|
+
&& CGRectGetHeight(frame) < CGRectGetWidth(frame)) {
|
|
196
|
+
statusBarSize = frame.size;
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
|
|
171
201
|
return FBResponseWithObject(
|
|
172
202
|
@{
|
|
173
203
|
@"screenSize":@{@"width": @(screenSize.width),
|
|
@@ -176,8 +206,8 @@
|
|
|
176
206
|
@"statusBarSize": @{@"width": @(statusBarSize.width),
|
|
177
207
|
@"height": @(statusBarSize.height),
|
|
178
208
|
},
|
|
179
|
-
@"displayId": @(
|
|
180
|
-
@"scale": @(
|
|
209
|
+
@"displayId": @(screen.displayID),
|
|
210
|
+
@"scale": @(screen.scale),
|
|
181
211
|
});
|
|
182
212
|
}
|
|
183
213
|
|
|
@@ -777,4 +807,35 @@
|
|
|
777
807
|
return FBResponseWithObject(result);
|
|
778
808
|
}
|
|
779
809
|
|
|
810
|
+
+ (id<FBResponsePayload>)handleGetSimulatedHingeAngle:(FBRouteRequest *)request
|
|
811
|
+
{
|
|
812
|
+
if (!XCUIDevice.sharedDevice.fb_supportsHingeAngleReading) {
|
|
813
|
+
return FBResponseWithStatus([FBCommandStatus unsupportedOperationErrorWithMessage:
|
|
814
|
+
@"Hinge angle reading is unavailable on this device" traceback:nil]);
|
|
815
|
+
}
|
|
816
|
+
NSError *error;
|
|
817
|
+
NSNumber *angle = [XCUIDevice.sharedDevice fb_getSimulatedHingeAngle:&error];
|
|
818
|
+
return nil == angle ? FBResponseWithUnknownError(error) : FBResponseWithObject(angle);
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
+ (id<FBResponsePayload>)handleSetSimulatedHingeAngle:(FBRouteRequest *)request
|
|
822
|
+
{
|
|
823
|
+
id angle = request.arguments[@"angle"];
|
|
824
|
+
if (![angle isKindOfClass:NSNumber.class]
|
|
825
|
+
|| CFGetTypeID((__bridge CFTypeRef)angle) == CFBooleanGetTypeID()
|
|
826
|
+
|| !isfinite([angle doubleValue]) || [angle doubleValue] < 0 || [angle doubleValue] > 180) {
|
|
827
|
+
return FBResponseWithStatus([FBCommandStatus invalidArgumentErrorWithMessage:
|
|
828
|
+
@"'angle' must be a finite number between 0 and 180 degrees" traceback:nil]);
|
|
829
|
+
}
|
|
830
|
+
if (!XCUIDevice.sharedDevice.fb_canAttemptSimulatedHingeAngleInjection) {
|
|
831
|
+
return FBResponseWithStatus([FBCommandStatus unsupportedOperationErrorWithMessage:
|
|
832
|
+
@"Setting a simulated hinge angle requires a compatible foldable device" traceback:nil]);
|
|
833
|
+
}
|
|
834
|
+
NSError *error;
|
|
835
|
+
if (![XCUIDevice.sharedDevice fb_setSimulatedHingeAngle:[angle doubleValue] error:&error]) {
|
|
836
|
+
return FBResponseWithUnknownError(error);
|
|
837
|
+
}
|
|
838
|
+
return FBResponseWithOK();
|
|
839
|
+
}
|
|
840
|
+
|
|
780
841
|
@end
|
|
@@ -15,11 +15,11 @@
|
|
|
15
15
|
<key>CFBundlePackageType</key>
|
|
16
16
|
<string>FMWK</string>
|
|
17
17
|
<key>CFBundleShortVersionString</key>
|
|
18
|
-
<string>16.
|
|
18
|
+
<string>16.14.1</string>
|
|
19
19
|
<key>CFBundleSignature</key>
|
|
20
20
|
<string>????</string>
|
|
21
21
|
<key>CFBundleVersion</key>
|
|
22
|
-
<string>16.
|
|
22
|
+
<string>16.14.1</string>
|
|
23
23
|
<key>NSPrincipalClass</key>
|
|
24
24
|
<string/>
|
|
25
25
|
</dict>
|
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
#import "FBScreenRecordingRequest.h"
|
|
10
10
|
|
|
11
11
|
#import "FBErrorBuilder.h"
|
|
12
|
+
#import "FBScreen.h"
|
|
12
13
|
#import "XCUIScreen.h"
|
|
13
14
|
|
|
14
15
|
@implementation FBScreenRecordingRequest
|
|
@@ -56,6 +57,10 @@
|
|
|
56
57
|
|
|
57
58
|
- (id)toNativeRequestWithError:(NSError **)error
|
|
58
59
|
{
|
|
60
|
+
XCUIScreen *screen = [FBScreen currentScreenWithError:error];
|
|
61
|
+
if (nil == screen) {
|
|
62
|
+
return nil;
|
|
63
|
+
}
|
|
59
64
|
Class screenRecordingRequestClass = NSClassFromString(@"XCTScreenRecordingRequest");
|
|
60
65
|
if (nil == screenRecordingRequestClass) {
|
|
61
66
|
[[[FBErrorBuilder builder]
|
|
@@ -80,8 +85,8 @@
|
|
|
80
85
|
NSMethodSignature *screenRecordingRequestContructorSignature = [screenRecordingRequestAllocated methodSignatureForSelector:screenRecordingRequestConstructorSelector];
|
|
81
86
|
NSInvocation *screenRecordingRequestInitInvocation = [NSInvocation invocationWithMethodSignature:screenRecordingRequestContructorSignature];
|
|
82
87
|
[screenRecordingRequestInitInvocation setSelector:screenRecordingRequestConstructorSelector];
|
|
83
|
-
long long
|
|
84
|
-
[screenRecordingRequestInitInvocation setArgument:&
|
|
88
|
+
long long screenId = screen.displayID;
|
|
89
|
+
[screenRecordingRequestInitInvocation setArgument:&screenId atIndex:2];
|
|
85
90
|
CGRect fullScreenRect = CGRectNull;
|
|
86
91
|
[screenRecordingRequestInitInvocation setArgument:&fullScreenRect atIndex:3];
|
|
87
92
|
[screenRecordingRequestInitInvocation setArgument:&videoEncoding atIndex:4];
|
|
@@ -24,14 +24,14 @@ NS_ASSUME_NONNULL_BEGIN
|
|
|
24
24
|
* Calculates the accessbility element which is located at the given screen coordinates
|
|
25
25
|
*
|
|
26
26
|
* @param point The screen coordinates
|
|
27
|
-
* @returns The retrieved accessbility element or nil if it cannot be detected
|
|
27
|
+
* @returns The retrieved accessbility element or nil if it cannot be detected or a secondary display is selected
|
|
28
28
|
*/
|
|
29
29
|
+ (nullable id<FBXCAccessibilityElement>)axElementWithPoint:(CGPoint)point;
|
|
30
30
|
|
|
31
31
|
/**
|
|
32
32
|
* Retrieves the accessbility element for the current screen point
|
|
33
33
|
*
|
|
34
|
-
* @returns The retrieved accessbility element or nil if it cannot be detected
|
|
34
|
+
* @returns The retrieved accessbility element or nil if it cannot be detected or a secondary display is selected
|
|
35
35
|
*/
|
|
36
36
|
- (nullable id<FBXCAccessibilityElement>)axElement;
|
|
37
37
|
|
|
@@ -13,6 +13,10 @@
|
|
|
13
13
|
#endif
|
|
14
14
|
|
|
15
15
|
#import "FBErrorBuilder.h"
|
|
16
|
+
#import "FBScreen.h"
|
|
17
|
+
#import "FBConfiguration.h"
|
|
18
|
+
#import "FBExceptions.h"
|
|
19
|
+
#import "XCUIScreen.h"
|
|
16
20
|
#import "FBLogger.h"
|
|
17
21
|
#import "FBXCTestDaemonsProxy.h"
|
|
18
22
|
#import "XCTMessagingChannel_RunnerToDaemon-Protocol.h"
|
|
@@ -45,6 +49,22 @@
|
|
|
45
49
|
|
|
46
50
|
+ (id<FBXCAccessibilityElement>)axElementWithPoint:(CGPoint)point
|
|
47
51
|
{
|
|
52
|
+
if (nil != FBConfiguration.sharedInstance.currentDisplayId) {
|
|
53
|
+
NSError *error;
|
|
54
|
+
XCUIScreen *screen = [FBScreen currentScreenWithError:&error];
|
|
55
|
+
if (nil == screen) {
|
|
56
|
+
@throw [NSException exceptionWithName:FBInvalidArgumentException
|
|
57
|
+
reason:error.localizedDescription
|
|
58
|
+
userInfo:nil];
|
|
59
|
+
}
|
|
60
|
+
// XCTest's point lookup has no display parameter and always hits the main
|
|
61
|
+
// display. On Duo this can select the outer SpringBoard while the app is
|
|
62
|
+
// foreground on the inner display. Let callers use their active-app fallback
|
|
63
|
+
// instead of treating an element from a different display as authoritative.
|
|
64
|
+
if (screen.displayID != XCUIScreen.mainScreen.displayID) {
|
|
65
|
+
return nil;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
48
68
|
__block id<FBXCAccessibilityElement> onScreenElement = nil;
|
|
49
69
|
id<XCTMessagingChannel_RunnerToDaemon> proxy = [FBXCTestDaemonsProxy testRunnerProxy];
|
|
50
70
|
dispatch_semaphore_t sem = dispatch_semaphore_create(0);
|
|
@@ -369,7 +369,7 @@ typedef NS_ENUM(NSInteger, FBConfigurationKeyboardPreference) {
|
|
|
369
369
|
@property (atomic, assign) BOOL enforceCustomSnapshots;
|
|
370
370
|
|
|
371
371
|
/**
|
|
372
|
-
* The identifier of the display targeted by screenshots.
|
|
372
|
+
* The identifier of the display targeted by screenshots, MJPEG, and new screen recordings.
|
|
373
373
|
* nil means the main display. Reset to nil for each new session.
|
|
374
374
|
*/
|
|
375
375
|
@property (atomic, copy, nullable) NSNumber *currentDisplayId;
|