Skip to content

Commit 022d754

Browse files
committed
feat(accessibility): implement core helpers
1 parent 3e4b862 commit 022d754

4 files changed

Lines changed: 179 additions & 54 deletions

File tree

‎Sources/OpenSwiftUICore/Accessibility/AccessibilityCore.swift‎

Lines changed: 87 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,10 +3,17 @@
33
// OpenSwiftUICore
44
//
55
// Audited for 6.5.4
6-
// Status: TODO
6+
// Status: Complete
7+
8+
public import Foundation
9+
import OpenSwiftUI_SPI
10+
11+
// MARK: - AccessibilityCore
712

813
package enum AccessibilityCore {}
914

15+
// MARK: - _ViewInputs/_GraphInputs + needsAccessibility
16+
1017
extension _GraphInputs {
1118
package var needsAccessibility: Bool {
1219
get { options.contains(.needsAccessibility) }
@@ -21,25 +28,99 @@ extension _ViewInputs {
2128
}
2229
}
2330

31+
// MARK: - WithinAccessibilityRotor
32+
2433
package struct WithinAccessibilityRotor: ViewInputBoolFlag {
25-
package init() {}
34+
package init() {
35+
_openSwiftUIEmptyStub()
36+
}
2637
}
2738

2839
extension _ViewInputs {
2940
@inline(__always)
3041
package var withinAccessibilityRotor: Bool {
31-
needsAccessibility && self[WithinAccessibilityRotor.self]
42+
get { self[WithinAccessibilityRotor.self] }
43+
set { self[WithinAccessibilityRotor.self] = newValue }
44+
}
45+
}
46+
47+
// MARK: - PlatformAccessibilityElementProtocol
48+
49+
@_spi(ForOpenSwiftUIOnly)
50+
@available(OpenSwiftUI_v6_0, *)
51+
#if canImport(ObjectiveC)
52+
@objc
53+
#endif
54+
public protocol PlatformAccessibilityElementProtocol: NSObjectProtocol {
55+
#if os(macOS)
56+
@objc dynamic var knownRepresentedElement: PlatformAccessibilityElement { get }
57+
@objc dynamic var rotorOwnerElement: PlatformAccessibilityElement { get }
58+
#endif
59+
}
60+
61+
// MARK: - PlatformAccessibilityElement
62+
63+
@_spi(ForOpenSwiftUIOnly)
64+
@available(OpenSwiftUI_v6_0, *)
65+
public typealias PlatformAccessibilityElement = NSObject & PlatformAccessibilityElementProtocol
66+
67+
// MARK: - NSObject + PlatformAccessibilityElementProtocol
68+
69+
@_spi(ForOpenSwiftUIOnly)
70+
@available(OpenSwiftUI_v6_0, *)
71+
extension NSObject: PlatformAccessibilityElementProtocol {
72+
#if canImport(ObjectiveC)
73+
@objc
74+
#endif
75+
dynamic open var knownRepresentedElement: PlatformAccessibilityElement {
76+
self
77+
}
78+
79+
#if canImport(ObjectiveC)
80+
@objc
81+
#endif
82+
dynamic open var rotorOwnerElement: PlatformAccessibilityElement {
83+
self
84+
}
85+
}
86+
87+
// MARK: - AccessibilityLayoutRole
88+
89+
package enum AccessibilityLayoutRole: Hashable {
90+
case stack
91+
case grid
92+
}
93+
94+
// MARK: - Locale.bcp47LanguageCode
95+
96+
extension Locale {
97+
package var bcp47LanguageCode: String? {
98+
guard let languageCode = language.languageCode?.identifier,
99+
!languageCode.isEmpty else {
100+
return nil
101+
}
102+
return language.maximalIdentifier
32103
}
33104
}
34105

35-
// TODO
106+
// MARK: - AccessibilityCore + description
36107

37108
extension AccessibilityCore {
38109
package static func description(
39110
for symbolName: String,
40111
in environment: EnvironmentValues
41112
) -> String? {
42-
_openSwiftUIUnimplementedWarning()
43-
return nil
113+
#if canImport(Darwin)
114+
let description = soft_AXSSAccessibilityDescriptionForSymbolName(
115+
symbolName,
116+
environment.locale.identifier
117+
)
118+
guard !description.isEmpty else {
119+
return nil
120+
}
121+
return description.capitalized(with: environment.locale)
122+
#else
123+
_openSwiftUIPlatformUnimplementedFailure()
124+
#endif
44125
}
45126
}

‎Sources/OpenSwiftUICore/Accessibility/PlatformAccessibilityElement.swift‎

Lines changed: 0 additions & 48 deletions
This file was deleted.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//
2+
// AccessibilitySharedSupport.h
3+
// OpenSwiftUI_SPI
4+
//
5+
// Audited for 6.5.4
6+
// Status: Complete
7+
8+
#ifndef AccessibilitySharedSupport_h
9+
#define AccessibilitySharedSupport_h
10+
11+
#include "OpenSwiftUIBase.h"
12+
13+
#if OPENSWIFTUI_TARGET_OS_DARWIN
14+
15+
#import <Foundation/Foundation.h>
16+
17+
OPENSWIFTUI_EXTERN_C_BEGIN
18+
OPENSWIFTUI_ASSUME_NONNULL_BEGIN
19+
20+
OPENSWIFTUI_EXPORT
21+
NSString *soft_AXSSAccessibilityDescriptionForSymbolName(NSString *symbolName, NSString *localeIdentifier);
22+
23+
OPENSWIFTUI_ASSUME_NONNULL_END
24+
OPENSWIFTUI_EXTERN_C_END
25+
26+
#endif /* OPENSWIFTUI_TARGET_OS_DARWIN */
27+
28+
#endif /* AccessibilitySharedSupport_h */
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
//
2+
// AccessibilitySharedSupport.m
3+
// OpenSwiftUI_SPI
4+
//
5+
// Audited for 6.5.4
6+
// Status: Complete
7+
8+
#include "AccessibilitySharedSupport.h"
9+
10+
#if OPENSWIFTUI_TARGET_OS_DARWIN
11+
12+
#include <dlfcn.h>
13+
#include <stdlib.h>
14+
#include <string.h>
15+
16+
void abort_report_np(const char *format, ...) __attribute__((noreturn, format(printf, 1, 2)));
17+
18+
static void *AccessibilitySharedSupportLibraryCore(char **error) {
19+
static void *frameworkLibrary;
20+
if (frameworkLibrary == NULL) {
21+
frameworkLibrary = dlopen(
22+
"/System/Library/PrivateFrameworks/AccessibilitySharedSupport.framework/AccessibilitySharedSupport",
23+
RTLD_LAZY | RTLD_LOCAL
24+
);
25+
if (frameworkLibrary == NULL) {
26+
*error = strdup(dlerror());
27+
}
28+
}
29+
return frameworkLibrary;
30+
}
31+
32+
static void *AccessibilitySharedSupportLibrary(void) {
33+
char *error = NULL;
34+
void *frameworkLibrary = AccessibilitySharedSupportLibraryCore(&error);
35+
if (frameworkLibrary == NULL) {
36+
abort_report_np("%s", error);
37+
}
38+
if (error != NULL) {
39+
free(error);
40+
}
41+
return frameworkLibrary;
42+
}
43+
44+
static void *getAXSSAccessibilityDescriptionForSymbolNameSymbolLoc(void) {
45+
static void *ptr;
46+
if (ptr == NULL) {
47+
ptr = dlsym(
48+
AccessibilitySharedSupportLibrary(),
49+
"AXSSAccessibilityDescriptionForSymbolName"
50+
);
51+
}
52+
return ptr;
53+
}
54+
55+
NSString *soft_AXSSAccessibilityDescriptionForSymbolName(NSString *symbolName, NSString *localeIdentifier) {
56+
NSString *(*function)(NSString *, NSString *) =
57+
(NSString *(*)(NSString *, NSString *))getAXSSAccessibilityDescriptionForSymbolNameSymbolLoc();
58+
if (function == NULL) {
59+
abort_report_np("%s", dlerror());
60+
}
61+
return function(symbolName, localeIdentifier);
62+
}
63+
64+
#endif /* OPENSWIFTUI_TARGET_OS_DARWIN */

0 commit comments

Comments
 (0)