1/* 2 * Copyright 2017 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17package androidx.recyclerview.selection; 18 19import android.graphics.Point; 20import android.view.KeyEvent; 21import android.view.MotionEvent; 22 23import androidx.annotation.NonNull; 24 25/** 26 * Utility methods for working with {@link MotionEvent} instances. 27 */ 28final class MotionEvents { 29 30 private MotionEvents() {} 31 32 static boolean isMouseEvent(@NonNull MotionEvent e) { 33 return e.getToolType(0) == MotionEvent.TOOL_TYPE_MOUSE; 34 } 35 36 static boolean isTouchEvent(@NonNull MotionEvent e) { 37 return e.getToolType(0) == MotionEvent.TOOL_TYPE_FINGER; 38 } 39 40 static boolean isActionMove(@NonNull MotionEvent e) { 41 return e.getActionMasked() == MotionEvent.ACTION_MOVE; 42 } 43 44 static boolean isActionDown(@NonNull MotionEvent e) { 45 return e.getActionMasked() == MotionEvent.ACTION_DOWN; 46 } 47 48 static boolean isActionUp(@NonNull MotionEvent e) { 49 return e.getActionMasked() == MotionEvent.ACTION_UP; 50 } 51 52 static boolean isActionPointerUp(@NonNull MotionEvent e) { 53 return e.getActionMasked() == MotionEvent.ACTION_POINTER_UP; 54 } 55 56 @SuppressWarnings("unused") 57 static boolean isActionPointerDown(@NonNull MotionEvent e) { 58 return e.getActionMasked() == MotionEvent.ACTION_POINTER_DOWN; 59 } 60 61 static boolean isActionCancel(@NonNull MotionEvent e) { 62 return e.getActionMasked() == MotionEvent.ACTION_CANCEL; 63 } 64 65 static Point getOrigin(@NonNull MotionEvent e) { 66 return new Point((int) e.getX(), (int) e.getY()); 67 } 68 69 static boolean isPrimaryMouseButtonPressed(@NonNull MotionEvent e) { 70 return isButtonPressed(e, MotionEvent.BUTTON_PRIMARY); 71 } 72 73 static boolean isSecondaryMouseButtonPressed(@NonNull MotionEvent e) { 74 return isButtonPressed(e, MotionEvent.BUTTON_SECONDARY); 75 } 76 77 static boolean isTertiaryMouseButtonPressed(@NonNull MotionEvent e) { 78 return isButtonPressed(e, MotionEvent.BUTTON_TERTIARY); 79 } 80 81 // NOTE: Can replace this with MotionEvent.isButtonPressed once targeting 21 or higher. 82 private static boolean isButtonPressed(MotionEvent e, int button) { 83 if (button == 0) { 84 return false; 85 } 86 return (e.getButtonState() & button) == button; 87 } 88 89 static boolean isShiftKeyPressed(@NonNull MotionEvent e) { 90 return hasBit(e.getMetaState(), KeyEvent.META_SHIFT_ON); 91 } 92 93 static boolean isCtrlKeyPressed(@NonNull MotionEvent e) { 94 return hasBit(e.getMetaState(), KeyEvent.META_CTRL_ON); 95 } 96 97 static boolean isAltKeyPressed(@NonNull MotionEvent e) { 98 return hasBit(e.getMetaState(), KeyEvent.META_ALT_ON); 99 } 100 101 static boolean isTouchpadScroll(@NonNull MotionEvent e) { 102 // Touchpad inputs are treated as mouse inputs, and when scrolling, there are no buttons 103 // returned. 104 return isMouseEvent(e) && isActionMove(e) && e.getButtonState() == 0; 105 } 106 107 /** 108 * Returns true if the event is a drag event (which is presumbaly, but not 109 * explicitly required to be a mouse event). 110 * @param e 111 */ 112 static boolean isPointerDragEvent(MotionEvent e) { 113 return isPrimaryMouseButtonPressed(e) 114 && isActionMove(e); 115 } 116 117 private static boolean hasBit(int metaState, int bit) { 118 return (metaState & bit) != 0; 119 } 120} 121