androidx.core.view.accessibility.AccessibilityEventCompat Java Examples

The following examples show how to use androidx.core.view.accessibility.AccessibilityEventCompat. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: Compositor.java    From talkback with Apache License 2.0 6 votes vote down vote up
/** Handles a standard AccessibilityEvent */
public void handleEvent(
    AccessibilityEvent event, @Nullable EventId eventId, EventInterpretation eventInterpreted) {

  final AccessibilityRecordCompat record = AccessibilityEventCompat.asRecord(event);
  @Event int eventType = eventInterpreted.getEvent();

  // TODO
  // Allocate source node & delegate which must be recycled.
  AccessibilityNodeInfoCompat sourceNode = record.getSource();
  ParseTree.VariableDelegate delegate =
      mVariablesFactory.createLocalVariableDelegate(event, sourceNode, eventInterpreted);

  // Compute speech and speech flags.
  HandleEventOptions options =
      new HandleEventOptions().object(event).interpretation(eventInterpreted).source(sourceNode);
  handleEvent(eventType, eventId, delegate, options);
  AccessibilityNodeInfoUtils.recycleNodes(sourceNode);
}
 
Example #2
Source File: ProcessorGestureVibrator.java    From talkback with Apache License 2.0 6 votes vote down vote up
@Override
public void onAccessibilityEvent(AccessibilityEvent event, EventId eventId) {
  switch (event.getEventType()) {
    case AccessibilityEventCompat.TYPE_GESTURE_DETECTION_START:
      {
        feedbackReturner.returnFeedback(
            eventId,
            Feedback.interrupt(GESTURE_VIBRATION, /* level= */ 1)
                .setDelayMs(FEEDBACK_DELAY)
                .vibration(R.array.gesture_detection_repeated_pattern)
                .sound(R.raw.gesture_begin));
      break;
      }
    case AccessibilityEventCompat.TYPE_GESTURE_DETECTION_END:
      {
        feedbackReturner.returnFeedback(
            eventId,
            Feedback.interrupt(GESTURE_VIBRATION, /* level= */ 1)
                .setInterruptSoundAndVibration(true));
      break;
      }
    default: // fall out
  }
}
 
Example #3
Source File: KeyboardAccessibilityNodeProvider.java    From AOSP-Kayboard-7.1.2 with Apache License 2.0 6 votes vote down vote up
/**
 * Performs the specified accessibility action for the given key.
 *
 * @param key The on which to perform the action.
 * @param action The action to perform.
 * @return The result of performing the action, or false if the action is not supported.
 */
