summaryrefslogtreecommitdiffstats
path: root/core/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'core/java/android')
-rw-r--r--core/java/android/app/AssistStructure.java11
-rw-r--r--core/java/android/view/HapticFeedbackConstants.java5
-rw-r--r--core/java/android/view/MotionEvent.java12
-rw-r--r--core/java/android/view/View.java181
-rw-r--r--core/java/android/view/ViewAssistStructure.java2
-rw-r--r--core/java/android/view/accessibility/AccessibilityEvent.java14
-rw-r--r--core/java/android/view/accessibility/AccessibilityNodeInfo.java34
7 files changed, 251 insertions, 8 deletions
diff --git a/core/java/android/app/AssistStructure.java b/core/java/android/app/AssistStructure.java
index 9946d79..3abbb5b 100644
--- a/core/java/android/app/AssistStructure.java
+++ b/core/java/android/app/AssistStructure.java
@@ -224,6 +224,7 @@ final public class AssistStructure implements Parcelable {
static final int FLAGS_CHECKED = 0x00000200;
static final int FLAGS_CLICKABLE = 0x00004000;
static final int FLAGS_LONG_CLICKABLE = 0x00200000;
+ static final int FLAGS_STYLUS_BUTTON_PRESSABLE = 0x00400000;
int mFlags;
@@ -401,6 +402,10 @@ final public class AssistStructure implements Parcelable {
return (mFlags&ViewNode.FLAGS_LONG_CLICKABLE) != 0;
}
+ public boolean isStylusButtonPressable() {
+ return (mFlags&ViewNode.FLAGS_STYLUS_BUTTON_PRESSABLE) != 0;
+ }
+
public String getClassName() {
return mClassName;
}
@@ -513,6 +518,12 @@ final public class AssistStructure implements Parcelable {
}
@Override
+ public void setStylusButtonPressable(boolean state) {
+ mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_STYLUS_BUTTON_PRESSABLE)
+ | (state ? ViewNode.FLAGS_STYLUS_BUTTON_PRESSABLE : 0);
+ }
+
+ @Override
public void setFocusable(boolean state) {
mNode.mFlags = (mNode.mFlags&~ViewNode.FLAGS_FOCUSABLE)
| (state ? ViewNode.FLAGS_FOCUSABLE : 0);
diff --git a/core/java/android/view/HapticFeedbackConstants.java b/core/java/android/view/HapticFeedbackConstants.java
index cc090ad..6651b83 100644
--- a/core/java/android/view/HapticFeedbackConstants.java
+++ b/core/java/android/view/HapticFeedbackConstants.java
@@ -52,6 +52,11 @@ public class HapticFeedbackConstants {
public static final int CALENDAR_DATE = 5;
/**
+ * The user has touched the screen with a stylus and pressed the stylus button.
+ */
+ public static final int STYLUS_BUTTON_PRESS = 6;
+
+ /**
* This is a private constant. Feel free to renumber as desired.
* @hide
*/
diff --git a/core/java/android/view/MotionEvent.java b/core/java/android/view/MotionEvent.java
index 5e45c8f..5df596a 100644
--- a/core/java/android/view/MotionEvent.java
+++ b/core/java/android/view/MotionEvent.java
@@ -3180,6 +3180,18 @@ public final class MotionEvent extends InputEvent implements Parcelable {
return (getButtonState() & button) == button;
}
+ /**
+ * Checks if a stylus is being used and if the first stylus button is
+ * pressed.
+ *
+ * @return True if the tool is a stylus and if the first stylus button is
+ * pressed.
+ * @see #BUTTON_SECONDARY
+ */
+ public final boolean isStylusButtonPressed() {
+ return (isButtonPressed(BUTTON_SECONDARY) && getToolType(0) == TOOL_TYPE_STYLUS);
+ }
+
public static final Parcelable.Creator<MotionEvent> CREATOR
= new Parcelable.Creator<MotionEvent>() {
public MotionEvent createFromParcel(Parcel in) {
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java
index b5b7f0f..81ad5ad 100644
--- a/core/java/android/view/View.java
+++ b/core/java/android/view/View.java
@@ -987,6 +987,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
*/
static final int DUPLICATE_PARENT_STATE = 0x00400000;
+ /**
+ * <p>
+ * Indicates this view can be stylus button pressed. When stylus button
+ * pressable, a View reacts to stylus button presses by notifiying
+ * the OnStylusButtonPressListener.
+ * </p>
+ * {@hide}
+ */
+ static final int STYLUS_BUTTON_PRESSABLE = 0x00800000;
+
+
/** @hide */
@IntDef({
SCROLLBARS_INSIDE_OVERLAY,
@@ -3270,6 +3281,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
protected OnLongClickListener mOnLongClickListener;
/**
+ * Listener used to dispatch stylus touch and button press events. This field should be made
+ * private, so it is hidden from the SDK.
+ * {@hide}
+ */
+ protected OnStylusButtonPressListener mOnStylusButtonPressListener;
+
+ /**
* Listener used to build the context menu.
* This field should be made private, so it is hidden from the SDK.
* {@hide}
@@ -3360,6 +3378,13 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
private boolean mHasPerformedLongPress;
/**
+ * Whether the stylus button is currently pressed down. This is true when
+ * the stylus is touching the screen and the button has been pressed, this
+ * is false once the stylus has been lifted.
+ */
+ private boolean mInStylusButtonPress = false;
+
+ /**
* The minimum height of the view. We'll try our best to have the height
* of this view to at least this amount.
*/
@@ -3875,6 +3900,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
viewFlagMasks |= LONG_CLICKABLE;
}
break;
+ case com.android.internal.R.styleable.View_stylusButtonPressable:
+ if (a.getBoolean(attr, false)) {
+ viewFlagValues |= STYLUS_BUTTON_PRESSABLE;
+ viewFlagMasks |= STYLUS_BUTTON_PRESSABLE;
+ }
+ break;
case com.android.internal.R.styleable.View_saveEnabled:
if (!a.getBoolean(attr, true)) {
viewFlagValues |= SAVE_DISABLED;
@@ -4340,6 +4371,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
out.append((mViewFlags&SCROLLBARS_VERTICAL) != 0 ? 'V' : '.');
out.append((mViewFlags&CLICKABLE) != 0 ? 'C' : '.');
out.append((mViewFlags&LONG_CLICKABLE) != 0 ? 'L' : '.');
+ out.append((mViewFlags & STYLUS_BUTTON_PRESSABLE) != 0 ? 'S' : '.');
out.append(' ');
out.append((mPrivateFlags&PFLAG_IS_ROOT_NAMESPACE) != 0 ? 'R' : '.');
out.append((mPrivateFlags&PFLAG_FOCUSED) != 0 ? 'F' : '.');
@@ -4835,6 +4867,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Register a callback to be invoked when this view is touched with a stylus and the button is
+ * pressed.
+ *
+ * @param l The callback that will run
+ * @see #setStylusButtonPressable(boolean)
+ */
+ public void setOnStylusButtonPressListener(@Nullable OnStylusButtonPressListener l) {
+ if (!isStylusButtonPressable()) {
+ setStylusButtonPressable(true);
+ }
+ getListenerInfo().mOnStylusButtonPressListener = l;
+ }
+
+ /**
* Register a callback to be invoked when the context menu for this view is
* being built. If this view is not long clickable, it becomes long clickable.
*
@@ -4912,6 +4958,46 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Call this view's OnStylusButtonPressListener, if it is defined.
+ *
+ * @return True if there was an assigned OnStylusButtonPressListener that consumed the event,
+ * false otherwise.
+ */
+ public boolean performStylusButtonPress() {
+ sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_STYLUS_BUTTON_PRESSED);
+
+ boolean handled = false;
+ ListenerInfo li = mListenerInfo;
+ if (li != null && li.mOnStylusButtonPressListener != null) {
+ handled = li.mOnStylusButtonPressListener.onStylusButtonPress(View.this);
+ }
+ if (handled) {
+ performHapticFeedback(HapticFeedbackConstants.STYLUS_BUTTON_PRESS);
+ }
+ return handled;
+ }
+
+ /**
+ * Checks for a stylus button press and calls the listener.
+ *
+ * @param event The event.
+ * @return True if the event was consumed.
+ */
+ private boolean performStylusActionOnButtonPress(MotionEvent event) {
+ if (isStylusButtonPressable() && !mInStylusButtonPress
+ && !mHasPerformedLongPress && event.isStylusButtonPressed()) {
+ if (performStylusButtonPress()) {
+ mInStylusButtonPress = true;
+ setPressed(true, event.getX(), event.getY());
+ removeTapCallback();
+ removeLongPressCallback();
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
* Performs button-related actions during a touch down event.
*
* @param event The event.
@@ -5701,6 +5787,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* <li>{@link AccessibilityNodeInfo#setFocused(boolean)},</li>
* <li>{@link AccessibilityNodeInfo#setLongClickable(boolean)},</li>
* <li>{@link AccessibilityNodeInfo#setSelected(boolean)},</li>
+ * <li>{@link AccessibilityNodeInfo#setStylusButtonPressable(boolean)}</li>
* </ul>
* <p>
* Subclasses should override this method, call the super implementation,
@@ -5852,6 +5939,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
structure.setChecked(true);
}
}
+ if (isStylusButtonPressable()) {
+ structure.setStylusButtonPressable(true);
+ }
structure.setClassName(getAccessibilityClassName().toString());
structure.setContentDescription(getContentDescription());
}
@@ -5909,6 +5999,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
structure.setChecked(true);
}
}
+ if (info.isStylusButtonPressable()) {
+ structure.setStylusButtonPressable(true);
+ }
CharSequence cname = info.getClassName();
structure.setClassName(cname != null ? cname.toString() : null);
structure.setContentDescription(info.getContentDescription());
@@ -6038,6 +6131,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
info.setAccessibilityFocused(isAccessibilityFocused());
info.setSelected(isSelected());
info.setLongClickable(isLongClickable());
+ info.setStylusButtonPressable(isStylusButtonPressable());
info.setLiveRegion(getAccessibilityLiveRegion());
// TODO: These make sense only if we are in an AdapterView but all
@@ -6068,6 +6162,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
info.addAction(AccessibilityNodeInfo.ACTION_LONG_CLICK);
}
+ if (isStylusButtonPressable() && isEnabled()) {
+ info.addAction(AccessibilityAction.ACTION_STYLUS_BUTTON_PRESS);
+ }
+
CharSequence text = getIterableTextForAccessibility();
if (text != null && text.length() > 0) {
info.setTextSelection(getAccessibilitySelectionStart(), getAccessibilitySelectionEnd());
@@ -7442,6 +7540,31 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Indicates whether this view reacts to stylus button press events or not.
+ *
+ * @return true if the view is stylus button pressable, false otherwise
+ * @see #setStylusButtonPressable(boolean)
+ * @attr ref android.R.styleable#View_stylusButtonPressable
+ */
+ public boolean isStylusButtonPressable() {
+ return (mViewFlags & STYLUS_BUTTON_PRESSABLE) == STYLUS_BUTTON_PRESSABLE;
+ }
+
+ /**
+ * Enables or disables stylus button press events for this view. When a view is stylus button
+ * pressable it reacts to the user touching the screen with a stylus and pressing the first
+ * stylus button. This event can launch the listener.
+ *
+ * @param stylusButtonPressable true to make the view react to a stylus button press, false
+ * otherwise
+ * @see #isStylusButtonPressable()
+ * @attr ref android.R.styleable#View_stylusButtonPressable
+ */
+ public void setStylusButtonPressable(boolean stylusButtonPressable) {
+ setFlags(stylusButtonPressable ? STYLUS_BUTTON_PRESSABLE : 0, STYLUS_BUTTON_PRESSABLE);
+ }
+
+ /**
* Sets the pressed state for this view and provides a touch coordinate for
* animation hinting.
*
@@ -7856,7 +7979,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
public void addTouchables(ArrayList<View> views) {
final int viewFlags = mViewFlags;
- if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
+ if (((viewFlags & CLICKABLE) == CLICKABLE || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
+ || (viewFlags & STYLUS_BUTTON_PRESSABLE) == STYLUS_BUTTON_PRESSABLE)
&& (viewFlags & ENABLED_MASK) == ENABLED) {
views.add(this);
}
@@ -8571,6 +8695,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
return requestRectangleOnScreen(r, true);
}
} break;
+ case R.id.accessibilityActionStylusButtonPress: {
+ if (isStylusButtonPressable()) {
+ performStylusButtonPress();
+ return true;
+ }
+ } break;
}
return false;
}
@@ -9728,7 +9858,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
return (viewFlags & CLICKABLE) == CLICKABLE
- || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE;
+ || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE
+ || (viewFlags & STYLUS_BUTTON_PRESSABLE) == STYLUS_BUTTON_PRESSABLE;
}
/**
@@ -9811,15 +9942,17 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
final float x = event.getX();
final float y = event.getY();
final int viewFlags = mViewFlags;
+ final int action = event.getAction();
if ((viewFlags & ENABLED_MASK) == DISABLED) {
- if (event.getAction() == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
+ if (action == MotionEvent.ACTION_UP && (mPrivateFlags & PFLAG_PRESSED) != 0) {
setPressed(false);
}
// A disabled view that is clickable still consumes the touch
// events, it just doesn't respond to them.
- return (((viewFlags & CLICKABLE) == CLICKABLE ||
- (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE));
+ return (((viewFlags & CLICKABLE) == CLICKABLE
+ || (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)
+ || (viewFlags & STYLUS_BUTTON_PRESSABLE) == STYLUS_BUTTON_PRESSABLE);
}
if (mTouchDelegate != null) {
@@ -9829,9 +9962,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
if (((viewFlags & CLICKABLE) == CLICKABLE ||
- (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
- switch (event.getAction()) {
+ (viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) ||
+ (viewFlags & STYLUS_BUTTON_PRESSABLE) == STYLUS_BUTTON_PRESSABLE) {
+ switch (action) {
case MotionEvent.ACTION_UP:
+ if (mInStylusButtonPress) {
+ mInStylusButtonPress = false;
+ mHasPerformedLongPress = false;
+ }
boolean prepressed = (mPrivateFlags & PFLAG_PREPRESSED) != 0;
if ((mPrivateFlags & PFLAG_PRESSED) != 0 || prepressed) {
// take focus if we don't have it already and we should in
@@ -9885,6 +10023,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
case MotionEvent.ACTION_DOWN:
mHasPerformedLongPress = false;
+ mInStylusButtonPress = false;
+
+ if (performStylusActionOnButtonPress(event)) {
+ break;
+ }
if (performButtonActionOnTouchDown(event)) {
break;
@@ -9914,6 +10057,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
setPressed(false);
removeTapCallback();
removeLongPressCallback();
+ if (mInStylusButtonPress) {
+ mInStylusButtonPress = false;
+ mHasPerformedLongPress = false;
+ }
break;
case MotionEvent.ACTION_MOVE:
@@ -9929,6 +10076,9 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
setPressed(false);
}
+ } else if (performStylusActionOnButtonPress(event)) {
+ // Check for stylus button press if we're within the view.
+ break;
}
break;
}
@@ -10216,7 +10366,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
if (accessibilityEnabled) {
if ((changed & FOCUSABLE_MASK) != 0 || (changed & VISIBILITY_MASK) != 0
- || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0) {
+ || (changed & CLICKABLE) != 0 || (changed & LONG_CLICKABLE) != 0
+ || (changed & STYLUS_BUTTON_PRESSABLE) != 0) {
if (oldIncludeForAccessibility != includeForAccessibility()) {
notifySubtreeAccessibilityStateChangedIfNeeded();
} else {
@@ -20782,6 +20933,20 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
}
/**
+ * Interface definition for a callback to be invoked when a view is touched with a stylus while
+ * the stylus button is pressed.
+ */
+ public interface OnStylusButtonPressListener {
+ /**
+ * Called when a view is touched with a stylus while the stylus button is pressed.
+ *
+ * @param v The view that was touched.
+ * @return true if the callback consumed the stylus button press, false otherwise.
+ */
+ boolean onStylusButtonPress(View v);
+ }
+
+ /**
* Interface definition for a callback to be invoked when the context menu
* for this view is being built.
*/
diff --git a/core/java/android/view/ViewAssistStructure.java b/core/java/android/view/ViewAssistStructure.java
index 346b8ec..fccfbb8 100644
--- a/core/java/android/view/ViewAssistStructure.java
+++ b/core/java/android/view/ViewAssistStructure.java
@@ -40,6 +40,8 @@ public abstract class ViewAssistStructure {
public abstract void setLongClickable(boolean state);
+ public abstract void setStylusButtonPressable(boolean state);
+
public abstract void setFocusable(boolean state);
public abstract void setFocused(boolean state);
diff --git a/core/java/android/view/accessibility/AccessibilityEvent.java b/core/java/android/view/accessibility/AccessibilityEvent.java
index 417e22c..b0dbeca 100644
--- a/core/java/android/view/accessibility/AccessibilityEvent.java
+++ b/core/java/android/view/accessibility/AccessibilityEvent.java
@@ -684,6 +684,11 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
public static final int TYPE_WINDOWS_CHANGED = 0x00400000;
/**
+ * Represents the event of a stylus button press on a {@link android.view.View}.
+ */
+ public static final int TYPE_VIEW_STYLUS_BUTTON_PRESSED = 0x00800000;
+
+ /**
* Change type for {@link #TYPE_WINDOW_CONTENT_CHANGED} event:
* The type of change is not defined.
*/
@@ -731,6 +736,7 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
* @see #TYPE_TOUCH_INTERACTION_START
* @see #TYPE_TOUCH_INTERACTION_END
* @see #TYPE_WINDOWS_CHANGED
+ * @see #TYPE_VIEW_STYLUS_BUTTON_PRESSED
*/
public static final int TYPES_ALL_MASK = 0xFFFFFFFF;
@@ -1396,6 +1402,14 @@ public final class AccessibilityEvent extends AccessibilityRecord implements Par
builder.append("TYPE_WINDOWS_CHANGED");
eventTypeCount++;
} break;
+ case TYPE_VIEW_STYLUS_BUTTON_PRESSED: {
+ if (eventTypeCount > 0) {
+ builder.append(", ");
+ }
+ builder.append("TYPE_VIEW_STYLUS_BUTTON_PRESSED");
+ eventTypeCount++;
+ }
+ break;
}
}
if (eventTypeCount > 1) {
diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
index 0736ed8..bf4b7ae 100644
--- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java
@@ -520,6 +520,8 @@ public class AccessibilityNodeInfo implements Parcelable {
private static final int BOOLEAN_PROPERTY_CONTENT_INVALID = 0x00010000;
+ private static final int BOOLEAN_PROPERTY_STYLUS_BUTTON_PRESSABLE = 0x00020000;
+
/**
* Bits that provide the id of a virtual descendant of a view.
*/
@@ -1930,6 +1932,30 @@ public class AccessibilityNodeInfo implements Parcelable {
}
/**
+ * Gets whether this node is stylus button pressable.
+ *
+ * @return True if the node is stylus button pressable.
+ */
+ public boolean isStylusButtonPressable() {
+ return getBooleanProperty(BOOLEAN_PROPERTY_STYLUS_BUTTON_PRESSABLE);
+ }
+
+ /**
+ * Sets whether this node is stylus button pressable.
+ * <p>
+ * <strong>Note:</strong> Cannot be called from an
+ * {@link android.accessibilityservice.AccessibilityService}. This class is made immutable
+ * before being delivered to an AccessibilityService.
+ * </p>
+ *
+ * @param stylusButtonPressable True if the node is stylus button pressable.
+ * @throws IllegalStateException If called from an AccessibilityService.
+ */
+ public void setStylusButtonPressable(boolean stylusButtonPressable) {
+ setBooleanProperty(BOOLEAN_PROPERTY_STYLUS_BUTTON_PRESSABLE, stylusButtonPressable);
+ }
+
+ /**
* Gets the node's live region mode.
* <p>
* A live region is a node that contains information that is important for
@@ -3117,6 +3143,7 @@ public class AccessibilityNodeInfo implements Parcelable {
builder.append("; selected: ").append(isSelected());
builder.append("; clickable: ").append(isClickable());
builder.append("; longClickable: ").append(isLongClickable());
+ builder.append("; stylusButtonPressable: ").append(isStylusButtonPressable());
builder.append("; enabled: ").append(isEnabled());
builder.append("; password: ").append(isPassword());
builder.append("; scrollable: ").append(isScrollable());
@@ -3472,6 +3499,12 @@ public class AccessibilityNodeInfo implements Parcelable {
public static final AccessibilityAction ACTION_SCROLL_TO_POSITION =
new AccessibilityAction(R.id.accessibilityActionScrollToPosition, null);
+ /**
+ * Action that stylus button presses the node.
+ */
+ public static final AccessibilityAction ACTION_STYLUS_BUTTON_PRESS =
+ new AccessibilityAction(R.id.accessibilityActionStylusButtonPress, null);
+
private static final ArraySet<AccessibilityAction> sStandardActions = new ArraySet<>();
static {
sStandardActions.add(ACTION_FOCUS);
@@ -3498,6 +3531,7 @@ public class AccessibilityNodeInfo implements Parcelable {
sStandardActions.add(ACTION_SET_TEXT);
sStandardActions.add(ACTION_SHOW_ON_SCREEN);
sStandardActions.add(ACTION_SCROLL_TO_POSITION);
+ sStandardActions.add(ACTION_STYLUS_BUTTON_PRESS);
}
private final int mActionId;