Loading services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java +46 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.text.TextUtils; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.PointerIcon; import android.view.View; import android.view.WindowInsets; import android.view.WindowManager; Loading Loading @@ -68,6 +69,7 @@ public class AutoclickTypePanel { // Initial panel position in screen coordinates. private int mPanelStartX, mPanelStartY; private boolean mIsDragging = false; private PointerIcon mCurrentCursor; // Types of click the AutoclickTypePanel supports. @IntDef({ Loading Loading @@ -195,11 +197,24 @@ public class AutoclickTypePanel { mLongPressButton = mContentView.findViewById(R.id.accessibility_autoclick_long_press_layout); // Initialize the cursor icons. mCurrentCursor = PointerIcon.getSystemIcon(context, PointerIcon.TYPE_ARROW); initializeButtonState(); // Set up touch event handling for the panel to allow the user to drag and reposition the // panel by touching and moving it. mContentView.setOnTouchListener(this::onPanelTouch); // Set hover behavior for the panel, show grab when hovering. mContentView.setOnHoverListener((v, event) -> { mCurrentCursor = PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_GRAB); v.setPointerIcon(mCurrentCursor); return false; }); // Show default cursor when hovering over buttons. setDefaultCursorForButtons(); } /** Loading @@ -223,6 +238,13 @@ public class AutoclickTypePanel { v.getLocationOnScreen(location); mPanelStartX = location[0]; mPanelStartY = location[1]; // Show grabbing cursor when dragging starts. boolean isSynthetic = (event.getFlags() & MotionEvent.FLAG_IS_GENERATED_GESTURE) != 0; if (!isSynthetic) { mCurrentCursor = PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_GRABBING); v.setPointerIcon(mCurrentCursor); } return true; case MotionEvent.ACTION_MOVE: mIsDragging = true; Loading @@ -248,6 +270,9 @@ public class AutoclickTypePanel { snapToNearestEdge(mParams); } mIsDragging = false; // Show grab cursor when dragging ends. mCurrentCursor = PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_GRAB); v.setPointerIcon(mCurrentCursor); return true; case MotionEvent.ACTION_OUTSIDE: if (mExpanded) { Loading Loading @@ -678,6 +703,22 @@ public class AutoclickTypePanel { } } private void setDefaultCursorForButtons() { View[] buttons = { mLeftClickButton, mRightClickButton, mDoubleClickButton, mScrollButton, mDragButton, mLongPressButton, mPauseButton, mPositionButton }; for (View button : buttons) { button.setOnHoverListener((v, event) -> { mCurrentCursor = PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW); v.setPointerIcon(mCurrentCursor); return false; }); } } @VisibleForTesting boolean getExpansionStateForTesting() { return mExpanded; Loading Loading @@ -705,6 +746,11 @@ public class AutoclickTypePanel { return mIsDragging; } @VisibleForTesting PointerIcon getCurrentCursorForTesting() { return mCurrentCursor; } /** * Retrieves the layout params for AutoclickIndicatorView, used when it's added to the Window * Manager. Loading services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickTypePanelTest.java +47 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import android.testing.TestableContext; import android.testing.TestableLooper; import android.view.Gravity; import android.view.MotionEvent; import android.view.PointerIcon; import android.view.View; import android.view.WindowManager; import android.widget.ImageButton; Loading Loading @@ -538,6 +539,52 @@ public class AutoclickTypePanelTest { assertThat(mHovered).isFalse(); } @Test public void cursorIcon_fullDragCycle() { View contentView = mAutoclickTypePanel.getContentViewForTesting(); int[] panelLocation = new int[2]; contentView.getLocationOnScreen(panelLocation); // Set up drag coordinates. float startX = panelLocation[0] + 10; float startY = panelLocation[1] + 10; float moveX = startX + 50; float moveY = startY + 20; // 1. Initial state. PointerIcon initialCursor = mAutoclickTypePanel.getCurrentCursorForTesting(); // 2. DOWN event - Touch starts. MotionEvent downEvent = MotionEvent.obtain( 0, 0, MotionEvent.ACTION_DOWN, startX, startY, 0); contentView.dispatchTouchEvent(downEvent); PointerIcon touchStartCursor = mAutoclickTypePanel.getCurrentCursorForTesting(); // 3. MOVE event - Dragging starts. MotionEvent moveEvent = MotionEvent.obtain( 0, 0, MotionEvent.ACTION_MOVE, moveX, moveY, 0); contentView.dispatchTouchEvent(moveEvent); PointerIcon draggingCursor = mAutoclickTypePanel.getCurrentCursorForTesting(); // 4. UP event - Drag ends. MotionEvent upEvent = MotionEvent.obtain( 0, 0, MotionEvent.ACTION_UP, moveX, moveY, 0); contentView.dispatchTouchEvent(upEvent); PointerIcon afterDragCursor = mAutoclickTypePanel.getCurrentCursorForTesting(); // Initial state should be default cursor. assertThat(initialCursor.getType()).isEqualTo(PointerIcon.TYPE_ARROW); // After touch down - cursor should change to grabbing. assertThat(touchStartCursor.getType()).isEqualTo(PointerIcon.TYPE_GRABBING); // During drag - should be in dragging state with grabbing cursor. assertThat(draggingCursor.getType()).isEqualTo(PointerIcon.TYPE_GRABBING); // After drag ends - should not be dragging and cursor should be grab. assertThat(afterDragCursor.getType()).isEqualTo(PointerIcon.TYPE_GRAB); } private void verifyButtonHasSelectedStyle(@NonNull LinearLayout button) { GradientDrawable gradientDrawable = (GradientDrawable) button.getBackground(); assertThat(gradientDrawable.getColor().getDefaultColor()) Loading Loading
services/accessibility/java/com/android/server/accessibility/autoclick/AutoclickTypePanel.java +46 −0 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.text.TextUtils; import android.view.Gravity; import android.view.LayoutInflater; import android.view.MotionEvent; import android.view.PointerIcon; import android.view.View; import android.view.WindowInsets; import android.view.WindowManager; Loading Loading @@ -68,6 +69,7 @@ public class AutoclickTypePanel { // Initial panel position in screen coordinates. private int mPanelStartX, mPanelStartY; private boolean mIsDragging = false; private PointerIcon mCurrentCursor; // Types of click the AutoclickTypePanel supports. @IntDef({ Loading Loading @@ -195,11 +197,24 @@ public class AutoclickTypePanel { mLongPressButton = mContentView.findViewById(R.id.accessibility_autoclick_long_press_layout); // Initialize the cursor icons. mCurrentCursor = PointerIcon.getSystemIcon(context, PointerIcon.TYPE_ARROW); initializeButtonState(); // Set up touch event handling for the panel to allow the user to drag and reposition the // panel by touching and moving it. mContentView.setOnTouchListener(this::onPanelTouch); // Set hover behavior for the panel, show grab when hovering. mContentView.setOnHoverListener((v, event) -> { mCurrentCursor = PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_GRAB); v.setPointerIcon(mCurrentCursor); return false; }); // Show default cursor when hovering over buttons. setDefaultCursorForButtons(); } /** Loading @@ -223,6 +238,13 @@ public class AutoclickTypePanel { v.getLocationOnScreen(location); mPanelStartX = location[0]; mPanelStartY = location[1]; // Show grabbing cursor when dragging starts. boolean isSynthetic = (event.getFlags() & MotionEvent.FLAG_IS_GENERATED_GESTURE) != 0; if (!isSynthetic) { mCurrentCursor = PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_GRABBING); v.setPointerIcon(mCurrentCursor); } return true; case MotionEvent.ACTION_MOVE: mIsDragging = true; Loading @@ -248,6 +270,9 @@ public class AutoclickTypePanel { snapToNearestEdge(mParams); } mIsDragging = false; // Show grab cursor when dragging ends. mCurrentCursor = PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_GRAB); v.setPointerIcon(mCurrentCursor); return true; case MotionEvent.ACTION_OUTSIDE: if (mExpanded) { Loading Loading @@ -678,6 +703,22 @@ public class AutoclickTypePanel { } } private void setDefaultCursorForButtons() { View[] buttons = { mLeftClickButton, mRightClickButton, mDoubleClickButton, mScrollButton, mDragButton, mLongPressButton, mPauseButton, mPositionButton }; for (View button : buttons) { button.setOnHoverListener((v, event) -> { mCurrentCursor = PointerIcon.getSystemIcon(mContext, PointerIcon.TYPE_ARROW); v.setPointerIcon(mCurrentCursor); return false; }); } } @VisibleForTesting boolean getExpansionStateForTesting() { return mExpanded; Loading Loading @@ -705,6 +746,11 @@ public class AutoclickTypePanel { return mIsDragging; } @VisibleForTesting PointerIcon getCurrentCursorForTesting() { return mCurrentCursor; } /** * Retrieves the layout params for AutoclickIndicatorView, used when it's added to the Window * Manager. Loading
services/tests/servicestests/src/com/android/server/accessibility/autoclick/AutoclickTypePanelTest.java +47 −0 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import android.testing.TestableContext; import android.testing.TestableLooper; import android.view.Gravity; import android.view.MotionEvent; import android.view.PointerIcon; import android.view.View; import android.view.WindowManager; import android.widget.ImageButton; Loading Loading @@ -538,6 +539,52 @@ public class AutoclickTypePanelTest { assertThat(mHovered).isFalse(); } @Test public void cursorIcon_fullDragCycle() { View contentView = mAutoclickTypePanel.getContentViewForTesting(); int[] panelLocation = new int[2]; contentView.getLocationOnScreen(panelLocation); // Set up drag coordinates. float startX = panelLocation[0] + 10; float startY = panelLocation[1] + 10; float moveX = startX + 50; float moveY = startY + 20; // 1. Initial state. PointerIcon initialCursor = mAutoclickTypePanel.getCurrentCursorForTesting(); // 2. DOWN event - Touch starts. MotionEvent downEvent = MotionEvent.obtain( 0, 0, MotionEvent.ACTION_DOWN, startX, startY, 0); contentView.dispatchTouchEvent(downEvent); PointerIcon touchStartCursor = mAutoclickTypePanel.getCurrentCursorForTesting(); // 3. MOVE event - Dragging starts. MotionEvent moveEvent = MotionEvent.obtain( 0, 0, MotionEvent.ACTION_MOVE, moveX, moveY, 0); contentView.dispatchTouchEvent(moveEvent); PointerIcon draggingCursor = mAutoclickTypePanel.getCurrentCursorForTesting(); // 4. UP event - Drag ends. MotionEvent upEvent = MotionEvent.obtain( 0, 0, MotionEvent.ACTION_UP, moveX, moveY, 0); contentView.dispatchTouchEvent(upEvent); PointerIcon afterDragCursor = mAutoclickTypePanel.getCurrentCursorForTesting(); // Initial state should be default cursor. assertThat(initialCursor.getType()).isEqualTo(PointerIcon.TYPE_ARROW); // After touch down - cursor should change to grabbing. assertThat(touchStartCursor.getType()).isEqualTo(PointerIcon.TYPE_GRABBING); // During drag - should be in dragging state with grabbing cursor. assertThat(draggingCursor.getType()).isEqualTo(PointerIcon.TYPE_GRABBING); // After drag ends - should not be dragging and cursor should be grab. assertThat(afterDragCursor.getType()).isEqualTo(PointerIcon.TYPE_GRAB); } private void verifyButtonHasSelectedStyle(@NonNull LinearLayout button) { GradientDrawable gradientDrawable = (GradientDrawable) button.getBackground(); assertThat(gradientDrawable.getColor().getDefaultColor()) Loading