boolean performActionForKey(final Key key, final int action) {
    switch (action) {
    case AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS:
        mAccessibilityFocusedView = getVirtualViewIdOf(key);
        sendAccessibilityEventForKey(
                key, AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
        return true;
    case AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS:
        mAccessibilityFocusedView = UNDEFINED;
        sendAccessibilityEventForKey(
                key, AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
        return true;
    case AccessibilityNodeInfoCompat.ACTION_CLICK:
        sendAccessibilityEventForKey(key, AccessibilityEvent.TYPE_VIEW_CLICKED);
        mDelegate.performClickOn(key);
        return true;
    case AccessibilityNodeInfoCompat.ACTION_LONG_CLICK:
        sendAccessibilityEventForKey(key, AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);
        mDelegate.performLongClickOn(key);
        return true;
    default:
        return false;
    }
}
 
Example #4
Source File: AccessibilityEventProcessor.java    From talkback with Apache License 2.0 6 votes vote down vote up
/**
 * Helper method for {@link #shouldDropEvent} that handles events that automatically occur
 * immediately after a window state change.
 *
 * @param event The automatically generated event to consider retaining.
 * @return Whether to retain the event.
 */
private boolean shouldKeepAutomaticEvent(AccessibilityEvent event) {
  final AccessibilityRecordCompat record = AccessibilityEventCompat.asRecord(event);

  // Don't drop focus events from EditTexts.
  if (event.getEventType() == AccessibilityEvent.TYPE_VIEW_FOCUSED) {
    AccessibilityNodeInfoCompat node = null;

    try {
      node = record.getSource();
      if (Role.getRole(node) == Role.ROLE_EDIT_TEXT) {
        return true;
      }
    } finally {
      AccessibilityNodeInfoUtils.recycleNodes(node);
    }
  }

  return false;
}
 
Example #5
Source File: SliderPager.java    From Android-Image-Slider with Apache License 2.0 6 votes vote down vote up
@SuppressLint("WrongConstant")
@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
    // Dispatch scroll events from this SliderPager.
    if (event.getEventType() == AccessibilityEventCompat.TYPE_VIEW_SCROLLED) {
        return super.dispatchPopulateAccessibilityEvent(event);
    }

    // Dispatch all other accessibility events from the current page.
    final int childCount = getChildCount();
    for (int i = 0; i < childCount; i++) {
        final View child = getChildAt(i);
        if (child.getVisibility() == VISIBLE) {
            final ItemInfo ii = infoForChild(child);
            if (ii != null && ii.position == mCurItem
                    && child.dispatchPopulateAccessibilityEvent(event)) {
                return true;
            }
        }
    }

    return false;
}
 
Example #6
Source File: TalkBackHelper.java    From libcommon with Apache License 2.0 6 votes vote down vote up
/**
 * 指定したテキストをTalkBackで読み上げる(TalkBackが有効な場合)
 * @param context
 * @param text
 * @throws IllegalStateException
 */
public static void announceText(@NonNull final Context context,
	@Nullable final CharSequence text) throws IllegalStateException {

	if (TextUtils.isEmpty(text) || (context == null)) return;
	final AccessibilityManager manager
		= ContextUtils.requireSystemService(context, AccessibilityManager.class);
	if ((manager != null) && manager.isEnabled()) {
		final AccessibilityEvent event = AccessibilityEvent.obtain();
		if (event != null) {
			event.setEventType(AccessibilityEventCompat.TYPE_ANNOUNCEMENT);
			event.setClassName(TalkBackHelper.class.getName());
			event.setPackageName(context.getPackageName());
			event.getText().add(text);
			manager.sendAccessibilityEvent(event);
		} else {
			throw new IllegalStateException("failed to obtain AccessibilityEvent");
		}
	} else {
		throw new IllegalStateException("AccessibilityManager is not available/or disabled");
	}
}
 
Example #7
Source File: TalkBackHelper.java    From libcommon with Apache License 2.0 6 votes vote down vote up
/**
 * 指定したテキストをTalkBackで読み上げる(TalkBackが有効な場合)
 * @param context
 * @param text
 * @throws IllegalStateException
 */
public static void announceText(@NonNull final Context context,
	@Nullable final CharSequence[] text) throws IllegalStateException {

	if ((text == null) || (text.length == 0) || (context == null)) return;
	final AccessibilityManager manager
		= ContextUtils.requireSystemService(context, AccessibilityManager.class);
	if ((manager != null) && manager.isEnabled()) {
		final AccessibilityEvent event = AccessibilityEvent.obtain();
		if (event != null) {
			event.setEventType(AccessibilityEventCompat.TYPE_ANNOUNCEMENT);
			event.setClassName(TalkBackHelper.class.getName());
			event.setPackageName(context.getPackageName());
			for (final CharSequence t: text) {
				event.getText().add(t);
			}
			manager.sendAccessibilityEvent(event);
		} else {
			throw new IllegalStateException("failed to obtain AccessibilityEvent");
		}
	} else {
		throw new IllegalStateException("AccessibilityManager is not available/or disabled");
	}
}
 
Example #8
Source File: CustomViewPager.java    From AsteroidOSSync with GNU General Public License v3.0 6 votes vote down vote up
@Override
public boolean dispatchPopulateAccessibilityEvent(AccessibilityEvent event) {
    // Dispatch scroll events from this ViewPager.
    if (event.getEventType() == AccessibilityEventCompat.TYPE_VIEW_SCROLLED) {
        return super.dispatchPopulateAccessibilityEvent(event);
    }

    // Dispatch all other accessibility events from the current page.
    final int childCount = getChildCount();
    for (int i = 0; i < childCount; i++) {
        final View child = getChildAt(i);
        if (child.getVisibility() == VISIBLE) {
            final ItemInfo ii = infoForChild(child);
            if (ii != null && ii.position == mCurItem
                    && child.dispatchPopulateAccessibilityEvent(event)) {
                return true;
            }
        }
    }

    return false;
}
 
Example #9
Source File: Role.java    From talkback with Apache License 2.0 6 votes vote down vote up
/**
 * Gets the source {@link Role} from the {@link AccessibilityEvent}.
 *
 * <p>It checks the role with {@link AccessibilityEvent#getClassName()}. If it returns {@link
 * #ROLE_NONE}, fallback to check {@link AccessibilityNodeInfoCompat#getClassName()} of the source
 * node.
 */
public static @RoleName int getSourceRole(AccessibilityEvent event) {
  if (event == null) {
    return ROLE_NONE;
  }

  // Try to get role from event's class name.
  @RoleName int role = sourceClassNameToRole(event);
  if (role != ROLE_NONE) {
    return role;
  }

  // Extract event's source node, and map source node class to role.
  AccessibilityRecordCompat eventRecord = AccessibilityEventCompat.asRecord(event);
  AccessibilityNodeInfoCompat source = eventRecord.getSource();
  try {
    return getRole(source);
  } finally {
    AccessibilityNodeInfoUtils.recycleNodes(source);
  }
}
 
Example #10
Source File: AccessibilityHintsManager.java    From talkback with Apache License 2.0 5 votes vote down vote up
/** Posts a hint about node. The hint will be spoken after the next utterance is completed. */
public void postHintForNode(AccessibilityEvent event, AccessibilityNodeInfoCompat node) {
  cancelA11yHint();

  // Store info about event that caused pending hint.
  mPendingHintSource = node;
  // The hint for a node is usually posted when the node is getting accessibility focus, thus
  // the default value for the hint event type should be TYPE_VIEW_ACCESSIBILITY_FOCUSED.
  mPendingHintEventType =
      (event != null)
          ? event.getEventType()
          : AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUSED;
  postA11yHintRunnable();
}
 
Example #11
Source File: NavigationMenuItemView.java    From material-components-android with Apache License 2.0 5 votes vote down vote up
@Override
public void setCheckable(boolean checkable) {
  refreshDrawableState();
  if (this.checkable != checkable) {
    this.checkable = checkable;
    accessibilityDelegate.sendAccessibilityEvent(
        textView, AccessibilityEventCompat.TYPE_WINDOW_CONTENT_CHANGED);
  }
}
 
Example #12
Source File: ScrollFeedbackManager.java    From talkback with Apache License 2.0 5 votes vote down vote up
private boolean shouldIgnoreEvent(AccessibilityEvent event) {
  switch (event.getEventType()) {
    case AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUSED:
    case AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED:
      return true;
    case AccessibilityEventCompat.TYPE_WINDOW_CONTENT_CHANGED:
    case AccessibilityEventCompat.TYPE_VIEW_SCROLLED:
      return shouldIgnoreWindowContentChangedOrViewScrolledEvent(event);
    default:
      return false;
  }
}
 
Example #13
Source File: ScrollFeedbackManager.java    From talkback with Apache License 2.0 5 votes vote down vote up
/**
 * Returns whether the event is a duplicate of the previous event, or the event is triggered by
 * auto-scroll.
 *
 * @param event The event from which information about the scroll position will be retrieved
 * @return {@code true} if the event is a duplicate of the previous event, or triggered by
 *     auto-scroll
 */
protected boolean isDuplicateScrollEventOrAutoScroll(AccessibilityEvent event) {
  int eventType = event.getEventType();
  if ((eventType != AccessibilityEventCompat.TYPE_WINDOW_CONTENT_CHANGED)
      && (eventType != AccessibilityEventCompat.TYPE_VIEW_SCROLLED)) {
    return false;
  }

  final int fromIndex = event.getFromIndex() + 1;
  final int itemCount = event.getItemCount();
  if (itemCount <= 0 || fromIndex <= 0) {
    return true;
  }

  EventId eventId;
  try {
    eventId = new EventId(event);
  } catch (Exception e) {
    return true;
  }

  final Integer cachedFromIndex = cachedFromValues.get(eventId);
  final Integer cachedItemCount = cachedItemCounts.get(eventId);

  if ((cachedFromIndex != null)
      && (cachedFromIndex == fromIndex)
      && (cachedItemCount != null)
      && (cachedItemCount == itemCount)) {
    // The from index hasn't changed, which means the event is coming
    // from a re-layout or resize and should not be spoken.
    return true;
  }

  // The behavior of put() for an existing key is unspecified, so we can't
  // recycle the old or new key nodes.
  cachedFromValues.put(eventId, fromIndex);
  cachedItemCounts.put(eventId, itemCount);

  return false;
}
 
Example #14
Source File: AccessibilityEventUtils.java    From talkback with Apache License 2.0 5 votes vote down vote up
/**
 * Returns true if the event came from a non main window event, such as invisible, toast, or IME
 * window; otherwise returns false. Examples:
 *
 * <ul>
 *   <li>Returns false for main activity windows.
 *   <li>Returns true for the soft keyboard window in an IME.
 *   <li>Returns true for toasts.
 *   <li>Returns true for volume slider.
 * </ul>
 */
// TODO: Add window-types similar to AccessibilityWindowInfo.getType(), but more
// specific and more stable across android versions.
public static boolean isNonMainWindowEvent(AccessibilityEvent event) {
  // If there's an actual window ID, we need to check the window type (if window available).
  boolean isNonMainWindow = false;
  AccessibilityRecordCompat record = AccessibilityEventCompat.asRecord(event);
  AccessibilityNodeInfoCompat source = record.getSource();
  if (source != null) {
    AccessibilityWindowInfoCompat window = AccessibilityNodeInfoUtils.getWindow(source);
    if (window == null) {
      // If window is not visible, we cannot know whether the window type is input method
      // or not. Let's assume that it comes from an IME. If window is visible but window
      // info is not available, it can be non-focusable visible window.
      isNonMainWindow = true;
    } else {
      switch (window.getType()) {
        case AccessibilityWindowInfoCompat.TYPE_INPUT_METHOD:
          // IME case.
          isNonMainWindow = true;
          break;
        case AccessibilityWindowInfoCompat.TYPE_SYSTEM:
          isNonMainWindow = isFromVolumeControlPanel(event);
          break;
        default: // fall out
      }
      window.recycle();
    }
    source.recycle();
  }
  return isNonMainWindow;
}
 
Example #15
Source File: SwitchAccessHighlightFeedbackController.java    From talkback with Apache License 2.0 5 votes vote down vote up
@Override
public void onFocusHint(
    int eventType,
    AccessibilityNodeInfoCompat accessibilityNodeInfoCompat,
    boolean hintForcedFeedbackAudioPlaybackActive,
    boolean hintForcedFeedbackMicrophoneActive) {
  // Make sure that AccessibilityNodeInfoCompats that correspond to OverlayActionNodes have their
  // original event type, TYPE_VIEW_ACCESSIBILITY_FOCUSED. This ensures that the hint is spoken.
  //
  // When an OverlayActionNode is selected, we change the type of the accompanying event from
  // TYPE_VIEW_ACCESSIBILITY_FOCUSED to TYPE_VIEW_FOCUSED. This ensures that the hint for the
  // OverlayActionNode is not canceled because of window state changes. Here, we need to
  // convert the event type back to its original type, TYPE_VIEW_ACCESSIBILITY_FOCUSED.
  if (accessibilityNodeInfoCompat != null
      && OverlayActionNode.class.getName().equals(accessibilityNodeInfoCompat.getClassName())
      && eventType == TYPE_VIEW_FOCUSED) {
    eventType = AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUSED;
  }

  @HintEventInterpretation.HintType
  int hintEventType =
      (eventType == TYPE_VIEW_FOCUSED)
          ? HintEventInterpretation.HINT_TYPE_INPUT_FOCUS
          : HintEventInterpretation.HINT_TYPE_ACCESSIBILITY_FOCUS;
  HintEventInterpretation hintInterp = new HintEventInterpretation(hintEventType);
  hintInterp.setForceFeedbackAudioPlaybackActive(hintForcedFeedbackAudioPlaybackActive);
  hintInterp.setForceFeedbackMicropphoneActive(hintForcedFeedbackMicrophoneActive);
  EventInterpretation eventInterp = new EventInterpretation(Compositor.EVENT_SPEAK_HINT);
  eventInterp.setHint(hintInterp);
  eventInterp.setHasMultipleSwitchAccessActions(currentNodeHasMultipleActions);

  // Send event to compositor to speak feedback.
  compositor.handleEvent(accessibilityNodeInfoCompat, EVENT_ID_UNTRACKED, eventInterp);
  isLastSpeech = true;
}
 
Example #16
Source File: ProcessorCursorState.java    From talkback with Apache License 2.0 5 votes vote down vote up
@Override
public void onAccessibilityEvent(AccessibilityEvent event, EventId eventId) {
  switch (event.getEventType()) {
    case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED:
      // Keep track of the accessibility focused EditText.
      overlay.hide();
      saveFocusedNode(AccessibilityEventCompat.asRecord(event));
      break;
    case AccessibilityEvent.TYPE_VIEW_FOCUSED:
      // On pre Android O devices, double-tap on screen will interpreted as touch down and up
      // action at the center of the focused node, which might set cursor to the middle of text if
      // the text is long enough. TalkBack overrides the cursor position to be the end of the
      // field to avoid the confusion of cursor movement. See  for details.
      if (SHOULD_HANDLE_TOUCH_EVENT) {
        // Reset the EditText cursor because focusing will snap it to the middle.
        resetNodeCursor(AccessibilityEventCompat.asRecord(event), eventId);
      }
      break;
    case AccessibilityEvent.TYPE_VIEW_SCROLLED:
      // Hide the overlay so it doesn't interfere with scrolling.
      overlay.hide();
      break;
    case AccessibilityEvent.TYPE_TOUCH_INTERACTION_START:
      if (SHOULD_HANDLE_TOUCH_EVENT) {
        // Show the overlay if the a11y-focused EditText is editing and we touch the screen.
        touchStart(event, eventId);
      }
      break;
    case AccessibilityEvent.TYPE_TOUCH_INTERACTION_END:
      if (SHOULD_HANDLE_TOUCH_EVENT) {
        // Hide the overlay when we stop touching the screen.
        touchEnd(event, eventId);
      }
      break;
    default: // fall out
  }
}
 
Example #17
Source File: ProcessorPermissionDialogs.java    From talkback with Apache License 2.0 5 votes vote down vote up
@Override
public void onAccessibilityEvent(AccessibilityEvent event, EventId eventId) {
  switch (event.getEventType()) {
    case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED:
      clearNode();
      AccessibilityRecordCompat record = AccessibilityEventCompat.asRecord(event);
      AccessibilityNodeInfoCompat source = record.getSource();
      if (source != null) {
        if (ALLOW_BUTTON.equals(source.getViewIdResourceName())
            && dimScreenController.isDimmingEnabled()) {
          Rect sourceRect = new Rect();
          source.getBoundsInScreen(sourceRect);
          overlay.show(sourceRect);
          allowNode = source;
        } else {
          source.recycle();
        }
      }
      break;
    case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED:
    case AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED:
      clearNode();
      break;
    default: // fall out
  }

  if (allowNode != null) {
    overlay.onAccessibilityEvent(event, eventId);
  }
}
 
Example #18
Source File: GlobalVariables.java    From talkback with Apache License 2.0 5 votes vote down vote up
public void updateStateFromEvent(AccessibilityEvent event) {
  switch (event.getEventType()) {
    case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED:
      {
        final AccessibilityRecordCompat record = AccessibilityEventCompat.asRecord(event);
        final AccessibilityNodeInfoCompat sourceNode = record.getSource();

        // Transition the collection state if necessary.
        mCollectionState.updateCollectionInformation(sourceNode, event);
        if (sourceNode != null) {
          final AccessibilityNodeInfoCompat scrollableNode =
              AccessibilityNodeInfoUtils.getSelfOrMatchingAncestor(
                  sourceNode, AccessibilityNodeInfoUtils.FILTER_SCROLLABLE);
          mIsLastFocusInScrollableNode = mIsCurrentFocusInScrollableNode;
          mIsCurrentFocusInScrollableNode = (scrollableNode != null);
          if (scrollableNode != null) {
            scrollableNode.recycle();
          }

          TraversalStrategy traversalStrategy = new SimpleTraversalStrategy();
          // TODO: TraversalStrategyUtils.isEdgeListItem() doesn't include Role check in
          // AccessibilityNodeInfoUtils.FILTER_AUTO_SCROLL. Shall we use
          // TraversalStrategyUtils.isAutoScrollEdgeListItem() instead?
          mIsFocusEdgeListItem =
              TraversalStrategyUtils.isEdgeListItem(sourceNode, traversalStrategy);
          traversalStrategy.recycle();

          mLastWindowId = mCurrentWindowId;
          mCurrentWindowId = sourceNode.getWindowId();
          sourceNode.recycle();
        }
      }
      break;
    default: // fall out
  }
}
 
Example #19
Source File: CheckableImageButton.java    From material-components-android with Apache License 2.0 5 votes vote down vote up
/** Sets image button to be checkable or not. */
public void setCheckable(boolean checkable) {
  if (this.checkable != checkable) {
    this.checkable = checkable;
    sendAccessibilityEvent(AccessibilityEventCompat.CONTENT_CHANGE_TYPE_UNDEFINED);
  }
}
 
Example #20
Source File: CheckableImageButton.java    From material-components-android with Apache License 2.0 5 votes vote down vote up
@Override
public void setChecked(boolean checked) {
  if (checkable && this.checked != checked) {
    this.checked = checked;
    refreshDrawableState();
    sendAccessibilityEvent(AccessibilityEventCompat.TYPE_WINDOW_CONTENT_CHANGED);
  }
}
 
Example #21
Source File: NestedScrollView.java    From AndroidAnimationExercise with Apache License 2.0 5 votes vote down vote up
@Override
public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
    super.onInitializeAccessibilityEvent(host, event);
    final NestedScrollView nsvHost = (NestedScrollView) host;
    event.setClassName(ScrollView.class.getName());
    final AccessibilityRecordCompat record = AccessibilityEventCompat.asRecord(event);
    final boolean scrollable = nsvHost.getScrollRange() > 0;
    record.setScrollable(scrollable);
    record.setScrollX(nsvHost.getScrollX());
    record.setScrollY(nsvHost.getScrollY());
    record.setMaxScrollX(nsvHost.getScrollX());
    record.setMaxScrollY(nsvHost.getScrollRange());
}
 
