Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Unified Diff: ui/accessibility/platform/text_marker_helper_mac.mm

Issue 2940923003: a11y: Move CreateTextMarker[Range] to TextMarkerHelperMac.
Patch Set: self review Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: ui/accessibility/platform/text_marker_helper_mac.mm
diff --git a/ui/accessibility/platform/text_marker_helper_mac.mm b/ui/accessibility/platform/text_marker_helper_mac.mm
new file mode 100644
index 0000000000000000000000000000000000000000..96f10ef1b85d4cc5d73b8082c82f4b44f8bf3c48
--- /dev/null
+++ b/ui/accessibility/platform/text_marker_helper_mac.mm
@@ -0,0 +1,255 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#import "ui/accessibility/platform/text_marker_helper_mac.h"
+
+#import <Cocoa/Cocoa.h>
+
+#import "base/mac/foundation_util.h"
+#include "base/mac/scoped_cftyperef.h"
+#include "ui/accessibility/ax_position.h"
+#include "ui/accessibility/ax_range.h"
+
+extern "C" {
+
+// The following are private accessibility APIs required for cursor navigation
+// and text selection. VoiceOver started relying on them in Mac OS X 10.11.
+AXTextMarkerRef AXTextMarkerCreate(CFAllocatorRef allocator,
+ const UInt8* bytes,
+ CFIndex length);
+
+AXTextMarkerRangeRef AXTextMarkerRangeCreate(CFAllocatorRef allocator,
+ AXTextMarkerRef start_marker,
+ AXTextMarkerRef end_marker);
+
+} // extern "C"
+
+namespace {
+
+// to call |release| on it to transfer ownership of the position to the text
+// marker object.
+id CreateTextMarker(std::unique_ptr<ui::AXPositionBase> position) {
+ AXTextMarkerRef text_marker = AXTextMarkerCreate(
+ kCFAllocatorDefault, reinterpret_cast<const UInt8*>(position.release()),
+ sizeof(ui::AXPositionBase));
+ return static_cast<id>(
+ base::mac::CFTypeRefToNSObjectAutorelease(text_marker));
+}
+
+// |range| is destructed at the end of this method and ownership of its |anchor|
+// and |focus| are transfered to the marker range object.
+id CreateTextMarkerRange(const ui::AXAbstractRange range) {
+ AXTextMarkerRef start_marker = AXTextMarkerCreate(
+ kCFAllocatorDefault, reinterpret_cast<const UInt8*>(range.anchor()),
+ sizeof(ui::AXPositionBase));
+ AXTextMarkerRef end_marker = AXTextMarkerCreate(
+ kCFAllocatorDefault, reinterpret_cast<const UInt8*>(range.focus()),
+ sizeof(ui::AXPositionBase));
+ AXTextMarkerRangeRef marker_range =
+ AXTextMarkerRangeCreate(kCFAllocatorDefault, start_marker, end_marker);
+ return static_cast<id>(
+ base::mac::CFTypeRefToNSObjectAutorelease(marker_range));
+}
+
+} // namespace
+
+@interface TextMarkerHelperMac ()
+- (std::unique_ptr<ui::AXPositionBase>)extractFrom:(id)parameter;
+@end
+
+@implementation TextMarkerHelperMac {
+ std::unique_ptr<ui::PositionFactory> factory_;
+}
+
+- (instancetype)initWithFactory:(std::unique_ptr<ui::PositionFactory>)factory {
+ if ((self = [super init])) {
+ factory_ = std::move(factory);
+ }
+ return self;
+}
+
+- (id)startTextMarker {
+ std::unique_ptr<ui::AXPositionBase> root = factory_->GetRoot();
+ return root ? CreateTextMarker(root->CreatePositionAtStartOfAnchor()) : nil;
+}
+
+- (id)endTextMarker {
+ std::unique_ptr<ui::AXPositionBase> root = factory_->GetRoot();
+ return root ? CreateTextMarker(root->CreatePositionAtEndOfAnchor()) : nil;
+}
+
+- (id)selectedTextMarkerRange {
+ std::unique_ptr<ui::AXAbstractRange> selection = factory_->GetSelection();
+ return selection ? CreateTextMarkerRange(std::move(*selection)) : nil;
+}
+
+- (std::unique_ptr<ui::AXPositionBase>)extractFrom:(id)parameter {
+ AXTextMarkerRef marker = base::mac::CFCastStrict<AXTextMarkerRef>(parameter);
+ return factory_->ExtractFromMarker(marker);
+}
+
+- (id)AXTextMarkerRangeForUIElement:(id)parameter {
+ std::unique_ptr<ui::AXPositionBase> startPosition = factory_->GetRoot();
+ std::unique_ptr<ui::AXPositionBase> endPosition =
+ startPosition->CreatePositionAtEndOfAnchor();
+ ui::AXAbstractRange range =
+ ui::AXAbstractRange(std::move(startPosition), std::move(endPosition));
+ return CreateTextMarkerRange(std::move(range));
+}
+
+- (id)AXNextTextMarkerForTextMarker:(id)parameter {
+ std::unique_ptr<ui::AXPositionBase> position = [self extractFrom:parameter];
+ if (position->IsNullPosition())
+ return nil;
+ return CreateTextMarker(position->CreateNextCharacterPosition());
+}
+
+- (id)AXPreviousTextMarkerForTextMarker:(id)parameter {
+ std::unique_ptr<ui::AXPositionBase> position = [self extractFrom:parameter];
+ if (position->IsNullPosition())
+ return nil;
+ return CreateTextMarker(position->CreatePreviousCharacterPosition());
+}
+
+- (id)AXLeftWordTextMarkerRangeForTextMarker:(id)parameter {
+ std::unique_ptr<ui::AXPositionBase> endPosition =
+ [self extractFrom:parameter];
+ if (endPosition->IsNullPosition())
+ return nil;
+
+ std::unique_ptr<ui::AXPositionBase> startWordPosition =
+ endPosition->CreatePreviousWordStartPosition();
+ std::unique_ptr<ui::AXPositionBase> endWordPosition =
+ endPosition->CreatePreviousWordEndPosition();
+ std::unique_ptr<ui::AXPositionBase> startPosition =
+ *startWordPosition <= *endWordPosition ? std::move(endWordPosition)
+ : std::move(startWordPosition);
+ ui::AXAbstractRange range(std::move(startPosition), std::move(endPosition));
+ return CreateTextMarkerRange(std::move(range));
+}
+
+- (id)AXRightWordTextMarkerRangeForTextMarker:(id)parameter {
+ std::unique_ptr<ui::AXPositionBase> startPosition =
+ [self extractFrom:parameter];
+ if (startPosition->IsNullPosition())
+ return nil;
+
+ std::unique_ptr<ui::AXPositionBase> endWordPosition =
+ startPosition->CreateNextWordEndPosition();
+ std::unique_ptr<ui::AXPositionBase> startWordPosition =
+ startPosition->CreateNextWordStartPosition();
+ std::unique_ptr<ui::AXPositionBase> endPosition =
+ *startWordPosition <= *endWordPosition ? std::move(startWordPosition)
+ : std::move(endWordPosition);
+ ui::AXAbstractRange range(std::move(startPosition), std::move(endPosition));
+ return CreateTextMarkerRange(std::move(range));
+}
+
+- (id)AXNextWordEndTextMarkerForTextMarker:(id)parameter {
+ std::unique_ptr<ui::AXPositionBase> position = [self extractFrom:parameter];
+ if (position->IsNullPosition())
+ return nil;
+ return CreateTextMarker(position->CreateNextWordEndPosition());
+}
+
+- (id)AXPreviousWordStartTextMarkerForTextMarker:(id)parameter {
+ std::unique_ptr<ui::AXPositionBase> position = [self extractFrom:parameter];
+ if (position->IsNullPosition())
+ return nil;
+ return CreateTextMarker(position->CreatePreviousWordStartPosition());
+}
+
+- (id)AXTextMarkerRangeForLine:(id)parameter {
+ std::unique_ptr<ui::AXPositionBase> position = [self extractFrom:parameter];
+ if (position->IsNullPosition())
+ return nil;
+
+ std::unique_ptr<ui::AXPositionBase> startPosition =
+ position->CreatePreviousLineStartPosition();
+ std::unique_ptr<ui::AXPositionBase> endPosition =
+ position->CreateNextLineEndPosition();
+ ui::AXAbstractRange range(std::move(startPosition), std::move(endPosition));
+ return CreateTextMarkerRange(std::move(range));
+}
+
+- (id)AXLeftLineTextMarkerRangeForTextMarker:(id)parameter {
+ std::unique_ptr<ui::AXPositionBase> endPosition =
+ [self extractFrom:parameter];
+ if (endPosition->IsNullPosition())
+ return nil;
+
+ std::unique_ptr<ui::AXPositionBase> startLinePosition =
+ endPosition->CreatePreviousLineStartPosition();
+ std::unique_ptr<ui::AXPositionBase> endLinePosition =
+ endPosition->CreatePreviousLineEndPosition();
+ std::unique_ptr<ui::AXPositionBase> startPosition =
+ *startLinePosition <= *endLinePosition ? std::move(endLinePosition)
+ : std::move(startLinePosition);
+ ui::AXAbstractRange range(std::move(startPosition), std::move(endPosition));
+ return CreateTextMarkerRange(std::move(range));
+}
+
+- (id)AXRightLineTextMarkerRangeForTextMarker:(id)parameter {
+ std::unique_ptr<ui::AXPositionBase> startPosition =
+ [self extractFrom:parameter];
+ if (startPosition->IsNullPosition())
+ return nil;
+
+ std::unique_ptr<ui::AXPositionBase> startLinePosition =
+ startPosition->CreateNextLineStartPosition();
+ std::unique_ptr<ui::AXPositionBase> endLinePosition =
+ startPosition->CreateNextLineEndPosition();
+ std::unique_ptr<ui::AXPositionBase> endPosition =
+ *startLinePosition <= *endLinePosition ? std::move(startLinePosition)
+ : std::move(endLinePosition);
+ ui::AXAbstractRange range(std::move(startPosition), std::move(endPosition));
+ return CreateTextMarkerRange(std::move(range));
+}
+
+- (id)AXNextLineEndTextMarkerForTextMarker:(id)parameter {
+ std::unique_ptr<ui::AXPositionBase> position = [self extractFrom:parameter];
+ if (position->IsNullPosition())
+ return nil;
+ return CreateTextMarker(position->CreateNextLineEndPosition());
+}
+
+- (id)AXPreviousLineStartTextMarkerForTextMarker:(id)parameter {
+ std::unique_ptr<ui::AXPositionBase> position = [self extractFrom:parameter];
+ if (position->IsNullPosition())
+ return nil;
+ return CreateTextMarker(position->CreatePreviousLineStartPosition());
+}
+
+- (id)AXLineTextMarkerRangeForTextMarker:(id)parameter {
+ std::unique_ptr<ui::AXPositionBase> position = [self extractFrom:parameter];
+ if (position->IsNullPosition())
+ return nil;
+
+ ui::AXAbstractRange range(position->CreatePreviousLineStartPosition(),
+ position->CreateNextLineEndPosition());
+ return CreateTextMarkerRange(std::move(range));
+}
+
+- (id)AXTextMarkerRangeForUnorderedTextMarkers:(id)parameter {
+ if (![parameter isKindOfClass:[NSArray class]])
+ return nil;
+
+ NSArray* text_marker_array = parameter;
+ if ([text_marker_array count] != 2)
+ return nil;
+
+ std::unique_ptr<ui::AXPositionBase> startPosition =
+ [self extractFrom:[text_marker_array objectAtIndex:0]];
+ std::unique_ptr<ui::AXPositionBase> endPosition =
+ [self extractFrom:[text_marker_array objectAtIndex:1]];
+ if (*startPosition <= *endPosition) {
+ return CreateTextMarkerRange(
+ ui::AXAbstractRange(std::move(startPosition), std::move(endPosition)));
+ } else {
+ return CreateTextMarkerRange(
+ ui::AXAbstractRange(std::move(endPosition), std::move(startPosition)));
+ }
+}
+
+@end

Powered by Google App Engine
This is Rietveld 408576698