summaryrefslogtreecommitdiff
path: root/services/accessibility
diff options
context:
space:
mode:
author Longbo Wei <longbowei@google.com> 2025-03-12 17:52:40 -0700
committer Android (Google) Code Review <android-gerrit@google.com> 2025-03-12 17:52:40 -0700
commit2047bdf19c3e529e85348cc76906aa048b7c8fa2 (patch)
tree3317c14c57c34b234afce8c9583911f2f697b7a9 /services/accessibility
parent5e848712cddcf0ee8b943f0a68306938324a5f48 (diff)
parentaf17ef561655e2a48477cf65b859fe08b2108f2a (diff)
Merge "a11y: Add countdown when hovering on exit" into main
Diffstat (limited to 'services/accessibility')
-rw-r--r--services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java54
-rw-r--r--services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickScrollPanel.java71
2 files changed, 91 insertions, 34 deletions
diff --git a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java
index 84158cf911ad..0b9c45de6e40 100644
--- a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java
+++ b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickController.java
@@ -25,6 +25,7 @@ import static android.view.accessibility.AccessibilityManager.AUTOCLICK_REVERT_T
import static com.android.server.accessibility.autoclick.AutoclickIndicatorView.SHOW_INDICATOR_DELAY_TIME;
import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_DOUBLE_CLICK;
+import static com.android.server.accessibility.autoclick.AutoclickScrollPanel.DIRECTION_NONE;
import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_LEFT_CLICK;
import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_RIGHT_CLICK;
import static com.android.server.accessibility.autoclick.AutoclickTypePanel.AUTOCLICK_TYPE_SCROLL;
@@ -97,6 +98,9 @@ public class AutoclickController extends BaseEventStreamTransformation {
// Default click type is left-click.
private @AutoclickType int mActiveClickType = AUTOCLICK_TYPE_LEFT_CLICK;
+ // Default scroll direction is DIRECTION_NONE.
+ private @AutoclickScrollPanel.ScrollDirection int mHoveredDirection = DIRECTION_NONE;
+
@VisibleForTesting
final ClickPanelControllerInterface clickPanelController =
new ClickPanelControllerInterface() {
@@ -131,14 +135,26 @@ public class AutoclickController extends BaseEventStreamTransformation {
final AutoclickScrollPanel.ScrollPanelControllerInterface mScrollPanelController =
new AutoclickScrollPanel.ScrollPanelControllerInterface() {
@Override
- public void handleScroll(@AutoclickScrollPanel.ScrollDirection int direction) {
- // TODO(b/388845721): Perform actual scroll.
- }
+ public void onHoverButtonChange(
+ @AutoclickScrollPanel.ScrollDirection int direction,
+ boolean hovered) {
+ // Update the hover direction.
+ if (hovered) {
+ mHoveredDirection = direction;
+ } else if (mHoveredDirection == direction) {
+ // Safety check: Only clear hover tracking if this is the same button
+ // we're currently tracking.
+ mHoveredDirection = AutoclickScrollPanel.DIRECTION_NONE;
+ }
- @Override
- public void exitScrollMode() {
- if (mAutoclickScrollPanel != null) {
- mAutoclickScrollPanel.hide();
+ // For exit button, we only trigger hover state changes, the autoclick system
+ // will handle the countdown.
+ if (direction == AutoclickScrollPanel.DIRECTION_EXIT) {
+ return;
+ }
+ // For direction buttons, perform scroll action immediately.
+ if (hovered && direction != AutoclickScrollPanel.DIRECTION_NONE) {
+ handleScroll(direction);
}
}
};
@@ -285,6 +301,22 @@ public class AutoclickController extends BaseEventStreamTransformation {
}
}
+ /**
+ * Handles scroll operations in the specified direction.
+ */
+ public void handleScroll(@AutoclickScrollPanel.ScrollDirection int direction) {
+ // TODO(b/388845721): Perform actual scroll.
+ }
+
+ /**
+ * Exits scroll mode and hides the scroll panel UI.
+ */
+ public void exitScrollMode() {
+ if (mAutoclickScrollPanel != null) {
+ mAutoclickScrollPanel.hide();
+ }
+ }
+
@VisibleForTesting
void onChangeForTesting(boolean selfChange, Uri uri) {
mAutoclickSettingsObserver.onChange(selfChange, uri);
@@ -776,6 +808,14 @@ public class AutoclickController extends BaseEventStreamTransformation {
return;
}
+ if (mAutoclickScrollPanel != null && mAutoclickScrollPanel.isVisible()) {
+ // If exit button is hovered, exit scroll mode after countdown and return early.
+ if (mHoveredDirection == AutoclickScrollPanel.DIRECTION_EXIT) {
+ exitScrollMode();
+ }
+ return;
+ }
+
// Handle scroll type specially, show scroll panel instead of sending click events.
if (mActiveClickType == AutoclickTypePanel.AUTOCLICK_TYPE_SCROLL) {
if (mAutoclickScrollPanel != null) {
diff --git a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickScrollPanel.java b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickScrollPanel.java
index e79be502a6fc..c71443149687 100644
--- a/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickScrollPanel.java
+++ b/services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickScrollPanel.java
@@ -23,6 +23,7 @@ import android.content.Context;
import android.graphics.PixelFormat;
import android.view.Gravity;
import android.view.LayoutInflater;
+import android.view.MotionEvent;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowManager;
@@ -41,12 +42,16 @@ public class AutoclickScrollPanel {
public static final int DIRECTION_DOWN = 1;
public static final int DIRECTION_LEFT = 2;
public static final int DIRECTION_RIGHT = 3;
+ public static final int DIRECTION_EXIT = 4;
+ public static final int DIRECTION_NONE = 5;
@IntDef({
DIRECTION_UP,
DIRECTION_DOWN,
DIRECTION_LEFT,
- DIRECTION_RIGHT
+ DIRECTION_RIGHT,
+ DIRECTION_EXIT,
+ DIRECTION_NONE,
})
@Retention(RetentionPolicy.SOURCE)
public @interface ScrollDirection {}
@@ -70,16 +75,12 @@ public class AutoclickScrollPanel {
*/
public interface ScrollPanelControllerInterface {
/**
- * Called when a scroll direction is hovered.
+ * Called when a button hover state changes.
*
- * @param direction The direction to scroll: one of {@link ScrollDirection} values.
+ * @param direction The direction associated with the button.
+ * @param hovered Whether the button is being hovered or not.
*/
- void handleScroll(@ScrollDirection int direction);
-
- /**
- * Called when the exit button is hovered.
- */
- void exitScrollMode();
+ void onHoverButtonChange(@ScrollDirection int direction, boolean hovered);
}
public AutoclickScrollPanel(Context context, WindowManager windowManager,
@@ -104,19 +105,12 @@ public class AutoclickScrollPanel {
* Sets up hover listeners for scroll panel buttons.
*/
private void initializeButtonState() {
- // Set up hover listeners for direction buttons.
- setupHoverListenerForDirectionButton(mUpButton, DIRECTION_UP);
- setupHoverListenerForDirectionButton(mLeftButton, DIRECTION_LEFT);
- setupHoverListenerForDirectionButton(mRightButton, DIRECTION_RIGHT);
- setupHoverListenerForDirectionButton(mDownButton, DIRECTION_DOWN);
-
- // Set up hover listener for exit button.
- mExitButton.setOnHoverListener((v, event) -> {
- if (mScrollPanelController != null) {
- mScrollPanelController.exitScrollMode();
- }
- return true;
- });
+ // Set up hover listeners for all buttons.
+ setupHoverListenerForButton(mUpButton, DIRECTION_UP);
+ setupHoverListenerForButton(mLeftButton, DIRECTION_LEFT);
+ setupHoverListenerForButton(mRightButton, DIRECTION_RIGHT);
+ setupHoverListenerForButton(mDownButton, DIRECTION_DOWN);
+ setupHoverListenerForButton(mExitButton, DIRECTION_EXIT);
}
/**
@@ -142,14 +136,37 @@ public class AutoclickScrollPanel {
}
/**
- * Sets up a hover listener for a direction button.
+ * Sets up a hover listener for a button.
*/
- private void setupHoverListenerForDirectionButton(ImageButton button,
- @ScrollDirection int direction) {
+ private void setupHoverListenerForButton(ImageButton button, @ScrollDirection int direction) {
button.setOnHoverListener((v, event) -> {
- if (mScrollPanelController != null) {
- mScrollPanelController.handleScroll(direction);
+ if (mScrollPanelController == null) {
+ return true;
+ }
+
+ boolean hovered;
+ switch (event.getAction()) {
+ case MotionEvent.ACTION_HOVER_ENTER:
+ hovered = true;
+ break;
+ case MotionEvent.ACTION_HOVER_MOVE:
+ // For direction buttons, continuously trigger scroll on hover move.
+ if (direction != DIRECTION_EXIT) {
+ hovered = true;
+ } else {
+ // Ignore hover move events for exit button.
+ return true;
+ }
+ break;
+ case MotionEvent.ACTION_HOVER_EXIT:
+ hovered = false;
+ break;
+ default:
+ return true;
}
+
+ // Notify the controller about the hover change.
+ mScrollPanelController.onHoverButtonChange(direction, hovered);
return true;
});
}