Example #22
Source File: CustomViewPager.java    From AsteroidOSSync with GNU General Public License v3.0 5 votes vote down vote up
@Override
public void onInitializeAccessibilityEvent(View host, AccessibilityEvent event) {
    super.onInitializeAccessibilityEvent(host, event);
    event.setClassName(CustomViewPager.class.getName());
    final AccessibilityRecordCompat recordCompat =
            AccessibilityEventCompat.asRecord(event);
    recordCompat.setScrollable(canScroll());
    if (event.getEventType() == AccessibilityEventCompat.TYPE_VIEW_SCROLLED
            && mAdapter != null) {
        recordCompat.setItemCount(mAdapter.getCount());
        recordCompat.setFromIndex(mCurItem);
        recordCompat.setToIndex(mCurItem);
    }
}
 
Example #23
Source File: ViewPagerLayoutManager.java    From OmegaRecyclerView with MIT License 5 votes vote down vote up
@Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
    super.onInitializeAccessibilityEvent(event);
    if (getChildCount() > 0) {
        final AccessibilityRecordCompat record = AccessibilityEventCompat.asRecord(event);
        record.setFromIndex(getPosition(getFirstChild()));
        record.setToIndex(getPosition(getLastChild()));
    }
}
 
Example #24
Source File: AccessibilityUtils.java    From AOSP-Kayboard-7.1.2 with Apache License 2.0 5 votes vote down vote up
/**
 * Sends the specified text to the {@link AccessibilityManager} to be
 * spoken.
 *
 * @param view The source view.
 * @param text The text to speak.
 */
public void announceForAccessibility(final View view, final CharSequence text) {
    if (!mAccessibilityManager.isEnabled()) {
        Log.e(TAG, "Attempted to speak when accessibility was disabled!");
        return;
    }

    // The following is a hack to avoid using the heavy-weight TextToSpeech
    // class. Instead, we're just forcing a fake AccessibilityEvent into
    // the screen reader to make it speak.
    final AccessibilityEvent event = AccessibilityEvent.obtain();

    event.setPackageName(PACKAGE);
    event.setClassName(CLASS);
    event.setEventTime(SystemClock.uptimeMillis());
    event.setEnabled(true);
    event.getText().add(text);

    // Platforms starting at SDK version 16 (Build.VERSION_CODES.JELLY_BEAN) should use
    // announce events.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        event.setEventType(AccessibilityEventCompat.TYPE_ANNOUNCEMENT);
    } else {
        event.setEventType(AccessibilityEvent.TYPE_VIEW_FOCUSED);
    }

    final ViewParent viewParent = view.getParent();
    if ((viewParent == null) || !(viewParent instanceof ViewGroup)) {
        Log.e(TAG, "Failed to obtain ViewParent in announceForAccessibility");
        return;
    }

    viewParent.requestSendAccessibilityEvent(view, event);
}
 
Example #25
Source File: KeyboardAccessibilityNodeProvider.java    From AOSP-Kayboard-7.1.2 with Apache License 2.0 5 votes vote down vote up
public void onHoverExitFrom(final Key key) {
    mHoveringNodeId = UNDEFINED;
    // Invalidate the node info of the key to be able to revert the change we have done
    // in {@link #onHoverEnterTo(Key)}.
    sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_WINDOW_CONTENT_CHANGED);
    sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_VIEW_HOVER_EXIT);
}
 
Example #26
Source File: KeyboardAccessibilityNodeProvider.java    From AOSP-Kayboard-7.1.2 with Apache License 2.0 5 votes vote down vote up
public void onHoverEnterTo(final Key key) {
    final int id = getVirtualViewIdOf(key);
    if (id == View.NO_ID) {
        return;
    }
    // Start hovering on the key. Because our accessibility model is lift-to-type, we should
    // report the node info without click and long click actions to avoid unnecessary
    // announcements.
    mHoveringNodeId = id;
    // Invalidate the node info of the key.
    sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_WINDOW_CONTENT_CHANGED);
    sendAccessibilityEventForKey(key, AccessibilityEventCompat.TYPE_VIEW_HOVER_ENTER);
}
 
Example #27
Source File: KeyboardAccessibilityNodeProvider.java    From AOSP-Kayboard-7.1.2 with Apache License 2.0 5 votes vote down vote up
/**
 * Creates and populates an {@link AccessibilityEvent} for the specified key
 * and event type.
 *
 * @param key A key on the host keyboard view.
 * @param eventType The event type to create.
 * @return A populated {@link AccessibilityEvent} for the key.
 * @see AccessibilityEvent
 */
public AccessibilityEvent createAccessibilityEvent(final Key key, final int eventType) {
    final int virtualViewId = getVirtualViewIdOf(key);
    final String keyDescription = getKeyDescription(key);
    final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
    event.setPackageName(mKeyboardView.getContext().getPackageName());
    event.setClassName(key.getClass().getName());
    event.setContentDescription(keyDescription);
    event.setEnabled(true);
    final AccessibilityRecordCompat record = AccessibilityEventCompat.asRecord(event);
    record.setSource(mKeyboardView, virtualViewId);
    return event;
}
 
Example #28
Source File: EventFilter.java    From talkback with Apache License 2.0 4 votes vote down vote up
private boolean shouldDropTextSelectionEvent(AccessibilityEvent event) {
  // Keep all events other than text-selection.
  final int eventType = event.getEventType();
  if (eventType != AccessibilityEvent.TYPE_VIEW_TEXT_SELECTION_CHANGED) {
    return false;
  }

  // Drop selected events until we've matched the number of changed
  // events. This prevents TalkBack from speaking automatic cursor
  // movement events that result from typing.
  if (textEventHistory.getTextChangesAwaitingSelection() > 0) {
    final boolean hasDelayElapsed =
        ((event.getEventTime() - textEventHistory.getLastTextChangeTime())
            >= TEXT_SELECTION_DELAY);
    final boolean hasPackageChanged =
        !TextUtils.equals(
            event.getPackageName(), textEventHistory.getLastTextChangePackageName());

    // If the state is still consistent, update the count and drop the event.
    if (!hasDelayElapsed && !hasPackageChanged) {
      textEventHistory.incrementTextChangesAwaitingSelection(-1);
      textEventHistory.setLastFromIndex(event.getFromIndex());
      textEventHistory.setLastToIndex(event.getToIndex());
      textEventHistory.setLastNode(event.getSource());
      return true;
    }

    // The state became inconsistent, so reset the counter.
    textEventHistory.setTextChangesAwaitingSelection(0);
  }

  // Drop selection events from views that don't have input focus.
  final AccessibilityRecordCompat record = AccessibilityEventCompat.asRecord(event);
  final AccessibilityNodeInfoCompat source = record.getSource();
  boolean isFocused = source != null && source.isFocused();
  AccessibilityNodeInfoUtils.recycleNodes(source);
  if (!isFocused) {
    LogUtils.v(TAG, "Dropped text-selection event from non-focused field");
    return true;
  }

  return false;
}
 
Example #29
Source File: Event.java    From talkback with Apache License 2.0 4 votes vote down vote up
/** Returns a bitmap of content changes. See public documentation of AccessibilityEvent. */
public final int getContentChangeTypes() {
  return AccessibilityEventCompat.getContentChangeTypes(getEvent());
}